From 8fe4f70d9acc740ddfac5e83b42fc98ef4a7b9f1 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sun, 7 Jul 2013 13:54:56 +0300 Subject: [PATCH] Lots of dispatch refactoring --- include/core/dispatch.hpp | 191 ++------------ include/library/dispatch.hpp | 135 ++++++++++ .../platform/wxwidgets/window_mainwindow.hpp | 5 + src/core/audioapi.cpp | 2 +- src/core/controller.cpp | 16 +- src/core/controllerframe.cpp | 6 +- src/core/dispatch.cpp | 249 +++--------------- src/core/framebuffer.cpp | 4 +- src/core/inthread.cpp | 14 +- src/core/loadlib.cpp | 2 +- src/core/mainloop.cpp | 63 +++-- src/core/memorywatch.cpp | 2 +- src/core/moviedata.cpp | 5 +- src/core/project.cpp | 5 +- src/core/subtitles.cpp | 4 +- src/core/window.cpp | 38 +-- src/library/dispatch.cpp | 7 + src/platform/wxwidgets/editor-authors.cpp | 3 +- src/platform/wxwidgets/editor-autohold.cpp | 83 +++--- src/platform/wxwidgets/editor-movie.cpp | 5 +- src/platform/wxwidgets/editor-subtitles.cpp | 19 +- src/platform/wxwidgets/editor-tasinput.cpp | 40 ++- src/platform/wxwidgets/editor-voicesub.cpp | 27 +- src/platform/wxwidgets/mainwindow.cpp | 48 +--- src/platform/wxwidgets/vumeter.cpp | 27 +- 25 files changed, 350 insertions(+), 650 deletions(-) create mode 100644 include/library/dispatch.hpp create mode 100644 src/library/dispatch.cpp diff --git a/include/core/dispatch.hpp b/include/core/dispatch.hpp index 6df24f04..eae2f055 100644 --- a/include/core/dispatch.hpp +++ b/include/core/dispatch.hpp @@ -3,6 +3,7 @@ #include "core/keymapper.hpp" #include "library/framebuffer.hpp" +#include "library/dispatch.hpp" #include #include @@ -101,95 +102,6 @@ public: * Destroy object. */ virtual ~information_dispatch() throw(); -/** - * Window close event received (this is not emulator close!) - * - * The default handler does nothing. - */ - virtual void on_close(); -/** - * Call all on_close() handlers. - */ - static void do_close() throw(); -/** - * Sound mute/unmute status might have been changed. - * - * The default handler does nothing. - * - * Parameter unmuted: If true, the sound is now enabled. If false, the sound is now disabled. - */ - virtual void on_sound_unmute(bool unmuted); -/** - * Call all on_sound_unmute() handlers. - */ - static void do_sound_unmute(bool unmuted) throw(); -/** - * Sound device might have been changed. - * - * The default handler does nothing. - * - * Parameter dev: The device name sound is now playing (if enabled) from. - */ - virtual void on_sound_change(std::pair dev); -/** - * Call all on_sound_change() handlers. - */ - static void do_sound_change(std::pair dev) throw(); -/** - * Emulator mode might have been changed. - * - * The default handler does nothing. - * - * Parameter readonly: True if readonly mode is now active, false if now in readwrite mode. - */ - virtual void on_mode_change(bool readonly); -/** - * Call all on_mode_change() handlers. - */ - static void do_mode_change(bool readonly) throw(); -/** - * Autohold on button might have been changed. - * - * The default handler does nothing. - * - * Parameter port: The port. - * Parameter controller: The controller - * Parameter ctrlnum: Physical control number (0-15). - * Parameter newstate: True if autohold is now active, false if autohold is now inactive. - */ - virtual void on_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate); -/** - * Call all on_autohold_update() handlers. - */ - static void do_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate) throw(); -/** - * Autofire on button might have been changed. - * - * The default handler does nothing. - * - * Parameter port: The port. - * Parameter controller: The controller - * Parameter ctrlnum: Physical control number (0-15). - * Parameter duty: Duty cycle. - * Parameter cyclelen: Cycle length. - */ - virtual void on_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen); -/** - * Call all on_autohold_update() handlers. - */ - static void do_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen) throw(); -/** - * Controller configuration may have been changed. - * - * The default handler does nothing. - */ - virtual void on_autohold_reconfigure(); -/** - * Call all on_autohold_reconfigure() handlers. - */ - static void do_autohold_reconfigure() throw(); /** * A frame has been received. * @@ -318,38 +230,6 @@ public: * Get name of target. */ const std::string& get_name() throw(); -/** - * Render buffer needs to be (possibly) resized, so that graphics plugin can update the mappings. - * - * Default implementation does nothing. - * - * parameter scr: The render buffer object. - */ - virtual void on_set_screen(framebuffer& scr); -/** - * Call on_set_screen on all objects. - */ - static void do_set_screen(framebuffer& scr) throw(); -/** - * Notify that new frame is available. - * - * Default implementation does nothing. - */ - virtual void on_screen_update(); -/** - * Call on_screen_update() in all objects. - */ - static void do_screen_update() throw(); -/** - * Notify that status buffer has been updated. - * - * Default implementation does nothing. - */ - virtual void on_status_update(); -/** - * Call on_status_update() in all objects. - */ - static void do_status_update() throw(); /** * Notify that some dumper has attached, deattached, popped into existence or disappeared. * @@ -360,57 +240,6 @@ public: * Call on_dumper_update on on all objects. */ static void do_dumper_update() throw(); -/** - * Notify that core changed. - * - * Default implementation does nothing. - */ - virtual void on_core_change(); -/** - * Call on_core_change on on all objects. - */ - static void do_core_change() throw(); -/** - * Notify that there is a new core. - * - * Default implementation does nothing. - */ - virtual void on_new_core(); -/** - * Call on_new_core on on all objects. - */ - static void do_new_core() throw(); -/** - * Notify about changes to voice streams. - * - * Default implementation does nothing. - */ - virtual void on_voice_stream_change(); -/** - * Call on_voice_stream_change on all objects. - */ - static void do_voice_stream_change() throw(); -/** - * Notify about changes to subtitles. - * - * Default implementation does nothing. - */ - virtual void on_subtitle_change(); -/** - * Call on_subtitle_change on all objects. - */ - static void do_subtitle_change() throw(); -/** - * Notify about changes to VU levels. - * - * Default implementation does nothing. - */ - virtual void on_vu_change(); -/** - * Call on_vu_change on all objects. - */ - static void do_vu_change() throw(); - protected: /** * Call to indicate this target is interested in sound sample data. @@ -424,4 +253,22 @@ private: bool notified_as_dumper; }; +void dispatch_set_error_streams(std::ostream* stream); + +extern struct dispatcher<> notify_autohold_reconfigure; +extern struct dispatcher notify_autohold_update; +extern struct dispatcher notify_autofire_update; +extern struct dispatcher<> notify_close; +extern struct dispatcher&> notify_set_screen; +extern struct dispatcher> notify_sound_change; +extern struct dispatcher<> notify_screen_update; +extern struct dispatcher<> notify_status_update; +extern struct dispatcher notify_sound_unmute; +extern struct dispatcher notify_mode_change; +extern struct dispatcher<> notify_core_change; +extern struct dispatcher<> notify_new_core; +extern struct dispatcher<> notify_voice_stream_change; +extern struct dispatcher<> notify_vu_change; +extern struct dispatcher<> notify_subtitle_change; + #endif diff --git a/include/library/dispatch.hpp b/include/library/dispatch.hpp new file mode 100644 index 00000000..b2fd3f36 --- /dev/null +++ b/include/library/dispatch.hpp @@ -0,0 +1,135 @@ +#ifndef _library__dispatch__hpp__included__ +#define _library__dispatch__hpp__included__ + +#include +#include +#include +#include +#include +#include "threadtypes.hpp" + +mutex_class& dispatch_global_init_lock(); + +template struct dispatcher; + +template struct dispatch_target +{ + dispatch_target() + { + src = NULL; + fn = dummy; + } + inline ~dispatch_target(); + inline void set(dispatcher& d, std::function _fn); +private: + static void dummy(T... args) {}; + void set_source(dispatcher* d) { src = d; } + void call(T... args) { fn(args...); } + dispatcher* src; + std::function fn; + friend class dispatcher; +}; + +template struct dispatcher +{ + dispatcher(const char* _name) + { + init(); + name = _name; + } + ~dispatcher() + { + delete _targets; + delete lck; + lck = NULL; + } + void operator()(T... args) + { + init(); + uint64_t k = 0; + typename std::map*>::iterator i; + lck->lock(); + i = targets().lower_bound(k); + while(i != targets().end()) { + k = i->first + 1; + dispatch_target* t = i->second; + lck->unlock(); + try { + t->call(args...); + } catch(std::exception& e) { + (*errstrm) << name << ": Error in handler: " << e.what() << std::endl; + } + lck->lock(); + i = targets().lower_bound(k); + } + lck->unlock(); + } + void connect(dispatch_target& target) + { + init(); + umutex_class h(*lck); + targets()[next_cbseq++] = ⌖ + target.set_source(this); + } + void disconnect(dispatch_target& target) + { + init(); + if(!lck) + return; + umutex_class h(*lck); + for(auto i = targets().begin(); i != targets().end(); i++) + if(i->second == &target) { + targets().erase(i); + break; + } + target.set_source(NULL); + } + void errors_to(std::ostream* to) + { + errstrm = to ? to : &std::cerr; + } +private: + void init() + { + if(inited) + return; + umutex_class h(dispatch_global_init_lock()); + if(inited) + return; + errstrm = &std::cerr; + next_cbseq = 0; + name = "(unknown)"; + _targets = NULL; + lck = new mutex_class; + inited = true; + } + mutex_class* lck; + std::map*>& targets() + { + if(!_targets) _targets = new std::map*>; + return *_targets; + } + std::map*>* _targets; + uint64_t next_cbseq; + std::ostream* errstrm; + const char* name; + bool inited; + dispatcher(const dispatcher&); + dispatcher& operator=(const dispatcher&); +}; + +template dispatch_target::~dispatch_target() +{ + if(src) + src->disconnect(*this); +} + +template void dispatch_target::set(dispatcher& d, std::function _fn) +{ + fn = _fn; + src = &d; + if(src) + src->connect(*this); +} + +#endif diff --git a/include/platform/wxwidgets/window_mainwindow.hpp b/include/platform/wxwidgets/window_mainwindow.hpp index dd64a66b..5420f1c4 100644 --- a/include/platform/wxwidgets/window_mainwindow.hpp +++ b/include/platform/wxwidgets/window_mainwindow.hpp @@ -3,6 +3,7 @@ #include "platform/wxwidgets/window_status.hpp" #include "platform/wxwidgets/menu_recent.hpp" +#include "library/dispatch.hpp" #include @@ -65,6 +66,10 @@ private: void* sounddev1; void* sounddev2; void* dmenu; + struct dispatch_target<> corechange; + struct dispatch_target<> newcore; + struct dispatch_target unmuted; + struct dispatch_target modechange; }; #endif diff --git a/src/core/audioapi.cpp b/src/core/audioapi.cpp index c17a16ac..6e494bc1 100644 --- a/src/core/audioapi.cpp +++ b/src/core/audioapi.cpp @@ -525,7 +525,7 @@ void audioapi_vumeter::update_vu() accumulator = 0; samples = 0; } - information_dispatch::do_vu_change(); + notify_vu_change(); } //VU values. diff --git a/src/core/controller.cpp b/src/core/controller.cpp index a33a4086..5ef24505 100644 --- a/src/core/controller.cpp +++ b/src/core/controller.cpp @@ -302,7 +302,7 @@ namespace if(lua_callback_do_button(x.port, x.controller, x.bind.control1, nstate ? "hold" : "unhold")) return; controls.autohold2(x.port, x.controller, x.bind.control1, nstate); - information_dispatch::do_autohold_update(x.port, x.controller, x.bind.control1, nstate); + notify_autohold_update(x.port, x.controller, x.bind.control1, nstate); } else if(mode == 2) { //Framehold. bool nstate = controls.framehold2(x.port, x.controller, x.bind.control1) ^ newstate; @@ -418,14 +418,14 @@ namespace << duty << " " << cyclelen).str().c_str())) return; controls.autofire2(z.port, z.controller, z.bind.control1, duty, cyclelen); - information_dispatch::do_autofire_update(z.port, z.controller, z.bind.control1, duty, + notify_autofire_update(z.port, z.controller, z.bind.control1, duty, cyclelen); } else if(mode == 0 || (mode == -1 && afire.first != 0)) { //Turn off. if(lua_callback_do_button(z.port, z.controller, z.bind.control1, "autofire")) return; controls.autofire2(z.port, z.controller, z.bind.control1, 0, 1); - information_dispatch::do_autofire_update(z.port, z.controller, z.bind.control1, 0, 1); + notify_autofire_update(z.port, z.controller, z.bind.control1, 0, 1); } } @@ -501,16 +501,14 @@ namespace controls.do_macro(a, 2); }); - class new_core_snoop : public information_dispatch + class new_core_snoop { public: - new_core_snoop() : information_dispatch("controller-newcore") + new_core_snoop() { + ncore.set(notify_new_core, []() { init_buttonmap(); }); } - void on_new_core() - { - init_buttonmap(); - } + struct dispatch_target<> ncore; } coresnoop; } diff --git a/src/core/controllerframe.cpp b/src/core/controllerframe.cpp index 8d9600bf..448fc46a 100644 --- a/src/core/controllerframe.cpp +++ b/src/core/controllerframe.cpp @@ -63,7 +63,7 @@ void controller_state::analog(unsigned port, unsigned controller, unsigned contr void controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid, bool newstate) throw() { _autohold.axis3(port, controller, pbid, newstate ? 1 : 0); - information_dispatch::do_autohold_update(port, controller, pbid, newstate); + notify_autohold_update(port, controller, pbid, newstate); } bool controller_state::autohold2(unsigned port, unsigned controller, unsigned pbid) throw() @@ -190,7 +190,7 @@ void controller_state::set_ports(const port_type_set& ptype) throw(std::runtime_ _autohold = _autohold.blank_frame(); } reread_active_buttons(); - information_dispatch::do_autohold_reconfigure(); + notify_autohold_reconfigure(); } controller_frame controller_state::get_blank() throw() @@ -361,7 +361,7 @@ void controller_state::do_macro(const std::string& a, int mode) { } end: update_movie_state(); - information_dispatch::do_status_update(); + notify_status_update(); } std::set controller_state::active_macro_set() diff --git a/src/core/dispatch.cpp b/src/core/dispatch.cpp index a15769b1..e04634e1 100644 --- a/src/core/dispatch.cpp +++ b/src/core/dispatch.cpp @@ -127,106 +127,6 @@ information_dispatch::~information_dispatch() throw() } } -void information_dispatch::on_close() -{ - //Do nothing. -} - -void information_dispatch::do_close() throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_close(); - END_EH_BLOCK(i, "on_close"); - } -} - -void information_dispatch::on_sound_unmute(bool unmuted) -{ - //Do nothing. -} - -void information_dispatch::do_sound_unmute(bool unmuted) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_sound_unmute(unmuted); - END_EH_BLOCK(i, "on_sound_unmute"); - } -} - -void information_dispatch::on_sound_change(std::pair dev) -{ - //Do nothing. -} - -void information_dispatch::do_sound_change(std::pair dev) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_sound_change(dev); - END_EH_BLOCK(i, "on_sound_change"); - } -} - -void information_dispatch::on_mode_change(bool readonly) -{ - //Do nothing. -} - -void information_dispatch::do_mode_change(bool readonly) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_mode_change(readonly); - END_EH_BLOCK(i, "on_mode_change"); - } -} - -void information_dispatch::on_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate) -{ - //Do nothing. -} - -void information_dispatch::do_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_autohold_update(port, controller, ctrlnum, newstate); - END_EH_BLOCK(i, "on_autohold_update"); - } -} - -void information_dispatch::on_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen) -{ - //Do nothing. -} - -void information_dispatch::do_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_autofire_update(port, controller, ctrlnum, duty, cyclelen); - END_EH_BLOCK(i, "on_autofire_update"); - } -} - -void information_dispatch::on_autohold_reconfigure() -{ - //Do nothing. -} - -void information_dispatch::do_autohold_reconfigure() throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_autohold_reconfigure(); - END_EH_BLOCK(i, "on_autohold_reconfigure"); - } -} - void information_dispatch::on_frame(struct framebuffer_raw& _frame, uint32_t fps_n, uint32_t fps_d) { //Do nothing. @@ -399,48 +299,6 @@ void information_dispatch::update_dumpers(bool nocalls) throw() } } -void information_dispatch::on_set_screen(framebuffer& scr) -{ - //Do nothing. -} - -void information_dispatch::do_set_screen(framebuffer& scr) throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_set_screen(scr); - END_EH_BLOCK(i, "on_set_screen"); - } -} - -void information_dispatch::on_screen_update() -{ - //Do nothing. -} - -void information_dispatch::do_screen_update() throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_screen_update(); - END_EH_BLOCK(i, "on_screen_update"); - } -} - -void information_dispatch::on_status_update() -{ - //Do nothing. -} - -void information_dispatch::do_status_update() throw() -{ - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_status_update(); - END_EH_BLOCK(i, "on_status_update"); - } -} - void information_dispatch::enable_send_sound() throw(std::bad_alloc) { dispatch_audio().push_back(this); @@ -462,82 +320,37 @@ void information_dispatch::do_dumper_update() throw() } } -void information_dispatch::on_core_change() +void dispatch_set_error_streams(std::ostream* stream) { - //Do nothing. + notify_autofire_update.errors_to(stream); + notify_autohold_reconfigure.errors_to(stream); + notify_autohold_update.errors_to(stream); + notify_close.errors_to(stream); + notify_core_change.errors_to(stream); + notify_mode_change.errors_to(stream); + notify_new_core.errors_to(stream); + notify_screen_update.errors_to(stream); + notify_set_screen.errors_to(stream); + notify_sound_change.errors_to(stream); + notify_sound_unmute.errors_to(stream); + notify_status_update.errors_to(stream); + notify_subtitle_change.errors_to(stream); + notify_voice_stream_change.errors_to(stream); + notify_vu_change.errors_to(stream); } -void information_dispatch::do_core_change() throw() -{ - if(in_global_ctors()) - return; - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_core_change(); - END_EH_BLOCK(i, "on_core_change"); - } -} - -void information_dispatch::on_new_core() -{ - //Do nothing. -} - -void information_dispatch::do_new_core() throw() -{ - if(in_global_ctors()) - return; - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_new_core(); - END_EH_BLOCK(i, "on_new_core"); - } -} - -void information_dispatch::on_voice_stream_change() -{ - //Do nothing. -} - -void information_dispatch::do_voice_stream_change() throw() -{ - if(in_global_ctors()) - return; - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_voice_stream_change(); - END_EH_BLOCK(i, "on_voice_stream_change"); - } -} - -void information_dispatch::on_subtitle_change() -{ - //Do nothing. -} - -void information_dispatch::do_subtitle_change() throw() -{ - if(in_global_ctors()) - return; - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_subtitle_change(); - END_EH_BLOCK(i, "on_subtitle_change"); - } -} - -void information_dispatch::on_vu_change() -{ - //Do nothing. -} - -void information_dispatch::do_vu_change() throw() -{ - if(in_global_ctors()) - return; - for(auto& i : dispatch()) { - START_EH_BLOCK - i->on_vu_change(); - END_EH_BLOCK(i, "on_vu_change"); - } -} +struct dispatcher<> notify_autohold_reconfigure("autohold_reconfigure"); +struct dispatcher notify_autohold_update("autohold_update"); +struct dispatcher notify_autofire_update("autofire_update"); +struct dispatcher<> notify_close("notify_close"); +struct dispatcher&> notify_set_screen("set_screen"); +struct dispatcher> notify_sound_change("sound_change"); +struct dispatcher<> notify_screen_update("screen_update"); +struct dispatcher<> notify_status_update("status_update"); +struct dispatcher notify_sound_unmute("sound_unmute"); +struct dispatcher notify_mode_change("mode_change"); +struct dispatcher<> notify_core_change("core_change"); +struct dispatcher<> notify_new_core("new_core"); +struct dispatcher<> notify_voice_stream_change("voice_stream_change"); +struct dispatcher<> notify_vu_change("vu_change"); +struct dispatcher<> notify_subtitle_change("subtitle_change"); diff --git a/src/core/framebuffer.cpp b/src/core/framebuffer.cpp index ff8a9889..5fe8b6e6 100644 --- a/src/core/framebuffer.cpp +++ b/src/core/framebuffer.cpp @@ -190,7 +190,7 @@ void redraw_framebuffer(framebuffer_raw& todraw, bool no_lua, bool spontaneous) ri.tgap = lrc.top_gap; ri.bgap = lrc.bottom_gap; buffering.end_write(); - information_dispatch::do_screen_update(); + notify_screen_update(); last_redraw_no_lua = no_lua; } @@ -212,7 +212,7 @@ void render_framebuffer() main_screen.set_origin(ri.lgap, ri.tgap); main_screen.copy_from(ri.fbuf, ri.hscl, ri.vscl); ri.rq.run(main_screen); - information_dispatch::do_set_screen(main_screen); + notify_set_screen(main_screen); //We would want divide by 2, but we'll do it ourselves in order to do mouse. keyboard_key* mouse_x = lsnes_kbd.try_lookup_key("mouse_x"); keyboard_key* mouse_y = lsnes_kbd.try_lookup_key("mouse_y"); diff --git a/src/core/inthread.cpp b/src/core/inthread.cpp index 2bc31793..f6b11c1a 100644 --- a/src/core/inthread.cpp +++ b/src/core/inthread.cpp @@ -1525,7 +1525,7 @@ out: messages << "Can't add stream: " << e.what() << std::endl; active_stream->put_ref(); } - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } else active_stream->put_ref(); active_stream = NULL; @@ -1800,7 +1800,7 @@ uint64_t voicesub_import_stream(uint64_t ts, const std::string& filename, extern throw; } st->unlock(); //Not locked. - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); return id; } @@ -1810,7 +1810,7 @@ void voicesub_delete_stream(uint64_t id) if(!current_collection) throw std::runtime_error("No collection loaded"); current_collection->delete_stream(id); - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } void voicesub_export_superstream(const std::string& filename) @@ -1834,7 +1834,7 @@ void voicesub_load_collection(const std::string& filename) if(current_collection) delete current_collection; current_collection = newc; - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } void voicesub_unload_collection() @@ -1843,7 +1843,7 @@ void voicesub_unload_collection() if(current_collection) delete current_collection; current_collection = NULL; - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } void voicesub_alter_timebase(uint64_t id, uint64_t ts) @@ -1852,7 +1852,7 @@ void voicesub_alter_timebase(uint64_t id, uint64_t ts) if(!current_collection) throw std::runtime_error("No collection loaded"); current_collection->alter_stream_timebase(id, ts); - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } float voicesub_get_gain(uint64_t id) @@ -1872,7 +1872,7 @@ void voicesub_set_gain(uint64_t id, float gain) if(_gain < -32768 || _gain > 32767) throw std::runtime_error("Gain out of range (+-128dB)"); current_collection->alter_stream_gain(id, _gain); - information_dispatch::do_voice_stream_change(); + notify_voice_stream_change(); } double voicesub_ts_seconds(uint64_t ts) diff --git a/src/core/loadlib.cpp b/src/core/loadlib.cpp index 9a68a844..b9c7a989 100644 --- a/src/core/loadlib.cpp +++ b/src/core/loadlib.cpp @@ -13,7 +13,7 @@ void handle_post_loadlibrary() { if(new_core_flag) { new_core_flag = false; - information_dispatch::do_new_core(); + notify_new_core(); } } diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index cf4df261..35beb5b2 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -245,9 +245,7 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo } location_special = SPECIAL_FRAME_START; update_movie_state(); - } - information_dispatch::do_status_update(); platform::flush_command_queue(); controller_frame tmp = controls.get(movb.get_movie().get_current_frame()); our_rom->rtype->pre_emulate_frame(tmp); //Preset controls, the lua will override if needed. @@ -300,7 +298,7 @@ namespace our_movie.romimg_sha256[i] = ""; our_movie.romxml_sha256[i] = ""; } - information_dispatch::do_core_change(); + notify_core_change(); return true; } @@ -351,7 +349,7 @@ namespace return false; } messages << "Using core: " << our_rom->rtype->get_core_identifier() << std::endl; - information_dispatch::do_core_change(); + notify_core_change(); return true; } @@ -366,7 +364,6 @@ namespace save_jukebox_pointer = 0; } update_movie_state(); - information_dispatch::do_status_update(); } }; } @@ -459,6 +456,7 @@ void update_movie_state() c.display(pindex.first, pindex.second, buffer); _status.set((stringfmt() << "P" << (i + 1)).str(), buffer); } + notify_status_update(); } uint64_t audio_irq_time; @@ -593,7 +591,6 @@ namespace if(save_jukebox_pointer >= jukebox_size) save_jukebox_pointer = 0; update_movie_state(); - information_dispatch::do_status_update(); }); function_ptr_command<> save_jukebox_next(lsnes_cmd, "cycle-jukebox-forward", "Cycle save jukebox forwards", @@ -608,7 +605,6 @@ namespace if(save_jukebox_pointer >= jukebox_size) save_jukebox_pointer = 0; update_movie_state(); - information_dispatch::do_status_update(); }); function_ptr_command<> load_jukebox(lsnes_cmd, "load-jukebox", "Load save from jukebox", @@ -778,19 +774,17 @@ namespace "Syntax: set-rwmode\nSwitches to read/write mode\n", []() throw(std::bad_alloc, std::runtime_error) { movb.get_movie().readonly_mode(false); - information_dispatch::do_mode_change(false); + notify_mode_change(false); lua_callback_do_readwrite(); update_movie_state(); - information_dispatch::do_status_update(); }); function_ptr_command<> set_romode(lsnes_cmd, "set-romode", "Switch to read-only mode", "Syntax: set-romode\nSwitches to read-only mode\n", []() throw(std::bad_alloc, std::runtime_error) { movb.get_movie().readonly_mode(true); - information_dispatch::do_mode_change(true); + notify_mode_change(true); update_movie_state(); - information_dispatch::do_status_update(); }); function_ptr_command<> toggle_rwmode(lsnes_cmd, "toggle-rwmode", "Toggle read/write mode", @@ -798,11 +792,10 @@ namespace []() throw(std::bad_alloc, std::runtime_error) { bool c = movb.get_movie().readonly_mode(); movb.get_movie().readonly_mode(!c); - information_dispatch::do_mode_change(!c); + notify_mode_change(!c); if(c) lua_callback_do_readwrite(); update_movie_state(); - information_dispatch::do_status_update(); }); function_ptr_command<> repaint(lsnes_cmd, "repaint", "Redraw the screen", @@ -966,7 +959,26 @@ namespace class mywindowcallbacks : public information_dispatch { public: - mywindowcallbacks() : information_dispatch("mainloop-window-callbacks") {} + mywindowcallbacks() : information_dispatch("mainloop-window-callbacks") + { + closenotify.set(notify_close, [this]() { + if(on_quit_prompt) { + amode = ADVANCE_QUIT; + platform::set_paused(false); + platform::cancel_wait(); + return; + } + on_quit_prompt = true; + try { + amode = ADVANCE_QUIT; + platform::set_paused(false); + platform::cancel_wait(); + } catch(...) { + } + on_quit_prompt = false; + }); + } + ~mywindowcallbacks() throw() {} void on_new_dumper(const std::string& n) { update_movie_state(); @@ -975,23 +987,8 @@ namespace { update_movie_state(); } - void on_close() throw() - { - if(on_quit_prompt) { - amode = ADVANCE_QUIT; - platform::set_paused(false); - platform::cancel_wait(); - return; - } - on_quit_prompt = true; - try { - amode = ADVANCE_QUIT; - platform::set_paused(false); - platform::cancel_wait(); - } catch(...) { - } - on_quit_prompt = false; - } + private: + struct dispatch_target<> closenotify; } mywcb; //If there is a pending load, perform it. Return 1 on successful load, 0 if nothing to load, -1 on load @@ -1002,7 +999,7 @@ namespace uint64_t t = get_utime(); std::vector s; lua_callback_do_unsafe_rewind(s, 0, 0, movb.get_movie(), unsafe_rewind_obj); - information_dispatch::do_mode_change(false); + notify_mode_change(false); do_unsafe_rewind = false; our_movie.is_savestate = true; location_special = SPECIAL_SAVEPOINT; @@ -1058,7 +1055,6 @@ nothing_to_do: if(!system_corrupt) { location_special = SPECIAL_SAVEPOINT; update_movie_state(); - information_dispatch::do_status_update(); platform::flush_command_queue(); } if(old_project != our_movie.projectid) @@ -1109,6 +1105,7 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_ std::runtime_error) { //Basic initialization. + dispatch_set_error_streams(&messages.getstream()); emulation_thread = this_thread_id(); jukebox_size_listener jlistener; voicethread_task(); diff --git a/src/core/memorywatch.cpp b/src/core/memorywatch.cpp index dc22e9c1..74f8efec 100644 --- a/src/core/memorywatch.cpp +++ b/src/core/memorywatch.cpp @@ -413,7 +413,7 @@ void set_watchexpr_for(const std::string& w, const std::string& expr) throw(std: } if(p) project_flush(p); - information_dispatch::do_status_update(); + notify_status_update(); } void do_watch_memory() diff --git a/src/core/moviedata.cpp b/src/core/moviedata.cpp index adb0ecc2..ae894538 100644 --- a/src/core/moviedata.cpp +++ b/src/core/moviedata.cpp @@ -109,7 +109,6 @@ namespace mprefix = pfx; } update_movie_state(); - information_dispatch::do_status_update(); } std::string get_mprefix_for_project(const std::string& prjid) @@ -324,7 +323,7 @@ void do_load_beginning(bool reload) throw(std::bad_alloc, std::runtime_error) redraw_framebuffer(screen_corrupt, true); throw; } - information_dispatch::do_mode_change(movb.get_movie().readonly_mode()); + notify_mode_change(movb.get_movie().readonly_mode()); our_movie.is_savestate = false; our_movie.host_memory.clear(); if(reload) @@ -457,7 +456,7 @@ void do_load_state(struct moviefile& _movie, int lmode) } else redraw_framebuffer(our_rom->rtype->draw_cover()); } - information_dispatch::do_mode_change(movb.get_movie().readonly_mode()); + notify_mode_change(movb.get_movie().readonly_mode()); if(our_rom->rtype) messages << "ROM Type " << our_rom->rtype->get_hname() << " region " << our_rom->region->get_hname() << std::endl; diff --git a/src/core/project.cpp b/src/core/project.cpp index 9de24b75..fe9bb26a 100644 --- a/src/core/project.cpp +++ b/src/core/project.cpp @@ -352,7 +352,7 @@ bool project_set(project_info* p, bool current) if(active_project) voicesub_unload_collection(); active_project = p; - information_dispatch::do_core_change(); + notify_core_change(); return true; } @@ -404,8 +404,7 @@ skip_rom_movie: if(switched) { do_flush_slotinfo(); update_movie_state(); - information_dispatch::do_status_update(); - information_dispatch::do_core_change(); + notify_core_change(); } return switched; } diff --git a/src/core/subtitles.cpp b/src/core/subtitles.cpp index 5643f21c..b9e5502b 100644 --- a/src/core/subtitles.cpp +++ b/src/core/subtitles.cpp @@ -112,7 +112,7 @@ namespace our_movie.subtitles.erase(key); else our_movie.subtitles[key] = s_unescape(text); - information_dispatch::do_subtitle_change(); + notify_subtitle_change(); redraw_framebuffer(); }); @@ -234,6 +234,6 @@ void set_subtitle_for(uint64_t f, uint64_t l, const std::string& x) our_movie.subtitles.erase(key); else our_movie.subtitles[key] = s_unescape(x); - information_dispatch::do_subtitle_change(); + notify_subtitle_change(); redraw_framebuffer(); } diff --git a/src/core/window.cpp b/src/core/window.cpp index a7fa0563..175b1841 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -152,7 +152,7 @@ void platform::sound_enable(bool enable) throw() { audioapi_driver_enable(enable); sounds_enabled = enable; - information_dispatch::do_sound_unmute(enable); + notify_sound_unmute(enable); } void platform::set_sound_device(const std::string& pdev, const std::string& rdev) throw() @@ -170,8 +170,7 @@ void platform::set_sound_device(const std::string& pdev, const std::string& rdev } } //After failed change, we don't know what is selected. - information_dispatch::do_sound_change(std::make_pair(audioapi_driver_get_device(true), - audioapi_driver_get_device(false))); + notify_sound_change(std::make_pair(audioapi_driver_get_device(true), audioapi_driver_get_device(false))); } bool platform::is_sound_enabled() throw() @@ -497,30 +496,19 @@ namespace mutex_class _msgbuf_lock; framebuffer* our_screen; - struct painter_listener : public information_dispatch + struct painter_listener { - painter_listener(); - void on_set_screen(framebuffer& scr); - void on_screen_update(); - void on_status_update(); + painter_listener() + { + screenupdate.set(notify_screen_update, []() { graphics_driver_notify_screen(); }); + statusupdate.set(notify_status_update, []() { graphics_driver_notify_status(); }); + setscreen.set(notify_set_screen, [](framebuffer& scr) { our_screen = &scr; }); + } + private: + struct dispatch_target<> screenupdate; + struct dispatch_target<> statusupdate; + struct dispatch_target&> setscreen; } x; - - painter_listener::painter_listener() : information_dispatch("painter-listener") {} - - void painter_listener::on_set_screen(framebuffer& scr) - { - our_screen = &scr; - } - - void painter_listener::on_screen_update() - { - graphics_driver_notify_screen(); - } - - void painter_listener::on_status_update() - { - graphics_driver_notify_status(); - } } mutex_class& platform::msgbuf_lock() throw() diff --git a/src/library/dispatch.cpp b/src/library/dispatch.cpp new file mode 100644 index 00000000..3e03fba2 --- /dev/null +++ b/src/library/dispatch.cpp @@ -0,0 +1,7 @@ +#include "dispatch.hpp" + +mutex_class& dispatch_global_init_lock() +{ + static mutex_class m; + return m; +} diff --git a/src/platform/wxwidgets/editor-authors.cpp b/src/platform/wxwidgets/editor-authors.cpp index 788920f5..cabd86a0 100644 --- a/src/platform/wxwidgets/editor-authors.cpp +++ b/src/platform/wxwidgets/editor-authors.cpp @@ -229,8 +229,7 @@ void wxeditor_authors::on_ok(wxCommandEvent& e) //For save status to immediately update. do_flush_slotinfo(); update_movie_state(); - information_dispatch::do_status_update(); - information_dispatch::do_core_change(); + notify_core_change(); } else { our_movie.gamename = gamename; our_movie.authors = newauthors; diff --git a/src/platform/wxwidgets/editor-autohold.cpp b/src/platform/wxwidgets/editor-autohold.cpp index 358b393a..0e06b274 100644 --- a/src/platform/wxwidgets/editor-autohold.cpp +++ b/src/platform/wxwidgets/editor-autohold.cpp @@ -20,7 +20,7 @@ #include #include -class wxeditor_autohold : public wxDialog, public information_dispatch +class wxeditor_autohold : public wxDialog { public: wxeditor_autohold(wxWindow* parent); @@ -28,11 +28,11 @@ public: bool ShouldPreventAppExit() const; void on_wclose(wxCloseEvent& e); void on_checkbox(wxCommandEvent& e); - void on_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate); - void on_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen); - void on_autohold_reconfigure(); private: + struct dispatch_target ahupdate; + struct dispatch_target afupdate; + struct dispatch_target<> ahreconfigure; + struct control_triple { unsigned port; @@ -71,8 +71,7 @@ namespace wxeditor_autohold::~wxeditor_autohold() throw() {} wxeditor_autohold::wxeditor_autohold(wxWindow* parent) - : wxDialog(parent, wxID_ANY, wxT("lsnes: Autohold/Autofire"), wxDefaultPosition, wxSize(-1, -1)), - information_dispatch("autohold-listener") + : wxDialog(parent, wxID_ANY, wxT("lsnes: Autohold/Autofire"), wxDefaultPosition, wxSize(-1, -1)) { closing = false; Centre(); @@ -82,46 +81,42 @@ wxeditor_autohold::wxeditor_autohold(wxWindow* parent) update_controls(); hsizer->SetSizeHints(this); Fit(); -} -void wxeditor_autohold::on_autohold_update(unsigned port, unsigned controller, unsigned ctrlnum, bool newstate) -{ - runuifun([this, port, controller, ctrlnum, newstate]() { - for(auto i : this->autoholds) { - if(i.second.port != port) continue; - if(i.second.controller != controller) continue; - if(i.second.index != ctrlnum) continue; - i.second.check->SetValue(newstate); - } + ahupdate.set(notify_autohold_update, [this](unsigned port, unsigned controller, unsigned ctrlnum, + bool newstate) { + runuifun([this, port, controller, ctrlnum, newstate]() { + for(auto i : this->autoholds) { + if(i.second.port != port) continue; + if(i.second.controller != controller) continue; + if(i.second.index != ctrlnum) continue; + i.second.check->SetValue(newstate); + } + }); }); -} - -void wxeditor_autohold::on_autofire_update(unsigned port, unsigned controller, unsigned ctrlnum, unsigned duty, - unsigned cyclelen) -{ - runuifun([this, port, controller, ctrlnum, duty]() { - for(auto i : this->autoholds) { - if(i.second.port != port) continue; - if(i.second.controller != controller) continue; - if(i.second.index != ctrlnum) continue; - i.second.afcheck->SetValue(duty != 0); - } + afupdate.set(notify_autofire_update, [this](unsigned port, unsigned controller, unsigned ctrlnum, + unsigned duty, unsigned cyclelen) { + runuifun([this, port, controller, ctrlnum, duty]() { + for(auto i : this->autoholds) { + if(i.second.port != port) continue; + if(i.second.controller != controller) continue; + if(i.second.index != ctrlnum) continue; + i.second.afcheck->SetValue(duty != 0); + } + }); }); -} - -void wxeditor_autohold::on_autohold_reconfigure() -{ - runuifun([this]() { - try { - this->update_controls(); - } catch(std::runtime_error& e) { - //Close the window. - bool wasc = closing; - closing = true; - autohold_open = NULL; - if(!wasc) - Destroy(); - } + ahreconfigure.set(notify_autohold_reconfigure, [this]() { + runuifun([this]() { + try { + this->update_controls(); + } catch(std::runtime_error& e) { + //Close the window. + bool wasc = closing; + closing = true; + autohold_open = NULL; + if(!wasc) + Destroy(); + } + }); }); } diff --git a/src/platform/wxwidgets/editor-movie.cpp b/src/platform/wxwidgets/editor-movie.cpp index ef3644ff..b1c182b4 100644 --- a/src/platform/wxwidgets/editor-movie.cpp +++ b/src/platform/wxwidgets/editor-movie.cpp @@ -275,7 +275,7 @@ public: scroll_bar* get_scroll(); void update(); private: - struct _moviepanel : public wxPanel, public information_dispatch + struct _moviepanel : public wxPanel { _moviepanel(wxeditor_movie* v); ~_moviepanel() throw(); @@ -388,8 +388,7 @@ wxeditor_movie::_moviepanel::~_moviepanel() throw() {} wxeditor_movie::~wxeditor_movie() throw() {} wxeditor_movie::_moviepanel::_moviepanel(wxeditor_movie* v) - : wxPanel(v, wxID_ANY, wxDefaultPosition, wxSize(100, 100), wxWANTS_CHARS), - information_dispatch("movieeditor-listener") + : wxPanel(v, wxID_ANY, wxDefaultPosition, wxSize(100, 100), wxWANTS_CHARS) { m = v; Connect(wxEVT_PAINT, wxPaintEventHandler(_moviepanel::on_paint), NULL, this); diff --git a/src/platform/wxwidgets/editor-subtitles.cpp b/src/platform/wxwidgets/editor-subtitles.cpp index 34d35d65..d62d6359 100644 --- a/src/platform/wxwidgets/editor-subtitles.cpp +++ b/src/platform/wxwidgets/editor-subtitles.cpp @@ -37,20 +37,6 @@ public: void on_wclose(wxCloseEvent& e); void refresh(); private: - struct refresh_listener : public information_dispatch - { - refresh_listener(wxeditor_subtitles* v) - : information_dispatch("subtitle-editor-change-listener") - { - obj = v; - } - void on_subtitle_change() - { - wxeditor_subtitles* _obj = obj; - runuifun([_obj]() -> void { _obj->refresh(); }); - } - wxeditor_subtitles* obj; - }; bool closing; wxListBox* subs; wxTextCtrl* subtext; @@ -59,7 +45,7 @@ private: wxButton* _delete; wxButton* close; std::map subtexts; - refresh_listener* rlistener; + struct dispatch_target<> subchange; }; namespace @@ -205,13 +191,12 @@ wxeditor_subtitles::wxeditor_subtitles(wxWindow* parent) pbutton_s->SetSizeHints(this); top_s->SetSizeHints(this); Fit(); - rlistener = new refresh_listener(this); + subchange.set(notify_subtitle_change, [this]() { runuifun([this]() -> void { this->refresh(); }); }); refresh(); } wxeditor_subtitles::~wxeditor_subtitles() throw() { - delete rlistener; } bool wxeditor_subtitles::ShouldPreventAppExit() const diff --git a/src/platform/wxwidgets/editor-tasinput.cpp b/src/platform/wxwidgets/editor-tasinput.cpp index 5f6b535e..67cc8df3 100644 --- a/src/platform/wxwidgets/editor-tasinput.cpp +++ b/src/platform/wxwidgets/editor-tasinput.cpp @@ -68,7 +68,7 @@ namespace } } -class wxeditor_tasinput : public wxDialog, public information_dispatch +class wxeditor_tasinput : public wxDialog { public: wxeditor_tasinput(wxWindow* parent); @@ -76,10 +76,10 @@ public: bool ShouldPreventAppExit() const; void on_wclose(wxCloseEvent& e); void on_control(wxCommandEvent& e); - void on_autohold_reconfigure(); void on_keyboard_up(wxKeyEvent& e); void on_keyboard_down(wxKeyEvent& e); private: + struct dispatch_target<> ahreconfigure; struct xypanel; struct control_triple { @@ -239,8 +239,7 @@ void wxeditor_tasinput::xypanel::Destroy() wxeditor_tasinput::~wxeditor_tasinput() throw() {} wxeditor_tasinput::wxeditor_tasinput(wxWindow* parent) - : wxDialog(parent, wxID_ANY, wxT("lsnes: TAS input plugin"), wxDefaultPosition, wxSize(-1, -1)), - information_dispatch("tasinput-listener") + : wxDialog(parent, wxID_ANY, wxT("lsnes: TAS input plugin"), wxDefaultPosition, wxSize(-1, -1)) { closing = false; Centre(); @@ -250,6 +249,22 @@ wxeditor_tasinput::wxeditor_tasinput(wxWindow* parent) update_controls(); hsizer->SetSizeHints(this); Fit(); + + ahreconfigure.set(notify_autohold_reconfigure, [this]() { + runuifun([this]() { + try { + this->update_controls(); + } catch(std::runtime_error& e) { + //Close the window. + bool wasc = closing; + closing = true; + tasinput_open = NULL; + controls.tasinput_enable(false); + if(!wasc) + Destroy(); + } + }); + }); } void wxeditor_tasinput::connect_keyboard_recursive(wxWindow* win) @@ -263,23 +278,6 @@ void wxeditor_tasinput::connect_keyboard_recursive(wxWindow* win) } } -void wxeditor_tasinput::on_autohold_reconfigure() -{ - runuifun([this]() { - try { - this->update_controls(); - } catch(std::runtime_error& e) { - //Close the window. - bool wasc = closing; - closing = true; - tasinput_open = NULL; - controls.tasinput_enable(false); - if(!wasc) - Destroy(); - } - }); -} - void wxeditor_tasinput::on_control(wxCommandEvent& e) { int id = e.GetId(); diff --git a/src/platform/wxwidgets/editor-voicesub.cpp b/src/platform/wxwidgets/editor-voicesub.cpp index c2c4fa95..4b1b4e0a 100644 --- a/src/platform/wxwidgets/editor-voicesub.cpp +++ b/src/platform/wxwidgets/editor-voicesub.cpp @@ -43,25 +43,6 @@ public: void on_wclose(wxCloseEvent& e); void refresh(); private: - struct refresh_listener : public information_dispatch - { - refresh_listener(wxeditor_voicesub* v) - : information_dispatch("voicesub-editor-change-listner") - { - obj = v; - } - void on_voice_stream_change() - { - wxeditor_voicesub* _obj = obj; - runuifun([_obj]() -> void { _obj->refresh(); }); - } - void on_core_change() - { - wxeditor_voicesub* _obj = obj; - runuifun([_obj]() -> void { _obj->refresh(); }); - } - wxeditor_voicesub* obj; - }; bool closing; uint64_t get_id(); std::map smap; @@ -79,8 +60,8 @@ private: wxButton* unloadbutton; wxButton* refreshbutton; wxButton* closebutton; - refresh_listener* rlistener; - + struct dispatch_target<> corechange; + struct dispatch_target<> vstreamchange; }; wxeditor_voicesub::wxeditor_voicesub(wxWindow* parent) @@ -169,13 +150,13 @@ wxeditor_voicesub::wxeditor_voicesub(wxWindow* parent) top_s->SetSizeHints(this); Fit(); - rlistener = new refresh_listener(this); + vstreamchange.set(notify_voice_stream_change, [this]() { runuifun([this]() -> void { this->refresh(); }); }); + corechange.set(notify_core_change, [this]() { runuifun([this]() -> void { this->refresh(); }); }); refresh(); } wxeditor_voicesub::~wxeditor_voicesub() throw() { - delete rlistener; } void wxeditor_voicesub::on_select(wxCommandEvent& e) diff --git a/src/platform/wxwidgets/mainwindow.cpp b/src/platform/wxwidgets/mainwindow.cpp index 6b77a0ee..b7751a46 100644 --- a/src/platform/wxwidgets/mainwindow.cpp +++ b/src/platform/wxwidgets/mainwindow.cpp @@ -496,39 +496,6 @@ namespace set_speed_multiplier(target / 100); } - class broadcast_listener : public information_dispatch - { - public: - broadcast_listener(wxwin_mainwindow* win); - void on_sound_unmute(bool unmute) throw(); - void on_mode_change(bool readonly) throw(); - void on_core_change(); - void on_new_core(); - private: - wxwin_mainwindow* mainw; - }; - - broadcast_listener::broadcast_listener(wxwin_mainwindow* win) - : information_dispatch("wxwidgets-broadcast-listener") - { - mainw = win; - } - - void broadcast_listener::on_core_change() - { - signal_core_change(); - } - - void broadcast_listener::on_sound_unmute(bool unmute) throw() - { - runuifun([this, unmute]() { this->mainw->menu_check(wxID_AUDIO_ENABLED, unmute); }); - } - - void broadcast_listener::on_mode_change(bool readonly) throw() - { - runuifun([this, readonly]() { this->mainw->menu_check(wxID_READONLY_MODE, readonly); }); - } - void update_preferences() { preferred_core.clear(); @@ -542,15 +509,9 @@ namespace std::string key2 = "type:" + i->get_iname(); if(core_selections.count(key2) && core_selections[key2] == val) preferred_core[key2] = i; - } } - void broadcast_listener::on_new_core() - { - update_preferences(); - } - std::string movie_path() { return lsnes_vset["moviepath"].str(); @@ -852,7 +813,6 @@ wxwin_mainwindow::wxwin_mainwindow() : wxFrame(NULL, wxID_ANY, getname(), wxDefaultPosition, wxSize(-1, -1), wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLIP_CHILDREN | wxCLOSE_BOX) { - broadcast_listener* blistener = new broadcast_listener(this); Centre(); mwindow = NULL; toplevel = new wxFlexGridSizer(1, 2, 0, 0); @@ -981,6 +941,14 @@ wxwin_mainwindow::wxwin_mainwindow() menu_start(wxT("Help")); menu_entry(wxID_ABOUT, wxT("About...")); + corechange.set(notify_core_change, []() { signal_core_change(); }); + newcore.set(notify_new_core, []() { update_preferences(); }); + unmuted.set(notify_sound_unmute, [this](bool unmute) { + runuifun([this, unmute]() { this->menu_check(wxID_AUDIO_ENABLED, unmute); }); + }); + modechange.set(notify_mode_change, [this](bool readonly) { + runuifun([this, readonly]() { this->menu_check(wxID_READONLY_MODE, readonly); }); + }); gpanel->SetDropTarget(new loadfile(this)); spanel->SetDropTarget(new loadfile(this)); } diff --git a/src/platform/wxwidgets/vumeter.cpp b/src/platform/wxwidgets/vumeter.cpp index 08752ce0..c5459700 100644 --- a/src/platform/wxwidgets/vumeter.cpp +++ b/src/platform/wxwidgets/vumeter.cpp @@ -193,27 +193,10 @@ private: } } }; - struct refresh_listener : public information_dispatch - { - refresh_listener(wxwin_vumeter* v) - : information_dispatch("voicesub-editor-change-listner") - { - obj = v; - } - void on_vu_change() - { - wxwin_vumeter* _obj = obj; - if(!obj->update_sent) { - obj->update_sent = true; - runuifun([_obj]() -> void { _obj->refresh(); }); - } - } - wxwin_vumeter* obj; - }; volatile bool update_sent; bool closing; wxButton* closebutton; - refresh_listener* rlistener; + struct dispatch_target<> vulistener; _vupanel* vupanel; wxStaticText* rate; wxSlider* gamevol; @@ -267,13 +250,17 @@ wxwin_vumeter::wxwin_vumeter(wxWindow* parent) top_s->SetSizeHints(this); Fit(); - rlistener = new refresh_listener(this); + vulistener.set(notify_vu_change, [this]() { + if(!this->update_sent) { + this->update_sent = true; + runuifun([this]() -> void { this->refresh(); }); + } + }); refresh(); } wxwin_vumeter::~wxwin_vumeter() throw() { - delete rlistener; } void wxwin_vumeter::on_game_change(wxScrollEvent& e)