diff --git a/configure.ac b/configure.ac index ff14d3a8..0da3372b 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,11 @@ AC_PROG_CXX AC_PROG_RANLIB AC_SYS_LARGEFILE -AC_SEARCH_LIBS(wbkgdset, ncurses curses,,echo "*** The ncurses library is required!";exit 1) + +AC_SEARCH_LIBS(add_wch, ncursesw, + AC_DEFINE(HAVE_NCURSESW, 1, defined if ncurses wide character support is available), + AC_SEARCH_LIBS(wbkgdset, ncurses curses,,echo "*** The ncurses library is required!";exit 1) +) TORRENT_CHECK_EXECINFO() TORRENT_CHECK_CURL() diff --git a/rak/functional_fun.h b/rak/functional_fun.h index 8b62fc6d..3d870de0 100644 --- a/rak/functional_fun.h +++ b/rak/functional_fun.h @@ -194,6 +194,21 @@ private: Func m_func; }; +template +class ptr_fn0_b1_t : public function_base0 { +public: + typedef Result (*Func)(Arg1); + + ptr_fn0_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {} + virtual ~ptr_fn0_b1_t() {} + + virtual Result operator () () { return m_func(m_arg1); } + +private: + Func m_func; + Arg1 m_arg1; +}; + template class ptr_fn1_b1_t : public function_base1 { public: @@ -245,6 +260,12 @@ ptr_fn(Result (*func)(Arg1)) { return new ptr_fn1_t(func); } +template +function_base0* +bind_ptr_fn(Result (*func)(Arg1), const Arg1 arg1) { + return new ptr_fn0_b1_t(func, arg1); +} + template function_base1* bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) { diff --git a/src/control.cc b/src/control.cc index f2f79059..38fca7e4 100644 --- a/src/control.cc +++ b/src/control.cc @@ -92,8 +92,8 @@ Control::initialize() { display::Window::slot_unschedule(rak::make_mem_fun(m_display, &display::Manager::unschedule)); display::Window::slot_adjust(rak::make_mem_fun(m_display, &display::Manager::adjust_layout)); - m_core->get_poll_manager()->signal_interrupted().connect(sigc::mem_fun(*m_inputStdin, &input::InputEvent::event_read)); - m_core->get_poll_manager()->signal_interrupted().connect(sigc::ptr_fun(display::Canvas::do_update)); +// m_core->get_poll_manager()->signal_interrupted().connect(sigc::mem_fun(*m_inputStdin, &input::InputEvent::event_read)); +// m_core->get_poll_manager()->signal_interrupted().connect(sigc::ptr_fun(display::Canvas::do_update)); m_core->get_poll_manager()->get_http_stack()->set_user_agent(std::string(PACKAGE "/" VERSION "/") + torrent::version()); m_core->initialize_second(); diff --git a/src/core/curl_get.cc b/src/core/curl_get.cc index a01ac84f..d3c9ea67 100644 --- a/src/core/curl_get.cc +++ b/src/core/curl_get.cc @@ -137,6 +137,11 @@ CurlGet::set_http_proxy(const char* s) { curl_easy_setopt(m_handle, CURLOPT_PROXY, s); } +void +CurlGet::set_bind_address(const char* s) { + curl_easy_setopt(m_handle, CURLOPT_INTERFACE, s); +} + void CurlGet::perform(CURLMsg* msg) { if (msg->msg != CURLMSG_DONE) diff --git a/src/core/curl_get.h b/src/core/curl_get.h index 6c11312d..0db760b1 100644 --- a/src/core/curl_get.h +++ b/src/core/curl_get.h @@ -68,6 +68,7 @@ class CurlGet : public torrent::Http { void set_user_agent(const char* s); void set_http_proxy(const char* s); + void set_bind_address(const char* s); protected: CURL* handle() { return m_handle; } diff --git a/src/core/curl_stack.cc b/src/core/curl_stack.cc index 8aea14f6..f2921a07 100644 --- a/src/core/curl_stack.cc +++ b/src/core/curl_stack.cc @@ -109,6 +109,9 @@ CurlStack::add_get(CurlGet* get) { if (!m_httpProxy.empty()) get->set_http_proxy(m_httpProxy.c_str()); + if (!m_bindAddress.empty()) + get->set_bind_address(m_bindAddress.c_str()); + CURLMcode code; if ((code = curl_multi_add_handle((CURLM*)m_handle, get->handle())) > 0) diff --git a/src/core/curl_stack.h b/src/core/curl_stack.h index fcd9ad4f..6800b2f2 100644 --- a/src/core/curl_stack.h +++ b/src/core/curl_stack.h @@ -71,6 +71,9 @@ class CurlStack { const std::string& http_proxy() const { return m_httpProxy; } void set_http_proxy(const std::string& s) { m_httpProxy = s; } + const std::string& bind_address() const { return m_bindAddress; } + void set_bind_address(const std::string& s) { m_bindAddress = s; } + static void global_init(); static void global_cleanup(); @@ -89,6 +92,7 @@ class CurlStack { std::string m_userAgent; std::string m_httpProxy; + std::string m_bindAddress; }; } diff --git a/src/core/download.cc b/src/core/download.cc index b759b8c2..b342e4d4 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -41,6 +41,7 @@ #include #include #include +#include #include "utils/variable_generic.h" @@ -61,15 +62,24 @@ Download::Download(torrent::Download d) : m_variables.insert("connection_current", new utils::VariableSlotString(rak::mem_fn(this, &Download::connection_current), rak::mem_fn(this, &Download::set_connection_current))); - m_variables.insert("connection_leech", new utils::VariableValue(connection_type_to_string(torrent::Download::CONNECTION_LEECH))); - m_variables.insert("connection_seed", new utils::VariableValue(connection_type_to_string(torrent::Download::CONNECTION_SEED))); + m_variables.insert("connection_leech", new utils::VariableAny(connection_type_to_string(torrent::Download::CONNECTION_LEECH))); + m_variables.insert("connection_seed", new utils::VariableAny(connection_type_to_string(torrent::Download::CONNECTION_SEED))); m_variables.insert("directory", new utils::VariableSlotString(NULL, rak::mem_fn(this, &Download::set_root_directory))); m_variables.insert("tied_to_file", new utils::VariableBencode(&m_download.bencode(), "tied_to_file", torrent::Bencode::TYPE_STRING)); - m_variables.insert("peers_min", new utils::VariableSlotValue(rak::mem_fn(&m_download, &torrent::Download::peers_min), + m_variables.insert("min_peers", new utils::VariableSlotValue(rak::mem_fn(&m_download, &torrent::Download::peers_min), rak::mem_fn(&m_download, &torrent::Download::set_peers_min), "%u")); + m_variables.insert("max_peers", new utils::VariableSlotValue(rak::mem_fn(&m_download, &torrent::Download::peers_max), + rak::mem_fn(&m_download, &torrent::Download::set_peers_max), + "%u")); + m_variables.insert("max_uploads", new utils::VariableSlotValue(rak::mem_fn(&m_download, &torrent::Download::uploads_max), + rak::mem_fn(&m_download, &torrent::Download::set_uploads_max), + "%u")); + m_variables.insert("priority", new utils::VariableSlotValue(rak::mem_fn(this, &Download::priority), + rak::mem_fn(this, &Download::set_priority), + "%u")); } Download::~Download() { @@ -106,10 +116,25 @@ Download::enable_udp_trackers(bool state) { m_download.tracker(i).disable(); } +uint32_t +Download::priority() { + return get_bencode().get_key("rtorrent").get_key("priority").as_value(); +} + +void +Download::set_priority(uint32_t p) { + if (p >= 4) + throw torrent::input_error("Priority out of range."); + + torrent::download_set_priority(m_download, p * 2); + get_bencode().get_key("rtorrent").insert_key("priority", (int64_t)p); +} + void Download::receive_finished() { m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string())); - torrent::download_set_priority(m_download, 2); + // FIXME + //torrent::download_set_priority(m_download, 2); } void @@ -148,6 +173,36 @@ Download::connection_type_to_string(torrent::Download::ConnectionType t) { } } +uint32_t +Download::string_to_priority(const std::string& name) { + if (name == "off") + return 0; + else if (name == "low") + return 1; + else if (name == "normal") + return 2; + else if (name == "high") + return 3; + else + throw torrent::input_error("Could not convert string to priority."); +} + +const char* +Download::priority_to_string(uint32_t p) { + switch (p) { + case 0: + return "off"; + case 1: + return "low"; + case 2: + return "normal"; + case 3: + return "high"; + default: + throw torrent::input_error("Priority out of range."); + } +} + void Download::receive_chunk_failed(uint32_t idx) { m_chunksFailed++; diff --git a/src/core/download.h b/src/core/download.h index 6b4d4327..1557491f 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -71,6 +71,9 @@ public: void enable_udp_trackers(bool state); + uint32_t priority(); + void set_priority(uint32_t p); + // Helper functions for calling functions in torrent::Download // through sigc++. template @@ -86,6 +89,9 @@ public: static ConnType string_to_connection_type(const std::string& name); static const char* connection_type_to_string(ConnType t); + static uint32_t string_to_priority(const std::string& name); + static const char* priority_to_string(uint32_t p); + private: Download(const Download&); void operator () (const Download&); diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 6d5af71f..0d8adc6a 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -67,9 +67,9 @@ DownloadFactory::DownloadFactory(const std::string& uri, Manager* m) : m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load)); m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit)); - m_variables.insert("connection_leech", new utils::VariableValue(control->variables()->get("connection_leech"))); - m_variables.insert("connection_seed", new utils::VariableValue(control->variables()->get("connection_seed"))); - m_variables.insert("directory", new utils::VariableValue(control->variables()->get("directory"))); + m_variables.insert("connection_leech", new utils::VariableAny(control->variables()->get("connection_leech"))); + m_variables.insert("connection_seed", new utils::VariableAny(control->variables()->get("connection_seed"))); + m_variables.insert("directory", new utils::VariableAny(control->variables()->get("directory"))); m_variables.insert("tied_to_file", new utils::VariableBool(false)); } @@ -150,9 +150,16 @@ DownloadFactory::receive_success() { (*itr)->variables()->set("connection_leech", m_variables.get("connection_leech")); (*itr)->variables()->set("connection_seed", m_variables.get("connection_seed")); (*itr)->variables()->set("directory", m_variables.get("directory")); + (*itr)->variables()->set("min_peers", control->variables()->get("min_peers")); + (*itr)->variables()->set("max_peers", control->variables()->get("max_peers")); + (*itr)->variables()->set("max_uploads", control->variables()->get("max_uploads")); -// if (control->variables()->get("peers_min") -// (*itr)->variables()->set("peers_min", m_variables.get("directory")); + if ((*itr)->get_bencode().get_key("rtorrent").has_key("priority") && + (*itr)->get_bencode().get_key("rtorrent").get_key("priority").is_value()) + (*itr)->variables()->set("priority", (*itr)->get_bencode().get_key("rtorrent").get_key("priority").as_value() % 4); + else + (*itr)->variables()->set("priority", (int64_t)2); + torrent::Bencode& bencode = (*itr)->get_bencode(); diff --git a/src/core/manager.cc b/src/core/manager.cc index 8ef17881..a7f7f5c4 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -290,6 +290,8 @@ Manager::bind(const std::string& addr) { } else { torrent::set_bind_address(addr); } + + m_pollManager->get_http_stack()->set_bind_address(torrent::bind_address()); } void diff --git a/src/core/poll_manager.cc b/src/core/poll_manager.cc index 30143414..0b6cd184 100644 --- a/src/core/poll_manager.cc +++ b/src/core/poll_manager.cc @@ -95,8 +95,6 @@ void PollManager::check_error() { if (errno != EINTR) throw std::runtime_error("Poll::work(): select error"); - - m_signalInterrupted.emit(); } } diff --git a/src/core/poll_manager.h b/src/core/poll_manager.h index bd225bf8..e89e9911 100644 --- a/src/core/poll_manager.h +++ b/src/core/poll_manager.h @@ -63,9 +63,6 @@ public: virtual void poll(rak::timer timeout) = 0; - // Use a signal, connect checking for input and updating the display. - Signal& signal_interrupted() { return m_signalInterrupted; } - protected: PollManager(const PollManager&); void operator = (const PollManager&); @@ -79,8 +76,6 @@ protected: fd_set* m_readSet; fd_set* m_writeSet; fd_set* m_errorSet; - - Signal m_signalInterrupted; }; } diff --git a/src/display/canvas.cc b/src/display/canvas.cc index 6b0436ee..e0498b83 100644 --- a/src/display/canvas.cc +++ b/src/display/canvas.cc @@ -36,6 +36,9 @@ #include "config.h" +#include +#include + #include "canvas.h" namespace display { @@ -74,4 +77,14 @@ Canvas::cleanup() { endwin(); } +std::pair +Canvas::term_size() { + struct winsize ws; + + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) + return std::pair(ws.ws_col, ws.ws_row); + else + return std::pair(80, 24); +} + } diff --git a/src/display/canvas.h b/src/display/canvas.h index 0e0eeffc..64877766 100644 --- a/src/display/canvas.h +++ b/src/display/canvas.h @@ -51,10 +51,14 @@ public: void refresh() { wnoutrefresh(m_window); } static void refresh_std() { wnoutrefresh(stdscr); } void redraw() { redrawwin(m_window); } + static void redraw_std() { redrawwin(stdscr); } void resize(int w, int h) { wresize(m_window, h, w); } void resize(int x, int y, int w, int h); + static void resize_term(int x, int y) { resizeterm(y, x); } + static void resize_term(std::pair dim) { resizeterm(dim.second, dim.first); } + int get_x() { int x, y; getyx(m_window, y, x); return x; } int get_y() { int x, y; getyx(m_window, y, x); return y; } int get_width() { int x, y; getmaxyx(m_window, y, x); return x; } @@ -116,6 +120,8 @@ public: static int get_screen_width() { int x, y; getmaxyx(stdscr, y, x); return x; } static int get_screen_height() { int x, y; getmaxyx(stdscr, y, x); return y; } + static std::pair term_size(); + static void do_update() { doupdate(); } private: diff --git a/src/display/manager.cc b/src/display/manager.cc index e566c12f..89fc38c3 100644 --- a/src/display/manager.cc +++ b/src/display/manager.cc @@ -47,7 +47,8 @@ namespace display { -Manager::Manager() { +Manager::Manager() : + m_forceRedraw(false) { m_taskUpdate.set_slot(rak::mem_fn(this, &Manager::receive_update)); } @@ -55,6 +56,12 @@ Manager::~Manager() { priority_queue_erase(&taskScheduler, &m_taskUpdate); } +void +Manager::force_redraw() { + m_forceRedraw = true; +} + + Manager::iterator Manager::insert(iterator pos, Window* w) { return Base::insert(pos, w); @@ -131,6 +138,14 @@ Manager::adjust_layout() { void Manager::receive_update() { + if (m_forceRedraw) { + m_forceRedraw = false; + + display::Canvas::resize_term(display::Canvas::term_size()); + Canvas::redraw_std(); + adjust_layout(); + } + Canvas::refresh_std(); rak::priority_queue_perform(&m_scheduler, cachedTime); diff --git a/src/display/manager.h b/src/display/manager.h index 5eddcc8f..21b003c7 100644 --- a/src/display/manager.h +++ b/src/display/manager.h @@ -64,6 +64,8 @@ public: Manager(); ~Manager(); + void force_redraw(); + iterator insert(iterator pos, Window* w); iterator erase(iterator pos); iterator erase(Window* w); @@ -80,6 +82,7 @@ private: void schedule_update(); + bool m_forceRedraw; rak::timer m_timeLastUpdate; rak::priority_queue_default m_scheduler; diff --git a/src/display/utils.cc b/src/display/utils.cc index 7f4e6887..b75e7821 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -123,6 +123,8 @@ print_download_info(char* buf, unsigned int length, core::Download* d) { buf = print_download_time_left(buf, last - buf, d); + *buf = '\0'; + return buf; } @@ -159,7 +161,7 @@ print_download_time_left(char* buf, unsigned int length, core::Download* d) { if (!d->get_download().is_active() || (rate = d->get_download().down_rate()->rate()) < 512) { - buf += std::max(0, snprintf(buf, length, "--:--:--")); + buf += std::max(snprintf(buf, length, "--:--:--"), 0); return buf; } diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index c65e5573..af117653 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -83,7 +83,7 @@ WindowDownloadList::redraw() { int pos = 0; while (range.first != range.second) { - char buffer[m_canvas->get_width() - 2]; + char buffer[m_canvas->get_width()]; char* position; char* last = buffer + m_canvas->get_width() - 2; diff --git a/src/display/window_download_statusbar.cc b/src/display/window_download_statusbar.cc index 163ec87e..18cecab2 100644 --- a/src/display/window_download_statusbar.cc +++ b/src/display/window_download_statusbar.cc @@ -65,15 +65,20 @@ WindowDownloadStatusbar::redraw() { position = print_download_info(buffer, last - buffer, m_download); m_canvas->print(0, 0, "%s", buffer); - m_canvas->print(0, 1, "Peers: %i(%i) Min/Max: %i/%i Uploads: %i U/I: %i/%i Failed: %i", - (int)m_download->get_download().peers_connected(), - (int)m_download->get_download().peers_not_connected(), - (int)m_download->get_download().peers_min(), - (int)m_download->get_download().peers_max(), - (int)m_download->get_download().uploads_max(), - (int)m_download->get_download().peers_currently_unchoked(), - (int)m_download->get_download().peers_currently_interested(), - (int)m_download->chunks_failed()); + position = buffer + std::max(snprintf(buffer, last - buffer, "Peers: %i(%i) Min/Max: %i/%i Uploads: %i U/I: %i/%i Failed: %i", + (int)m_download->get_download().peers_connected(), + (int)m_download->get_download().peers_not_connected(), + (int)m_download->get_download().peers_min(), + (int)m_download->get_download().peers_max(), + (int)m_download->get_download().uploads_max(), + (int)m_download->get_download().peers_currently_unchoked(), + (int)m_download->get_download().peers_currently_interested(), + (int)m_download->chunks_failed()), + 0); + position = buffer + std::max(snprintf(position, last - buffer, " Priority: %s", + core::Download::priority_to_string(m_download->variables()->get("priority").as_value())), + 0); + m_canvas->print(0, 1, "%s", buffer); position = print_download_status(buffer, last - buffer, m_download); m_canvas->print(0, 2, "[%c:%i] %s", diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index 501583dc..ba7ec3d3 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -52,6 +52,21 @@ WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) : m_focus(focus) { } +std::wstring +hack_wstring(const std::string& src) { + size_t length = ::mbstowcs(NULL, src.c_str(), src.size()); + + if (length == (size_t)-1) + return std::wstring(L""); + + std::wstring dest; + dest.resize(length); + + ::mbstowcs(&*dest.begin(), src.c_str(), src.size()); + + return dest; +} + void WindowFileList::redraw() { m_slotSchedule(this, (cachedTime + 10 * 1000000).round_seconds()); diff --git a/src/main.cc b/src/main.cc index bdb411db..c09bd264 100644 --- a/src/main.cc +++ b/src/main.cc @@ -157,6 +157,9 @@ int main(int argc, char** argv) { try { + // Temporary. + setlocale(LC_ALL, ""); + cachedTime = rak::timer::current(); control = new Control; @@ -167,10 +170,11 @@ main(int argc, char** argv) { initialize_option_handler(control); SignalHandler::set_ignore(SIGPIPE); - SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_shutdown)); - SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV)); - SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); - SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE)); + SignalHandler::set_handler(SIGINT, sigc::mem_fun(control, &Control::receive_shutdown)); + SignalHandler::set_handler(SIGWINCH, sigc::mem_fun(control->display(), &display::Manager::force_redraw)); + SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV)); + SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); + SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE)); control->core()->initialize_first(); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index c828e08d..b90048bd 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -88,31 +88,6 @@ OptionHandlerString::process(const std::string& key, const std::string& arg) { m_apply(m_control, arg); } -void -apply_download_min_peers(Control* m, int arg) { - m->core()->get_download_list().slot_map_insert()["1_min_peers"] = sigc::bind(sigc::mem_fun(&core::Download::call), arg); -} - -void -apply_download_max_peers(Control* m, int arg) { - m->core()->get_download_list().slot_map_insert()["1_max_peers"] = sigc::bind(sigc::mem_fun(&core::Download::call), arg); -} - -void -apply_download_max_uploads(Control* m, int arg) { - m->core()->get_download_list().slot_map_insert()["1_max_uploads"] = sigc::bind(sigc::mem_fun(&core::Download::call), arg); -} - -void -apply_global_download_rate(Control* m, int arg) { - m->ui()->set_down_throttle(arg); -} - -void -apply_global_upload_rate(Control* m, int arg) { - m->ui()->set_up_throttle(arg); -} - void apply_umask(int arg) { umask(arg); @@ -128,21 +103,6 @@ apply_hash_interval(Control* m, int arg) { torrent::set_hash_interval(arg * 1000); } -void -apply_hash_max_tries(Control* m, int arg) { - torrent::set_hash_max_tries(arg); -} - -void -apply_max_open_files(Control* m, int arg) { - torrent::set_max_open_files(arg); -} - -void -apply_max_open_sockets(Control* m, int arg) { - torrent::set_max_open_sockets(arg); -} - // The arg string *must* have been checked with validate_port_range // first. void @@ -263,33 +223,33 @@ initialize_option_handler(Control* c) { utils::VariableMap* variables = control->variables(); // Cleaned up. - variables->insert("check_hash", new utils::VariableValue("yes")); - variables->insert("port_random", new utils::VariableValue("yes")); + variables->insert("check_hash", new utils::VariableAny("yes")); + variables->insert("port_random", new utils::VariableAny("yes")); variables->insert("session", new utils::VariableSlotString<>(NULL, rak::mem_fn(&control->core()->get_download_store(), &core::DownloadStore::use))); - variables->insert("connection_leech", new utils::VariableValue("leech")); - variables->insert("connection_seed", new utils::VariableValue("seed")); + variables->insert("connection_leech", new utils::VariableAny("leech")); + variables->insert("connection_seed", new utils::VariableAny("seed")); - variables->insert("directory", new utils::VariableValue(std::string())); + variables->insert("directory", new utils::VariableAny(std::string())); variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&torrent::set_local_address))); + variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind))); + + variables->insert("min_peers", new utils::VariableValue(40)); + variables->insert("max_peers", new utils::VariableValue(100)); + variables->insert("max_uploads", new utils::VariableValue(15)); + + variables->insert("download_rate", new utils::VariableSlotValue(NULL, rak::mem_fn(control->ui(), &ui::Root::set_down_throttle), "%i")); + variables->insert("upload_rate", new utils::VariableSlotValue(NULL, rak::mem_fn(control->ui(), &ui::Root::set_up_throttle), "%i")); + + variables->insert("hash_max_tries", new utils::VariableSlotValue(NULL, rak::ptr_fn(&torrent::set_hash_max_tries), "%i")); + variables->insert("max_open_files", new utils::VariableSlotValue(NULL, rak::ptr_fn(&torrent::set_max_open_files), "%i")); + variables->insert("max_open_sockets", new utils::VariableSlotValue(NULL, rak::ptr_fn(&torrent::set_max_open_sockets), "%i")); // Old. - variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind))); variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c))); - variables->insert("max_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i")); - - variables->insert("min_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i")); - variables->insert("max_uploads", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_uploads, c), "%i")); - - variables->insert("download_rate", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_global_download_rate, c), "%i")); - variables->insert("upload_rate", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_global_upload_rate, c), "%i")); - variables->insert("hash_read_ahead", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_read_ahead, c), "%i")); variables->insert("hash_interval", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_interval, c), "%i")); - variables->insert("hash_max_tries", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_max_tries, c), "%i")); - variables->insert("max_open_files", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i")); - variables->insert("max_open_sockets", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i")); variables->insert("umask", new utils::VariableSlotValue(NULL, rak::ptr_fn(&apply_umask), "%o")); diff --git a/src/ui/download.cc b/src/ui/download.cc index 526b707b..93e97b57 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -229,6 +229,11 @@ Download::receive_snub_peer() { mark_dirty(); } +void +Download::receive_next_priority() { + m_download->set_priority((m_download->priority() + 1) % 4); +} + void Download::bind_keys() { (*m_bindings)['1'] = sigc::bind(sigc::mem_fun(*this, &Download::receive_max_uploads), -1); @@ -237,6 +242,7 @@ Download::bind_keys() { (*m_bindings)['4'] = sigc::bind(sigc::mem_fun(*this, &Download::receive_min_peers), 5); (*m_bindings)['5'] = sigc::bind(sigc::mem_fun(*this, &Download::receive_max_peers), -5); (*m_bindings)['6'] = sigc::bind(sigc::mem_fun(*this, &Download::receive_max_peers), 5); + (*m_bindings)['+'] = sigc::mem_fun(*this, &Download::receive_next_priority); (*m_bindings)['t'] = sigc::bind(sigc::mem_fun(m_download->get_download(), &torrent::Download::tracker_manual_request), false); (*m_bindings)['T'] = sigc::bind(sigc::mem_fun(m_download->get_download(), &torrent::Download::tracker_manual_request), true); diff --git a/src/ui/download.h b/src/ui/download.h index de53180c..12487467 100644 --- a/src/ui/download.h +++ b/src/ui/download.h @@ -105,6 +105,8 @@ private: void receive_snub_peer(); + void receive_next_priority(); + void bind_keys(); void mark_dirty(); diff --git a/src/ui/root.cc b/src/ui/root.cc index 0564a698..868b73fa 100644 --- a/src/ui/root.cc +++ b/src/ui/root.cc @@ -108,8 +108,9 @@ Root::setup_keys() { m_bindings['D'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), 50); m_bindings['C'] = sigc::bind(sigc::mem_fun(*this, &Root::adjust_down_throttle), -50); - m_bindings[KEY_RESIZE] = sigc::mem_fun(*m_control->display(), &display::Manager::adjust_layout); - m_bindings['\x11'] = sigc::mem_fun(*m_control, &Control::receive_shutdown); + //m_bindings[KEY_RESIZE] = sigc::mem_fun(*m_control->display(), &display::Manager::adjust_layout); + m_bindings['\x0C'] = sigc::mem_fun(m_control->display(), &display::Manager::force_redraw); + m_bindings['\x11'] = sigc::mem_fun(m_control, &Control::receive_shutdown); } void diff --git a/src/utils/variable_generic.cc b/src/utils/variable_generic.cc index 604fd993..5393a063 100644 --- a/src/utils/variable_generic.cc +++ b/src/utils/variable_generic.cc @@ -36,10 +36,25 @@ #include "config.h" +#include + #include "variable_generic.h" namespace utils { +VariableAny::~VariableAny() { +} + +const torrent::Bencode& +VariableAny::get() { + return m_variable; +} + +void +VariableAny::set(const torrent::Bencode& arg) { + m_variable = arg; +} + VariableValue::~VariableValue() { } @@ -50,7 +65,32 @@ VariableValue::get() { void VariableValue::set(const torrent::Bencode& arg) { - m_variable = arg; + uint64_t value; + const char* first; + char* last; + + switch (arg.get_type()) { + case torrent::Bencode::TYPE_NONE: + m_variable = (int64_t)0; + break; + + case torrent::Bencode::TYPE_VALUE: + m_variable = arg; + break; + + case torrent::Bencode::TYPE_STRING: + first = arg.as_string().c_str(); + value = std::strtoll(first, &last, 0); + + if (last == first || *last != '\0') + throw torrent::input_error("Could not convert string to value."); + + m_variable = value; + break; + + default: + throw torrent::input_error("VariableValue unsupported type restriction."); + } } VariableBool::~VariableBool() { diff --git a/src/utils/variable_generic.h b/src/utils/variable_generic.h index ecda2c7c..575f6fdb 100644 --- a/src/utils/variable_generic.h +++ b/src/utils/variable_generic.h @@ -49,9 +49,22 @@ namespace utils { +class VariableAny : public Variable { +public: + VariableAny(const torrent::Bencode& v = torrent::Bencode()) : + m_variable(v) {} + virtual ~VariableAny(); + + virtual const torrent::Bencode& get(); + virtual void set(const torrent::Bencode& arg); + +private: + torrent::Bencode m_variable; +}; + class VariableValue : public Variable { public: - VariableValue(const torrent::Bencode& v = torrent::Bencode()) : m_variable(v) {} + VariableValue(int64_t v) : m_variable(v) {} virtual ~VariableValue(); virtual const torrent::Bencode& get();