diff --git a/src/Makefile.am b/src/Makefile.am index 128fc201..3e040bbd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,7 @@ rtorrent_SOURCES = \ command_network.cc \ command_peer.cc \ command_tracker.cc \ + command_scheduler.cc \ command_ui.cc \ control.cc \ control.h \ diff --git a/src/command_events.cc b/src/command_events.cc index 8febed4d..ca118a7c 100644 --- a/src/command_events.cc +++ b/src/command_events.cc @@ -65,10 +65,15 @@ apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Obje if (args.size() == 0 || args.size() > 2) throw torrent::input_error("Wrong number of arguments."); - if (args.front().as_string().empty()) + const std::string& rawKey = args.front().as_string(); + + if (rawKey.empty()) throw torrent::input_error("Empty key."); - std::string key = "1_state_" + args.front().as_string(); + // If the key starts with '_' then it's supposed to be literal, with + // the initial '_' removed. This allows us to get proper ordering + // for internal rtorrent tasks. + std::string key = rawKey[0] != '_' ? ("1_state_" + rawKey) : rawKey.substr(1); if (args.size() == 1) slotMap->erase(key); diff --git a/src/command_helpers.cc b/src/command_helpers.cc index 5d877fea..c2f75265 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -69,6 +69,7 @@ void initialize_command_peer(); void initialize_command_local(); void initialize_command_network(); void initialize_command_tracker(); +void initialize_command_scheduler(); void initialize_command_ui(); void @@ -81,6 +82,7 @@ initialize_commands() { initialize_command_file(); initialize_command_peer(); initialize_command_tracker(); + initialize_command_scheduler(); #ifdef ADDING_COMMANDS if (commandSlotsItr > commandSlots + COMMAND_SLOTS_SIZE || diff --git a/src/command_helpers.h b/src/command_helpers.h index 865d6022..099b77f7 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -181,6 +181,19 @@ add_variable(key, NULL, NULL, &rpc::CommandVariable::get_string, NULL, std::stri // DOWNLOAD RELATED COMMANDS // +#define CMD_V(prefix, postfix, type, defaultValue) \ + add_variable(prefix "" postfix, prefix "set_" postfix, NULL, &rpc::CommandVariable::get_##type, &rpc::CommandVariable::set_##type, defaultValue); + +#define CMD_G_SLOT(key, function, slot, parm, doc) \ + commandAnySlotsItr->set_slot(slot); \ + rpc::commands.insert_type(key, commandAnySlotsItr++, &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); + +#define CMD_G(key, slot) \ + CMD_G_SLOT(key, call_unknown, slot, "i:", "") + +#define CMD_G_STRING(key, slot) \ + CMD_G_SLOT(key, call_string, slot, "i:", "") + #define CMD_D_SLOT(key, function, slot, parm, doc) \ commandDownloadSlotsItr->set_slot(slot); \ rpc::commands.insert_type(key, commandDownloadSlotsItr++, &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); diff --git a/src/command_scheduler.cc b/src/command_scheduler.cc new file mode 100644 index 00000000..a6daf501 --- /dev/null +++ b/src/command_scheduler.cc @@ -0,0 +1,53 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005-2007, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "config.h" + +#include "rpc/command_variable.h" + +#include "globals.h" +#include "control.h" +#include "command_helpers.h" + +void +initialize_command_scheduler() { +// core::DownloadList* dList = control->core()->download_list(); + +// CMD_G("scheduler.active", rak::bind_ptr_fn(&cmd_call, "view.size=active")); + + CMD_V("scheduler.", "max_active", value, (int64_t)-1); + +} diff --git a/src/command_ui.cc b/src/command_ui.cc index 0b32a9e6..698d4b1d 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -179,6 +179,11 @@ apply_not(rpc::target_type target, const torrent::Object& rawArgs) { return (int64_t)!as_boolean(rawArgs); } +torrent::Object +apply_false(rpc::target_type target, const torrent::Object& rawArgs) { + return (int64_t)0; +} + torrent::Object apply_and(rpc::target_type target, const torrent::Object& rawArgs) { if (rawArgs.type() != torrent::Object::TYPE_LIST) @@ -378,6 +383,16 @@ apply_if(int flags, rpc::target_type target, const torrent::Object& rawArgs) { } } +torrent::Object +cmd_view_size(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { + return (*control->view_manager()->find_throw(rawArgs.as_string()))->size_visible(); +} + +torrent::Object +cmd_view_size_not_visible(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) { + return (*control->view_manager()->find_throw(rawArgs.as_string()))->size_not_visible(); +} + torrent::Object cmd_ui_unfocus_download(core::Download* download, const torrent::Object& rawArgs) { control->ui()->download_list()->unfocus_download(download); @@ -426,6 +441,8 @@ initialize_command_ui() { // Cleanup and add . to view. + CMD_G_STRING("view.size", rak::ptr_fn(&cmd_view_size)); + CMD_G_STRING("view.size_not_visible", rak::ptr_fn(&cmd_view_size_not_visible)); CMD_D_STRING("view.filter_download", rak::ptr_fn(&cmd_view_filter_download)); CMD_D_STRING("view.set_visible", rak::ptr_fn(&cmd_view_set_visible)); CMD_D_STRING("view.set_not_visible", rak::ptr_fn(&cmd_view_set_not_visible)); @@ -441,6 +458,7 @@ initialize_command_ui() { ADD_ANY_NONE("cat", rak::ptr_fn(&apply_cat)); ADD_ANY_NONE("if", rak::bind_ptr_fn(&apply_if, 0)); ADD_ANY_NONE("not", rak::ptr_fn(&apply_not)); + ADD_ANY_NONE("false", rak::ptr_fn(&apply_false)); ADD_ANY_NONE("and", rak::ptr_fn(&apply_and)); ADD_ANY_NONE("or", rak::ptr_fn(&apply_or)); diff --git a/src/core/view.h b/src/core/view.h index eeabc91f..97a6ca07 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -83,6 +83,8 @@ public: bool empty_visible() const { return m_size == 0; } size_type size() const { return m_size; } + size_type size_visible() const { return m_size; } + size_type size_not_visible() const { return base_type::size() - m_size; } // Perhaps this should be renamed? iterator begin_visible() { return begin(); } diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index f672325c..253970c9 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -36,6 +36,7 @@ #include "config.h" +#include #include #include #include @@ -133,6 +134,9 @@ WindowFileList::redraw() { m_canvas->print(16 + itr.depth() - 1, pos, "/"); } else if (itr.is_file()) { + char buffer[std::max(m_canvas->width() + 1, 256)]; + Canvas::attributes_list attributes; + torrent::File* e = *itr; const char* priority; @@ -144,27 +148,26 @@ WindowFileList::redraw() { default: priority = "BUG"; break; }; - m_canvas->print(0, pos, "%3d %s ", done_percentage(e), priority); + sprintf(buffer, "%3d %s ", done_percentage(e), priority); int64_t val = e->size_bytes(); if (val < (int64_t(1000) << 20)) - m_canvas->print(8, pos, "%5.1f M", (double)val / (int64_t(1) << 20)); + sprintf(buffer + 8, "%5.1f M", (double)val / (int64_t(1) << 20)); else if (val < (int64_t(1000) << 30)) - m_canvas->print(8, pos, "%5.1f G", (double)val / (int64_t(1) << 30)); + sprintf(buffer + 8, "%5.1f G", (double)val / (int64_t(1) << 30)); else - m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40)); + sprintf(buffer + 8, "%5.1f T", (double)val / (int64_t(1) << 40)); - m_canvas->print(16 + itr.depth(), pos, "| %s", - itr.depth() < (*itr)->path()->size() ? (*itr)->path()->at(itr.depth()).c_str() : "UNKNOWN"); + std::fill_n(buffer + 15, 64, ' '); -// m_canvas->print(104, pos, "%i - %i %c%c %u %u", -// e->range().first, -// e->range().first != e->range().second ? (e->range().second - 1) : e->range().second, -// e->is_created() ? 'E' : 'M', -// e->is_correct_size() ? 'C' : 'W', -// e->match_depth_prev(), -// e->match_depth_next()); + int first = 16 + std::min(itr.depth(), 8); + int last = std::max(m_canvas->width() + 1, 16 + 12); + + std::snprintf(buffer + first, last - first, "| %s", + itr.depth() < (*itr)->path()->size() ? (*itr)->path()->at(itr.depth()).c_str() : "UNKNOWN"); + + m_canvas->print_attributes(0, pos, buffer, buffer + std::strlen(buffer), &attributes); } else { m_canvas->print(0, pos, "BORK BORK"); diff --git a/src/main.cc b/src/main.cc index deb166bf..c56270d7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -183,13 +183,16 @@ main(int argc, char** argv) { "view_sort_new = name,less=d.get_name=\n" "view_sort_current = name,less=d.get_name=\n" + "view_add = active\n" + "view_filter = active,false=\n" + "view_add = started\n" - "view_filter = started,d.get_state=\n" + "view_filter = started,false=\n" "view_event_added = started,d.resume=\n" "view_event_removed = started,d.pause=\n" "view_add = stopped\n" - "view_filter = stopped,not=$d.get_state=\n" + "view_filter = stopped,false=\n" "view_add = complete\n" "view_filter = complete,d.get_complete=\n" diff --git a/src/rpc/xmlrpc.cc b/src/rpc/xmlrpc.cc index a7014f70..0cc89eb9 100644 --- a/src/rpc/xmlrpc.cc +++ b/src/rpc/xmlrpc.cc @@ -195,7 +195,7 @@ xmlrpc_to_target(xmlrpc_env* env, xmlrpc_value* value) { if (*str == '\0' || *end != '\0') throw xmlrpc_error(XMLRPC_TYPE_ERROR, "Invalid index."); - target = rpc::make_target(XmlRpc::call_file, xmlrpc.get_slot_find_tracker()(download, index)); + target = rpc::make_target(XmlRpc::call_tracker, xmlrpc.get_slot_find_tracker()(download, index)); break; default: diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc index 203a0e01..44204af7 100644 --- a/src/ui/element_download_list.cc +++ b/src/ui/element_download_list.cc @@ -88,7 +88,7 @@ ElementDownloadList::ElementDownloadList() : m_bindings['6'] = sigc::bind(sigc::mem_fun(*this, &ElementDownloadList::receive_change_view), "incomplete"); m_bindings['7'] = sigc::bind(sigc::mem_fun(*this, &ElementDownloadList::receive_change_view), "hashing"); m_bindings['8'] = sigc::bind(sigc::mem_fun(*this, &ElementDownloadList::receive_change_view), "seeding"); -// m_bindings['8'] = sigc::bind(sigc::mem_fun(*this, &ElementDownloadList::receive_command), "view_set=main,seeding", (const char*)NULL); + m_bindings['9'] = sigc::bind(sigc::mem_fun(*this, &ElementDownloadList::receive_change_view), "active"); m_bindings[KEY_UP] = m_bindings['P' - '@'] = sigc::mem_fun(*this, &ElementDownloadList::receive_prev); m_bindings[KEY_DOWN] = m_bindings['N' - '@'] = sigc::mem_fun(*this, &ElementDownloadList::receive_next);