diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml
index 6be07fa7..6ac3f513 100644
--- a/doc/rtorrent.1.xml
+++ b/doc/rtorrent.1.xml
@@ -584,23 +584,6 @@ the schedule option.
-
- stop_on_ratio = min_ratio
- stop_on_ratio = min_ratio,min_upload
- stop_on_ratio = min_ratio,min_upload,max_ratio
-
-Stop torrents when they reach the given upload ratio
-min_ratio in percent. If the optional
-min_upload is given, require a total
-upload amount of this many bytes as well. If the optional
-max_ratio is given, stop the torrent
-when reaching this ratio regardless of the total upload
-amount. Exclude certain torrent by pressing
-Shift+I in the downlist list.
-Use with the schedule option.
-
-
-
load = file
load_verbose = file
@@ -624,6 +607,40 @@ torrent::input_error exception on bad input.
+
+ stop_on_ratio = min_ratio
+ stop_on_ratio = min_ratio,min_upload
+ stop_on_ratio = min_ratio,min_upload,max_ratio
+
+Stop torrents when they reach the given upload ratio
+min_ratio in percent. If the optional
+min_upload is given, require a total
+upload amount of this many bytes as well. If the optional
+max_ratio is given, stop the torrent
+when reaching this ratio regardless of the total upload
+amount. Exclude certain torrent by pressing
+Shift+I in the downlist list.
+Use with the schedule option.
+
+
+
+
+ on_insert = id,command
+ on_erase = id,command
+ on_open = id,command
+ on_close = id,command
+ on_start = id,command
+ on_stop = id,command
+ on_hash_queued = id,command
+ on_hash_removed = id,command
+ on_hash_done = id,command
+ on_finished = id,command
+
+Call a command on a download when its state changes. Only a subset of
+commands are available.
+
+
+
@@ -789,6 +806,38 @@ to .part.
+
+ DOWNLOAD SETTINGS
+
+Settings that require a download as a target, requireing it to be
+called through f.ex on_finished.
+
+
+
+
+
+ create_link = type,path,suffix
+ delete_link = type,path,suffix
+
+
+Create or delete a symbolic link. The link path is the concatenation
+of path, the result of
+the type on the download,
+and suffix.
+
+
+
+Available types are; tied is the path of the file
+this download is tied to, see start_tied.
+
+
+
+
+
+
+
+
+
ADVANCED SETTINGS
diff --git a/rak/functional_fun.h b/rak/functional_fun.h
index 336f6725..37297917 100644
--- a/rak/functional_fun.h
+++ b/rak/functional_fun.h
@@ -159,6 +159,20 @@ private:
Func m_func;
};
+template
+class ptr_fn2_t : public function_base2 {
+public:
+ typedef Result (*Func)(Arg1, Arg2);
+
+ ptr_fn2_t(Func func) : m_func(func) {}
+ virtual ~ptr_fn2_t() {}
+
+ virtual Result operator () (Arg1 arg1, Arg2 arg2) { return m_func(arg1, arg2); }
+
+private:
+ Func m_func;
+};
+
template
class mem_fn0_t : public function_base0 {
public:
@@ -384,6 +398,12 @@ ptr_fn(Result (*func)(Arg1)) {
return new ptr_fn1_t(func);
}
+template
+inline function_base2*
+ptr_fn(Result (*func)(Arg1, Arg2)) {
+ return new ptr_fn2_t(func);
+}
+
template
inline function_base0*
mem_fn(Object* object, Result (Object::*func)()) {
diff --git a/src/control.cc b/src/control.cc
index bcdd8d3a..e5b451cb 100644
--- a/src/control.cc
+++ b/src/control.cc
@@ -68,6 +68,7 @@ Control::Control() :
m_commandScheduler(new CommandScheduler()),
m_variables(new utils::VariableMap()),
+ m_downloadVariables(new utils::VariableMap()),
m_tick(0) {
@@ -89,6 +90,7 @@ Control::~Control() {
delete m_commandScheduler;
delete m_variables;
+ delete m_downloadVariables;
delete m_viewManager;
diff --git a/src/control.h b/src/control.h
index a97ed8ca..feddc9bf 100644
--- a/src/control.h
+++ b/src/control.h
@@ -95,7 +95,9 @@ public:
input::InputEvent* input_stdin() { return m_inputStdin; }
CommandScheduler* command_scheduler() { return m_commandScheduler; }
+
utils::VariableMap* variable() { return m_variables; }
+ utils::VariableMap* download_variables() { return m_downloadVariables; }
uint64_t tick() const { return m_tick; }
void inc_tick() { m_tick++; }
@@ -124,6 +126,7 @@ private:
CommandScheduler* m_commandScheduler;
utils::VariableMap* m_variables;
+ utils::VariableMap* m_downloadVariables;
uint64_t m_tick;
diff --git a/src/core/download.cc b/src/core/download.cc
index 38548a6b..6ba8f1f3 100644
--- a/src/core/download.cc
+++ b/src/core/download.cc
@@ -49,31 +49,13 @@
#include
#include "utils/variable_generic.h"
+#include "utils/variable_map.h"
+#include "control.h"
#include "download.h"
namespace core {
-template
-utils::Variable*
-var_d_value(Target target, GetFunc getFunc, SetFunc setFunc) {
- return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(std::mem_fun(target), std::mem_fun(getFunc))),
- rak::ftor_fn2(rak::on2(std::mem_fun(target), std::mem_fun(setFunc))));
-}
-
-template
-utils::Variable*
-var_d2_value(Target target, GetFunc getFunc, SetFunc setFunc) {
- return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(rak::on(std::mem_fun(&Download::download), std::mem_fun(target)), std::mem_fun(getFunc))),
- rak::ftor_fn2(rak::on2(rak::on(std::mem_fun(&Download::download), std::mem_fun(target)), std::mem_fun(setFunc))));
-}
-
-template
-utils::Variable*
-var_d2_get_value(Target target, GetFunc getFunc) {
- return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(rak::on(std::mem_fun(&Download::download), std::mem_fun(target)), std::mem_fun(getFunc))), NULL);
-}
-
Download::Download(download_type d) :
m_download(d),
m_trackerList(d.tracker_list()),
@@ -87,51 +69,6 @@ Download::Download(download_type d) :
m_connStorageError = m_download.signal_storage_error(sigc::mem_fun(*this, &Download::receive_storage_error));
m_download.signal_chunk_failed(sigc::mem_fun(*this, &Download::receive_chunk_failed));
-
- m_variables.insert("connection_current", new utils::VariableDownloadStringSlot(rak::ftor_fn1(std::mem_fun(&Download::connection_current)),
- rak::ftor_fn2(std::mem_fun(&Download::set_connection_current))));
-
- m_variables.insert("connection_leech", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_LEECH)));
- m_variables.insert("connection_seed", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_SEED)));
-
- // 0 - stopped
- // 1 - started
- m_variables.insert("state", new utils::VariableObject("rtorrent", "state", torrent::Object::TYPE_VALUE));
- m_variables.insert("complete", new utils::VariableObject("rtorrent", "complete", torrent::Object::TYPE_VALUE));
-
- // 0 - Not hashing
- // 1 - Normal hashing
- // 2 - Download finished, hashing
- m_variables.insert("hashing", new utils::VariableObject("rtorrent", "hashing", torrent::Object::TYPE_VALUE));
- m_variables.insert("tied_to_file", new utils::VariableObject("rtorrent", "tied_to_file", torrent::Object::TYPE_STRING));
-
- // The "state_changed" variable is required to be a valid unix time
- // value, it indicates the last time the torrent changed its state,
- // resume/pause.
- m_variables.insert("state_changed", new utils::VariableObject("rtorrent", "state_changed", torrent::Object::TYPE_VALUE));
-
- m_variables.insert("directory", new utils::VariableDownloadStringSlot(rak::ftor_fn1(rak::on(std::mem_fun(&Download::file_list), std::mem_fun(&torrent::FileList::root_dir))),
- rak::ftor_fn2(std::mem_fun(&Download::set_root_directory))));
- m_variables.insert("min_peers", var_d_value(&Download::download, &download_type::peers_min, &download_type::set_peers_min));
- m_variables.insert("max_peers", var_d_value(&Download::download, &download_type::peers_max, &download_type::set_peers_max));
- m_variables.insert("max_uploads", var_d_value(&Download::download, &download_type::uploads_max, &download_type::set_uploads_max));
-
- m_variables.insert("max_file_size", var_d_value(&Download::file_list, &file_list_type::max_file_size, &file_list_type::set_max_file_size));
-
-// m_variables.insert("split_file_size", new utils::VariableValueSlot(rak::mem_fn(file_list(), &file_list_type::split_file_size), rak::mem_fn(file_list(), &file_list_type::set_split_file_size)));
-// m_variables.insert("split_suffix", new utils::VariableStringSlot(rak::mem_fn(file_list(), &file_list_type::split_suffix), rak::mem_fn(file_list(), &file_list_type::set_split_suffix)));
-
- m_variables.insert("up_rate", var_d2_get_value(&download_type::mutable_up_rate, &torrent::Rate::rate));
- m_variables.insert("up_total", var_d2_get_value(&download_type::mutable_up_rate, &torrent::Rate::total));
- m_variables.insert("down_rate", var_d2_get_value(&download_type::mutable_down_rate, &torrent::Rate::rate));
- m_variables.insert("down_total", var_d2_get_value(&download_type::mutable_down_rate, &torrent::Rate::total));
- m_variables.insert("skip_rate", var_d2_get_value(&download_type::mutable_skip_rate, &torrent::Rate::rate));
- m_variables.insert("skip_total", var_d2_get_value(&download_type::mutable_skip_rate, &torrent::Rate::total));
-
- m_variables.insert("priority", new utils::VariableDownloadValueSlot(rak::ftor_fn1(std::mem_fun(&Download::priority)), rak::ftor_fn2(std::mem_fun(&Download::set_priority))));
- m_variables.insert("tracker_numwant", var_d_value(&Download::tracker_list, &tracker_list_type::numwant, &tracker_list_type::set_numwant));
-
- m_variables.insert("ignore_commands", new utils::VariableObject("rtorrent", "ignore_commands", torrent::Object::TYPE_VALUE));
}
Download::~Download() {
@@ -269,6 +206,14 @@ Download::receive_chunk_failed(__UNUSED uint32_t idx) {
m_chunksFailed++;
}
+int64_t Download::get_value(const char* key) { return control->download_variables()->get_d_value(this, key); }
+const std::string& Download::get_string(const char* key) { return control->download_variables()->get_d_string(this, key); }
+int64_t Download::get_std_value(const std::string& key) { return control->download_variables()->get_d_value(this, key.c_str()); }
+const std::string& Download::get_std_string(const std::string& key) { return control->download_variables()->get_d_string(this, key.c_str()); }
+void Download::set(const char* key, const torrent::Object& value) { return control->download_variables()->set_d(this, key, value); }
+void Download::set_value(const char* key, int64_t value) { return control->download_variables()->set_d_value(this, key, value); }
+void Download::set_string(const char* key, const std::string& value) { return control->download_variables()->set_d_string(this, key, value); }
+
// Clean up.
void
Download::set_root_directory(const std::string& path) {
diff --git a/src/core/download.h b/src/core/download.h
index e092b5b2..adacfc85 100644
--- a/src/core/download.h
+++ b/src/core/download.h
@@ -43,7 +43,7 @@
#include
#include
-#include "utils/variable_map.h"
+#include "globals.h"
namespace torrent {
class TrackerList;
@@ -57,7 +57,6 @@ public:
typedef torrent::FileList file_list_type;
typedef torrent::TrackerList tracker_list_type;
typedef download_type::ConnectionType connection_type;
- typedef utils::VariableMap variable_map_type;
static const int variable_hashing_stopped = 0;
static const int variable_hashing_initial = 1;
@@ -101,18 +100,18 @@ public:
uint32_t priority();
void set_priority(uint32_t p);
-// variable_map_type* variable() { return &m_variables; }
+ int64_t get_value(const char* key);
+ const std::string& get_string(const char* key);
- int64_t get_value(const char* key) { return m_variables.get_d_value(this, key); }
- const std::string& get_string(const char* key) { return m_variables.get_d_string(this, key); }
+ int64_t get_std_value(const std::string& key);
+ const std::string& get_std_string(const std::string& key);
- int64_t get_std_value(const std::string& key) { return m_variables.get_d_value(this, key.c_str()); }
- const std::string& get_std_string(const std::string& key) { return m_variables.get_d_string(this, key.c_str()); }
+ void set(const char* key, const torrent::Object& value);
- void set(const char* key, const torrent::Object& value) { return m_variables.set_d(this, key, value); }
+ void set_value(const char* key, int64_t value);
+ void set_string(const char* key, const std::string& value);
- void set_value(const char* key, int64_t value) { return m_variables.set_d_value(this, key, value); }
- void set_string(const char* key, const std::string& value) { return m_variables.set_d_string(this, key, value); }
+ void set_root_directory(const std::string& path);
bool operator == (const std::string& str) const;
@@ -121,6 +120,9 @@ public:
static connection_type string_to_connection_type(const std::string& name);
static const char* connection_type_to_string(connection_type t);
+ const char* connection_current() const { return connection_type_to_string(m_download.connection_type()); }
+ void set_connection_current(const std::string& t) { return m_download.set_connection_type(string_to_connection_type(t.c_str())); }
+
static uint32_t string_to_priority(const std::string& name);
static const char* priority_to_string(uint32_t p);
@@ -135,11 +137,6 @@ private:
void receive_chunk_failed(uint32_t idx);
- const char* connection_current() const { return connection_type_to_string(m_download.connection_type()); }
- void set_connection_current(const std::string& t) { return m_download.set_connection_type(string_to_connection_type(t.c_str())); }
-
- void set_root_directory(const std::string& path);
-
// Store the FileList instance so we can use slots etc on it.
download_type m_download;
tracker_list_type m_trackerList;
@@ -149,8 +146,6 @@ private:
std::string m_message;
uint32_t m_chunksFailed;
- variable_map_type m_variables;
-
sigc::connection m_connTrackerSucceded;
sigc::connection m_connTrackerFailed;
sigc::connection m_connStorageError;
diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc
index 2820e437..28900b8f 100644
--- a/src/core/download_factory.cc
+++ b/src/core/download_factory.cc
@@ -50,6 +50,7 @@
#include "utils/variable_generic.h"
#include "curl_get.h"
+#include "control.h"
#include "http_queue.h"
#include "globals.h"
#include "manager.h"
diff --git a/src/core/download_list.cc b/src/core/download_list.cc
index b000650f..eab35a58 100644
--- a/src/core/download_list.cc
+++ b/src/core/download_list.cc
@@ -39,14 +39,16 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
-#include "rak/functional.h"
+#include "utils/variable_map.h"
+#include "control.h"
#include "globals.h"
#include "manager.h"
diff --git a/src/core/manager.cc b/src/core/manager.cc
index 7770228d..8e8a0a69 100644
--- a/src/core/manager.cc
+++ b/src/core/manager.cc
@@ -59,6 +59,7 @@
#include "globals.h"
#include "curl_get.h"
+#include "control.h"
#include "download.h"
#include "download_factory.h"
#include "download_store.h"
@@ -241,7 +242,7 @@ Manager::initialize_second() {
m_downloadList->slot_map_insert()["1_connect_storage_log"] = sigc::bind(sigc::ptr_fun(&connect_signal_storage_log), sigc::mem_fun(m_logComplete, &Log::push_front));
m_downloadList->slot_map_insert()["1_connect_tracker_dump"] = sigc::bind(sigc::ptr_fun(&connect_signal_tracker_dump), sigc::ptr_fun(&receive_tracker_dump));
- m_downloadList->slot_map_erase()["1_delete_tied"] = sigc::mem_fun(this, &Manager::delete_tied);
+ m_downloadList->slot_map_erase()["9_delete_tied"] = sigc::mem_fun(this, &Manager::delete_tied);
torrent::connection_manager()->set_signal_handshake_log(sigc::mem_fun(this, &Manager::handshake_log));
}
diff --git a/src/core/scheduler.cc b/src/core/scheduler.cc
index 5b078938..c5abc644 100644
--- a/src/core/scheduler.cc
+++ b/src/core/scheduler.cc
@@ -38,6 +38,7 @@
#include
#include
+#include
#include "download.h"
#include "download_list.h"
diff --git a/src/core/view.cc b/src/core/view.cc
index 70661667..c8bdb810 100644
--- a/src/core/view.cc
+++ b/src/core/view.cc
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include "download.h"
#include "download_list.h"
diff --git a/src/core/view_manager.cc b/src/core/view_manager.cc
index eb2f24a9..0975223e 100644
--- a/src/core/view_manager.cc
+++ b/src/core/view_manager.cc
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include "globals.h"
diff --git a/src/display/utils.cc b/src/display/utils.cc
index 1bef4e6f..aacf3266 100644
--- a/src/display/utils.cc
+++ b/src/display/utils.cc
@@ -53,6 +53,7 @@
#include "core/download.h"
#include "core/manager.h"
+#include "control.h"
#include "globals.h"
#include "utils.h"
diff --git a/src/globals.h b/src/globals.h
index 526e0a0e..d83af5cc 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -40,7 +40,7 @@
#include
#include
-#include "control.h"
+class Control;
extern rak::priority_queue_default taskScheduler;
extern rak::timer cachedTime;
diff --git a/src/main.cc b/src/main.cc
index a3f687c1..10670d65 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -163,7 +163,8 @@ main(int argc, char** argv) {
// Initialize option handlers after libtorrent to ensure
// torrent::ConnectionManager* is valid etc.
- initialize_option_handler(control);
+ initialize_variables();
+ initialize_download_variables();
control->variable()->process_multiple
(
diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc
index e4443133..5b36e37d 100644
--- a/src/option_handler_rules.cc
+++ b/src/option_handler_rules.cc
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -90,49 +91,49 @@ namespace core {
// }
void
-apply_hash_read_ahead(__UNUSED Control* m, int arg) {
+apply_hash_read_ahead(int arg) {
torrent::set_hash_read_ahead(arg << 20);
}
void
-apply_hash_interval(__UNUSED Control* m, int arg) {
+apply_hash_interval(int arg) {
torrent::set_hash_interval(arg * 1000);
}
// The arg string *must* have been checked with validate_port_range
// first.
void
-apply_port_range(Control* m, const std::string& arg) {
+apply_port_range(const std::string& arg) {
int a = 0, b = 0;
std::sscanf(arg.c_str(), "%i-%i", &a, &b);
- m->core()->set_port_range(a, b);
+ control->core()->set_port_range(a, b);
}
void
-apply_load(Control* m, const std::string& arg) {
- m->core()->try_create_download_expand(arg, false, false, true);
+apply_load(const std::string& arg) {
+ control->core()->try_create_download_expand(arg, false, false, true);
}
void
-apply_load_verbose(Control* m, const std::string& arg) {
- m->core()->try_create_download_expand(arg, false, true, true);
+apply_load_verbose(const std::string& arg) {
+ control->core()->try_create_download_expand(arg, false, true, true);
}
void
-apply_load_start(Control* m, const std::string& arg) {
- m->core()->try_create_download_expand(arg, true, false, true);
+apply_load_start(const std::string& arg) {
+ control->core()->try_create_download_expand(arg, true, false, true);
}
void
-apply_load_start_verbose(Control* m, const std::string& arg) {
- m->core()->try_create_download_expand(arg, true, true, true);
+apply_load_start_verbose(const std::string& arg) {
+ control->core()->try_create_download_expand(arg, true, true, true);
}
void
-apply_start_tied(Control* m) {
- for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
+apply_start_tied() {
+ for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if ((*itr)->get_value("state") == 1)
continue;
@@ -140,13 +141,13 @@ apply_start_tied(Control* m) {
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile)))
- m->core()->download_list()->start_try(*itr);
+ control->core()->download_list()->start_try(*itr);
}
}
void
-apply_stop_untied(Control* m) {
- for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
+apply_stop_untied() {
+ for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
if ((*itr)->get_value("state") == 0)
continue;
@@ -154,41 +155,41 @@ apply_stop_untied(Control* m) {
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
- m->core()->download_list()->stop_try(*itr);
+ control->core()->download_list()->stop_try(*itr);
}
}
void
-apply_close_untied(Control* m) {
- for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
+apply_close_untied() {
+ for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ++itr) {
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
- if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && m->core()->download_list()->stop_try(*itr))
- m->core()->download_list()->close(*itr);
+ if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr))
+ control->core()->download_list()->close(*itr);
}
}
void
-apply_remove_untied(Control* m) {
- for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ) {
+apply_remove_untied() {
+ for (core::DownloadList::iterator itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
- if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && m->core()->download_list()->stop_try(*itr))
- itr = m->core()->download_list()->erase(itr);
+ if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && control->core()->download_list()->stop_try(*itr))
+ itr = control->core()->download_list()->erase(itr);
else
++itr;
}
}
void
-apply_close_low_diskspace(Control* m, int64_t arg) {
- core::Manager::DListItr itr = m->core()->download_list()->begin();
+apply_close_low_diskspace(int64_t arg) {
+ core::Manager::DListItr itr = control->core()->download_list()->begin();
- while ((itr = std::find_if(itr, m->core()->download_list()->end(), std::mem_fun(&core::Download::is_downloading))) != m->core()->download_list()->end()) {
+ while ((itr = std::find_if(itr, control->core()->download_list()->end(), std::mem_fun(&core::Download::is_downloading))) != control->core()->download_list()->end()) {
if ((*itr)->file_list()->free_diskspace() < (uint64_t)arg) {
- m->core()->download_list()->close(*itr);
+ control->core()->download_list()->close(*itr);
(*itr)->set_hash_failed(true);
(*itr)->set_message(std::string("Low diskspace."));
@@ -199,7 +200,7 @@ apply_close_low_diskspace(Control* m, int64_t arg) {
}
void
-apply_stop_on_ratio(Control* m, const std::string& arg) {
+apply_stop_on_ratio(const std::string& arg) {
int64_t minRatio = 0; // first argument: minimum ratio to reach
int64_t minUpload = 0; // second argument: minimum upload amount to reach [optional]
int64_t maxRatio = 0; // third argument: maximum ratio to reach [optional]
@@ -214,14 +215,14 @@ apply_stop_on_ratio(Control* m, const std::string& arg) {
if (++sitr != rak::split_iterator(arg))
utils::Variable::string_to_value_unit(rak::trim(*sitr).c_str(), &maxRatio, 0, 1);
- core::Manager::DListItr itr = m->core()->download_list()->begin();
+ core::Manager::DListItr itr = control->core()->download_list()->begin();
- while ((itr = std::find_if(itr, m->core()->download_list()->end(), std::mem_fun(&core::Download::is_seeding))) != m->core()->download_list()->end()) {
+ while ((itr = std::find_if(itr, control->core()->download_list()->end(), std::mem_fun(&core::Download::is_seeding))) != control->core()->download_list()->end()) {
int64_t totalUpload = (*itr)->download()->up_rate()->total();
int64_t totalDone = (*itr)->download()->bytes_done();
if ((totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) || (maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio)) {
- m->core()->download_list()->stop_try(*itr);
+ control->core()->download_list()->stop_try(*itr);
(*itr)->set("ignore_commands", (int64_t)1);
}
@@ -229,25 +230,24 @@ apply_stop_on_ratio(Control* m, const std::string& arg) {
}
}
-// void
-// apply_on_finished(const std::string& arg) {
-// std::string::const_iterator itr = std::find(arg.begin(), arg.end(), ',');
+void
+apply_on_state_change(core::DownloadList::slot_map* slotMap, const std::string& arg) {
+ std::string::const_iterator itr = std::find(arg.begin(), arg.end(), ',');
-// std::string key = rak::trim(std::string(arg.begin(), itr));
-// std::string value = rak::trim(std::string(itr != arg.end() ? itr + 1 : itr, arg.end()));
+ std::string key = rak::trim(std::string(arg.begin(), itr));
+ std::string value = rak::trim(std::string(itr != arg.end() ? itr + 1 : itr, arg.end()));
-// if (key.empty())
-// throw torrent::input_error("Empty key.");
+ if (key.empty())
+ throw torrent::input_error("Empty key.");
-// if (value.empty())
-// control->core()->download_list()->slot_map_finished().erase("0_finished_" + key);
-// else
-// control->core()->download_list()->slot_map_finished().insert("0_finished_" + key, );
-// ->process_std_single(value);
-// }
+ if (value.empty())
+ slotMap->erase("1_start_" + key);
+ else
+ (*slotMap)["1_start_" + key] = sigc::bind(sigc::mem_fun(control->download_variables(), &utils::VariableMap::process_d_std_single), value);
+}
void
-apply_encoding_list(__UNUSED Control* m, const std::string& arg) {
+apply_encoding_list(const std::string& arg) {
torrent::encoding_list()->push_back(arg);
}
@@ -282,10 +282,10 @@ apply_encryption(const std::string& arg) {
}
void
-apply_enable_trackers(Control* m, __UNUSED const std::string& arg) {
+apply_enable_trackers(__UNUSED const std::string& arg) {
bool state = (arg != "no");
- for (core::Manager::DListItr itr = m->core()->download_list()->begin(), last = m->core()->download_list()->end(); itr != last; ++itr) {
+ for (core::Manager::DListItr itr = control->core()->download_list()->begin(), last = control->core()->download_list()->end(); itr != last; ++itr) {
torrent::TrackerList tl = (*itr)->download()->tracker_list();
@@ -327,7 +327,7 @@ apply_tos(const std::string& arg) {
}
void
-apply_view_filter(Control* control, const std::string& arg) {
+apply_view_filter(const std::string& arg) {
rak::split_iterator_t itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
@@ -348,7 +348,7 @@ apply_view_filter(Control* control, const std::string& arg) {
}
void
-apply_view_filter_on(Control* control, const std::string& arg) {
+apply_view_filter_on(const std::string& arg) {
rak::split_iterator_t itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
@@ -369,7 +369,7 @@ apply_view_filter_on(Control* control, const std::string& arg) {
}
void
-apply_view_sort(Control* control, const std::string& arg) {
+apply_view_sort(const std::string& arg) {
rak::split_iterator_t itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
@@ -394,7 +394,7 @@ apply_view_sort(Control* control, const std::string& arg) {
}
void
-apply_view_sort_current(Control* control, const std::string& arg) {
+apply_view_sort_current(const std::string& arg) {
rak::split_iterator_t itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
@@ -415,7 +415,7 @@ apply_view_sort_current(Control* control, const std::string& arg) {
}
void
-apply_view_sort_new(Control* control, const std::string& arg) {
+apply_view_sort_new(const std::string& arg) {
rak::split_iterator_t itr = rak::split_iterator(arg, ',');
std::string name = rak::trim(*itr);
@@ -448,7 +448,7 @@ apply_try_import(const std::string& path) {
}
void
-initialize_option_handler(Control* c) {
+initialize_variables() {
utils::VariableMap* variables = control->variable();
variables->insert("check_hash", new utils::VariableBool(true));
@@ -462,14 +462,14 @@ initialize_option_handler(Control* c) {
rak::mem_fn(control->core()->download_store(), &core::DownloadStore::set_path)));
variables->insert("session_lock", new utils::VariableBool(true));
variables->insert("session_on_completion", new utils::VariableBool(true));
- variables->insert("session_save", new utils::VariableVoidSlot(rak::mem_fn(c->core()->download_list(), &core::DownloadList::session_save)));
+ variables->insert("session_save", new utils::VariableVoidSlot(rak::mem_fn(control->core()->download_list(), &core::DownloadList::session_save)));
variables->insert("connection_leech", new utils::VariableAny("leech"));
variables->insert("connection_seed", new utils::VariableAny("seed"));
variables->insert("directory", new utils::VariableAny("./"));
- variables->insert("tos", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_tos)));
+ variables->insert("tos", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_tos)));
variables->insert("bind", new utils::VariableStringSlot(rak::mem_fn(control->core(), &core::Manager::bind_address),
rak::mem_fn(control->core(), &core::Manager::set_bind_address)));
@@ -478,8 +478,8 @@ initialize_option_handler(Control* c) {
variables->insert("connection_proxy", new utils::VariableStringSlot(rak::mem_fn(control->core(), &core::Manager::proxy_address),
rak::mem_fn(control->core(), &core::Manager::set_proxy_address)));
- variables->insert("http_proxy", new utils::VariableStringSlot(rak::mem_fn(c->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::http_proxy),
- rak::mem_fn(c->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::set_http_proxy)));
+ variables->insert("http_proxy", new utils::VariableStringSlot(rak::mem_fn(control->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::http_proxy),
+ rak::mem_fn(control->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::set_http_proxy)));
variables->insert("min_peers", new utils::VariableValue(40));
variables->insert("max_peers", new utils::VariableValue(100));
@@ -499,26 +499,26 @@ initialize_option_handler(Control* c) {
variables->insert("max_open_files", new utils::VariableValueSlot(rak::ptr_fn(&torrent::max_open_files), rak::ptr_fn(&torrent::set_max_open_files)));
variables->insert("max_open_sockets", new utils::VariableValueSlot(rak::mem_fn(torrent::connection_manager(), &torrent::ConnectionManager::max_size),
rak::mem_fn(torrent::connection_manager(), &torrent::ConnectionManager::set_max_size)));
- variables->insert("max_open_http", new utils::VariableValueSlot(rak::mem_fn(c->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::max_active),
- rak::mem_fn(c->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::set_max_active)));
+ variables->insert("max_open_http", new utils::VariableValueSlot(rak::mem_fn(control->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::max_active),
+ rak::mem_fn(control->core()->get_poll_manager()->get_http_stack(), &core::CurlStack::set_max_active)));
- variables->insert("print", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(control->core(), &core::Manager::push_log)));
- variables->insert("import", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_import)));
- variables->insert("try_import", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_try_import)));
+ variables->insert("print", new utils::VariableStringSlot(NULL, rak::mem_fn(control->core(), &core::Manager::push_log)));
+ variables->insert("import", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_import)));
+ variables->insert("try_import", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_try_import)));
- variables->insert("view_add", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->view_manager(), &core::ViewManager::insert_throw)));
- variables->insert("view_filter", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_filter, c)));
- variables->insert("view_filter_on", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_filter_on, c)));
+ variables->insert("view_add", new utils::VariableStringSlot(NULL, rak::mem_fn(control->view_manager(), &core::ViewManager::insert_throw)));
+ variables->insert("view_filter", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_view_filter)));
+ variables->insert("view_filter_on", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_view_filter_on)));
- variables->insert("view_sort", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort, c)));
- variables->insert("view_sort_new", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_new, c)));
- variables->insert("view_sort_current", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_view_sort_current, c)));
+ variables->insert("view_sort", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_view_sort)));
+ variables->insert("view_sort_new", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_view_sort_new)));
+ variables->insert("view_sort_current", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_view_sort_current)));
variables->insert("key_layout", new utils::VariableAny(std::string("qwerty")));
- variables->insert("schedule", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::mem_fn(c->command_scheduler(), &CommandScheduler::parse)));
- variables->insert("schedule_remove", new utils::VariableStringSlot(rak::value_fn(std::string()),
- rak::mem_fn(c->command_scheduler(), &CommandScheduler::erase)));
+ variables->insert("schedule", new utils::VariableStringSlot(NULL, rak::mem_fn(control->command_scheduler(), &CommandScheduler::parse)));
+ variables->insert("schedule_remove", new utils::VariableStringSlot(NULL,
+ rak::mem_fn(control->command_scheduler(), &CommandScheduler::erase)));
variables->insert("download_scheduler", new utils::VariableVoidSlot(rak::mem_fn(control->scheduler(), &core::Scheduler::update)));
@@ -554,33 +554,179 @@ initialize_option_handler(Control* c) {
variables->insert("split_file_size", new utils::VariableValue(-1));
variables->insert("split_suffix", new utils::VariableAny(".part"));
- variables->insert("port_range", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_port_range, c)));
+ variables->insert("port_range", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_port_range)));
- variables->insert("hash_read_ahead", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_read_ahead), rak::bind_ptr_fn(&apply_hash_read_ahead, c)));
- variables->insert("hash_interval", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_interval), rak::bind_ptr_fn(&apply_hash_interval, c)));
+ variables->insert("hash_read_ahead", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_read_ahead), rak::ptr_fn(&apply_hash_read_ahead)));
+ variables->insert("hash_interval", new utils::VariableValueSlot(rak::ptr_fn(torrent::hash_interval), rak::ptr_fn(&apply_hash_interval)));
variables->insert("umask", new utils::VariableValueSlot(rak::mem_fn(control, &Control::umask), rak::mem_fn(control, &Control::set_umask), 8));
variables->insert("working_directory", new utils::VariableStringSlot(rak::mem_fn(control, &Control::working_directory),
rak::mem_fn(control, &Control::set_working_directory)));
- variables->insert("load", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load, c)));
- variables->insert("load_verbose", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load_verbose, c)));
- variables->insert("load_start", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load_start, c)));
- variables->insert("load_start_verbose", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load_start_verbose, c)));
+ variables->insert("load", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load)));
+ variables->insert("load_verbose", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load_verbose)));
+ variables->insert("load_start", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load_start)));
+ variables->insert("load_start_verbose", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_load_start_verbose)));
- variables->insert("start_tied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_start_tied, c)));
- variables->insert("stop_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_stop_untied, c)));
- variables->insert("close_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_close_untied, c)));
- variables->insert("remove_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_remove_untied, c)));
+ variables->insert("start_tied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_start_tied)));
+ variables->insert("stop_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_stop_untied)));
+ variables->insert("close_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_close_untied)));
+ variables->insert("remove_untied", new utils::VariableVoidSlot(rak::ptr_fn(&apply_remove_untied)));
- variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::bind_ptr_fn(&apply_close_low_diskspace, c)));
- variables->insert("stop_on_ratio", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_stop_on_ratio, c)));
+ variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::ptr_fn(&apply_close_low_diskspace)));
+ variables->insert("stop_on_ratio", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_stop_on_ratio)));
-// variables->insert("on_finished", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_on_finished)));
+ variables->insert("on_insert", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_insert())));
+ variables->insert("on_erase", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_erase())));
+ variables->insert("on_open", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_open())));
+ variables->insert("on_close", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_close())));
+ variables->insert("on_start", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_start())));
+ variables->insert("on_stop", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_stop())));
+ variables->insert("on_hash_queued", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_hash_queued())));
+ variables->insert("on_hash_removed", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_hash_removed())));
+ variables->insert("on_hash_done", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_hash_done())));
+ variables->insert("on_finished", new utils::VariableStringSlot(NULL, rak::bind_ptr_fn(&apply_on_state_change, &control->core()->download_list()->slot_map_finished())));
- variables->insert("enable_trackers", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_enable_trackers, c)));
- variables->insert("encoding_list", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_encoding_list, c)));
+ variables->insert("enable_trackers", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_enable_trackers)));
+ variables->insert("encoding_list", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_encoding_list)));
- variables->insert("encryption", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_encryption)));
+ variables->insert("encryption", new utils::VariableStringSlot(NULL, rak::ptr_fn(&apply_encryption)));
variables->insert("handshake_log", new utils::VariableBool(false));
}
+
+template
+utils::Variable*
+var_d_value(Target target, GetFunc getFunc, SetFunc setFunc) {
+ return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(std::mem_fun(target), std::mem_fun(getFunc))),
+ rak::ftor_fn2(rak::on2(std::mem_fun(target), std::mem_fun(setFunc))));
+}
+
+template
+utils::Variable*
+var_d2_value(Target target, GetFunc getFunc, SetFunc setFunc) {
+ return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(rak::on(std::mem_fun(&core::Download::download), std::mem_fun(target)), std::mem_fun(getFunc))),
+ rak::ftor_fn2(rak::on2(rak::on(std::mem_fun(&core::Download::download), std::mem_fun(target)), std::mem_fun(setFunc))));
+}
+
+template
+utils::Variable*
+var_d2_get_value(Target target, GetFunc getFunc) {
+ return new utils::VariableDownloadValueSlot(rak::ftor_fn1(rak::on(rak::on(std::mem_fun(&core::Download::download), std::mem_fun(target)), std::mem_fun(getFunc))), NULL);
+}
+
+void
+apply_d_create_link(core::Download* download, const std::string& args) {
+ rak::split_iterator_t itr = rak::split_iterator(args, ',');
+
+ std::string type = rak::trim(*itr); ++itr;
+ std::string prefix = rak::trim(*itr); ++itr;
+ std::string postfix = rak::trim(*itr); ++itr;
+
+ if (type.empty())
+ throw torrent::input_error("Invalid arguments.");
+
+ std::string target;
+ std::string link;
+
+ if (type == "tied") {
+ target = rak::path_expand(download->get_string("tied_to_file"));
+ link = rak::path_expand(prefix + target.substr(target.rfind('/') != std::string::npos ? target.rfind('/') + 1 : 0) + postfix);
+ } else {
+ throw torrent::input_error("Unknown type argument.");
+ }
+
+ if (target.empty())
+ return;
+
+ if (symlink(target.c_str(), link.c_str()) == -1)
+ ; // control->core()->push_log("create_link failed: " + std::string(rak::error_number::current().c_str()));
+}
+
+void
+apply_d_delete_link(core::Download* download, const std::string& args) {
+ rak::split_iterator_t itr = rak::split_iterator(args, ',');
+
+ std::string type = rak::trim(*itr); ++itr;
+ std::string prefix = rak::trim(*itr); ++itr;
+ std::string postfix = rak::trim(*itr); ++itr;
+
+ if (type.empty())
+ throw torrent::input_error("Invalid arguments.");
+
+ std::string target;
+ std::string link;
+
+ if (type == "tied") {
+ target = rak::path_expand(download->get_string("tied_to_file"));
+ link = rak::path_expand(prefix + target.substr(target.rfind('/') != std::string::npos ? target.rfind('/') + 1 : 0) + postfix);
+ } else {
+ throw torrent::input_error("Unknown type argument.");
+ }
+
+ if (target.empty())
+ return;
+
+ rak::file_stat fileStat;
+ rak::error_number::clear_global();
+
+ if (!fileStat.update_link(link) || !fileStat.is_link() ||
+ unlink(link.c_str()) == -1)
+ ; // control->core()->push_log("delete_link failed: " + std::string(rak::error_number::current().c_str()));
+}
+
+void
+initialize_download_variables() {
+ utils::VariableMap* variables = control->download_variables();
+
+ variables->insert("connection_current", new utils::VariableDownloadStringSlot(rak::ftor_fn1(std::mem_fun(&core::Download::connection_current)),
+ rak::ftor_fn2(std::mem_fun(&core::Download::set_connection_current))));
+
+ variables->insert("connection_leech", new utils::VariableAny(core::Download::connection_type_to_string(torrent::Download::CONNECTION_LEECH)));
+ variables->insert("connection_seed", new utils::VariableAny(core::Download::connection_type_to_string(torrent::Download::CONNECTION_SEED)));
+
+ // 0 - stopped
+ // 1 - started
+ variables->insert("state", new utils::VariableObject("rtorrent", "state", torrent::Object::TYPE_VALUE));
+ variables->insert("complete", new utils::VariableObject("rtorrent", "complete", torrent::Object::TYPE_VALUE));
+
+ // 0 - Not hashing
+ // 1 - Normal hashing
+ // 2 - Download finished, hashing
+ variables->insert("hashing", new utils::VariableObject("rtorrent", "hashing", torrent::Object::TYPE_VALUE));
+ variables->insert("tied_to_file", new utils::VariableObject("rtorrent", "tied_to_file", torrent::Object::TYPE_STRING));
+
+ // The "state_changed" variable is required to be a valid unix time
+ // value, it indicates the last time the torrent changed its state,
+ // resume/pause.
+ variables->insert("state_changed", new utils::VariableObject("rtorrent", "state_changed", torrent::Object::TYPE_VALUE));
+
+ variables->insert("directory", new utils::VariableDownloadStringSlot(rak::ftor_fn1(rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir))),
+ rak::ftor_fn2(std::mem_fun(&core::Download::set_root_directory))));
+ variables->insert("min_peers", var_d_value(&core::Download::download, &torrent::Download::peers_min, &torrent::Download::set_peers_min));
+ variables->insert("max_peers", var_d_value(&core::Download::download, &torrent::Download::peers_max, &torrent::Download::set_peers_max));
+ variables->insert("max_uploads", var_d_value(&core::Download::download, &torrent::Download::uploads_max, &torrent::Download::set_uploads_max));
+
+ variables->insert("max_file_size", var_d_value(&core::Download::file_list, &torrent::FileList::max_file_size, &torrent::FileList::set_max_file_size));
+
+ // variables->insert("split_file_size", new utils::VariableValueSlot(rak::mem_fn(file_list(), &torrent::FileList::split_file_size),
+ // rak::mem_fn(file_list(), &torrent::FileList::set_split_file_size)));
+ // variables->insert("split_suffix", new utils::VariableStringSlot(rak::mem_fn(file_list(), &torrent::FileList::split_suffix),
+ // rak::mem_fn(file_list(), &torrent::FileList::set_split_suffix)));
+
+ variables->insert("up_rate", var_d2_get_value(&torrent::Download::mutable_up_rate, &torrent::Rate::rate));
+ variables->insert("up_total", var_d2_get_value(&torrent::Download::mutable_up_rate, &torrent::Rate::total));
+ variables->insert("down_rate", var_d2_get_value(&torrent::Download::mutable_down_rate, &torrent::Rate::rate));
+ variables->insert("down_total", var_d2_get_value(&torrent::Download::mutable_down_rate, &torrent::Rate::total));
+ variables->insert("skip_rate", var_d2_get_value(&torrent::Download::mutable_skip_rate, &torrent::Rate::rate));
+ variables->insert("skip_total", var_d2_get_value(&torrent::Download::mutable_skip_rate, &torrent::Rate::total));
+
+ variables->insert("priority", new utils::VariableDownloadValueSlot(rak::ftor_fn1(std::mem_fun(&core::Download::priority)), rak::ftor_fn2(std::mem_fun(&core::Download::set_priority))));
+ variables->insert("tracker_numwant", var_d_value(&core::Download::tracker_list, &torrent::TrackerList::numwant, &torrent::TrackerList::set_numwant));
+
+ variables->insert("ignore_commands", new utils::VariableObject("rtorrent", "ignore_commands", torrent::Object::TYPE_VALUE));
+
+ // Hmm... do we need dupicates?
+ variables->insert("print", new utils::VariableStringSlot(NULL, rak::mem_fn(control->core(), &core::Manager::push_log)));
+ variables->insert("create_link", new utils::VariableDownloadStringSlot(NULL, rak::ptr_fn(&apply_d_create_link)));
+ variables->insert("delete_link", new utils::VariableDownloadStringSlot(NULL, rak::ptr_fn(&apply_d_delete_link)));
+}
diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h
index 61432253..c07f76bc 100644
--- a/src/option_handler_rules.h
+++ b/src/option_handler_rules.h
@@ -39,6 +39,7 @@
class Control;
-void initialize_option_handler(Control* c);
+void initialize_variables();
+void initialize_download_variables();
#endif
diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
index 4c2616a5..47e68454 100644
--- a/src/ui/download_list.cc
+++ b/src/ui/download_list.cc
@@ -56,6 +56,8 @@
#include "display/window_log.h"
#include "display/window_title.h"
+#include "utils/variable_map.h"
+
#include "control.h"
#include "download.h"
#include "download_list.h"
diff --git a/src/ui/element_download_list.cc b/src/ui/element_download_list.cc
index c4867aee..9d2d3735 100644
--- a/src/ui/element_download_list.cc
+++ b/src/ui/element_download_list.cc
@@ -38,6 +38,7 @@
#include
#include
+#include
#include "core/download.h"
#include "core/manager.h"
diff --git a/src/utils/variable_generic.cc b/src/utils/variable_generic.cc
index def7ca46..6aeba4d7 100644
--- a/src/utils/variable_generic.cc
+++ b/src/utils/variable_generic.cc
@@ -234,9 +234,7 @@ VariableStringSlot::get() {
if (!m_slotGet.is_valid())
return m_cache = torrent::Object();
- m_cache = m_slotGet();
-
- return m_cache;
+ return m_cache = m_slotGet();
}
void
diff --git a/src/utils/variable_generic.h b/src/utils/variable_generic.h
index 45d9d458..ea37307e 100644
--- a/src/utils/variable_generic.h
+++ b/src/utils/variable_generic.h
@@ -234,6 +234,12 @@ public:
typedef rak::function0 slot_get_type;
typedef rak::function1 slot_set_type;
+ template
+ VariableStringSlot(void* slotGet, SlotSet* slotSet) {
+ m_slotGet.set(NULL);
+ m_slotSet.set(rak::convert_fn(slotSet));
+ }
+
template
VariableStringSlot(SlotGet* slotGet, SlotSet* slotSet) {
m_slotGet.set(rak::convert_fn(slotGet));
@@ -258,6 +264,12 @@ public:
typedef rak::function1 slot_get_d_type;
typedef rak::function2 slot_set_d_type;
+ template
+ VariableDownloadStringSlot(void* slotGetDownload, SlotSetDownload* slotSetDownload) {
+ m_slotGetDownload.set(NULL);
+ m_slotSetDownload.set(rak::convert_fn(slotSetDownload));
+ }
+
template
VariableDownloadStringSlot(SlotGetDownload* slotGetDownload, SlotSetDownload* slotSetDownload) {
m_slotGetDownload.set(rak::convert_fn(slotGetDownload));
diff --git a/src/utils/variable_map.cc b/src/utils/variable_map.cc
index 00e623e7..d6afd496 100644
--- a/src/utils/variable_map.cc
+++ b/src/utils/variable_map.cc
@@ -205,6 +205,35 @@ VariableMap::process_single(const char* first, const char* last) {
return std::find_if(first, last, std::not1(variable_map_is_space()));
}
+const char*
+VariableMap::process_d_single(core::Download* download, const char* first, const char* last) {
+ first = std::find_if(first, last, std::not1(variable_map_is_space()));
+
+ if (first == last || *first == '#')
+ return last;
+
+ std::string key;
+ first = parse_name(first, last, &key);
+ first = std::find_if(first, last, std::not1(variable_map_is_space()));
+
+ if (first == last || *first != '=')
+ throw torrent::input_error("Could not find '='.");
+
+ mapped_type args(mapped_type::TYPE_LIST);
+ first = parse_args(first + 1, last, &args.as_list());
+
+ if (args.as_list().empty())
+ set_d(download, key.c_str(), mapped_type());
+
+ else if (++args.as_list().begin() == args.as_list().end())
+ set_d(download, key.c_str(), *args.as_list().begin());
+
+ else
+ set_d(download, key.c_str(), args);
+
+ return std::find_if(first, last, std::not1(variable_map_is_space()));
+}
+
// void
// VariableMap::process_command(const std::string& command) {
// std::string::const_iterator pos = command.begin();
diff --git a/src/utils/variable_map.h b/src/utils/variable_map.h
index 6091c5d5..085bfcfa 100644
--- a/src/utils/variable_map.h
+++ b/src/utils/variable_map.h
@@ -96,8 +96,9 @@ public:
void set(key_type key, const mapped_type& arg);
void set_d(core::Download* download, key_type key, const mapped_type& arg);
- void set_string(key_type key, const std::string& arg) { set(key, mapped_type(arg)); }
- void set_d_string(core::Download* download, key_type key, const std::string& arg) { set_d(download, key, mapped_type(arg)); }
+ void set_string(key_type key, const std::string& arg) { set(key, mapped_type(arg)); }
+ void set_d_string(core::Download* download, key_type key, const std::string& arg) { set_d(download, key, mapped_type(arg)); }
+ void set_d_std_string(core::Download* download, const std::string& key, const std::string& arg) { set_d(download, key.c_str(), mapped_type(arg)); }
void set_value(key_type key, mapped_value_type arg) { set(key, mapped_type(arg)); }
void set_d_value(core::Download* download, key_type key, mapped_value_type arg) { set_d(download, key, mapped_type(arg)); }
@@ -108,6 +109,9 @@ public:
const char* process_single(const char* first, const char* last);
void process_std_single(const std::string& cmd) { process_single(cmd.c_str(), cmd.c_str() + cmd.size()); }
+ const char* process_d_single(core::Download* download, const char* first, const char* last);
+ void process_d_std_single(core::Download* download, const std::string& cmd) { process_d_single(download, cmd.c_str(), cmd.c_str() + cmd.size()); }
+
void process_multiple(const char* first);
void process_stream(std::istream* str);