diff --git a/src/command_ui.cc b/src/command_ui.cc index a5d778e7..d5a6a5c8 100644 --- a/src/command_ui.cc +++ b/src/command_ui.cc @@ -53,8 +53,7 @@ #include "control.h" #include "command_helpers.h" -typedef void (core::ViewManager::*view_cfilter_slot)(const std::string&, const torrent::Object&); -typedef void (core::ViewManager::*view_event_slot)(const std::string&, const std::string&); +typedef void (core::ViewManager::*view_event_slot)(const std::string&, const torrent::Object&); torrent::Object apply_view_filter_on(const torrent::Object::list_type& args) { @@ -76,33 +75,12 @@ apply_view_filter_on(const torrent::Object::list_type& args) { return torrent::Object(); } -torrent::Object -apply_view_cfilter(view_cfilter_slot viewFilterSlot, const torrent::Object::list_type& args) { - if (args.size() != 2) - throw torrent::input_error("Too few arguments."); - - const std::string& name = args.front().as_string(); - - if (name.empty()) - throw torrent::input_error("First argument must be a string."); - - (control->view_manager()->*viewFilterSlot)(name, args.back()); - - return torrent::Object(); -} - torrent::Object apply_view_event(view_event_slot viewFilterSlot, const torrent::Object::list_type& args) { if (args.size() != 2) - throw torrent::input_error("Too few arguments."); - - const std::string& name = args.front().as_string(); - - if (name.empty()) - throw torrent::input_error("First argument must be a string."); - - (control->view_manager()->*viewFilterSlot)(name, args.back().as_string()); + throw torrent::input_error("Wrong argument count."); + (control->view_manager()->*viewFilterSlot)(args.front().as_string(), args.back()); return torrent::Object(); } @@ -472,7 +450,7 @@ torrent::Object cmd_view_persistent(const torrent::Object::string_type& args) { core::View* view = *control->view_manager()->find_throw(args); - if (!view->get_filter().is_empty() || !view->get_event_added().empty() || !view->get_event_removed().empty()) + if (!view->get_filter().is_empty() || !view->event_added().is_empty() || !view->event_removed().is_empty()) throw torrent::input_error("Cannot set modified views as persitent."); view->set_filter("d.views.has=" + args); @@ -546,12 +524,12 @@ initialize_command_ui() { CMD2_ANY_L ("view.list", tr1::bind(&apply_view_list)); CMD2_ANY_LIST("view.set", tr1::bind(&apply_view_set, tr1::placeholders::_2)); - CMD2_ANY_LIST("view.filter", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_filter, tr1::placeholders::_2)); + CMD2_ANY_LIST("view.filter", tr1::bind(&apply_view_event, &core::ViewManager::set_filter, tr1::placeholders::_2)); CMD2_ANY_LIST("view.filter_on", tr1::bind(&apply_view_filter_on, tr1::placeholders::_2)); CMD2_ANY_LIST("view.sort", tr1::bind(&apply_view_sort, tr1::placeholders::_2)); - CMD2_ANY_LIST("view.sort_new", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_sort_new, tr1::placeholders::_2)); - CMD2_ANY_LIST("view.sort_current", tr1::bind(&apply_view_cfilter, &core::ViewManager::set_sort_current, tr1::placeholders::_2)); + CMD2_ANY_LIST("view.sort_new", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_new, tr1::placeholders::_2)); + CMD2_ANY_LIST("view.sort_current", tr1::bind(&apply_view_event, &core::ViewManager::set_sort_current, tr1::placeholders::_2)); CMD2_ANY_LIST("view.event_added", tr1::bind(&apply_view_event, &core::ViewManager::set_event_added, tr1::placeholders::_2)); CMD2_ANY_LIST("view.event_removed", tr1::bind(&apply_view_event, &core::ViewManager::set_event_removed, tr1::placeholders::_2)); diff --git a/src/core/view.cc b/src/core/view.cc index 8f637396..d1969449 100644 --- a/src/core/view.cc +++ b/src/core/view.cc @@ -184,7 +184,7 @@ View::erase(Download* download) { } else { erase_internal(itr); - rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved); + rpc::call_object_nothrow(m_event_removed, rpc::make_target(download)); } } @@ -200,7 +200,7 @@ View::set_visible(Download* download) { base_type::erase(itr); insert_visible(download); - rpc::parse_command_multiple_d_nothrow(download, m_eventAdded); + rpc::call_object_nothrow(m_event_added, rpc::make_target(download)); } void @@ -218,7 +218,7 @@ View::set_not_visible(Download* download) { base_type::erase(itr); base_type::push_back(download); - rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved); + rpc::call_object_nothrow(m_event_removed, rpc::make_target(download)); } void @@ -275,11 +275,13 @@ View::filter() { // done by using a base_type* member variable, and making sure we // set the elements to NULL as we trigger commands on them. Or // perhaps always clear them, thus not throwing anything. - if (!m_eventRemoved.empty()) - std::for_each(changed.begin(), splitChanged, rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventRemoved)); + if (!m_event_removed.is_empty()) + std::for_each(changed.begin(), splitChanged, + tr1::bind(&rpc::call_object_d_nothrow, m_event_removed, tr1::placeholders::_1)); - if (!m_eventAdded.empty()) - std::for_each(splitChanged, changed.end(), rak::bind2nd(std::ptr_fun(&rpc::parse_command_multiple_d_nothrow), m_eventAdded)); + if (!m_event_added.is_empty()) + std::for_each(changed.begin(), splitChanged, + tr1::bind(&rpc::call_object_d_nothrow, m_event_added, tr1::placeholders::_1)); emit_changed(); } @@ -297,7 +299,7 @@ View::filter_download(core::Download* download) { erase_internal(itr); insert_visible(download); - rpc::parse_command_multiple_d_nothrow(download, m_eventAdded); + rpc::call_object_nothrow(m_event_added, rpc::make_target(download)); } else { // This makes sure the download is sorted even if it is @@ -315,7 +317,7 @@ View::filter_download(core::Download* download) { erase_internal(itr); base_type::push_back(download); - rpc::parse_command_multiple_d_nothrow(download, m_eventRemoved); + rpc::call_object_nothrow(m_event_removed, rpc::make_target(download)); } emit_changed(); diff --git a/src/core/view.h b/src/core/view.h index 2488ba75..98d366d3 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -127,10 +127,10 @@ public: void clear_filter_on(); - const std::string& get_event_added() const { return m_eventAdded; } - const std::string& get_event_removed() const { return m_eventRemoved; } - void set_event_added(const std::string& cmd) { m_eventAdded = cmd; } - void set_event_removed(const std::string& cmd) { m_eventRemoved = cmd; } + const torrent::Object& event_added() const { return m_event_added; } + const torrent::Object& event_removed() const { return m_event_removed; } + void set_event_added(const torrent::Object& cmd) { m_event_added = cmd; } + void set_event_removed(const torrent::Object& cmd) { m_event_removed = cmd; } // The time of the last change to the view, semantics of this is // user-dependent. Used by f.ex. ViewManager to decide if it should @@ -171,8 +171,8 @@ private: torrent::Object m_filter; - std::string m_eventAdded; - std::string m_eventRemoved; + torrent::Object m_event_added; + torrent::Object m_event_removed; rak::timer m_lastChanged; diff --git a/src/core/view_manager.h b/src/core/view_manager.h index 1f6c5da7..e2ef1ab2 100644 --- a/src/core/view_manager.h +++ b/src/core/view_manager.h @@ -95,8 +95,8 @@ public: void set_filter(const std::string& name, const torrent::Object& cmd); void set_filter_on(const std::string& name, const filter_args& args); - void set_event_added(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_added(cmd); } - void set_event_removed(const std::string& name, const std::string& cmd) { (*find_throw(name))->set_event_removed(cmd); } + void set_event_added(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_added(cmd); } + void set_event_removed(const std::string& name, const torrent::Object& cmd) { (*find_throw(name))->set_event_removed(cmd); } private: DownloadList* m_list; diff --git a/src/main.cc b/src/main.cc index 905f0ed1..a4b288f4 100644 --- a/src/main.cc +++ b/src/main.cc @@ -293,7 +293,7 @@ main(int argc, char** argv) { "group.insert = seeding,seeding\n" - "session.name.set = \"$cat=$system.hostname=,:,$system.pid=\"\n" + "session.name.set = (cat,(system.hostname),:,(system.pid))\n" // Currently not doing any sorting on main. "view.add = main\n" @@ -308,13 +308,13 @@ main(int argc, char** argv) { "view.add = started\n" "view.filter = started,((false))\n" - "view.event_added = started,\"view.set_not_visible=stopped ;d.state.set=1 ;scheduler.simple.added=\"\n" - "view.event_removed = started,\"view.set_visible=stopped ;scheduler.simple.removed=\"\n" + "view.event_added = started,{(view.set_not_visible,stopped),(d.state.set,1),(scheduler.simple.added)}\n" + "view.event_removed = started,{(view.set_visible,stopped),(scheduler.simple.removed)}\n" "view.add = stopped\n" "view.filter = stopped,((false))\n" - "view.event_added = stopped,\"d.state.set=0 ;view.set_not_visible=started\"\n" - "view.event_removed = stopped,view.set_visible=started\n" + "view.event_added = stopped,{(d.state.set,0),(view.set_not_visible,started)}\n" + "view.event_removed = stopped,((view.set_visible,started))\n" "view.add = complete\n" "view.filter = complete,((d.complete))\n" diff --git a/src/rpc/command_scheduler.cc b/src/rpc/command_scheduler.cc index 4968e8da..779cc4ac 100644 --- a/src/rpc/command_scheduler.cc +++ b/src/rpc/command_scheduler.cc @@ -97,24 +97,7 @@ CommandScheduler::call_item(value_type item) { // removed. try { - if (item->command().is_string()) { - rpc::parse_command_multiple_std(item->command().as_string()); - - } else if (item->command().is_dict_key()) { - // This can/should be optimized... - torrent::Object tmp_command = item->command(); - - // Unquote the root function object so 'parse_command_execute' - // doesn't end up calling it. - // - // TODO: Only call this if mask_function is set? - uint32_t flags = tmp_command.flags() & torrent::Object::mask_function; - tmp_command.unset_flags(torrent::Object::mask_function); - tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function); - - rpc::parse_command_execute(rpc::make_target(), &tmp_command); - rpc::commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj()); - } + rpc::call_object(item->command()); } catch (torrent::input_error& e) { if (m_slotErrorMessage.is_valid()) diff --git a/src/rpc/parse_commands.cc b/src/rpc/parse_commands.cc index 7eba5961..d49e5604 100644 --- a/src/rpc/parse_commands.cc +++ b/src/rpc/parse_commands.cc @@ -239,6 +239,39 @@ parse_command_file(const std::string& path) { return true; } +void +call_object(const torrent::Object& command, target_type target) { + switch (command.type()) { + case torrent::Object::TYPE_STRING: + parse_command_multiple(target, command.as_string().c_str(), command.as_string().c_str() + command.as_string().size()); + break; + + case torrent::Object::TYPE_LIST: + for (torrent::Object::list_const_iterator itr = command.as_list().begin(), last = command.as_list().end(); itr != last; itr++) + call_object(*itr, target); + break; + + case torrent::Object::TYPE_DICT_KEY: + { + // This can/should be optimized... + torrent::Object tmp_command = command; + + // Unquote the root function object so 'parse_command_execute' + // doesn't end up calling it. + // + // TODO: Only call this if mask_function is set? + uint32_t flags = tmp_command.flags() & torrent::Object::mask_function; + tmp_command.unset_flags(torrent::Object::mask_function); + tmp_command.set_flags((flags >> 1) & torrent::Object::mask_function); + + parse_command_execute(make_target(), &tmp_command); + commands.call_command(tmp_command.as_dict_key().c_str(), tmp_command.as_dict_obj(), target); + } + default: + break; + } +} + // // // diff --git a/src/rpc/parse_commands.h b/src/rpc/parse_commands.h index bf3893e6..d4bd83a1 100644 --- a/src/rpc/parse_commands.h +++ b/src/rpc/parse_commands.h @@ -124,6 +124,18 @@ call_command_d_range(const char* key, core::Download* download, torrent::Object: return commands.call_command_d(key, download, rawArgs); } +void call_object(const torrent::Object& command, target_type target = make_target()); + +inline void +call_object_nothrow(const torrent::Object& command, target_type target = make_target()) { + try { call_object(command, target); } catch (torrent::input_error& e) {} +} + +inline void +call_object_d_nothrow(const torrent::Object& command, core::Download* download) { + try { call_object(command, make_target(download)); } catch (torrent::input_error& e) {} +} + // // //