diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml
index aa31331b..45d0f0bb 100644
--- a/doc/rtorrent.1.xml
+++ b/doc/rtorrent.1.xml
@@ -416,6 +416,23 @@
+
+ hash_interval = ms
+
+ Interval between attempts to check the hash when the chunk
+ is not in memory, in milliseconds.
+
+
+
+
+ hash_max_tries = tries
+
+ Number of attempts to check the hash while using the mincore
+ status, before forcing. Overworked systems might need lower
+ values to get a decent hash checking rate.
+
+
+
max_open_files = value
diff --git a/doc/rtorrent.rc b/doc/rtorrent.rc
index f64d2a22..fff1b9bd 100644
--- a/doc/rtorrent.rc
+++ b/doc/rtorrent.rc
@@ -53,6 +53,14 @@
# pages in memory thus end up trashing.
#hash_read_ahead = 10
+# Interval between attempts to check the hash, in milliseconds.
+#hash_interval = 100
+
+# Number of attempts to check the hash while using the mincore status,
+# before forcing. Overworked systems might need lower values to get a
+# decent hash checking rate.
+#hash_max_tries = 10
+
# Max number of files to keep open simultaniously.
#max_open_files = 100
diff --git a/src/core/download.h b/src/core/download.h
index 07e93c9e..65811658 100644
--- a/src/core/download.h
+++ b/src/core/download.h
@@ -25,6 +25,7 @@
#include
#include
+#include
namespace core {
@@ -38,6 +39,7 @@ public:
torrent::Download& get_download() { return m_download; }
std::string get_hash() { return m_download.get_hash(); }
+ torrent::Bencode& get_bencode() { return torrent::download_bencode(m_download.get_hash()); }
const std::string& get_message() { return m_message; }
diff --git a/src/core/manager.cc b/src/core/manager.cc
index 7697483b..03ddbcda 100644
--- a/src/core/manager.cc
+++ b/src/core/manager.cc
@@ -31,7 +31,6 @@
#include
#include
#include
-#include
#include "download.h"
#include "manager.h"
@@ -54,8 +53,9 @@ Manager::initialize() {
// Register slots to be called when a download is inserted/erased,
// opened or closed.
+ m_downloadList.slot_map_insert().insert("0_initialize_bencode", sigc::mem_fun(*this, &Manager::initialize_bencode));
m_downloadList.slot_map_insert().insert("1_connect_network_log", sigc::bind(sigc::ptr_fun(&connect_signal_network_log), sigc::mem_fun(m_logComplete, &Log::push_front)));
- m_downloadList.slot_map_insert().insert("3_manager_start", sigc::mem_fun(*this, &Manager::start));
+ m_downloadList.slot_map_insert().insert("3_manager_inserted", sigc::mem_fun(*this, &Manager::receive_download_inserted));
m_downloadList.slot_map_insert().insert("4_store_save", sigc::mem_fun(m_downloadStore, &DownloadStore::save));
m_downloadList.slot_map_erase().insert("1_hash_queue_remove", sigc::mem_fun(m_hashQueue, &HashQueue::remove));
@@ -87,6 +87,16 @@ Manager::cleanup() {
core::CurlStack::cleanup();
}
+void
+Manager::shutdown(bool force) {
+ if (!force)
+ std::for_each(m_downloadList.begin(), m_downloadList.end(),
+ std::bind1st(std::mem_fun(&DownloadList::stop), &m_downloadList));
+ else
+ std::for_each(m_downloadList.begin(), m_downloadList.end(),
+ std::bind1st(std::mem_fun(&DownloadList::close), &m_downloadList));
+}
+
void
Manager::insert(std::string uri) {
if (std::strncmp(uri.c_str(), "http://", 7) == 0) {
@@ -111,6 +121,8 @@ Manager::erase(DListItr itr) {
void
Manager::start(Download* d) {
try {
+ d->get_bencode()["rtorrent"]["state"] = "started";
+
if (d->get_download().is_active())
return;
@@ -132,6 +144,8 @@ Manager::start(Download* d) {
void
Manager::stop(Download* d) {
try {
+ d->get_bencode()["rtorrent"]["state"] = "stopped";
+
m_downloadList.stop(d);
} catch (torrent::local_error& e) {
@@ -212,6 +226,21 @@ Manager::create_final(std::istream* s) {
}
}
+void
+Manager::initialize_bencode(Download* d) {
+ torrent::Bencode& bencode = d->get_bencode();
+
+ // TODO: Check that stuff are the right type, like state etc.
+ if (bencode.has_key("rtorrent") &&
+ bencode["rtorrent"].is_map() &&
+ bencode["rtorrent"].has_key("state") &&
+ bencode["rtorrent"]["state"].is_string())
+ return;
+
+ bencode.insert_key("rtorrent", torrent::Bencode(torrent::Bencode::TYPE_MAP));
+ bencode["rtorrent"].insert_key("state", "started");
+}
+
void
Manager::prepare_hash_check(Download* d) {
m_downloadList.close(d);
@@ -242,4 +271,14 @@ Manager::receive_download_done_hash_checked(Download* d) {
d->get_download().tracker_send_completed();
}
+void
+Manager::receive_download_inserted(Download* d) {
+ // Check if there is an "rtorrent" section in the bencoded data.
+
+ torrent::Bencode& bencode = d->get_bencode();
+
+ if (bencode["rtorrent"]["state"].as_string() == "started")
+ start(d);
+}
+
}
diff --git a/src/core/manager.h b/src/core/manager.h
index cd0532c1..d351351e 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -61,6 +61,8 @@ public:
void initialize();
void cleanup();
+ void shutdown(bool force);
+
void insert(std::string uri);
DListItr erase(DListItr itr);
@@ -77,10 +79,13 @@ private:
void create_http(const std::string& uri);
void create_final(std::istream* s);
+ void initialize_bencode(Download* d);
+
void prepare_hash_check(Download* d);
void receive_http_failed(std::string msg);
void receive_download_done_hash_checked(Download* d);
+ void receive_download_inserted(Download* d);
DownloadList m_downloadList;
DownloadStore m_downloadStore;
diff --git a/src/display/manager.cc b/src/display/manager.cc
index 9baf3fce..bd8bd4f1 100644
--- a/src/display/manager.cc
+++ b/src/display/manager.cc
@@ -83,8 +83,7 @@ void
Manager::do_update() {
Canvas::refresh_std();
- std::for_each(begin(), end(), rak::if_then(std::mem_fun(&Window::is_active), rak::if_then(std::mem_fun(&Window::is_dirty),
- std::mem_fun(&Window::redraw))));
+ utils::displayScheduler.execute(utils::Timer::cache());
std::for_each(begin(), end(), rak::if_then(std::mem_fun(&Window::is_active), std::mem_fun(&Window::refresh)));
Canvas::do_update();
diff --git a/src/display/window.cc b/src/display/window.cc
index fd8a0172..5b54ef8e 100644
--- a/src/display/window.cc
+++ b/src/display/window.cc
@@ -30,10 +30,31 @@ namespace display {
Window::Slot Window::m_slotAdjust;
+Window::Window(Canvas* c, bool d, int h) :
+ m_canvas(c),
+ m_active(true),
+ m_dynamic(d),
+ m_minHeight(h) {
+
+ m_taskUpdate.set_iterator(utils::displayScheduler.end());
+ m_taskUpdate.set_slot(sigc::mem_fun(*this, &Window::redraw));
+}
+
Window::~Window() {
+ utils::displayScheduler.erase(&m_taskUpdate);
delete m_canvas;
}
+void
+Window::set_active(bool a) {
+ if (a)
+ mark_dirty();
+ else
+ utils::displayScheduler.erase(&m_taskUpdate);
+
+ m_active = a;
+}
+
void
Window::resize(int x, int y, int w, int h) {
if (x < 0 || y < 0)
diff --git a/src/display/window.h b/src/display/window.h
index 00971103..0d368f1b 100644
--- a/src/display/window.h
+++ b/src/display/window.h
@@ -26,6 +26,7 @@
#include
#include "canvas.h"
+#include "utils/task.h"
#include "utils/timer.h"
namespace display {
@@ -36,46 +37,51 @@ class Window {
public:
typedef sigc::slot0 Slot;
- Window(Canvas* c = NULL, bool d = false, int h = 1) :
- m_canvas(c), m_active(true), m_dynamic(d), m_minHeight(h) {}
+ Window(Canvas* c = NULL, bool d = false, int h = 1);
virtual ~Window();
- bool is_active() { return m_active; }
- bool is_dynamic() { return m_dynamic; }
- bool is_dirty() { return m_nextDraw <= utils::Timer::cache(); }
+ bool is_active() { return m_active; }
+ bool is_dynamic() { return m_dynamic; }
+ bool is_dirty() { return utils::displayScheduler.is_scheduled(&m_taskUpdate); }
- utils::Timer get_next_draw() { return m_nextDraw; }
+ //utils::Timer get_next_draw() { return m_nextDraw; }
- int get_min_height() { return m_minHeight; }
+ int get_min_height() { return m_minHeight; }
- bool get_active() { return m_active; }
- void set_active(bool a) { m_active = a; }
+ bool get_active() { return m_active; }
+ void set_active(bool a);
- void refresh() { m_canvas->refresh(); }
- void resize(int x, int y, int w, int h);
+ void refresh() { m_canvas->refresh(); }
+ void resize(int x, int y, int w, int h);
- void mark_dirty() { m_nextDraw = utils::Timer::min(); }
+ void mark_dirty();
- virtual void redraw() = 0;
+ virtual void redraw() = 0;
- static void slot_adjust(Slot s) { m_slotAdjust = s; }
+ static void slot_adjust(Slot s) { m_slotAdjust = s; }
protected:
Window(const Window&);
void operator = (const Window&);
- static Slot m_slotAdjust;
+ static Slot m_slotAdjust;
- Canvas* m_canvas;
+ Canvas* m_canvas;
- bool m_active;
- bool m_dynamic;
- int m_minHeight;
+ bool m_active;
+ bool m_dynamic;
+ int m_minHeight;
- utils::Timer m_nextDraw;
+ utils::TaskItem m_taskUpdate;
};
+inline void
+Window::mark_dirty() {
+ utils::displayScheduler.erase(&m_taskUpdate);
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache());
+}
+
}
#endif
diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc
index dab07994..7df3e1c7 100644
--- a/src/display/window_download_list.cc
+++ b/src/display/window_download_list.cc
@@ -44,7 +44,7 @@ WindowDownloadList::~WindowDownloadList() {
void
WindowDownloadList::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
diff --git a/src/display/window_download_statusbar.cc b/src/display/window_download_statusbar.cc
index 98267567..83ca9f7e 100644
--- a/src/display/window_download_statusbar.cc
+++ b/src/display/window_download_statusbar.cc
@@ -37,7 +37,7 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) :
void
WindowDownloadStatusbar::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc
index 80c14dcf..8220e84b 100644
--- a/src/display/window_file_list.cc
+++ b/src/display/window_file_list.cc
@@ -39,7 +39,7 @@ WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) :
void
WindowFileList::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 10 * 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 10 * 1000000);
m_canvas->erase();
if (m_download->get_download().get_entry_size() == 0 ||
diff --git a/src/display/window_http_queue.cc b/src/display/window_http_queue.cc
index 5ef8d9a8..6b8a5eec 100644
--- a/src/display/window_http_queue.cc
+++ b/src/display/window_http_queue.cc
@@ -44,7 +44,7 @@ WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) :
void
WindowHttpQueue::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
cleanup_list();
diff --git a/src/display/window_input.cc b/src/display/window_input.cc
index 8af55706..f7ff0b4a 100644
--- a/src/display/window_input.cc
+++ b/src/display/window_input.cc
@@ -37,9 +37,7 @@ WindowInput::WindowInput(input::TextInput* input) :
void
WindowInput::redraw() {
- m_nextDraw = utils::Timer::max();
m_canvas->erase();
-
m_canvas->print(0, 0, "> %s", m_input->c_str());
if (m_focus)
diff --git a/src/display/window_log.cc b/src/display/window_log.cc
index 99367dec..0651df46 100644
--- a/src/display/window_log.cc
+++ b/src/display/window_log.cc
@@ -34,7 +34,7 @@ WindowLog::WindowLog(core::Log* l) :
Window(new Canvas, false, 0),
m_log(l) {
- set_active(false);
+ m_active = false;
// We're trying out scheduled tasks instead.
m_connUpdate = l->signal_update().connect(sigc::mem_fun(*this, &WindowLog::receive_update));
@@ -51,8 +51,6 @@ WindowLog::find_older() {
void
WindowLog::redraw() {
- m_nextDraw = utils::Timer::max();
-
m_canvas->erase();
int pos = 0;
diff --git a/src/display/window_log_complete.cc b/src/display/window_log_complete.cc
index ec3e202f..faf7f1e0 100644
--- a/src/display/window_log_complete.cc
+++ b/src/display/window_log_complete.cc
@@ -49,8 +49,6 @@ WindowLogComplete::find_older() {
void
WindowLogComplete::redraw() {
- m_nextDraw = utils::Timer::max();
-
m_canvas->erase();
int pos = 0;
diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc
index 91dfb227..1c92b20c 100644
--- a/src/display/window_peer_info.cc
+++ b/src/display/window_peer_info.cc
@@ -42,7 +42,7 @@ WindowPeerInfo::WindowPeerInfo(core::Download* d, PList* l, PList::iterator* f)
void
WindowPeerInfo::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
int y = 0;
diff --git a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc
index 1e734d44..607e55e9 100644
--- a/src/display/window_peer_list.cc
+++ b/src/display/window_peer_list.cc
@@ -41,7 +41,7 @@ WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f)
void
WindowPeerList::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
int x = 2;
diff --git a/src/display/window_statusbar.cc b/src/display/window_statusbar.cc
index 7bcf91ad..e9e0c547 100644
--- a/src/display/window_statusbar.cc
+++ b/src/display/window_statusbar.cc
@@ -39,7 +39,7 @@ WindowStatusbar::WindowStatusbar(core::Manager* c) :
void
WindowStatusbar::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
diff --git a/src/display/window_string_list.cc b/src/display/window_string_list.cc
index b7c427ff..8b5d81df 100644
--- a/src/display/window_string_list.cc
+++ b/src/display/window_string_list.cc
@@ -37,8 +37,6 @@ WindowStringList::~WindowStringList() {
void
WindowStringList::redraw() {
- m_nextDraw = utils::Timer::max();
-
m_canvas->erase();
size_t ypos = 0;
diff --git a/src/display/window_title.cc b/src/display/window_title.cc
index a865ce23..3037f722 100644
--- a/src/display/window_title.cc
+++ b/src/display/window_title.cc
@@ -34,7 +34,7 @@ WindowTitle::WindowTitle(const std::string& s) :
void
WindowTitle::redraw() {
- m_nextDraw = utils::Timer::cache().round_seconds() + 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 1000000);
m_canvas->erase();
m_canvas->print(std::max(0, (m_canvas->get_width() - (int)m_title.size()) / 2 - 4), 0,
diff --git a/src/display/window_tracker_list.cc b/src/display/window_tracker_list.cc
index b03a1fd7..baaf2916 100644
--- a/src/display/window_tracker_list.cc
+++ b/src/display/window_tracker_list.cc
@@ -41,7 +41,7 @@ WindowTrackerList::WindowTrackerList(core::Download* d, unsigned int* focus) :
void
WindowTrackerList::redraw() {
// TODO: Make this depend on tracker signal.
- m_nextDraw = utils::Timer::cache().round_seconds() + 10 * 1000000;
+ utils::displayScheduler.insert(&m_taskUpdate, utils::Timer::cache().round_seconds() + 10 * 1000000);
m_canvas->erase();
int pos = 0;
diff --git a/src/main.cc b/src/main.cc
index da25deca..55da4e48 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -42,7 +42,6 @@
#include "display/canvas.h"
#include "display/window.h"
#include "ui/control.h"
-#include "ui/root.h"
#include "input/bindings.h"
#include "utils/task.h"
@@ -64,6 +63,7 @@ void print_help();
namespace utils {
TaskScheduler taskScheduler;
+ TaskScheduler displayScheduler;
}
bool
@@ -85,15 +85,12 @@ do_shutdown(ui::Control* c) {
is_shutting_down = true;
torrent::listen_close();
-
- std::for_each(c->get_core().get_download_list().begin(), c->get_core().get_download_list().end(),
- std::bind1st(std::mem_fun(&core::Manager::stop), &c->get_core()));
+ c->get_core().shutdown(false);
} else {
// Close all torrents, this will stop all tracker connections and cause
// a quick shutdown.
- std::for_each(c->get_core().get_download_list().begin(), c->get_core().get_download_list().end(),
- std::mem_fun(&core::Download::call));
+ c->get_core().shutdown(true);
}
}
@@ -132,7 +129,9 @@ initialize_option_handler(ui::Control* c, OptionHandler* optionHandler) {
optionHandler->insert("check_hash", new OptionHandlerString(c, &apply_check_hash, &validate_yes_no));
optionHandler->insert("directory", new OptionHandlerString(c, &apply_download_directory, &validate_directory));
- optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_read_ahead));
+ optionHandler->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead, &validate_hash_read_ahead));
+ optionHandler->insert("hash_interval", new OptionHandlerInt(c, &apply_hash_interval, &validate_hash_interval));
+ optionHandler->insert("hash_max_tries", new OptionHandlerInt(c, &apply_hash_max_tries, &validate_hash_max_tries));
optionHandler->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files, &validate_fd));
optionHandler->insert("throttle_interval", new OptionHandlerInt(c, &apply_throttle_interval, &validate_throttle_interval));
@@ -186,7 +185,6 @@ int
main(int argc, char** argv) {
OptionHandler optionHandler;
ui::Control uiControl;
- ui::Root uiRoot(&uiControl);
utils::Timer::update();
@@ -198,10 +196,10 @@ main(int argc, char** argv) {
try {
SignalHandler::set_ignore(SIGPIPE);
- SignalHandler::set_handler(SIGINT, sigc::bind(sigc::mem_fun(uiRoot, &ui::Root::set_shutdown_received), true));
+ SignalHandler::set_handler(SIGINT, sigc::bind(sigc::mem_fun(uiControl, &ui::Control::set_shutdown_received), true));
SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV));
- SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS));
- SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE));
+ SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS));
+ SignalHandler::set_handler(SIGFPE, sigc::bind(sigc::ptr_fun(&do_panic), SIGFPE));
// Need to initialize this before parseing options.
torrent::initialize();
@@ -214,7 +212,7 @@ main(int argc, char** argv) {
initialize_display(&uiControl);
initialize_core(&uiControl);
- uiRoot.init();
+ uiControl.get_ui().init(&uiControl);
load_session_torrents(&uiControl);
load_arg_torrents(&uiControl, argv + firstArg, argv + argc);
@@ -223,9 +221,9 @@ main(int argc, char** argv) {
while (!is_shutting_down || !torrent::is_inactive()) {
- if (uiRoot.get_shutdown_received()) {
+ if (uiControl.get_shutdown_received()) {
do_shutdown(&uiControl);
- uiRoot.set_shutdown_received(false);
+ uiControl.set_shutdown_received(false);
}
utils::Timer::update();
@@ -233,14 +231,16 @@ main(int argc, char** argv) {
// This needs to be called every second or so. Currently done by
// the throttle task in libtorrent.
- uiControl.get_display().do_update();
+ if (!utils::displayScheduler.empty() &&
+ utils::displayScheduler.get_next_timeout() <= utils::Timer::cache())
+ uiControl.get_display().do_update();
uiControl.get_core().get_poll().poll(!utils::taskScheduler.empty() ?
utils::taskScheduler.get_next_timeout() - utils::Timer::cache() :
60 * 1000000);
}
- uiRoot.cleanup();
+ uiControl.get_ui().cleanup();
uiControl.get_core().cleanup();
display::Canvas::erase_std();
diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc
index e41c48b6..e0e84e8d 100644
--- a/src/option_handler_rules.cc
+++ b/src/option_handler_rules.cc
@@ -71,10 +71,20 @@ validate_rate(int arg) {
}
bool
-validate_read_ahead(int arg) {
+validate_hash_read_ahead(int arg) {
return arg >= 1 && arg < 64;
}
+bool
+validate_hash_interval(int arg) {
+ return arg >= 1 && arg < 1000;
+}
+
+bool
+validate_hash_max_tries(int arg) {
+ return arg >= 1 && arg < 20;
+}
+
bool
validate_fd(int arg) {
return arg >= 10 && arg < (1 << 16);
@@ -123,6 +133,16 @@ apply_hash_read_ahead(ui::Control* m, int arg) {
torrent::set_hash_read_ahead(arg << 20);
}
+void
+apply_hash_interval(ui::Control* m, int arg) {
+ torrent::set_hash_interval(arg * 1000);
+}
+
+void
+apply_hash_max_tries(ui::Control* m, int arg) {
+ torrent::set_hash_max_tries(arg);
+}
+
void
apply_max_open_files(ui::Control* m, int arg) {
torrent::set_max_open_files(arg);
diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h
index 016f162b..67f16365 100644
--- a/src/option_handler_rules.h
+++ b/src/option_handler_rules.h
@@ -41,7 +41,9 @@ bool validate_yes_no(const std::string& arg);
bool validate_download_peers(int arg);
bool validate_rate(int arg);
-bool validate_read_ahead(int arg);
+bool validate_hash_read_ahead(int arg);
+bool validate_hash_interval(int arg);
+bool validate_hash_max_tries(int arg);
bool validate_fd(int arg);
bool validate_throttle_interval(int arg);
@@ -56,6 +58,8 @@ void apply_global_download_rate(ui::Control* m, int arg);
void apply_global_upload_rate(ui::Control* m, int arg);
void apply_hash_read_ahead(ui::Control* m, int arg);
+void apply_hash_interval(ui::Control* m, int arg);
+void apply_hash_max_tries(ui::Control* m, int arg);
void apply_max_open_files(ui::Control* m, int arg);
void apply_throttle_interval(ui::Control* m, int arg);
diff --git a/src/ui/control.h b/src/ui/control.h
index 046ccd42..14f6187d 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -27,23 +27,32 @@
#include "display/manager.h"
#include "input/manager.h"
+#include "root.h"
+
namespace ui {
class Control {
public:
- Control() {}
+ Control() : m_shutdownReceived(false) {}
- core::Manager& get_core() { return m_core; }
- display::Manager& get_display() { return m_display; }
- input::Manager& get_input() { return m_input; }
+ bool get_shutdown_received() { return m_shutdownReceived; }
+ void set_shutdown_received(bool v) { m_shutdownReceived = v; }
+
+ Root& get_ui() { return m_ui; }
+ core::Manager& get_core() { return m_core; }
+ display::Manager& get_display() { return m_display; }
+ input::Manager& get_input() { return m_input; }
private:
Control(const Control&);
void operator = (const Control&);
- core::Manager m_core;
- display::Manager m_display;
- input::Manager m_input;
+ bool m_shutdownReceived;
+
+ Root m_ui;
+ core::Manager m_core;
+ display::Manager m_display;
+ input::Manager m_input;
};
}
diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc
index 474a9953..c6ed82d3 100644
--- a/src/ui/download_list.cc
+++ b/src/ui/download_list.cc
@@ -37,6 +37,7 @@
#include "display/window_input.h"
#include "display/window_log.h"
#include "display/window_title.h"
+#include "display/window_statusbar.h"
#include "control.h"
#include "download.h"
@@ -113,15 +114,15 @@ DownloadList::disable() {
if (!is_active())
throw std::logic_error("ui::Download::disable() called on an already disabled object");
- disable_display();
-
- utils::taskScheduler.erase(&m_taskUpdate);
-
if (m_windowTextInput->is_active()) {
m_windowTextInput->get_input()->clear();
receive_exit_input();
}
+ disable_display();
+
+ utils::taskScheduler.erase(&m_taskUpdate);
+
m_control->get_display().erase(m_window);
m_control->get_display().erase(m_windowTitle);
m_control->get_display().erase(m_windowTextInput);
@@ -225,7 +226,7 @@ DownloadList::receive_check_hash() {
void
DownloadList::receive_view_input() {
- //m_windowStatus->set_active(false);
+ m_control->get_ui().window_statusbar()->set_active(false);
m_windowTextInput->set_active(true);
m_control->get_display().adjust_layout();
@@ -239,7 +240,7 @@ DownloadList::receive_view_input() {
void
DownloadList::receive_exit_input() {
- //m_windowStatus->set_active(true);
+ m_control->get_ui().window_statusbar()->set_active(true);
m_windowTextInput->set_active(false);
m_control->get_input().set_text_input();
diff --git a/src/ui/root.cc b/src/ui/root.cc
index 4a6e2190..68757700 100644
--- a/src/ui/root.cc
+++ b/src/ui/root.cc
@@ -34,24 +34,24 @@
namespace ui {
-Root::Root(Control* c) :
- m_shutdownReceived(false),
- m_control(c),
+Root::Root() :
+ m_control(NULL),
m_downloadList(NULL),
- m_windowStatus(NULL) {
+ m_windowStatusbar(NULL) {
}
void
-Root::init() {
- if (m_downloadList != NULL)
+Root::init(Control* c) {
+ if (m_control != NULL)
throw std::logic_error("Root::init() called twice on the same object");
+ m_control = c;
setup_keys();
- m_windowStatus = new WStatus(&m_control->get_core());
- m_downloadList = new DownloadList(m_control);
+ m_windowStatusbar = new WStatusbar(&m_control->get_core());
+ m_downloadList = new DownloadList(m_control);
- m_control->get_display().push_back(m_windowStatus);
+ m_control->get_display().push_back(m_windowStatusbar);
m_downloadList->activate();
m_downloadList->slot_open_uri(sigc::mem_fun(m_control->get_core(), &core::Manager::insert));
@@ -59,15 +59,19 @@ Root::init() {
void
Root::cleanup() {
+ if (m_control == NULL)
+ throw std::logic_error("Root::cleanup() called twice on the same object");
+
if (m_downloadList->is_active())
m_downloadList->disable();
- m_control->get_display().erase(m_windowStatus);
+ m_control->get_display().erase(m_windowStatusbar);
delete m_downloadList;
- delete m_windowStatus;
+ delete m_windowStatusbar;
m_control->get_input().erase(&m_bindings);
+ m_control = NULL;
}
void
@@ -89,19 +93,19 @@ Root::setup_keys() {
m_bindings['C'] = sigc::bind(sigc::mem_fun(*this, &Root::receive_read_throttle), -50);
m_bindings[KEY_RESIZE] = sigc::mem_fun(m_control->get_display(), &display::Manager::adjust_layout);
- m_bindings['\x11'] = sigc::bind(sigc::mem_fun(*this, &Root::set_shutdown_received), true);
+ m_bindings['\x11'] = sigc::bind(sigc::mem_fun(*m_control, &Control::set_shutdown_received), true);
}
void
Root::receive_read_throttle(int t) {
- //m_downloadList->mark_dirty();
+ m_windowStatusbar->mark_dirty();
torrent::set_read_throttle(torrent::get_read_throttle() + t * 1024);
}
void
Root::receive_write_throttle(int t) {
- //m_downloadList->mark_dirty();
+ m_windowStatusbar->mark_dirty();
torrent::set_write_throttle(torrent::get_write_throttle() + t * 1024);
}
diff --git a/src/ui/root.h b/src/ui/root.h
index 5736ce38..d6fe4d48 100644
--- a/src/ui/root.h
+++ b/src/ui/root.h
@@ -32,18 +32,18 @@ namespace display {
namespace ui {
class DownloadList;
+class Control;
class Root {
public:
- typedef display::WindowStatusbar WStatus;
+ typedef display::WindowStatusbar WStatusbar;
- Root(Control* c);
+ Root();
- void init();
+ void init(Control* c);
void cleanup();
- bool get_shutdown_received() { return m_shutdownReceived; }
- void set_shutdown_received(bool v) { m_shutdownReceived = v; }
+ WStatusbar* window_statusbar() { return m_windowStatusbar; }
private:
void setup_keys();
@@ -51,12 +51,10 @@ private:
void receive_read_throttle(int t);
void receive_write_throttle(int t);
- bool m_shutdownReceived;
-
Control* m_control;
DownloadList* m_downloadList;
- WStatus* m_windowStatus;
+ WStatusbar* m_windowStatusbar;
input::Bindings m_bindings;
};
diff --git a/src/utils/task.h b/src/utils/task.h
index 366ba11d..2f468c2e 100644
--- a/src/utils/task.h
+++ b/src/utils/task.h
@@ -28,6 +28,7 @@
namespace utils {
extern TaskScheduler taskScheduler;
+extern TaskScheduler displayScheduler;
}