Lots of dispatch refactoring
This commit is contained in:
parent
95bbae153e
commit
8fe4f70d9a
25 changed files with 350 additions and 650 deletions
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "core/keymapper.hpp"
|
||||
#include "library/framebuffer.hpp"
|
||||
#include "library/dispatch.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
@ -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<std::string, std::string> dev);
|
||||
/**
|
||||
* Call all on_sound_change() handlers.
|
||||
*/
|
||||
static void do_sound_change(std::pair<std::string, std::string> 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<false>& scr);
|
||||
/**
|
||||
* Call on_set_screen on all objects.
|
||||
*/
|
||||
static void do_set_screen(framebuffer<false>& 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<unsigned, unsigned, unsigned, bool> notify_autohold_update;
|
||||
extern struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update;
|
||||
extern struct dispatcher<> notify_close;
|
||||
extern struct dispatcher<framebuffer<false>&> notify_set_screen;
|
||||
extern struct dispatcher<std::pair<std::string, std::string>> notify_sound_change;
|
||||
extern struct dispatcher<> notify_screen_update;
|
||||
extern struct dispatcher<> notify_status_update;
|
||||
extern struct dispatcher<bool> notify_sound_unmute;
|
||||
extern struct dispatcher<bool> 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
|
||||
|
|
135
include/library/dispatch.hpp
Normal file
135
include/library/dispatch.hpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#ifndef _library__dispatch__hpp__included__
|
||||
#define _library__dispatch__hpp__included__
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include "threadtypes.hpp"
|
||||
|
||||
mutex_class& dispatch_global_init_lock();
|
||||
|
||||
template<typename... T> struct dispatcher;
|
||||
|
||||
template<typename... T> struct dispatch_target
|
||||
{
|
||||
dispatch_target()
|
||||
{
|
||||
src = NULL;
|
||||
fn = dummy;
|
||||
}
|
||||
inline ~dispatch_target();
|
||||
inline void set(dispatcher<T...>& d, std::function<void(T...)> _fn);
|
||||
private:
|
||||
static void dummy(T... args) {};
|
||||
void set_source(dispatcher<T...>* d) { src = d; }
|
||||
void call(T... args) { fn(args...); }
|
||||
dispatcher<T...>* src;
|
||||
std::function<void(T...)> fn;
|
||||
friend class dispatcher<T...>;
|
||||
};
|
||||
|
||||
template<typename... T> 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<uint64_t, dispatch_target<T...>*>::iterator i;
|
||||
lck->lock();
|
||||
i = targets().lower_bound(k);
|
||||
while(i != targets().end()) {
|
||||
k = i->first + 1;
|
||||
dispatch_target<T...>* 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<T...>& target)
|
||||
{
|
||||
init();
|
||||
umutex_class h(*lck);
|
||||
targets()[next_cbseq++] = ⌖
|
||||
target.set_source(this);
|
||||
}
|
||||
void disconnect(dispatch_target<T...>& 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<uint64_t, dispatch_target<T...>*>& targets()
|
||||
{
|
||||
if(!_targets) _targets = new std::map<uint64_t, dispatch_target<T...>*>;
|
||||
return *_targets;
|
||||
}
|
||||
std::map<uint64_t, dispatch_target<T...>*>* _targets;
|
||||
uint64_t next_cbseq;
|
||||
std::ostream* errstrm;
|
||||
const char* name;
|
||||
bool inited;
|
||||
dispatcher(const dispatcher<T...>&);
|
||||
dispatcher<T...>& operator=(const dispatcher<T...>&);
|
||||
};
|
||||
|
||||
template <typename... T> dispatch_target<T...>::~dispatch_target()
|
||||
{
|
||||
if(src)
|
||||
src->disconnect(*this);
|
||||
}
|
||||
|
||||
template <typename... T> void dispatch_target<T...>::set(dispatcher<T...>& d, std::function<void(T...)> _fn)
|
||||
{
|
||||
fn = _fn;
|
||||
src = &d;
|
||||
if(src)
|
||||
src->connect(*this);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "platform/wxwidgets/window_status.hpp"
|
||||
#include "platform/wxwidgets/menu_recent.hpp"
|
||||
#include "library/dispatch.hpp"
|
||||
|
||||
#include <stack>
|
||||
|
||||
|
@ -65,6 +66,10 @@ private:
|
|||
void* sounddev1;
|
||||
void* sounddev2;
|
||||
void* dmenu;
|
||||
struct dispatch_target<> corechange;
|
||||
struct dispatch_target<> newcore;
|
||||
struct dispatch_target<bool> unmuted;
|
||||
struct dispatch_target<bool> modechange;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -525,7 +525,7 @@ void audioapi_vumeter::update_vu()
|
|||
accumulator = 0;
|
||||
samples = 0;
|
||||
}
|
||||
information_dispatch::do_vu_change();
|
||||
notify_vu_change();
|
||||
}
|
||||
|
||||
//VU values.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<std::string> controller_state::active_macro_set()
|
||||
|
|
|
@ -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<std::string, std::string> dev)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_sound_change(std::pair<std::string,std::string> 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<false>& scr)
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_set_screen(framebuffer<false>& 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<unsigned, unsigned, unsigned, bool> notify_autohold_update("autohold_update");
|
||||
struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update("autofire_update");
|
||||
struct dispatcher<> notify_close("notify_close");
|
||||
struct dispatcher<framebuffer<false>&> notify_set_screen("set_screen");
|
||||
struct dispatcher<std::pair<std::string, std::string>> notify_sound_change("sound_change");
|
||||
struct dispatcher<> notify_screen_update("screen_update");
|
||||
struct dispatcher<> notify_status_update("status_update");
|
||||
struct dispatcher<bool> notify_sound_unmute("sound_unmute");
|
||||
struct dispatcher<bool> 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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -13,7 +13,7 @@ void handle_post_loadlibrary()
|
|||
{
|
||||
if(new_core_flag) {
|
||||
new_core_flag = false;
|
||||
information_dispatch::do_new_core();
|
||||
notify_new_core();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<char> 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();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<false>* our_screen;
|
||||
|
||||
struct painter_listener : public information_dispatch
|
||||
struct painter_listener
|
||||
{
|
||||
painter_listener();
|
||||
void on_set_screen(framebuffer<false>& 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<false>& scr) { our_screen = &scr; });
|
||||
}
|
||||
private:
|
||||
struct dispatch_target<> screenupdate;
|
||||
struct dispatch_target<> statusupdate;
|
||||
struct dispatch_target<framebuffer<false>&> setscreen;
|
||||
} x;
|
||||
|
||||
painter_listener::painter_listener() : information_dispatch("painter-listener") {}
|
||||
|
||||
void painter_listener::on_set_screen(framebuffer<false>& 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()
|
||||
|
|
7
src/library/dispatch.cpp
Normal file
7
src/library/dispatch.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "dispatch.hpp"
|
||||
|
||||
mutex_class& dispatch_global_init_lock()
|
||||
{
|
||||
static mutex_class m;
|
||||
return m;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <wx/combobox.h>
|
||||
#include <wx/statline.h>
|
||||
|
||||
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<unsigned, unsigned, unsigned, bool> ahupdate;
|
||||
struct dispatch_target<unsigned, unsigned, unsigned, unsigned, unsigned> 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();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<int, subdata> 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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<int, uint64_t> 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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue