From 2c5ce1989aee0ddc5e5e97769fdd4285d82441fd Mon Sep 17 00:00:00 2001 From: rakshasa Date: Sun, 26 Jun 2005 19:51:20 +0000 Subject: [PATCH] Added setting for session directory. Added support for quotation in settings. Added key for changing the priority of all files in a torrent. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@477 e378c898-3ddf-0310-93e7-cc216c733640 --- doc/rtorrent.1.xml | 29 +++++++++++--------- doc/rtorrent.rc | 5 ++++ src/core/download_store.cc | 10 +------ src/core/download_store.h | 4 +-- src/core/manager.cc | 4 +-- src/core/manager.h | 10 +++---- src/main.cc | 3 ++- src/option_file.cc | 17 +++++++----- src/option_handler_rules.cc | 16 +++++++++-- src/option_handler_rules.h | 2 ++ src/ui/download.cc | 10 +++---- src/ui/element_file_list.cc | 53 +++++++++++++++++++++++++------------ src/ui/element_file_list.h | 6 ++++- src/utils/directory.cc | 11 ++++++++ src/utils/directory.h | 2 ++ 15 files changed, 118 insertions(+), 64 deletions(-) diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml index c95040d9..fb7fe775 100644 --- a/doc/rtorrent.1.xml +++ b/doc/rtorrent.1.xml @@ -1,6 +1,6 @@ - + @@ -144,14 +144,14 @@ Add torrent using an URL or file path. Use tab to view directory content and do - autocomplete. + auto-complete. l - View log. Exit by pressing the spacebar. + View log. Exit by pressing the space-bar. @@ -167,8 +167,9 @@ -> - View torrent file list. Use the spacebar to change file - priorities. + View torrent file list. Use the space-bar to change the + file priority and * to change the + priority of all files. @@ -198,7 +199,7 @@ o Display the tracker list. Cycle the trackers in a group - with the spacebar. + with the space-bar. @@ -282,7 +283,8 @@ Session management will be enabled and the torrent files for all open downloads will be stored in this directory. Only one instance of rtorrent should be used with each session - directory, though at the moment no locking is done. + directory, though at the moment no locking is done. An empty + string will disable the session directory. @@ -316,7 +318,7 @@ max_uploads = value - Set the maximum number of simultanious uploads per download. + Set the maximum number of simultaneous uploads per download. @@ -328,7 +330,7 @@ - upload_rate = kb + upload_rate = KB Set the maximum global upload rate. @@ -375,10 +377,13 @@ session = directory + Session management will be enabled and the torrent files for all open downloads will be stored in this directory. Only one instance of rtorrent should be used with each session - directory, though at the moment no locking is done. + directory, though at the moment no locking is done. An empty + string will disable the session directory. + @@ -407,8 +412,8 @@ max_open_files = value - Number of files to simultaniously keep open. Libtorrent - dynamicly opens and closes files when mapping files to + Number of files to simultaneously keep open. Libtorrent + dynamically opens and closes files when mapping files to memory. diff --git a/doc/rtorrent.rc b/doc/rtorrent.rc index fc6008de..f61bef0e 100644 --- a/doc/rtorrent.rc +++ b/doc/rtorrent.rc @@ -21,6 +21,11 @@ # space yet. #directory = ./ +# Default session directory. Make sure you don't run multiple instance +# of rtorrent using the same session directory. Perhaps using a +# relative path? +#session = + # The ip address reported to the tracker. #ip = 127.0.0.1 diff --git a/src/core/download_store.cc b/src/core/download_store.cc index 37303d73..3fed61e0 100644 --- a/src/core/download_store.cc +++ b/src/core/download_store.cc @@ -36,21 +36,13 @@ namespace core { void -DownloadStore::activate(const std::string& path) { +DownloadStore::use(const std::string& path) { m_path = path; - if (m_path.empty()) - throw std::logic_error("core::DownloadStore::activate(...) received an empty path"); - if (*m_path.rbegin() != '/') m_path += '/'; } -void -DownloadStore::disable() { - m_path = ""; -} - void DownloadStore::save(Download* d) { if (!is_active()) diff --git a/src/core/download_store.h b/src/core/download_store.h index 85d3cee4..712ffdbe 100644 --- a/src/core/download_store.h +++ b/src/core/download_store.h @@ -34,8 +34,8 @@ class Download; class DownloadStore { public: - void activate(const std::string& path); - void disable(); + // Disable by passing an empty string. + void use(const std::string& path); bool is_active() { return !m_path.empty(); } diff --git a/src/core/manager.cc b/src/core/manager.cc index 901e9115..4d832123 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -97,8 +97,8 @@ Manager::insert(std::string uri) { } } -Manager::iterator -Manager::erase(DownloadList::iterator itr) { +Manager::DListItr +Manager::erase(DListItr itr) { if ((*itr)->get_download().is_active()) throw std::logic_error("core::Manager::erase(...) called on an active download"); diff --git a/src/core/manager.h b/src/core/manager.h index 59945254..93c4b8ca 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -40,11 +40,11 @@ namespace core { class Manager { public: - typedef DownloadList::iterator iterator; + typedef DownloadList::iterator DListItr; typedef sigc::slot1 SlotReady; typedef sigc::slot0 SlotFailed; - Manager() : m_portFirst(6890), m_portLast(6999), m_debugTracker(-1) {} + Manager() : m_portFirst(6890), m_portLast(6999) {} DownloadList& get_download_list() { return m_downloadList; } DownloadStore& get_download_store() { return m_downloadStore; } @@ -59,7 +59,7 @@ public: void cleanup(); void insert(std::string uri); - iterator erase(DownloadList::iterator itr); + DListItr erase(DListItr itr); void start(Download* d); void stop(Download* d); @@ -68,8 +68,6 @@ public: void set_port_range(int a, int b) { m_portFirst = a; m_portLast = b; } - void debug_tracker() { m_debugTracker = 0; } - private: void create_http(const std::string& uri); void create_final(std::istream* s); @@ -88,8 +86,6 @@ private: int m_portFirst; int m_portLast; - - int m_debugTracker; }; } diff --git a/src/main.cc b/src/main.cc index c6b908bd..5bbe37a7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -108,7 +108,7 @@ parse_options(ui::Control* c, OptionHandler* optionHandler, int argc, char** arg optionParser.insert_option('d', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "directory")); optionParser.insert_option('i', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "ip")); optionParser.insert_option('p', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "port")); - optionParser.insert_option('s', sigc::mem_fun(c->get_core().get_download_store(), &core::DownloadStore::activate)); + optionParser.insert_option('s', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "session")); optionParser.insert_option_list('o', sigc::mem_fun(*optionHandler, &OptionHandler::process)); @@ -133,6 +133,7 @@ initialize_option_handler(ui::Control* c, OptionHandler* optionHandler) { optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_read_ahead)); optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files, &validate_fd)); + optionHandler->insert("session", new OptionHandlerString(c, &apply_session_directory, &validate_directory)); optionHandler->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump, &validate_yes_no)); } diff --git a/src/option_file.cc b/src/option_file.cc index 17c56f16..7351af0f 100644 --- a/src/option_file.cc +++ b/src/option_file.cc @@ -45,16 +45,21 @@ OptionFile::parse_line(const char* line) { if (line[0] == '#') return; + int result; char key[64]; char opt[512]; - int result; + opt[0] = '\0'; // Check for empty lines, and options within "abc". - if ((result = std::sscanf(line, "%64s = %512s", key, opt)) == 2) - m_slotOption(key, opt); - - // Don't throw on empty lines or lines with key and opt. - if (result == 1) + if ((result = std::sscanf(line, "%64s = \"%512[^\"]s", key, opt)) != 2 && + (result = std::sscanf(line, "%64s = %512s", key, opt)) != 2 && + result == 1) throw std::runtime_error("Error parseing option file."); + + if (opt[0] == '"' && opt[1] == '"') + opt[0] = '\0'; + + if (result >= 1) + m_slotOption(key, opt); } diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 481c6f00..6156ccab 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -26,6 +26,7 @@ #include #include +#include "utils/directory.h" #include "ui/control.h" #include "option_handler_rules.h" @@ -38,15 +39,18 @@ validate_ip(const std::string& arg) { return inet_aton(arg.c_str(), &addr); } +// We consider an empty string to be valid as this allows us to +// disable options. bool validate_directory(const std::string& arg) { + //return arg.empty() || utils::Directory(arg).is_valid(); return true; } bool validate_port_range(const std::string& arg) { int a, b; - + return std::sscanf(arg.c_str(), "%i-%i", &a, &b) == 2 && a <= b && a > 0 && b < (1 << 16); } @@ -93,7 +97,10 @@ apply_download_max_uploads(ui::Control* m, int arg) { void apply_download_directory(ui::Control* m, const std::string& arg) { - m->get_core().get_download_list().slot_map_insert().insert("1_directory", sigc::bind(sigc::mem_fun(&core::Download::set_root_directory), arg)); + if (!arg.empty()) + m->get_core().get_download_list().slot_map_insert().insert("1_directory", sigc::bind(sigc::mem_fun(&core::Download::set_root_directory), arg)); + else + m->get_core().get_download_list().slot_map_insert().erase("1_directory"); } void @@ -152,3 +159,8 @@ apply_check_hash(ui::Control* m, const std::string& arg) { else m->get_core().get_download_list().slot_map_finished().erase("1_check_hash"); } + +void +apply_session_directory(ui::Control* m, const std::string& arg) { + m->get_core().get_download_store().use(arg); +} diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h index fc60415e..109f3de2 100644 --- a/src/option_handler_rules.h +++ b/src/option_handler_rules.h @@ -62,6 +62,8 @@ void apply_port_range(ui::Control* m, const std::string& arg); void apply_tracker_dump(ui::Control* m, const std::string& arg); void apply_check_hash(ui::Control* m, const std::string& arg); +void apply_session_directory(ui::Control* m, const std::string& arg); + class OptionHandlerInt : public OptionHandlerBase { public: typedef bool (*Validate)(int); diff --git a/src/ui/download.cc b/src/ui/download.cc index dbc0ec1e..cb242465 100644 --- a/src/ui/download.cc +++ b/src/ui/download.cc @@ -74,16 +74,16 @@ Download::~Download() { if (m_window != m_control->get_display().end()) throw std::logic_error("ui::Download::~Download() called on an active object"); + m_connPeerConnected.disconnect(); + m_connPeerDisconnected.disconnect(); + + delete m_bindings; + std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete()); delete m_windowTitle; delete m_windowDownloadStatus; delete m_windowMainStatus; - - delete m_bindings; - - m_connPeerConnected.disconnect(); - m_connPeerDisconnected.disconnect(); } void diff --git a/src/ui/element_file_list.cc b/src/ui/element_file_list.cc index 4176a157..d33f6a6f 100644 --- a/src/ui/element_file_list.cc +++ b/src/ui/element_file_list.cc @@ -37,6 +37,7 @@ ElementFileList::ElementFileList(core::Download* d) : m_focus(0) { m_bindings[' '] = sigc::mem_fun(*this, &ElementFileList::receive_priority); + m_bindings['*'] = sigc::mem_fun(*this, &ElementFileList::receive_change_all); m_bindings[KEY_DOWN] = sigc::mem_fun(*this, &ElementFileList::receive_next); m_bindings[KEY_UP] = sigc::mem_fun(*this, &ElementFileList::receive_prev); } @@ -99,26 +100,44 @@ ElementFileList::receive_priority() { torrent::Entry e = m_download->get_download().get_entry(m_focus); - switch (e.get_priority()) { - case torrent::Entry::STOPPED: - e.set_priority(torrent::Entry::HIGH); - break; - - case torrent::Entry::NORMAL: - e.set_priority(torrent::Entry::STOPPED); - break; - - case torrent::Entry::HIGH: - e.set_priority(torrent::Entry::NORMAL); - break; - - default: - e.set_priority(torrent::Entry::NORMAL); - break; - }; + e.set_priority(next_priority(e.get_priority())); m_download->get_download().update_priorities(); m_window->mark_dirty(); } +void +ElementFileList::receive_change_all() { + if (m_window == NULL) + throw std::logic_error("ui::ElementFileList::receive_prev(...) called on a disabled object"); + + if (m_focus >= m_download->get_download().get_entry_size()) + return; + + Priority p = next_priority(m_download->get_download().get_entry(m_focus).get_priority()); + + for (int i = 0, e = m_download->get_download().get_entry_size(); i != e; ++i) + m_download->get_download().get_entry(i).set_priority(p); + + m_download->get_download().update_priorities(); + m_window->mark_dirty(); +} + +ElementFileList::Priority +ElementFileList::next_priority(Priority p) { + switch(p) { + case torrent::Entry::STOPPED: + return torrent::Entry::HIGH; + + case torrent::Entry::NORMAL: + return torrent::Entry::STOPPED; + + case torrent::Entry::HIGH: + return torrent::Entry::NORMAL; + + default: + return torrent::Entry::NORMAL; + }; +} + } diff --git a/src/ui/element_file_list.h b/src/ui/element_file_list.h index 31468d85..5a4f74ce 100644 --- a/src/ui/element_file_list.h +++ b/src/ui/element_file_list.h @@ -37,7 +37,8 @@ class Control; class ElementFileList : public ElementBase { public: - typedef display::WindowFileList WFileList; + typedef torrent::Entry::Priority Priority; + typedef display::WindowFileList WFileList; ElementFileList(core::Download* d); @@ -49,6 +50,9 @@ private: void receive_prev(); void receive_priority(); + void receive_change_all(); + + Priority next_priority(Priority p); core::Download* m_download; WFileList* m_window; diff --git a/src/utils/directory.cc b/src/utils/directory.cc index 0d18ba0d..f163ff4a 100644 --- a/src/utils/directory.cc +++ b/src/utils/directory.cc @@ -31,6 +31,17 @@ namespace utils { +bool +Directory::is_valid() const { + if (m_path.empty()) + return false; + + DIR* d = opendir(m_path.c_str()); + closedir(d); + + return d; +} + bool Directory::update() { if (m_path.empty()) diff --git a/src/utils/directory.h b/src/utils/directory.h index 1a09fde5..0072268e 100644 --- a/src/utils/directory.h +++ b/src/utils/directory.h @@ -50,6 +50,8 @@ public: Directory() {} Directory(const std::string& path) : m_path(path) {} + bool is_valid() const; + bool update(); const std::string& get_path() { return m_path; }