Wxwidgets: Allow controlling dumper start/stop from menu
This commit is contained in:
parent
34a5e281ca
commit
8df91c55f2
19 changed files with 646 additions and 103 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1-β3
|
||||
1-β4
|
||||
|
|
87
include/core/advdumper.hpp
Normal file
87
include/core/advdumper.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef _advdumper__hpp__included__
|
||||
#define _advdumper__hpp__included__
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
|
||||
class adv_dumper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Register a dumper.
|
||||
*
|
||||
* Parameter id: The ID of dumper.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
adv_dumper(const std::string& id) throw(std::bad_alloc);
|
||||
/**
|
||||
* Unregister a dumper.
|
||||
*/
|
||||
~adv_dumper();
|
||||
/**
|
||||
* Get ID of dumper.
|
||||
*
|
||||
* Returns: The id.
|
||||
*/
|
||||
const std::string& id() throw();
|
||||
/**
|
||||
* Get set of all dumpers.
|
||||
*
|
||||
* Returns: The set.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
static std::set<adv_dumper*> get_dumper_set() throw(std::bad_alloc);
|
||||
/**
|
||||
* List all valid submodes.
|
||||
*
|
||||
* Returns: List of all valid submodes. Empty list means this dumper has no submodes.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
virtual std::set<std::string> list_submodes() throw(std::bad_alloc) = 0;
|
||||
/**
|
||||
* Does this dumper want a prefix?
|
||||
*
|
||||
* parameter mode: The submode.
|
||||
*/
|
||||
virtual bool wants_prefix(const std::string& mode) throw() = 0;
|
||||
/**
|
||||
* Get human-readable name for this dumper.
|
||||
*
|
||||
* Returns: The name.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
virtual std::string name() throw(std::bad_alloc) = 0;
|
||||
/**
|
||||
* Get human-readable name for submode.
|
||||
*
|
||||
* Parameter mode: The submode.
|
||||
* Returns: The name.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
*/
|
||||
virtual std::string modename(const std::string& mode) throw(std::bad_alloc) = 0;
|
||||
/**
|
||||
* Is this dumper busy dumping?
|
||||
*
|
||||
* Return: True if busy, false if not.
|
||||
*/
|
||||
virtual bool busy() = 0;
|
||||
/**
|
||||
* Start dump.
|
||||
*
|
||||
* parameter mode: The mode to dump using.
|
||||
* parameter targetname: The target filename or prefix.
|
||||
* Throws std::bad_alloc: Not enough memory.
|
||||
* Throws std::runtime_error: Can't start dump.
|
||||
*/
|
||||
virtual void start(const std::string& mode, const std::string& targetname) throw(std::bad_alloc,
|
||||
std::runtime_error) = 0;
|
||||
/**
|
||||
* End current dump.
|
||||
*/
|
||||
virtual void end() throw() = 0;
|
||||
private:
|
||||
std::string d_id;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -429,6 +429,16 @@ public:
|
|||
* 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.
|
||||
*
|
||||
* Default implementation does nothing.
|
||||
*/
|
||||
virtual void on_dumper_update();
|
||||
/**
|
||||
* Call on_dumper_update on on all objects.
|
||||
*/
|
||||
static void do_dumper_update() throw();
|
||||
protected:
|
||||
/**
|
||||
* Call to indicate this target is interested in sound sample data.
|
||||
|
|
|
@ -268,4 +268,13 @@ private:
|
|||
*/
|
||||
std::string format_address(void* addr);
|
||||
|
||||
/**
|
||||
* Get state of running global ctors flag.
|
||||
*/
|
||||
bool in_global_ctors();
|
||||
/**
|
||||
* Clear the global ctors flag.
|
||||
*/
|
||||
void reached_main();
|
||||
|
||||
#endif
|
||||
|
|
23
include/plat-wxwidgets/menu_dump.hpp
Normal file
23
include/plat-wxwidgets/menu_dump.hpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef _plat_wxwidgets__menu_dump__hpp__included__
|
||||
#define _plat_wxwidgets__menu_dump__hpp__included__
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/wx.h>
|
||||
|
||||
class dumper_menu_monitor;
|
||||
|
||||
class dumper_menu : public wxMenu
|
||||
{
|
||||
public:
|
||||
dumper_menu(wxWindow* win, int wxid_low, int wxid_high);
|
||||
~dumper_menu();
|
||||
void on_select(wxCommandEvent& e);
|
||||
void update();
|
||||
private:
|
||||
dumper_menu_monitor* monitor;
|
||||
wxWindow* pwin;
|
||||
int wxid_range_low;
|
||||
int wxid_range_high;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -49,6 +49,7 @@ private:
|
|||
std::stack<wxMenu*> upper;
|
||||
void* ahmenu;
|
||||
void* sounddev;
|
||||
void* dmenu;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
36
src/core/advdumper.cpp
Normal file
36
src/core/advdumper.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "core/advdumper.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/globalwrap.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
globalwrap<std::map<std::string, adv_dumper*>> dumpers;
|
||||
}
|
||||
|
||||
const std::string& adv_dumper::id() throw()
|
||||
{
|
||||
return d_id;
|
||||
}
|
||||
|
||||
adv_dumper::~adv_dumper()
|
||||
{
|
||||
dumpers().erase(d_id);
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
std::set<adv_dumper*> adv_dumper::get_dumper_set() throw(std::bad_alloc)
|
||||
{
|
||||
std::set<adv_dumper*> d;
|
||||
for(auto i : dumpers())
|
||||
d.insert(i.second);
|
||||
return d;
|
||||
}
|
||||
|
||||
adv_dumper::adv_dumper(const std::string& id) throw(std::bad_alloc)
|
||||
{
|
||||
d_id = id;
|
||||
dumpers()[d_id] = this;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#include "cscd.hpp"
|
||||
#include "sox.hpp"
|
||||
|
||||
#include "core/advdumper.hpp"
|
||||
#include "core/command.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/lua.hpp"
|
||||
|
@ -153,11 +154,8 @@ namespace
|
|||
|
||||
avi_avsnoop* vid_dumper;
|
||||
|
||||
function_ptr_command<const std::string&> avi_dump("dump-avi", "Start AVI capture",
|
||||
"Syntax: dump-avi <prefix>\nStart AVI capture to <prefix>.\n",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
tokensplitter t(args);
|
||||
std::string prefix = t.tail();
|
||||
void startdump(const std::string& prefix)
|
||||
{
|
||||
if(prefix == "")
|
||||
throw std::runtime_error("Expected prefix");
|
||||
if(vid_dumper)
|
||||
|
@ -178,11 +176,11 @@ namespace
|
|||
throw std::runtime_error(x.str());
|
||||
}
|
||||
messages << "Dumping AVI(CSCD) to " << prefix << " at level " << level2 << std::endl;
|
||||
});
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<> end_avi("end-avi", "End AVI capture",
|
||||
"Syntax: end-avi\nEnd a AVI capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
void enddump()
|
||||
{
|
||||
if(!vid_dumper)
|
||||
throw std::runtime_error("No AVI(CSCD) video dump in progress");
|
||||
try {
|
||||
|
@ -195,5 +193,67 @@ namespace
|
|||
}
|
||||
delete vid_dumper;
|
||||
vid_dumper = NULL;
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<const std::string&> avi_dump("dump-avi", "Start AVI capture",
|
||||
"Syntax: dump-avi <prefix>\nStart AVI capture to <prefix>.\n",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
tokensplitter t(args);
|
||||
std::string prefix = t.tail();
|
||||
startdump(prefix);
|
||||
});
|
||||
|
||||
function_ptr_command<> end_avi("end-avi", "End AVI capture",
|
||||
"Syntax: end-avi\nEnd a AVI capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
enddump();
|
||||
});
|
||||
|
||||
class adv_avi_dumper : public adv_dumper
|
||||
{
|
||||
public:
|
||||
adv_avi_dumper() : adv_dumper("INTERNAL-AVI-CSCD") {information_dispatch::do_dumper_update(); }
|
||||
~adv_avi_dumper() throw();
|
||||
std::set<std::string> list_submodes() throw(std::bad_alloc)
|
||||
{
|
||||
std::set<std::string> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
bool wants_prefix(const std::string& mode) throw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string name() throw(std::bad_alloc)
|
||||
{
|
||||
return "AVI (internal CSCD)";
|
||||
}
|
||||
|
||||
std::string modename(const std::string& mode) throw(std::bad_alloc)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool busy()
|
||||
{
|
||||
return (vid_dumper != NULL);
|
||||
}
|
||||
|
||||
void start(const std::string& mode, const std::string& targetname) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
startdump(targetname);
|
||||
}
|
||||
|
||||
void end() throw()
|
||||
{
|
||||
enddump();
|
||||
}
|
||||
} adv;
|
||||
|
||||
adv_avi_dumper::~adv_avi_dumper() throw()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -546,3 +546,19 @@ void information_dispatch::enable_send_sound() throw(std::bad_alloc)
|
|||
{
|
||||
dispatch_audio().push_back(this);
|
||||
}
|
||||
|
||||
void information_dispatch::on_dumper_update()
|
||||
{
|
||||
//Do nothing.
|
||||
}
|
||||
|
||||
void information_dispatch::do_dumper_update() throw()
|
||||
{
|
||||
if(in_global_ctors())
|
||||
return;
|
||||
for(auto& i : dispatch()) {
|
||||
START_EH_BLOCK
|
||||
i->on_dumper_update();
|
||||
END_EH_BLOCK(i, "on_dumper_update");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "jmd.hpp"
|
||||
|
||||
#include "core/advdumper.hpp"
|
||||
#include "core/command.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/lua.hpp"
|
||||
|
@ -134,11 +135,8 @@ namespace
|
|||
|
||||
jmd_avsnoop* vid_dumper;
|
||||
|
||||
function_ptr_command<const std::string&> jmd_dump("dump-jmd", "Start JMD capture",
|
||||
"Syntax: dump-jmd <file>\nStart JMD capture to <file>.\n",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
tokensplitter t(args);
|
||||
std::string prefix = t.tail();
|
||||
void startdump(std::string prefix)
|
||||
{
|
||||
if(prefix == "")
|
||||
throw std::runtime_error("Expected filename");
|
||||
if(vid_dumper)
|
||||
|
@ -154,11 +152,11 @@ namespace
|
|||
throw std::runtime_error(x.str());
|
||||
}
|
||||
messages << "Dumping to " << prefix << " at level " << level2 << std::endl;
|
||||
});
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<> end_avi("end-jmd", "End JMD capture",
|
||||
"Syntax: end-jmd\nEnd a JMD capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
void enddump()
|
||||
{
|
||||
if(!vid_dumper)
|
||||
throw std::runtime_error("No JMD video dump in progress");
|
||||
try {
|
||||
|
@ -171,5 +169,67 @@ namespace
|
|||
}
|
||||
delete vid_dumper;
|
||||
vid_dumper = NULL;
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<const std::string&> jmd_dump("dump-jmd", "Start JMD capture",
|
||||
"Syntax: dump-jmd <file>\nStart JMD capture to <file>.\n",
|
||||
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
|
||||
tokensplitter t(args);
|
||||
std::string prefix = t.tail();
|
||||
startdump(prefix);
|
||||
});
|
||||
|
||||
function_ptr_command<> end_avi("end-jmd", "End JMD capture",
|
||||
"Syntax: end-jmd\nEnd a JMD capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
enddump();
|
||||
});
|
||||
|
||||
class adv_jmd_dumper : public adv_dumper
|
||||
{
|
||||
public:
|
||||
adv_jmd_dumper() : adv_dumper("INTERNAL-JMD") {information_dispatch::do_dumper_update(); }
|
||||
~adv_jmd_dumper() throw();
|
||||
std::set<std::string> list_submodes() throw(std::bad_alloc)
|
||||
{
|
||||
std::set<std::string> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
bool wants_prefix(const std::string& mode) throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name() throw(std::bad_alloc)
|
||||
{
|
||||
return "JMD";
|
||||
}
|
||||
|
||||
std::string modename(const std::string& mode) throw(std::bad_alloc)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool busy()
|
||||
{
|
||||
return (vid_dumper != NULL);
|
||||
}
|
||||
|
||||
void start(const std::string& mode, const std::string& targetname) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
startdump(targetname);
|
||||
}
|
||||
|
||||
void end() throw()
|
||||
{
|
||||
enddump();
|
||||
}
|
||||
} adv;
|
||||
|
||||
adv_jmd_dumper::~adv_jmd_dumper() throw()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace
|
|||
{
|
||||
std::string rseed;
|
||||
uint64_t rcounter = 0;
|
||||
bool reached_main_flag;
|
||||
|
||||
std::string get_random_hexstring_64(size_t index)
|
||||
{
|
||||
|
@ -306,4 +307,14 @@ std::string format_address(void* addr)
|
|||
return y.str();
|
||||
}
|
||||
|
||||
bool in_global_ctors()
|
||||
{
|
||||
return !reached_main_flag;
|
||||
}
|
||||
|
||||
void reached_main()
|
||||
{
|
||||
reached_main_flag = true;
|
||||
}
|
||||
|
||||
std::string bsnes_core_version;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "sdmp.hpp"
|
||||
#include "core/advdumper.hpp"
|
||||
#include "core/command.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/lua.hpp"
|
||||
|
@ -56,34 +57,18 @@ namespace
|
|||
|
||||
sdmp_avsnoop* vid_dumper;
|
||||
|
||||
function_ptr_command<const std::string&> jmd_dump("dump-sdmp", "Start sdmp capture",
|
||||
"Syntax: dump-sdmp <prefix>\nStart SDMP capture to <prefix>\n",
|
||||
[](const std::string& prefix) throw(std::bad_alloc, std::runtime_error) {
|
||||
if(prefix == "")
|
||||
throw std::runtime_error("Expected prefix");
|
||||
if(vid_dumper)
|
||||
throw std::runtime_error("SDMP Dump already in progress");
|
||||
try {
|
||||
vid_dumper = new sdmp_avsnoop(prefix, false);
|
||||
} catch(std::bad_alloc& e) {
|
||||
throw;
|
||||
} catch(std::exception& e) {
|
||||
std::ostringstream x;
|
||||
x << "Error starting SDMP dump: " << e.what();
|
||||
throw std::runtime_error(x.str());
|
||||
}
|
||||
messages << "Dumping SDMP to " << prefix << std::endl;
|
||||
});
|
||||
|
||||
function_ptr_command<const std::string&> jmd_dumpss("dump-sdmpss", "Start SS sdmp capture",
|
||||
"Syntax: dump-sdmpss <file>\nStart SS SDMP capture to <file>\n",
|
||||
[](const std::string& prefix) throw(std::bad_alloc, std::runtime_error) {
|
||||
if(prefix == "")
|
||||
void startdump(bool ss, const std::string& prefix)
|
||||
{
|
||||
if(prefix == "") {
|
||||
if(ss)
|
||||
throw std::runtime_error("Expected filename");
|
||||
else
|
||||
throw std::runtime_error("Expected prefix");
|
||||
}
|
||||
if(vid_dumper)
|
||||
throw std::runtime_error("SDMP Dump already in progress");
|
||||
try {
|
||||
vid_dumper = new sdmp_avsnoop(prefix, true);
|
||||
vid_dumper = new sdmp_avsnoop(prefix, ss);
|
||||
} catch(std::bad_alloc& e) {
|
||||
throw;
|
||||
} catch(std::exception& e) {
|
||||
|
@ -91,12 +76,15 @@ namespace
|
|||
x << "Error starting SDMP dump: " << e.what();
|
||||
throw std::runtime_error(x.str());
|
||||
}
|
||||
if(ss)
|
||||
messages << "Dumping SDMP (SS) to " << prefix << std::endl;
|
||||
else
|
||||
messages << "Dumping SDMP to " << prefix << std::endl;
|
||||
});
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<> end_avi("end-sdmp", "End SDMP capture",
|
||||
"Syntax: end-sdmp\nEnd a SDMP capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
void enddump()
|
||||
{
|
||||
if(!vid_dumper)
|
||||
throw std::runtime_error("No SDMP video dump in progress");
|
||||
try {
|
||||
|
@ -109,5 +97,73 @@ namespace
|
|||
}
|
||||
delete vid_dumper;
|
||||
vid_dumper = NULL;
|
||||
information_dispatch::do_dumper_update();
|
||||
}
|
||||
|
||||
function_ptr_command<const std::string&> sdmp_dump("dump-sdmp", "Start sdmp capture",
|
||||
"Syntax: dump-sdmp <prefix>\nStart SDMP capture to <prefix>\n",
|
||||
[](const std::string& prefix) throw(std::bad_alloc, std::runtime_error) {
|
||||
startdump(false, prefix);
|
||||
});
|
||||
|
||||
function_ptr_command<const std::string&> sdmp_dumpss("dump-sdmpss", "Start SS sdmp capture",
|
||||
"Syntax: dump-sdmpss <file>\nStart SS SDMP capture to <file>\n",
|
||||
[](const std::string& prefix) throw(std::bad_alloc, std::runtime_error) {
|
||||
startdump(true, prefix);
|
||||
});
|
||||
|
||||
function_ptr_command<> end_avi("end-sdmp", "End SDMP capture",
|
||||
"Syntax: end-sdmp\nEnd a SDMP capture.\n",
|
||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||
enddump();
|
||||
});
|
||||
|
||||
class adv_sdmp_dumper : public adv_dumper
|
||||
{
|
||||
public:
|
||||
adv_sdmp_dumper() : adv_dumper("INTERNAL-SDMP") { information_dispatch::do_dumper_update(); }
|
||||
~adv_sdmp_dumper() throw();
|
||||
std::set<std::string> list_submodes() throw(std::bad_alloc)
|
||||
{
|
||||
std::set<std::string> x;
|
||||
x.insert("ss");
|
||||
x.insert("ms");
|
||||
return x;
|
||||
}
|
||||
|
||||
bool wants_prefix(const std::string& mode) throw()
|
||||
{
|
||||
return (mode != "ss");
|
||||
}
|
||||
|
||||
std::string name() throw(std::bad_alloc)
|
||||
{
|
||||
return "SDMP";
|
||||
}
|
||||
|
||||
std::string modename(const std::string& mode) throw(std::bad_alloc)
|
||||
{
|
||||
return (mode == "ss" ? "Single-Segment" : "Multi-Segment");
|
||||
}
|
||||
|
||||
bool busy()
|
||||
{
|
||||
return (vid_dumper != NULL);
|
||||
}
|
||||
|
||||
void start(const std::string& mode, const std::string& targetname) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
startdump((mode == "ss"), targetname);
|
||||
}
|
||||
|
||||
void end() throw()
|
||||
{
|
||||
enddump();
|
||||
}
|
||||
} adv;
|
||||
|
||||
adv_sdmp_dumper::~adv_sdmp_dumper() throw()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ namespace
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
reached_main();
|
||||
std::vector<std::string> cmdline;
|
||||
for(int i = 1; i < argc; i++)
|
||||
cmdline.push_back(argv[i]);
|
||||
|
|
162
src/plat-wxwidgets/dumpmenu.cpp
Normal file
162
src/plat-wxwidgets/dumpmenu.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include "core/advdumper.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
|
||||
#include "plat-wxwidgets/menu_dump.hpp"
|
||||
#include "plat-wxwidgets/platform.hpp"
|
||||
|
||||
class dumper_menu_monitor : public information_dispatch
|
||||
{
|
||||
public:
|
||||
dumper_menu_monitor(dumper_menu* dmenu)
|
||||
: information_dispatch("wxwidgets-dumpmenu")
|
||||
{
|
||||
linked = dmenu;
|
||||
}
|
||||
|
||||
~dumper_menu_monitor()
|
||||
{
|
||||
}
|
||||
|
||||
void on_dumper_update()
|
||||
{
|
||||
runuifun([linked]() { if(linked) linked->update(); });
|
||||
}
|
||||
private:
|
||||
dumper_menu* linked;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
struct dumper_info
|
||||
{
|
||||
adv_dumper* instance;
|
||||
std::string name;
|
||||
bool active;
|
||||
std::map<std::string, std::string> modes;
|
||||
};
|
||||
std::map<std::string, dumper_info> existing_dumpers;
|
||||
std::map<std::string, dumper_info> new_dumpers;
|
||||
|
||||
struct dumper_menu_struct
|
||||
{
|
||||
int end_wxid;
|
||||
wxMenuItem* end_item;
|
||||
std::map<int, std::string> start_wxids;
|
||||
std::map<int, wxMenuItem*> start_items;
|
||||
wxMenuItem* sep;
|
||||
};
|
||||
std::map<std::string, dumper_menu_struct> menustructure;
|
||||
std::string last_processed;
|
||||
bool first;
|
||||
|
||||
void update_dumperinfo(adv_dumper* d)
|
||||
{
|
||||
struct dumper_info inf;
|
||||
inf.instance = d;
|
||||
inf.name = d->name();
|
||||
std::set<std::string> mset = d->list_submodes();
|
||||
for(auto i : mset)
|
||||
inf.modes[i] = d->modename(i);
|
||||
inf.active = d->busy();
|
||||
new_dumpers[d->id()] = inf;
|
||||
}
|
||||
|
||||
void fetch_dumperinfo()
|
||||
{
|
||||
runemufn([]() {
|
||||
std::set<adv_dumper*> dset = adv_dumper::get_dumper_set();
|
||||
for(auto i : dset)
|
||||
update_dumperinfo(i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dumper_menu::dumper_menu(wxWindow* win, int wxid_low, int wxid_high)
|
||||
{
|
||||
pwin = win;
|
||||
win->Connect(wxid_low, wxid_high, wxEVT_COMMAND_MENU_SELECTED,
|
||||
wxCommandEventHandler(dumper_menu::on_select), NULL, this);
|
||||
wxid_range_low = wxid_low;
|
||||
wxid_range_high = wxid_high;
|
||||
monitor = new dumper_menu_monitor(this);
|
||||
update();
|
||||
}
|
||||
|
||||
dumper_menu::~dumper_menu()
|
||||
{
|
||||
delete monitor;
|
||||
}
|
||||
|
||||
void dumper_menu::on_select(wxCommandEvent& e)
|
||||
{
|
||||
int id = e.GetId();
|
||||
if(id < wxid_range_low || id > wxid_range_high)
|
||||
return;
|
||||
for(auto i : menustructure) {
|
||||
adv_dumper* t = existing_dumpers[i.first].instance;
|
||||
if(i.second.end_wxid == id) {
|
||||
//Execute end of dump operation.
|
||||
runemufn([t]() { t->end(); });
|
||||
return;
|
||||
}
|
||||
if(i.second.start_wxids.count(id)) {
|
||||
//Execute start of dump operation.
|
||||
std::string mode = i.second.start_wxids[id];
|
||||
bool prefixed = t->wants_prefix(mode);
|
||||
std::string prefix;
|
||||
wxFileDialog* d = new wxFileDialog(pwin, towxstring(prefixed ? std::string("Choose prefix") :
|
||||
std::string("Choose file")), wxT("."));
|
||||
if(d->ShowModal() == wxID_OK)
|
||||
prefix = tostdstring(d->GetPath());
|
||||
d->Destroy();
|
||||
if(prefix == "")
|
||||
return;
|
||||
runemufn([t, mode, prefix]() { t->start(mode, prefix); });
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dumper_menu::update()
|
||||
{
|
||||
fetch_dumperinfo();
|
||||
//Destroy all old entries.
|
||||
for(auto i : menustructure) {
|
||||
struct dumper_menu_struct& m = i.second;
|
||||
if(m.end_item)
|
||||
Remove(m.end_item);
|
||||
for(auto mi : m.start_items)
|
||||
Remove(mi.second);
|
||||
if(m.sep)
|
||||
Remove(m.sep);
|
||||
}
|
||||
//And create new ones.
|
||||
int id = wxid_range_low;
|
||||
first = true;
|
||||
menustructure.clear();
|
||||
for(auto i : new_dumpers) {
|
||||
if(!first)
|
||||
menustructure[last_processed].sep = AppendSeparator();
|
||||
last_processed = i.first;
|
||||
first = false;
|
||||
menustructure[i.first].end_item = NULL;
|
||||
menustructure[i.first].end_wxid = wxID_ANY;
|
||||
if(!i.second.active) {
|
||||
if(i.second.modes.empty()) {
|
||||
menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
|
||||
i.second.name));
|
||||
menustructure[i.first].start_wxids[id++] = "";
|
||||
}
|
||||
for(auto j : i.second.modes) {
|
||||
menustructure[i.first].start_items[id] = Append(id, towxstring("Dump " +
|
||||
i.second.name + " (" + j.second + ")"));
|
||||
menustructure[i.first].start_wxids[id++] = j.second;
|
||||
}
|
||||
} else {
|
||||
menustructure[i.first].end_item = Append(id, towxstring("End " + i.second.name));
|
||||
menustructure[i.first].end_wxid = id++;
|
||||
}
|
||||
}
|
||||
existing_dumpers = new_dumpers;
|
||||
}
|
|
@ -214,6 +214,7 @@ IMPLEMENT_APP(lsnes_app)
|
|||
|
||||
bool lsnes_app::OnInit()
|
||||
{
|
||||
reached_main();
|
||||
set_random_seed();
|
||||
bring_app_foreground();
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "plat-wxwidgets/menu_dump.hpp"
|
||||
#include "plat-wxwidgets/platform.hpp"
|
||||
#include "plat-wxwidgets/window_mainwindow.hpp"
|
||||
|
||||
|
@ -64,6 +65,8 @@ enum
|
|||
wxID_EDIT_MEMORYWATCH,
|
||||
wxID_SAVE_MEMORYWATCH,
|
||||
wxID_LOAD_MEMORYWATCH,
|
||||
wxID_DUMP_FIRST,
|
||||
wxID_DUMP_LAST = wxID_DUMP_FIRST + 1023
|
||||
};
|
||||
|
||||
|
||||
|
@ -777,7 +780,7 @@ wxwin_mainwindow::wxwin_mainwindow()
|
|||
menu_entry(wxID_EXIT, wxT("&Quit"));
|
||||
menu_separator();
|
||||
menu_entry(wxID_ABOUT, wxT("About"));
|
||||
//File menu: (ACFOS)DELMNPRTV
|
||||
//File menu: (ACFOS)DELMNPRTUV
|
||||
menu_start(wxT("&File"));
|
||||
menu_entry_check(wxID_READONLY_MODE, wxT("Reado&nly mode"));
|
||||
menu_check(wxID_READONLY_MODE, is_readonly_mode());
|
||||
|
@ -793,6 +796,8 @@ wxwin_mainwindow::wxwin_mainwindow()
|
|||
menu_separator();
|
||||
menu_entry(wxID_SAVE_SCREENSHOT, wxT("Save sc&reenshot"));
|
||||
menu_separator();
|
||||
menu_special_sub(wxT("D&ump video"), reinterpret_cast<dumper_menu*>(dmenu = new dumper_menu(this,
|
||||
wxID_DUMP_FIRST, wxID_DUMP_LAST)));
|
||||
//Autohold menu: (ACFOS)
|
||||
menu_special(wxT("&Autohold"), reinterpret_cast<autohold_menu*>(ahmenu = new autohold_menu(this)));
|
||||
blistener->set_autohold_menu(reinterpret_cast<autohold_menu*>(ahmenu));
|
||||
|
|
|
@ -151,6 +151,7 @@ class my_interfaced : public SNES::Interface
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
reached_main();
|
||||
std::vector<std::string> cmdline;
|
||||
for(int i = 1; i < argc; i++)
|
||||
cmdline.push_back(argv[i]);
|
||||
|
|
|
@ -52,6 +52,7 @@ std::string escape_string(std::string x)
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
reached_main();
|
||||
if(argc != 2) {
|
||||
std::cerr << "Syntax: " << argv[0] << " <moviefile>" << std::endl;
|
||||
return 1;
|
||||
|
|
|
@ -795,8 +795,11 @@ void syntax()
|
|||
std::cerr << "-8\tDump using 8 bits instead of 16 bits." << std::endl;
|
||||
}
|
||||
|
||||
void reached_main();
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
reached_main();
|
||||
if(argc < 4) {
|
||||
syntax();
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Reference in a new issue