diff --git a/src/core/download.cc b/src/core/download.cc index b56d4319..c2a03848 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -11,7 +11,7 @@ void Download::set_download(torrent::Download d) { m_download = d; - m_connTrackerSucceded = m_download.signal_tracker_succeded(sigc::bind(sigc::mem_fun(*this, &Download::receive_tracker_msg), "^_^")); + m_connTrackerSucceded = m_download.signal_tracker_succeded(sigc::bind(sigc::mem_fun(*this, &Download::receive_tracker_msg), "")); m_connTrackerFailed = m_download.signal_tracker_failed(sigc::mem_fun(*this, &Download::receive_tracker_msg)); } diff --git a/src/core/log.cc b/src/core/log.cc index a48aed0f..5a915b2f 100644 --- a/src/core/log.cc +++ b/src/core/log.cc @@ -16,8 +16,8 @@ Log::push_front(const std::string& msg) { Log::iterator Log::find_older(utils::Timer t) { - return std::find_if(begin(), end(), func::on(func::mem_ptr_ref(&Type::first), - std::bind1st(std::less_equal(), t))); + return std::find_if(begin(), end(), + func::on(func::mem_ptr_ref(&Type::first), std::bind2nd(std::less_equal(), t))); } } diff --git a/src/core/poll.cc b/src/core/poll.cc index 5a5a3680..bd9f50a2 100644 --- a/src/core/poll.cc +++ b/src/core/poll.cc @@ -13,7 +13,7 @@ namespace core { void -Poll::poll() { +Poll::poll(utils::Timer timeout) { FD_ZERO(m_readSet); FD_ZERO(m_writeSet); FD_ZERO(m_exceptSet); @@ -29,15 +29,11 @@ Poll::poll() { m_maxFd = std::max(m_maxFd, n); } - uint64_t t = torrent::get(torrent::TIME_SELECT); - - if (t > 1000000) - t = 1000000; - - timeval timeout = {t / 1000000, t % 1000000}; + timeout = std::min(timeout, utils::Timer(torrent::get(torrent::TIME_SELECT))); + timeval t = timeout.tval(); errno = 0; - m_maxFd = select(m_maxFd + 1, m_readSet, m_writeSet, m_exceptSet, &timeout); + m_maxFd = select(m_maxFd + 1, m_readSet, m_writeSet, m_exceptSet, &t); if (m_maxFd >= 0) { work(); diff --git a/src/core/poll.h b/src/core/poll.h index 9301f120..2044ec39 100644 --- a/src/core/poll.h +++ b/src/core/poll.h @@ -4,6 +4,7 @@ #include #include +#include "utils/timer.h" #include "curl_stack.h" namespace core { @@ -19,7 +20,7 @@ public: Poll() : m_readSet(new fd_set), m_writeSet(new fd_set), m_exceptSet(new fd_set) {} ~Poll() { delete m_readSet; delete m_writeSet; delete m_exceptSet; } - void poll(); + void poll(utils::Timer t); SlotFactory get_http_factory(); diff --git a/src/display/utils.cc b/src/display/utils.cc index 4564def2..28e23e89 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -21,8 +21,11 @@ print_download_status(core::Download* d) { } else if (!d->get_download().is_active()) { str << "Inactive"; - } else { + } else if (!d->get_tracker_msg().empty()) { str << "Tracker: " << d->get_tracker_msg(); + + } else { + str << "---"; } return str.str(); diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index d9f6a0f6..635ac296 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -34,13 +34,13 @@ WindowDownloadList::redraw() { int i = 0; itr = last = *m_focus; - while (i < m_canvas->get_height() - y && !(itr == m_list->begin() && last == m_list->end())) { + while (i < m_canvas->get_height() - y - 3 && !(itr == m_list->begin() && last == m_list->end())) { if (last != m_list->end()) { ++last; i += 3; } - if (itr != m_list->begin() && i < m_canvas->get_height() - y) { + if (itr != m_list->begin() && i < m_canvas->get_height() - y - 3) { --itr; i += 3; } diff --git a/src/display/window_log.cc b/src/display/window_log.cc index 4076e98d..2030d80f 100644 --- a/src/display/window_log.cc +++ b/src/display/window_log.cc @@ -1,7 +1,5 @@ #include "config.h" -#include "core/log.h" - #include "canvas.h" #include "window_log.h" @@ -13,13 +11,19 @@ WindowLog::WindowLog(core::Log* l) : set_active(false); - m_connUpdate = l->signal_update().connect(sigc::mem_fun(*this, &WindowLog::receive_update)); + // We're trying out scheduled tasks instead. + //m_connUpdate = l->signal_update().connect(sigc::mem_fun(*this, &WindowLog::receive_update)); } WindowLog::~WindowLog() { m_connUpdate.disconnect(); } +WindowLog::iterator +WindowLog::find_older() { + return m_log->find_older(utils::Timer::cache() - 10*1000000); +} + void WindowLog::redraw() { if (!is_dirty()) @@ -31,18 +35,22 @@ WindowLog::redraw() { int pos = 0; - for (core::Log::iterator itr = m_log->begin(), end = m_log->end(); itr != end; ++itr) - m_canvas->print(0, pos++, "Log: %s", itr->second.c_str()); + //m_canvas->print(std::max(0, (int)m_canvas->get_width() / 2 - 5), pos++, "*** Log ***"); + m_canvas->print(0, 0, "___"); + + for (core::Log::iterator itr = m_log->begin(), end = find_older(); itr != end && pos < m_minHeight; ++itr) + m_canvas->print(0, pos++, ": %s", itr->second.c_str()); } void WindowLog::receive_update() { - int newHeight = std::min(m_log->size(), 5); + iterator itr = find_older(); + int h = std::distance(m_log->begin(), itr); - if (newHeight != m_minHeight) { - m_minHeight = newHeight; + if (h != m_minHeight) { + set_active(h != 0); - set_active(m_minHeight != 0); + m_minHeight = h; m_slotAdjust(); } diff --git a/src/display/window_log.h b/src/display/window_log.h index 5529529d..9c386031 100644 --- a/src/display/window_log.h +++ b/src/display/window_log.h @@ -3,24 +3,26 @@ #include -#include "window.h" +#include "core/log.h" -namespace core { - class Log; -} +#include "window.h" namespace display { class WindowLog : public Window { public: + typedef core::Log::iterator iterator; + WindowLog(core::Log* l); ~WindowLog(); virtual void redraw(); -private: void receive_update(); +private: + inline iterator find_older(); + core::Log* m_log; sigc::connection m_connUpdate; }; diff --git a/src/main.cc b/src/main.cc index ace25d66..1f7f8f23 100644 --- a/src/main.cc +++ b/src/main.cc @@ -72,20 +72,6 @@ do_shutdown(ui::Control* c) { start_shutdown = false; } -void -test_dir(const std::string& s) { - utils::Directory d(s); - - d.update(); - - std::cout << "Listing dir \"" << s << '"' << std::endl; - - for (utils::Directory::iterator itr = d.begin(); itr != d.end(); ++itr) - std::cout << '"' << *itr << '"' << std::endl; - - exit(0); -} - int parse_options(ui::Control* c, int argc, char** argv) { OptionParser optionParser; @@ -126,11 +112,21 @@ register_main_keys(ui::Control* c, input::Bindings* b) { (*b)['\x11'] = sigc::ptr_fun(&set_shutdown); } +void +initialize_core(ui::Control* c) { + c->get_core().get_poll().slot_read_stdin(sigc::mem_fun(c->get_input(), &input::Manager::pressed)); + c->get_core().get_poll().slot_select_interrupted(sigc::ptr_fun(display::Canvas::do_update)); + + c->get_core().initialize(); +} + int main(int argc, char** argv) { ui::Control uiControl; input::Bindings inputMain; + utils::Timer::update(); + try { register_signals(&uiControl); @@ -147,10 +143,7 @@ main(int argc, char** argv) { register_main_keys(&uiControl, &inputMain); - uiControl.get_core().get_poll().slot_read_stdin(sigc::mem_fun(uiControl.get_input(), &input::Manager::pressed)); - uiControl.get_core().get_poll().slot_select_interrupted(sigc::ptr_fun(display::Canvas::do_update)); - - uiControl.get_core().initialize(); + initialize_core(&uiControl); load_session_torrents(&uiControl); load_arg_torrents(&uiControl, argv + firstArg, argv + argc); @@ -162,10 +155,11 @@ main(int argc, char** argv) { do_shutdown(&uiControl); utils::Timer::update(); - + utils::TaskSchedule::perform(utils::Timer::cache()); + uiControl.get_display().do_update(); - uiControl.get_core().get_poll().poll(); + uiControl.get_core().get_poll().poll(utils::TaskSchedule::get_timeout()); } display::Canvas::cleanup(); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 82d30d8f..b2a9f54d 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -28,6 +28,7 @@ DownloadList::DownloadList(Control* c) : m_textInput(new WInput(new input::TextInput)), m_windowHttpQueue(new WHttp(&c->get_core().get_http_queue())), + m_taskUpdate(sigc::mem_fun(*this, &DownloadList::task_update)), m_download(NULL), m_focus(c->get_core().get_download_list().end()), m_control(c), @@ -55,6 +56,8 @@ DownloadList::~DownloadList() { void DownloadList::activate() { + m_taskUpdate.insert(utils::Timer::cache() + 1000000); + m_textInput->set_active(false); m_control->get_input().push_front(m_bindings); @@ -69,6 +72,8 @@ DownloadList::activate() { void DownloadList::disable() { + m_taskUpdate.remove(); + if (m_textInput->is_active()) { m_textInput->get_input()->clear(); receive_exit_input(); @@ -191,6 +196,13 @@ DownloadList::receive_exit_input() { m_bindings->erase(KEY_ENTER); } +void +DownloadList::task_update() { + m_windowLog->receive_update(); + + m_taskUpdate.insert(utils::Timer::cache() + 1000000); +} + void DownloadList::bind_keys(input::Bindings* b) { (*b)['a'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_throttle), 1); diff --git a/src/ui/download_list.h b/src/ui/download_list.h index af0546d1..5454bb1b 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -3,6 +3,8 @@ #include +#include "utils/task.h" + namespace display { class WindowDownloadList; class WindowHttpQueue; @@ -60,6 +62,8 @@ private: void receive_view_input(); void receive_exit_input(); + void task_update(); + void bind_keys(input::Bindings* b); void mark_dirty(); @@ -71,6 +75,8 @@ private: WInput* m_textInput; WHttp* m_windowHttpQueue; + utils::Task m_taskUpdate; + Download* m_download; DList* m_list; diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index fc68ba42..0bc35760 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -6,6 +6,9 @@ libsub_utils_a_SOURCES = \ functional.h \ parse.cc \ parse.h \ + task.h \ + task_schedule.cc \ + task_schedule.h \ timer.h INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) diff --git a/src/utils/task.h b/src/utils/task.h new file mode 100644 index 00000000..18345bf9 --- /dev/null +++ b/src/utils/task.h @@ -0,0 +1,56 @@ +#ifndef RTORRENT_UTILS_TASK_H +#define RTORRENT_UTILS_TASK_H + +#include + +#include "timer.h" +#include "task_schedule.h" + +namespace utils { + +class Task { +public: + typedef sigc::slot Slot; + + Task(Slot s = Slot()) : m_slot(s) { clear_iterator(); } + ~Task() { remove(); } + + bool is_scheduled() { return m_itr != TaskSchedule::end(); } + + void set_slot(Slot s) { m_slot = s; } + Slot& get_slot() { return m_slot; } + + Timer get_time() { return m_time; } + + void insert(Timer t) { + remove(); + + m_time = t; + m_itr = TaskSchedule::insert(this); + } + + void remove() { + if (m_itr != TaskSchedule::end()) { + TaskSchedule::erase(m_itr); + clear_iterator(); + } + } + +protected: + friend class TaskSchedule; + + TaskSchedule::iterator get_iterator() { return m_itr; } + void clear_iterator() { m_itr = TaskSchedule::end(); } + +private: + Task(const Task&); + void operator () (const Task&); + + Timer m_time; + TaskSchedule::iterator m_itr; + Slot m_slot; +}; + +} + +#endif diff --git a/src/utils/task_schedule.cc b/src/utils/task_schedule.cc new file mode 100644 index 00000000..7692b623 --- /dev/null +++ b/src/utils/task_schedule.cc @@ -0,0 +1,54 @@ +#include "config.h" + +#include +#include + +#include "task.h" +#include "task_schedule.h" + +namespace utils { + +TaskSchedule::Container TaskSchedule::m_container; + +// Remove this, replace with stuff. +struct task_comp { + task_comp(Timer t) : m_time(t) {} + + bool operator () (Task* t) { + return m_time <= t->get_time(); + } + + Timer m_time; +}; + +inline void +TaskSchedule::execute_task(Task* t) { + t->clear_iterator(); + t->get_slot()(); +} + +void +TaskSchedule::perform(Timer t) { + Container c; + + c.splice(c.begin(), c, m_container.begin(), std::find_if(m_container.begin(), m_container.end(), task_comp(t))); + + std::for_each(c.begin(), c.end(), std::ptr_fun(&TaskSchedule::execute_task)); +} + +Timer +TaskSchedule::get_timeout() { + if (!m_container.empty()) + return std::max(m_container.front()->get_time() - Timer::current(), Timer()); + else + return Timer((int64_t)(1 << 30) * 1000000); +} + +TaskSchedule::iterator +TaskSchedule::insert(Task* t) { + iterator itr = std::find_if(m_container.begin(), m_container.end(), task_comp(t->get_time())); + + return m_container.insert(itr, t); +} + +} diff --git a/src/utils/task_schedule.h b/src/utils/task_schedule.h new file mode 100644 index 00000000..78de0b52 --- /dev/null +++ b/src/utils/task_schedule.h @@ -0,0 +1,37 @@ +#ifndef RTORRENT_UTILS_TASK_SCHEDULE_H +#define RTORRENT_UTILS_TASK_SCHEDULE_H + +#include + +#include "timer.h" + +namespace utils { + +class Task; + +class TaskSchedule { +public: + friend class Task; + + typedef std::list Container; + typedef Container::iterator iterator; + + static void perform(Timer t); + + static Timer get_timeout(); + +protected: + static iterator end() { return m_container.end(); } + + static iterator insert(Task* t); + static void erase(iterator itr) { m_container.erase(itr); } + +private: + static inline void execute_task(Task* t); + + static Container m_container; +}; + +} + +#endif