mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-14 06:02:31 +00:00
* Use user-modifiable commands instead of slots for the 'on_*' events.
git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1070 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
+113
-15
@@ -42,39 +42,74 @@
|
||||
#include "control.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
std::string
|
||||
system_method_generate_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) {
|
||||
std::string command;
|
||||
|
||||
while (first != last) {
|
||||
if (!command.empty())
|
||||
command += " ;";
|
||||
|
||||
command += (first++)->as_string();
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
// system.method.insert <generic> {name, "simple|private|const", ...}
|
||||
// system.method.insert <generic> {name, "list|private|const"}
|
||||
//
|
||||
// Add a new user-defined method called 'name' and any number of
|
||||
// lines.
|
||||
torrent::Object
|
||||
system_method_insert(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
// Allow arbritary number of args, just use what ever necessary in
|
||||
// order to create a function blob out of them.
|
||||
if (args.empty() || ++args.begin() == args.end())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
if (args.empty())
|
||||
return torrent::Object();
|
||||
|
||||
const std::string& rawKey = args.front().as_string();
|
||||
torrent::Object::list_const_iterator itrArgs = args.begin();
|
||||
const std::string& rawKey = (itrArgs++)->as_string();
|
||||
|
||||
if (rawKey.empty() || rpc::commands.has(rawKey))
|
||||
throw torrent::input_error("Invalid key.");
|
||||
|
||||
std::string command;
|
||||
rpc::Command* command = NULL;
|
||||
rpc::Command::any_slot slot = NULL;
|
||||
int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc;
|
||||
|
||||
for (torrent::Object::list_const_iterator itr = ++args.begin(), last = args.end(); itr != last; itr++) {
|
||||
if (!command.empty())
|
||||
command += " ;";
|
||||
const std::string& options = itrArgs->as_string();
|
||||
|
||||
command += itr->as_string();
|
||||
// Use a | separated list of options here, for non-modifable,
|
||||
// non-public methods, etc.
|
||||
if (options.find("list") != std::string::npos) {
|
||||
// Later, make it possible to add functions here.
|
||||
slot = &rpc::CommandFunctionList::call;
|
||||
command = new rpc::CommandFunctionList();
|
||||
|
||||
} else if (options.find("simple") != std::string::npos) {
|
||||
slot = &rpc::CommandFunction::call;
|
||||
command = new rpc::CommandFunction(system_method_generate_command(++itrArgs, args.end()));
|
||||
}
|
||||
|
||||
if (options.find("private") != std::string::npos)
|
||||
flags &= ~rpc::CommandMap::flag_public_xmlrpc;
|
||||
|
||||
if (options.find("const") != std::string::npos)
|
||||
flags &= ~rpc::CommandMap::flag_modifiable;
|
||||
|
||||
char* key = new char[rawKey.size() + 1];
|
||||
std::memcpy(key, rawKey.c_str(), rawKey.size() + 1);
|
||||
|
||||
rpc::commands.insert_type(key, new rpc::CommandFunction(command), &rpc::CommandFunction::call,
|
||||
rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc, NULL, NULL);
|
||||
|
||||
rpc::commands.insert_type(key, command, slot, flags, NULL, NULL);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
// system.method.erase <> {name}
|
||||
//
|
||||
// Erase a modifiable method called 'name. Trying to remove methods
|
||||
// that aren't modifiable, e.g. defined by rtorrent or set to
|
||||
// read-only by the user, will result in an error.
|
||||
torrent::Object
|
||||
system_method_erase(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(rawArgs.as_string().c_str());
|
||||
@@ -90,8 +125,71 @@ system_method_erase(__UNUSED rpc::target_type target, const torrent::Object& raw
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_method_set(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.empty())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
rpc::CommandFunction* function;
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(args.front().as_string().c_str());
|
||||
|
||||
if (itr == rpc::commands.end() || !(itr->second.m_flags & rpc::CommandMap::flag_modifiable) ||
|
||||
(function = dynamic_cast<rpc::CommandFunction*>(itr->second.m_variable)) == NULL)
|
||||
throw torrent::input_error("Command not modifiable or wrong type.");
|
||||
|
||||
function->set_command(system_method_generate_command(++args.begin(), args.end()));
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_method_set_key(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.empty() || ++args.begin() == args.end())
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
rpc::CommandFunctionList* function;
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(args.front().as_string().c_str());
|
||||
|
||||
if (itr == rpc::commands.end() || !(itr->second.m_flags & rpc::CommandMap::flag_modifiable) ||
|
||||
(function = dynamic_cast<rpc::CommandFunctionList*>(itr->second.m_variable)) == NULL)
|
||||
throw torrent::input_error("Command not modifiable or wrong type.");
|
||||
|
||||
torrent::Object::list_const_iterator itrArgs = ++args.begin();
|
||||
const std::string& key = (itrArgs++)->as_string();
|
||||
|
||||
if (itrArgs != args.end())
|
||||
function->insert(key, system_method_generate_command(itrArgs, args.end()));
|
||||
else
|
||||
function->erase(key);
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
system_method_has_key(__UNUSED rpc::target_type target, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.size() != 2)
|
||||
throw torrent::input_error("Invalid argument count.");
|
||||
|
||||
rpc::CommandFunctionList* function;
|
||||
rpc::CommandMap::iterator itr = rpc::commands.find(args.front().as_string().c_str());
|
||||
|
||||
if (itr == rpc::commands.end() ||
|
||||
(function = dynamic_cast<rpc::CommandFunctionList*>(itr->second.m_variable)) == NULL)
|
||||
throw torrent::input_error("Command is the wrong type.");
|
||||
|
||||
return torrent::Object((int64_t)(function->find(args.back().as_string().c_str()) != function->end()));
|
||||
}
|
||||
|
||||
void
|
||||
initialize_command_dynamic() {
|
||||
CMD_G("system.method.insert", rak::ptr_fn(&system_method_insert));
|
||||
CMD_G("system.method.insert", rak::ptr_fn(&system_method_insert));
|
||||
CMD_G_STRING("system.method.erase", rak::ptr_fn(&system_method_erase));
|
||||
CMD_G("system.method.set", rak::ptr_fn(&system_method_set));
|
||||
CMD_G("system.method.set_key", rak::ptr_fn(&system_method_set_key));
|
||||
CMD_G("system.method.has_key", rak::ptr_fn(&system_method_has_key));
|
||||
}
|
||||
|
||||
+26
-19
@@ -59,7 +59,7 @@
|
||||
#include "command_helpers.h"
|
||||
|
||||
torrent::Object
|
||||
apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Object& rawArgs) {
|
||||
apply_on_state_change(const char* name, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.size() == 0 || args.size() > 2)
|
||||
@@ -76,9 +76,18 @@ apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Obje
|
||||
std::string key = rawKey[0] != '_' ? ("1_state_" + rawKey) : rawKey.substr(1);
|
||||
|
||||
if (args.size() == 1)
|
||||
slotMap->erase(key);
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(), rpc::create_object_list(name, key));
|
||||
else
|
||||
(*slotMap)[key] = args.back().as_string();
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(), rpc::create_object_list(name, key, args.back()));
|
||||
|
||||
// Deprecated notice, remove this function in the next minor
|
||||
// version.
|
||||
static bool notify = true;
|
||||
|
||||
if (notify) {
|
||||
control->core()->push_log("Deprecated on_* commands, use 'system.method.set_key = event.download.{inserted, erased, ...}, <key>, <command>' instead.");
|
||||
notify = false;
|
||||
}
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
@@ -117,8 +126,8 @@ apply_on_ratio(int action, const torrent::Object& rawArgs) {
|
||||
switch (action) {
|
||||
// case core::DownloadList::SLOTS_CLOSE: success = downloadList->close_try(current); break;
|
||||
// case core::DownloadList::SLOTS_STOP: success = downloadList->stop_try(current); break;
|
||||
case core::DownloadList::SLOTS_CLOSE: rpc::parse_command_single(rpc::make_target(current), "d.try_close="); break;
|
||||
case core::DownloadList::SLOTS_STOP: rpc::parse_command_single(rpc::make_target(current), "d.try_stop="); break;
|
||||
case core::DownloadList::D_SLOTS_CLOSE: rpc::parse_command_single(rpc::make_target(current), "d.try_close="); break;
|
||||
case core::DownloadList::D_SLOTS_STOP: rpc::parse_command_single(rpc::make_target(current), "d.try_stop="); break;
|
||||
default: success = false; break;
|
||||
}
|
||||
|
||||
@@ -341,26 +350,24 @@ d_multicall(const torrent::Object& rawArgs) {
|
||||
|
||||
void
|
||||
initialize_command_events() {
|
||||
core::DownloadList* downloadList = control->core()->download_list();
|
||||
|
||||
ADD_VARIABLE_BOOL("check_hash", true);
|
||||
|
||||
ADD_VARIABLE_BOOL("session_lock", true);
|
||||
ADD_VARIABLE_BOOL("session_on_completion", true);
|
||||
|
||||
ADD_COMMAND_LIST("on_insert", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_insert()));
|
||||
ADD_COMMAND_LIST("on_erase", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_erase()));
|
||||
ADD_COMMAND_LIST("on_open", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_open()));
|
||||
ADD_COMMAND_LIST("on_close", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_close()));
|
||||
ADD_COMMAND_LIST("on_start", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_start()));
|
||||
ADD_COMMAND_LIST("on_stop", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_stop()));
|
||||
ADD_COMMAND_LIST("on_hash_queued", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_hash_queued()));
|
||||
ADD_COMMAND_LIST("on_hash_removed", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_hash_removed()));
|
||||
ADD_COMMAND_LIST("on_hash_done", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_hash_done()));
|
||||
ADD_COMMAND_LIST("on_finished", rak::bind_ptr_fn(&apply_on_state_change, &downloadList->slot_map_finished()));
|
||||
// Deprecated.
|
||||
ADD_COMMAND_LIST("on_insert", rak::bind_ptr_fn(&apply_on_state_change, "event.download.inserted"));
|
||||
ADD_COMMAND_LIST("on_erase" , rak::bind_ptr_fn(&apply_on_state_change, "event.download.erased"));
|
||||
ADD_COMMAND_LIST("on_open", rak::bind_ptr_fn(&apply_on_state_change, "event.download.opened"));
|
||||
ADD_COMMAND_LIST("on_close", rak::bind_ptr_fn(&apply_on_state_change, "event.download.closed"));
|
||||
ADD_COMMAND_LIST("on_start", rak::bind_ptr_fn(&apply_on_state_change, "event.download.resumed"));
|
||||
ADD_COMMAND_LIST("on_stop", rak::bind_ptr_fn(&apply_on_state_change, "event.download.paused"));
|
||||
ADD_COMMAND_LIST("on_hash_queued", rak::bind_ptr_fn(&apply_on_state_change, "event.download.hash_queued"));
|
||||
ADD_COMMAND_LIST("on_hash_removed", rak::bind_ptr_fn(&apply_on_state_change, "event.download.hash_removed"));
|
||||
ADD_COMMAND_LIST("on_finished", rak::bind_ptr_fn(&apply_on_state_change, "event.download.finished"));
|
||||
|
||||
ADD_COMMAND_LIST("stop_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::SLOTS_STOP));
|
||||
ADD_COMMAND_LIST("close_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::SLOTS_CLOSE));
|
||||
ADD_COMMAND_LIST("stop_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::D_SLOTS_STOP));
|
||||
ADD_COMMAND_LIST("close_on_ratio", rak::bind_ptr_fn(&apply_on_ratio, (int)core::DownloadList::D_SLOTS_CLOSE));
|
||||
|
||||
ADD_COMMAND_VOID("start_tied", &apply_start_tied);
|
||||
ADD_COMMAND_VOID("stop_untied", &apply_stop_untied);
|
||||
|
||||
+27
-27
@@ -72,19 +72,19 @@ DownloadList::check_contains(Download* d) {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct download_list_call {
|
||||
download_list_call(Download* d) : m_download(d) {}
|
||||
// struct download_list_call {
|
||||
// download_list_call(Download* d) : m_download(d) {}
|
||||
|
||||
void operator () (const DownloadList::slot_map::value_type& s) {
|
||||
try {
|
||||
rpc::parse_command_d_multiple_std(m_download, s.second);
|
||||
} catch (torrent::input_error& e) {
|
||||
control->core()->push_log((std::string("Download event action failed: ") + e.what()).c_str());
|
||||
}
|
||||
}
|
||||
// void operator () (const DownloadList::slot_map::value_type& s) {
|
||||
// try {
|
||||
// rpc::parse_command_d_multiple_std(m_download, s.second);
|
||||
// } catch (torrent::input_error& e) {
|
||||
// control->core()->push_log((std::string("Download event action failed: ") + e.what()).c_str());
|
||||
// }
|
||||
// }
|
||||
|
||||
Download* m_download;
|
||||
};
|
||||
// Download* m_download;
|
||||
// };
|
||||
|
||||
void
|
||||
DownloadList::clear() {
|
||||
@@ -171,7 +171,7 @@ DownloadList::insert(Download* download) {
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::insert), download));
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::filter_download), download));
|
||||
|
||||
std::for_each(slot_map_insert().begin(), slot_map_insert().end(), download_list_call(*itr));
|
||||
rpc::commands.call_catch("event.download.inserted", rpc::make_target(*itr), torrent::Object(), "Download event action failed: ");
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
// Should perhaps relax this, just print an error and remove the
|
||||
@@ -199,7 +199,7 @@ DownloadList::erase(iterator itr) {
|
||||
|
||||
control->core()->download_store()->remove(*itr);
|
||||
|
||||
std::for_each(slot_map_erase().begin(), slot_map_erase().end(), download_list_call(*itr));
|
||||
rpc::commands.call_catch("event.download.erased", rpc::make_target(*itr), torrent::Object(), "Download event action failed: ");
|
||||
std::for_each(control->view_manager()->begin(), control->view_manager()->end(), std::bind2nd(std::mem_fun(&View::erase), *itr));
|
||||
|
||||
torrent::download_remove(*(*itr)->download());
|
||||
@@ -230,8 +230,7 @@ DownloadList::open_throw(Download* download) {
|
||||
return;
|
||||
|
||||
download->download()->open(download->resume_flags());
|
||||
|
||||
std::for_each(slot_map_open().begin(), slot_map_open().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.opened", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -294,8 +293,8 @@ DownloadList::close_throw(Download* download) {
|
||||
if (!download->is_hash_failed() && rpc::call_command_value("d.get_hashing", rpc::make_target(download)) != Download::variable_hashing_stopped)
|
||||
throw torrent::internal_error("DownloadList::close_throw(...) called but we're going into a hashing loop.");
|
||||
|
||||
std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download));
|
||||
std::for_each(slot_map_close().begin(), slot_map_close().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_removed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
rpc::commands.call_catch("event.download.closed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -328,7 +327,7 @@ DownloadList::resume(Download* download, int flags) {
|
||||
if (rpc::call_command_value("d.get_hashing", rpc::make_target(download)) == Download::variable_hashing_stopped)
|
||||
rpc::call_command("d.set_hashing", Download::variable_hashing_initial, rpc::make_target(download));
|
||||
|
||||
std::for_each(slot_map_hash_queued().begin(), slot_map_hash_queued().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_queued", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -361,7 +360,7 @@ DownloadList::resume(Download* download, int flags) {
|
||||
|
||||
download->set_resume_flags(~uint32_t());
|
||||
|
||||
std::for_each(slot_map_start().begin(), slot_map_start().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.resumed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
|
||||
} catch (torrent::local_error& e) {
|
||||
control->core()->push_log(e.what());
|
||||
@@ -384,7 +383,7 @@ DownloadList::pause(Download* download, int flags) {
|
||||
download->download()->hash_stop();
|
||||
rpc::call_command_set_value("d.set_hashing", Download::variable_hashing_stopped, rpc::make_target(download));
|
||||
|
||||
std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_removed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
if (!download->download()->is_active())
|
||||
@@ -396,7 +395,7 @@ DownloadList::pause(Download* download, int flags) {
|
||||
// TODO: This is actually for pause, not stop... And doesn't get
|
||||
// called when the download isn't active, but was in the 'started'
|
||||
// view.
|
||||
std::for_each(slot_map_stop().begin(), slot_map_stop().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.paused", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
|
||||
rpc::call_command("d.set_state_changed", cachedTime.seconds(), rpc::make_target(download));
|
||||
rpc::call_command("d.set_state_counter", rpc::call_command_value("d.get_state_counter", rpc::make_target(download)), rpc::make_target(download));
|
||||
@@ -441,7 +440,7 @@ DownloadList::hash_done(Download* download) {
|
||||
if (!download->is_hash_checked()) {
|
||||
download->set_hash_failed(true);
|
||||
|
||||
std::for_each(slot_map_hash_done().begin(), slot_map_hash_done().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_done", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -497,7 +496,7 @@ DownloadList::hash_done(Download* download) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::for_each(slot_map_hash_done().begin(), slot_map_hash_done().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_done", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -512,8 +511,9 @@ DownloadList::hash_queue(Download* download, int type) {
|
||||
if (download->is_open()) {
|
||||
pause(download, torrent::Download::stop_skip_tracker);
|
||||
download->download()->close();
|
||||
std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download));
|
||||
std::for_each(slot_map_close().begin(), slot_map_close().end(), download_list_call(download));
|
||||
|
||||
rpc::commands.call_catch("event.download.hash_removed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
rpc::commands.call_catch("event.download.closed", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
torrent::resume_clear_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
|
||||
@@ -526,7 +526,7 @@ DownloadList::hash_queue(Download* download, int type) {
|
||||
|
||||
// If any more stuff is added here, make sure resume etc are still
|
||||
// correct.
|
||||
std::for_each(slot_map_hash_queued().begin(), slot_map_hash_queued().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.hash_queued", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -570,7 +570,7 @@ DownloadList::confirm_finished(Download* download) {
|
||||
// up/downloaded baseline.
|
||||
download->download()->tracker_list()->send_completed();
|
||||
|
||||
std::for_each(slot_map_finished().begin(), slot_map_finished().end(), download_list_call(download));
|
||||
rpc::commands.call_catch("event.download.finished", rpc::make_target(download), torrent::Object(), "Download event action failed: ");
|
||||
|
||||
if (download->resume_flags() != ~uint32_t())
|
||||
throw torrent::internal_error("DownloadList::confirm_finished(...) download->resume_flags() != ~uint32_t().");
|
||||
|
||||
+25
-55
@@ -60,7 +60,6 @@ class Download;
|
||||
class DownloadList : private std::list<Download*> {
|
||||
public:
|
||||
typedef std::list<Download*> base_type;
|
||||
typedef std::map<std::string, std::string> slot_map;
|
||||
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
@@ -115,40 +114,35 @@ public:
|
||||
void check_hash(Download* d);
|
||||
|
||||
enum {
|
||||
SLOTS_INSERT,
|
||||
SLOTS_ERASE,
|
||||
SLOTS_OPEN,
|
||||
SLOTS_CLOSE,
|
||||
SLOTS_START,
|
||||
SLOTS_STOP,
|
||||
SLOTS_HASH_QUEUED,
|
||||
SLOTS_HASH_REMOVED,
|
||||
SLOTS_HASH_DONE,
|
||||
SLOTS_FINISHED,
|
||||
D_SLOTS_INSERT,
|
||||
D_SLOTS_ERASE,
|
||||
D_SLOTS_OPEN,
|
||||
D_SLOTS_CLOSE,
|
||||
D_SLOTS_START,
|
||||
D_SLOTS_STOP,
|
||||
D_SLOTS_HASH_QUEUED,
|
||||
D_SLOTS_HASH_REMOVED,
|
||||
D_SLOTS_HASH_DONE,
|
||||
D_SLOTS_FINISHED,
|
||||
|
||||
SLOTS_MAX_SIZE
|
||||
};
|
||||
|
||||
slot_map& slots(int m) { return m_slotMaps[m]; }
|
||||
const slot_map& slots(int m) const { return m_slotMaps[m]; }
|
||||
|
||||
slot_map* slot_map_begin() { return m_slotMaps; }
|
||||
const slot_map* slot_map_begin() const { return m_slotMaps; }
|
||||
slot_map* slot_map_end() { return m_slotMaps + SLOTS_MAX_SIZE; }
|
||||
const slot_map* slot_map_end() const { return m_slotMaps + SLOTS_MAX_SIZE; }
|
||||
|
||||
slot_map& slot_map_insert() { return m_slotMaps[SLOTS_INSERT]; }
|
||||
const slot_map& slot_map_insert() const { return m_slotMaps[SLOTS_INSERT]; }
|
||||
slot_map& slot_map_erase() { return m_slotMaps[SLOTS_ERASE]; }
|
||||
const slot_map& slot_map_erase() const { return m_slotMaps[SLOTS_ERASE]; }
|
||||
slot_map& slot_map_open() { return m_slotMaps[SLOTS_OPEN]; }
|
||||
const slot_map& slot_map_open() const { return m_slotMaps[SLOTS_OPEN]; }
|
||||
slot_map& slot_map_close() { return m_slotMaps[SLOTS_CLOSE]; }
|
||||
const slot_map& slot_map_close() const { return m_slotMaps[SLOTS_CLOSE]; }
|
||||
slot_map& slot_map_start() { return m_slotMaps[SLOTS_START]; }
|
||||
const slot_map& slot_map_start() const { return m_slotMaps[SLOTS_START]; }
|
||||
slot_map& slot_map_stop() { return m_slotMaps[SLOTS_STOP]; }
|
||||
const slot_map& slot_map_stop() const { return m_slotMaps[SLOTS_STOP]; }
|
||||
static const char* slot_name(int m) {
|
||||
switch(m) {
|
||||
case D_SLOTS_INSERT: return "event.download.inserted";
|
||||
case D_SLOTS_ERASE: return "event.download.erased";
|
||||
case D_SLOTS_OPEN: return "event.download.opened";
|
||||
case D_SLOTS_CLOSE: return "event.download.closed";
|
||||
case D_SLOTS_START: return "event.download.resumed";
|
||||
case D_SLOTS_STOP: return "event.download.paused";
|
||||
case D_SLOTS_HASH_QUEUED: return "event.download.hash_queued";
|
||||
case D_SLOTS_HASH_REMOVED: return "event.download.hash_removed";
|
||||
case D_SLOTS_HASH_DONE: return "event.download.hash_done";
|
||||
case D_SLOTS_FINISHED: return "event.download.finished";
|
||||
default: return "BORK";
|
||||
}
|
||||
}
|
||||
|
||||
// The finished slots will be called when an active download with
|
||||
// "finished" == 0 performs a hash check which returns a done
|
||||
@@ -158,28 +152,6 @@ public:
|
||||
// Also we need to handle cases when a hashing torrent starts up
|
||||
// after a shutdown.
|
||||
|
||||
slot_map& slot_map_hash_queued() { return m_slotMaps[SLOTS_HASH_QUEUED]; }
|
||||
const slot_map& slot_map_hash_queued() const { return m_slotMaps[SLOTS_HASH_QUEUED]; }
|
||||
slot_map& slot_map_hash_removed() { return m_slotMaps[SLOTS_HASH_REMOVED]; }
|
||||
const slot_map& slot_map_hash_removed() const { return m_slotMaps[SLOTS_HASH_REMOVED]; }
|
||||
slot_map& slot_map_hash_done() { return m_slotMaps[SLOTS_HASH_DONE]; }
|
||||
const slot_map& slot_map_hash_done() const { return m_slotMaps[SLOTS_HASH_DONE]; }
|
||||
slot_map& slot_map_finished() { return m_slotMaps[SLOTS_FINISHED]; }
|
||||
const slot_map& slot_map_finished() const { return m_slotMaps[SLOTS_FINISHED]; }
|
||||
|
||||
bool has_slot_insert(const std::string& key) const { return slot_map_insert().find(key) != slot_map_insert().end(); }
|
||||
bool has_slot_erase(const std::string& key) const { return slot_map_erase().find(key) != slot_map_erase().end(); }
|
||||
bool has_slot_open(const std::string& key) const { return slot_map_open().find(key) != slot_map_open().end(); }
|
||||
bool has_slot_close(const std::string& key) const { return slot_map_close().find(key) != slot_map_close().end(); }
|
||||
bool has_slot_start(const std::string& key) const { return slot_map_start().find(key) != slot_map_start().end(); }
|
||||
bool has_slot_stop(const std::string& key) const { return slot_map_stop().find(key) != slot_map_stop().end(); }
|
||||
|
||||
bool has_slot_hash_queued(const std::string& key) const{ return slot_map_hash_queued().find(key) != slot_map_hash_queued().end(); }
|
||||
bool has_slot_hash_done(const std::string& key) const { return slot_map_hash_done().find(key) != slot_map_hash_done().end(); }
|
||||
bool has_slot_finished(const std::string& key) const { return slot_map_finished().find(key) != slot_map_finished().end(); }
|
||||
|
||||
static void erase_key(slot_map& sm, const std::string& key) { sm.erase(key); }
|
||||
|
||||
private:
|
||||
DownloadList(const DownloadList&);
|
||||
void operator = (const DownloadList&);
|
||||
@@ -191,8 +163,6 @@ private:
|
||||
|
||||
void received_finished(Download* d);
|
||||
void confirm_finished(Download* d);
|
||||
|
||||
slot_map m_slotMaps[SLOTS_MAX_SIZE];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -213,8 +213,8 @@ Manager::initialize_second() {
|
||||
|
||||
// Register slots to be called when a download is inserted/erased,
|
||||
// opened or closed.
|
||||
m_downloadList->slot_map_insert()["1_connect_logs"] = "d.initialize_logs=";
|
||||
m_downloadList->slot_map_erase()["9_delete_tied"] = "d.delete_tied=";
|
||||
rpc::parse_command_single(rpc::make_target(), "system.method.set_key = event.download.inserted, 1_connect_logs, d.initialize_logs=");
|
||||
rpc::parse_command_single(rpc::make_target(), "system.method.set_key = event.download.erased, 9_delete_tied, d.delete_tied=");
|
||||
|
||||
torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log));
|
||||
}
|
||||
|
||||
+12
-8
@@ -116,9 +116,10 @@ View::~View() {
|
||||
if (m_name.empty())
|
||||
return;
|
||||
|
||||
std::for_each(control->core()->download_list()->slot_map_begin(), control->core()->download_list()->slot_map_end(),
|
||||
rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name));
|
||||
|
||||
for (int i = 0; i < DownloadList::SLOTS_MAX_SIZE; i++)
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(),
|
||||
rpc::create_object_list(control->core()->download_list()->slot_name(i), "0_view_" + m_name));
|
||||
|
||||
priority_queue_erase(&taskScheduler, &m_delayChanged);
|
||||
}
|
||||
|
||||
@@ -133,7 +134,8 @@ View::initialize(const std::string& name) {
|
||||
std::string key = "0_view_" + name;
|
||||
core::DownloadList* dlist = control->core()->download_list();
|
||||
|
||||
if (dlist->has_slot_insert(key) || dlist->has_slot_erase(key))
|
||||
if (rpc::commands.call("system.method.has_key", rpc::make_target(), rpc::create_object_list("event.download.inserted", key)).as_value() ||
|
||||
rpc::commands.call("system.method.has_key", rpc::make_target(), rpc::create_object_list("event.download.erased", key)).as_value())
|
||||
throw torrent::internal_error("View::initialize(...) duplicate key name found in DownloadList.");
|
||||
|
||||
m_name = name;
|
||||
@@ -296,18 +298,20 @@ View::filter_download(core::Download* download) {
|
||||
|
||||
void
|
||||
View::set_filter_on(int event) {
|
||||
if (event == DownloadList::SLOTS_INSERT || event == DownloadList::SLOTS_ERASE || event >= DownloadList::SLOTS_MAX_SIZE)
|
||||
if (event == DownloadList::D_SLOTS_INSERT || event == DownloadList::D_SLOTS_ERASE || event >= DownloadList::SLOTS_MAX_SIZE)
|
||||
throw torrent::internal_error("View::filter_on(...) invalid event.");
|
||||
|
||||
control->core()->download_list()->slots(event)["0_view_" + m_name] = "view.filter_download=" + m_name;
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(),
|
||||
rpc::create_object_list(control->core()->download_list()->slot_name(event), "0_view_" + m_name, "view.filter_download=" + m_name));
|
||||
}
|
||||
|
||||
void
|
||||
View::clear_filter_on() {
|
||||
// Don't clear insert and erase as these are required to keep the
|
||||
// View up-to-date with the available downloads.
|
||||
std::for_each(control->core()->download_list()->slot_map_begin() + DownloadList::SLOTS_OPEN, control->core()->download_list()->slot_map_end(),
|
||||
rak::bind2nd(std::ptr_fun(&DownloadList::erase_key), "0_view_" + m_name));
|
||||
for (int i = DownloadList::D_SLOTS_OPEN; i < DownloadList::SLOTS_MAX_SIZE; i++)
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(),
|
||||
rpc::create_object_list(control->core()->download_list()->slot_name(i), "0_view_" + m_name));
|
||||
}
|
||||
|
||||
inline void
|
||||
|
||||
@@ -115,22 +115,22 @@ ViewManager::set_filter_on(const std::string& name, const filter_args& args) {
|
||||
for (filter_args::const_iterator itr = args.begin(); itr != args.end(); ++itr) {
|
||||
|
||||
if (*itr == "start")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_START);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_START);
|
||||
|
||||
else if (*itr == "stop")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_STOP);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_STOP);
|
||||
|
||||
else if (*itr == "hash_queued")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_HASH_QUEUED);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_HASH_QUEUED);
|
||||
|
||||
else if (*itr == "hash_removed")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_HASH_REMOVED);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_HASH_REMOVED);
|
||||
|
||||
else if (*itr == "hash_done")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_HASH_DONE);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_HASH_DONE);
|
||||
|
||||
else if (*itr == "finished")
|
||||
(*viewItr)->set_filter_on(DownloadList::SLOTS_FINISHED);
|
||||
(*viewItr)->set_filter_on(DownloadList::D_SLOTS_FINISHED);
|
||||
|
||||
else
|
||||
throw torrent::input_error("Invalid filter on identifier.");
|
||||
|
||||
+14
-2
@@ -171,8 +171,20 @@ main(int argc, char** argv) {
|
||||
// torrent::ConnectionManager* are valid etc.
|
||||
initialize_commands();
|
||||
|
||||
rpc::parse_command_multiple(rpc::make_target(),
|
||||
// "set_name = $cat={$system.hostname=,:,$system.pid=}\n"
|
||||
rpc::parse_command_multiple
|
||||
(rpc::make_target(),
|
||||
"system.method.insert = event.download.inserted,list\n"
|
||||
"system.method.insert = event.download.erased,list\n"
|
||||
"system.method.insert = event.download.opened,list\n"
|
||||
"system.method.insert = event.download.closed,list\n"
|
||||
"system.method.insert = event.download.resumed,list\n"
|
||||
"system.method.insert = event.download.paused,list\n"
|
||||
|
||||
"system.method.insert = event.download.finished,list\n"
|
||||
"system.method.insert = event.download.hash_done,list\n"
|
||||
"system.method.insert = event.download.hash_removed,list\n"
|
||||
"system.method.insert = event.download.hash_queued,list\n"
|
||||
|
||||
"set_name = \"$cat=$system.hostname=,:,$system.pid=\"\n"
|
||||
|
||||
// Currently not doing any sorting on main.
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <rak/functional.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "parse_commands.h"
|
||||
#include "command_function.h"
|
||||
@@ -51,4 +55,42 @@ CommandFunction::call(Command* rawCommand, target_type target, const torrent::Ob
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
const torrent::Object
|
||||
CommandFunctionList::call(Command* rawCommand, target_type target, const torrent::Object& args) {
|
||||
CommandFunctionList* command = reinterpret_cast<CommandFunctionList*>(rawCommand);
|
||||
|
||||
for (base_type::const_iterator itr = command->begin(), last = command->end(); itr != last; itr++)
|
||||
parse_command_multiple(target, itr->second.c_str(), itr->second.c_str() + itr->second.size());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
CommandFunctionList::const_iterator
|
||||
CommandFunctionList::find(const char* key) {
|
||||
base_type::iterator itr = std::find_if(begin(), end(), rak::greater_equal(key, rak::mem_ref(&base_type::value_type::first)));
|
||||
|
||||
if (itr == end() || itr->first != key)
|
||||
return end();
|
||||
else
|
||||
return itr;
|
||||
}
|
||||
|
||||
void
|
||||
CommandFunctionList::insert(const std::string& key, const std::string& cmd) {
|
||||
base_type::iterator itr = std::find_if(begin(), end(), rak::greater_equal(key, rak::mem_ref(&base_type::value_type::first)));
|
||||
|
||||
if (itr != end() && itr->first == key)
|
||||
itr->second = cmd;
|
||||
else
|
||||
base_type::insert(itr, base_type::value_type(key, cmd));
|
||||
}
|
||||
|
||||
void
|
||||
CommandFunctionList::erase(const std::string& key) {
|
||||
base_type::iterator itr = std::find_if(begin(), end(), rak::greater_equal(key, rak::mem_ref(&base_type::value_type::first)));
|
||||
|
||||
if (itr != end() && itr->first == key)
|
||||
base_type::erase(itr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#define RTORRENT_RPC_COMMAND_FUNCTION_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <inttypes.h>
|
||||
#include <torrent/object.h>
|
||||
@@ -50,14 +51,35 @@ class CommandFunction : public Command {
|
||||
public:
|
||||
CommandFunction(const std::string& cmd = std::string()) : m_command(cmd) {}
|
||||
|
||||
const std::string& command() const { return m_command; }
|
||||
void set_command(const std::string& cmd) { m_command = cmd; }
|
||||
const std::string& command() const { return m_command; }
|
||||
void set_command(const std::string& cmd) { m_command = cmd; }
|
||||
|
||||
static const torrent::Object call(Command* rawCommand, target_type target, const torrent::Object& args);
|
||||
|
||||
private:
|
||||
// TODO: Replace with a delete-me flag and const char*.
|
||||
std::string m_command;
|
||||
std::string m_command;
|
||||
};
|
||||
|
||||
class CommandFunctionList : public Command,
|
||||
private std::vector<std::pair<std::string, std::string> > {
|
||||
public:
|
||||
typedef std::vector<std::pair<std::string, std::string> > base_type;
|
||||
|
||||
using Command::value_type;
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
|
||||
CommandFunctionList() {}
|
||||
|
||||
const_iterator find(const char* key);
|
||||
|
||||
void insert(const std::string& key, const std::string& cmd);
|
||||
void erase(const std::string& key);
|
||||
|
||||
static const torrent::Object call(Command* rawCommand, target_type target, const torrent::Object& args);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/data/file_list_iterator.h>
|
||||
|
||||
// Get better logging...
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
#include "core/manager.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "command_map.h"
|
||||
|
||||
@@ -99,6 +104,16 @@ CommandMap::erase(iterator itr) {
|
||||
delete [] key;
|
||||
}
|
||||
|
||||
const CommandMap::mapped_type
|
||||
CommandMap::call_catch(key_type key, target_type target, const mapped_type& args, const char* err) {
|
||||
try {
|
||||
return call_command(key, args, target);
|
||||
} catch (torrent::input_error& e) {
|
||||
control->core()->push_log((err + std::string(e.what())).c_str());
|
||||
return torrent::Object();
|
||||
}
|
||||
}
|
||||
|
||||
const CommandMap::mapped_type
|
||||
CommandMap::call_command(key_type key, const mapped_type& arg, target_type target) {
|
||||
const_iterator itr = base_type::find(key);
|
||||
|
||||
+24
-1
@@ -62,7 +62,7 @@ struct command_map_data_type {
|
||||
|
||||
int target() const { return m_target; }
|
||||
|
||||
Command* m_variable;
|
||||
Command* m_variable;
|
||||
|
||||
union {
|
||||
Command::cleaned_slot m_genericSlot;
|
||||
@@ -124,6 +124,9 @@ public:
|
||||
void insert(key_type key, const command_map_data_type src);
|
||||
void erase(iterator itr);
|
||||
|
||||
const mapped_type call(key_type key, target_type target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
|
||||
const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
|
||||
|
||||
const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)Command::target_generic, NULL));
|
||||
const mapped_type call_command (const_iterator itr, const mapped_type& arg, target_type target = target_type((int)Command::target_generic, NULL));
|
||||
|
||||
@@ -151,6 +154,26 @@ inline target_type make_target_pair(T target1, T target2) {
|
||||
return target_type((int)target_type_id<T, T>::value, target1, target2);
|
||||
}
|
||||
|
||||
// TODO: Helper-functions that really should be in the
|
||||
// torrent/object.h header.
|
||||
|
||||
inline torrent::Object
|
||||
create_object_list(const torrent::Object& o1, const torrent::Object& o2) {
|
||||
torrent::Object tmp = torrent::Object::create_list();
|
||||
tmp.as_list().push_back(o1);
|
||||
tmp.as_list().push_back(o2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline torrent::Object
|
||||
create_object_list(const torrent::Object& o1, const torrent::Object& o2, const torrent::Object& o3) {
|
||||
torrent::Object tmp = torrent::Object::create_list();
|
||||
tmp.as_list().push_back(o1);
|
||||
tmp.as_list().push_back(o2);
|
||||
tmp.as_list().push_back(o3);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -98,7 +98,7 @@ DownloadList::activate(display::Frame* frame, bool focus) {
|
||||
m_frame = frame;
|
||||
|
||||
control->input()->push_back(&m_bindings);
|
||||
control->core()->download_list()->slot_map_erase()["0_download_list"] = "ui.unfocus_download=";
|
||||
rpc::commands.call("system.method.set_key", rpc::make_target(), rpc::create_object_list("event.download.erased", "0_download_list", "ui.unfocus_download="));
|
||||
|
||||
activate_display(DISPLAY_DOWNLOAD_LIST);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user