Merge branch 'rr1-maint'
This commit is contained in:
commit
96cd83d1b2
17 changed files with 776 additions and 220 deletions
|
@ -1,6 +1,8 @@
|
||||||
#ifndef _settings__hpp__included__
|
#ifndef _settings__hpp__included__
|
||||||
#define _settings__hpp__included__
|
#define _settings__hpp__included__
|
||||||
|
|
||||||
|
#include "core/window.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -106,8 +108,22 @@ public:
|
||||||
* Get set of all settings.
|
* Get set of all settings.
|
||||||
*/
|
*/
|
||||||
static std::set<std::string> get_settings_set() throw(std::bad_alloc);
|
static std::set<std::string> get_settings_set() throw(std::bad_alloc);
|
||||||
|
/**
|
||||||
|
* Lock holder
|
||||||
|
*/
|
||||||
|
struct lock_holder
|
||||||
|
{
|
||||||
|
lock_holder(setting* t) { (targ = t)->mut->lock(); }
|
||||||
|
~lock_holder() { targ->mut->unlock(); }
|
||||||
|
private:
|
||||||
|
setting* targ;
|
||||||
|
};
|
||||||
|
friend struct lock_holder;
|
||||||
protected:
|
protected:
|
||||||
std::string settingname;
|
std::string settingname;
|
||||||
|
private:
|
||||||
|
static setting* get_by_name(const std::string& name);
|
||||||
|
mutex* mut;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,6 +31,10 @@ struct mutex
|
||||||
* Create a mutex. The returned mutex can be deleted using delete.
|
* Create a mutex. The returned mutex can be deleted using delete.
|
||||||
*/
|
*/
|
||||||
static mutex& aquire() throw(std::bad_alloc);
|
static mutex& aquire() throw(std::bad_alloc);
|
||||||
|
/**
|
||||||
|
* Create a recursive mutex. The returned mutex can be deleted using delete.
|
||||||
|
*/
|
||||||
|
static mutex& aquire_rec() throw(std::bad_alloc);
|
||||||
/**
|
/**
|
||||||
* Destroy a mutex.
|
* Destroy a mutex.
|
||||||
*/
|
*/
|
||||||
|
@ -535,6 +539,9 @@ struct platform
|
||||||
|
|
||||||
static bool pausing_allowed;
|
static bool pausing_allowed;
|
||||||
static double global_volume;
|
static double global_volume;
|
||||||
|
static volatile bool do_exit_dummy_event_loop;
|
||||||
|
static void dummy_event_loop() throw();
|
||||||
|
static void exit_dummy_event_loop() throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
class modal_pause_holder
|
class modal_pause_holder
|
||||||
|
|
|
@ -27,6 +27,7 @@ void bring_app_foreground();
|
||||||
std::string pick_archive_member(wxWindow* parent, const std::string& filename) throw(std::bad_alloc);
|
std::string pick_archive_member(wxWindow* parent, const std::string& filename) throw(std::bad_alloc);
|
||||||
void boot_emulator(loaded_rom& rom, moviefile& movie);
|
void boot_emulator(loaded_rom& rom, moviefile& movie);
|
||||||
void handle_wx_keyboard(wxKeyEvent& e, bool polarity);
|
void handle_wx_keyboard(wxKeyEvent& e, bool polarity);
|
||||||
|
std::string map_keycode_to_key(int kcode);
|
||||||
void initialize_wx_keyboard();
|
void initialize_wx_keyboard();
|
||||||
void signal_program_exit();
|
void signal_program_exit();
|
||||||
void signal_resize_needed();
|
void signal_resize_needed();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "core/command.hpp"
|
#include "core/command.hpp"
|
||||||
#include "core/globalwrap.hpp"
|
#include "core/globalwrap.hpp"
|
||||||
#include "core/misc.hpp"
|
#include "core/misc.hpp"
|
||||||
|
#include "core/window.hpp"
|
||||||
#include "library/minmax.hpp"
|
#include "library/minmax.hpp"
|
||||||
#include "library/string.hpp"
|
#include "library/string.hpp"
|
||||||
#include "library/zip.hpp"
|
#include "library/zip.hpp"
|
||||||
|
@ -14,6 +15,24 @@ namespace
|
||||||
std::set<std::string> command_stack;
|
std::set<std::string> command_stack;
|
||||||
std::map<std::string, std::list<std::string>> aliases;
|
std::map<std::string, std::list<std::string>> aliases;
|
||||||
|
|
||||||
|
//Return the recursive mutex.
|
||||||
|
mutex& cmlock()
|
||||||
|
{
|
||||||
|
static mutex& m = mutex::aquire_rec();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
class cmlock_hold
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cmlock_hold() { cmlock().lock(); }
|
||||||
|
~cmlock_hold() { cmlock().unlock(); }
|
||||||
|
private:
|
||||||
|
cmlock_hold(const cmlock_hold& k);
|
||||||
|
cmlock_hold& operator=(const cmlock_hold& k);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
function_ptr_command<arg_filename> run_script("run-script", "run file as a script",
|
function_ptr_command<arg_filename> run_script("run-script", "run file as a script",
|
||||||
"Syntax: run-script <file>\nRuns file <file> just as it would have been entered in the command line\n",
|
"Syntax: run-script <file>\nRuns file <file> just as it would have been entered in the command line\n",
|
||||||
[](arg_filename filename) throw(std::bad_alloc, std::runtime_error) {
|
[](arg_filename filename) throw(std::bad_alloc, std::runtime_error) {
|
||||||
|
@ -34,6 +53,7 @@ namespace
|
||||||
function_ptr_command<> show_aliases("show-aliases", "show aliases",
|
function_ptr_command<> show_aliases("show-aliases", "show aliases",
|
||||||
"Syntax: show-aliases\nShow expansions of all aliases\n",
|
"Syntax: show-aliases\nShow expansions of all aliases\n",
|
||||||
[]() throw(std::bad_alloc, std::runtime_error) {
|
[]() throw(std::bad_alloc, std::runtime_error) {
|
||||||
|
cmlock_hold lck;
|
||||||
for(auto i : aliases)
|
for(auto i : aliases)
|
||||||
for(auto j : i.second)
|
for(auto j : i.second)
|
||||||
messages << "alias " << i.first << " " << j << std::endl;
|
messages << "alias " << i.first << " " << j << std::endl;
|
||||||
|
@ -45,6 +65,7 @@ namespace
|
||||||
auto r = regex("([^ \t]+)[ \t]*", t, "This command only takes one argument");
|
auto r = regex("([^ \t]+)[ \t]*", t, "This command only takes one argument");
|
||||||
if(!command::valid_alias_name(r[1]))
|
if(!command::valid_alias_name(r[1]))
|
||||||
throw std::runtime_error("Illegal alias name");
|
throw std::runtime_error("Illegal alias name");
|
||||||
|
cmlock_hold lck;
|
||||||
aliases[r[1]].clear();
|
aliases[r[1]].clear();
|
||||||
messages << "Command '" << r[1] << "' unaliased" << std::endl;
|
messages << "Command '" << r[1] << "' unaliased" << std::endl;
|
||||||
});
|
});
|
||||||
|
@ -56,6 +77,7 @@ namespace
|
||||||
auto r = regex("([^ \t]+)[ \t]+([^ \t].*)", t, "Alias name and command needed");
|
auto r = regex("([^ \t]+)[ \t]+([^ \t].*)", t, "Alias name and command needed");
|
||||||
if(!command::valid_alias_name(r[1]))
|
if(!command::valid_alias_name(r[1]))
|
||||||
throw std::runtime_error("Illegal alias name");
|
throw std::runtime_error("Illegal alias name");
|
||||||
|
cmlock_hold lck;
|
||||||
aliases[r[1]].push_back(r[2]);
|
aliases[r[1]].push_back(r[2]);
|
||||||
messages << "Command '" << r[1] << "' aliased to '" << r[2] << "'" << std::endl;
|
messages << "Command '" << r[1] << "' aliased to '" << r[2] << "'" << std::endl;
|
||||||
});
|
});
|
||||||
|
@ -63,6 +85,7 @@ namespace
|
||||||
|
|
||||||
command::command(const std::string& cmd) throw(std::bad_alloc)
|
command::command(const std::string& cmd) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
if(commands().count(cmd))
|
if(commands().count(cmd))
|
||||||
std::cerr << "WARNING: Command collision for " << cmd << "!" << std::endl;
|
std::cerr << "WARNING: Command collision for " << cmd << "!" << std::endl;
|
||||||
commands()[commandname = cmd] = this;
|
commands()[commandname = cmd] = this;
|
||||||
|
@ -70,6 +93,7 @@ command::command(const std::string& cmd) throw(std::bad_alloc)
|
||||||
|
|
||||||
command::~command() throw()
|
command::~command() throw()
|
||||||
{
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
commands().erase(commandname);
|
commands().erase(commandname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,12 +103,14 @@ void command::invokeC(const std::string& cmd) throw()
|
||||||
std::string cmd2 = strip_CR(cmd);
|
std::string cmd2 = strip_CR(cmd);
|
||||||
if(cmd2 == "?") {
|
if(cmd2 == "?") {
|
||||||
//The special ? command.
|
//The special ? command.
|
||||||
|
cmlock_hold lck;
|
||||||
for(auto i : commands())
|
for(auto i : commands())
|
||||||
messages << i.first << ": " << i.second->get_short_help() << std::endl;
|
messages << i.first << ": " << i.second->get_short_help() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(firstchar(cmd2) == '?') {
|
if(firstchar(cmd2) == '?') {
|
||||||
//?command.
|
//?command.
|
||||||
|
cmlock_hold lck;
|
||||||
std::string rcmd = cmd2.substr(1, min(cmd2.find_first_of(" \t"), cmd2.length()));
|
std::string rcmd = cmd2.substr(1, min(cmd2.find_first_of(" \t"), cmd2.length()));
|
||||||
if(firstchar(rcmd) != '*') {
|
if(firstchar(rcmd) != '*') {
|
||||||
//This may be an alias.
|
//This may be an alias.
|
||||||
|
@ -109,21 +135,33 @@ void command::invokeC(const std::string& cmd) throw()
|
||||||
may_be_alias_expanded = false;
|
may_be_alias_expanded = false;
|
||||||
cmd2 = cmd2.substr(1);
|
cmd2 = cmd2.substr(1);
|
||||||
}
|
}
|
||||||
if(may_be_alias_expanded && aliases.count(cmd2)) {
|
//Now this gets painful as command handlers must not be invoked with lock held.
|
||||||
for(auto i : aliases[cmd2])
|
if(may_be_alias_expanded) {
|
||||||
|
std::list<std::string> aexp;
|
||||||
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
|
if(!aliases.count(cmd))
|
||||||
|
goto not_alias;
|
||||||
|
aexp = aliases[cmd2];
|
||||||
|
}
|
||||||
|
for(auto i : aexp)
|
||||||
invokeC(i);
|
invokeC(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
not_alias:
|
||||||
try {
|
try {
|
||||||
size_t split = cmd2.find_first_of(" \t");
|
size_t split = cmd2.find_first_of(" \t");
|
||||||
std::string rcmd = cmd2.substr(0, min(split, cmd2.length()));
|
std::string rcmd = cmd2.substr(0, min(split, cmd2.length()));
|
||||||
std::string args = cmd2.substr(min(cmd2.find_first_not_of(" \t", split), cmd2.length()));
|
std::string args = cmd2.substr(min(cmd2.find_first_not_of(" \t", split), cmd2.length()));
|
||||||
command* cmdh = NULL;
|
command* cmdh = NULL;
|
||||||
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
if(!commands().count(rcmd)) {
|
if(!commands().count(rcmd)) {
|
||||||
messages << "Unknown command '" << rcmd << "'" << std::endl;
|
messages << "Unknown command '" << rcmd << "'" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cmdh = commands()[rcmd];
|
cmdh = commands()[rcmd];
|
||||||
|
}
|
||||||
if(command_stack.count(cmd2))
|
if(command_stack.count(cmd2))
|
||||||
throw std::runtime_error("Recursive command invocation");
|
throw std::runtime_error("Recursive command invocation");
|
||||||
command_stack.insert(cmd2);
|
command_stack.insert(cmd2);
|
||||||
|
@ -154,6 +192,7 @@ std::string command::get_long_help() throw(std::bad_alloc)
|
||||||
|
|
||||||
std::set<std::string> command::get_aliases() throw(std::bad_alloc)
|
std::set<std::string> command::get_aliases() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
std::set<std::string> r;
|
std::set<std::string> r;
|
||||||
for(auto i : aliases)
|
for(auto i : aliases)
|
||||||
r.insert(i.first);
|
r.insert(i.first);
|
||||||
|
@ -162,6 +201,7 @@ std::set<std::string> command::get_aliases() throw(std::bad_alloc)
|
||||||
|
|
||||||
std::string command::get_alias_for(const std::string& aname) throw(std::bad_alloc)
|
std::string command::get_alias_for(const std::string& aname) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
if(!valid_alias_name(aname))
|
if(!valid_alias_name(aname))
|
||||||
return "";
|
return "";
|
||||||
if(aliases.count(aname)) {
|
if(aliases.count(aname)) {
|
||||||
|
@ -175,6 +215,7 @@ std::string command::get_alias_for(const std::string& aname) throw(std::bad_allo
|
||||||
|
|
||||||
void command::set_alias_for(const std::string& aname, const std::string& avalue) throw(std::bad_alloc)
|
void command::set_alias_for(const std::string& aname, const std::string& avalue) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
cmlock_hold lck;
|
||||||
if(!valid_alias_name(aname))
|
if(!valid_alias_name(aname))
|
||||||
return;
|
return;
|
||||||
std::list<std::string> newlist;
|
std::list<std::string> newlist;
|
||||||
|
|
|
@ -110,6 +110,27 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, double> read() throw()
|
||||||
|
{
|
||||||
|
lock_holder lck(this);
|
||||||
|
return std::make_pair(target_infinite, target_fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_nominal_framerate(double fps)
|
||||||
|
{
|
||||||
|
lock_holder(this);
|
||||||
|
nominal_rate = fps;
|
||||||
|
if(target_nominal) {
|
||||||
|
target_fps = nominal_rate;
|
||||||
|
target_infinite = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_framerate()
|
||||||
|
{
|
||||||
|
lock_holder(this);
|
||||||
|
return 100.0 * get_realized_fps() / nominal_rate;
|
||||||
|
}
|
||||||
} targetfps;
|
} targetfps;
|
||||||
|
|
||||||
bool turboed = false;
|
bool turboed = false;
|
||||||
|
@ -151,16 +172,12 @@ void unfreeze_time(uint64_t curtime)
|
||||||
|
|
||||||
void set_nominal_framerate(double fps) throw()
|
void set_nominal_framerate(double fps) throw()
|
||||||
{
|
{
|
||||||
nominal_rate = fps;
|
targetfps.set_nominal_framerate(fps);
|
||||||
if(target_nominal) {
|
|
||||||
target_fps = nominal_rate;
|
|
||||||
target_infinite = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double get_framerate() throw()
|
double get_framerate() throw()
|
||||||
{
|
{
|
||||||
return 100.0 * get_realized_fps() / nominal_rate;
|
return targetfps.get_framerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ack_frame_tick(uint64_t usec) throw()
|
void ack_frame_tick(uint64_t usec) throw()
|
||||||
|
@ -171,22 +188,22 @@ void ack_frame_tick(uint64_t usec) throw()
|
||||||
|
|
||||||
uint64_t to_wait_frame(uint64_t usec) throw()
|
uint64_t to_wait_frame(uint64_t usec) throw()
|
||||||
{
|
{
|
||||||
if(!frame_number || target_infinite || turboed)
|
auto target = targetfps.read();
|
||||||
|
if(!frame_number || target.first || turboed)
|
||||||
return 0;
|
return 0;
|
||||||
uint64_t lintime = get_time(usec, true);
|
uint64_t lintime = get_time(usec, true);
|
||||||
uint64_t frame_lasted = lintime - frame_start_times[0];
|
uint64_t frame_lasted = lintime - frame_start_times[0];
|
||||||
uint64_t frame_should_last = 1000000 / (target_fps * nominal_rate / 100);
|
uint64_t frame_should_last = 1000000 / (target.second * nominal_rate / 100);
|
||||||
if(frame_lasted >= frame_should_last)
|
if(frame_lasted >= frame_should_last)
|
||||||
return 0; //We are late.
|
return 0; //We are late.
|
||||||
uint64_t history_frames = min(frame_number, static_cast<uint64_t>(HISTORY_FRAMES));
|
uint64_t history_frames = min(frame_number, static_cast<uint64_t>(HISTORY_FRAMES));
|
||||||
uint64_t history_lasted = lintime - frame_start_times[history_frames - 1];
|
uint64_t history_lasted = lintime - frame_start_times[history_frames - 1];
|
||||||
uint64_t history_should_last = history_frames * 1000000 / (target_fps * nominal_rate / 100);
|
uint64_t history_should_last = history_frames * 1000000 / (target.second * nominal_rate / 100);
|
||||||
if(history_lasted >= history_should_last)
|
if(history_lasted >= history_should_last)
|
||||||
return 0;
|
return 0;
|
||||||
return min(history_should_last - history_lasted, frame_should_last - frame_lasted);
|
return min(history_should_last - history_lasted, frame_should_last - frame_lasted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t get_utime()
|
uint64_t get_utime()
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
|
@ -78,6 +78,23 @@ namespace
|
||||||
globalwrap<std::map<std::string, std::string>> modifier_linkages;
|
globalwrap<std::map<std::string, std::string>> modifier_linkages;
|
||||||
globalwrap<std::map<std::string, keygroup*>> keygroups;
|
globalwrap<std::map<std::string, keygroup*>> keygroups;
|
||||||
|
|
||||||
|
//Return the recursive mutex.
|
||||||
|
mutex& kmlock()
|
||||||
|
{
|
||||||
|
static mutex& m = mutex::aquire_rec();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
class kmlock_hold
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
kmlock_hold() { kmlock().lock(); }
|
||||||
|
~kmlock_hold() { kmlock().unlock(); }
|
||||||
|
private:
|
||||||
|
kmlock_hold(const kmlock_hold& k);
|
||||||
|
kmlock_hold& operator=(const kmlock_hold& k);
|
||||||
|
};
|
||||||
|
|
||||||
//Returns orig if not linked.
|
//Returns orig if not linked.
|
||||||
const modifier* get_linked_modifier(const modifier* orig)
|
const modifier* get_linked_modifier(const modifier* orig)
|
||||||
{
|
{
|
||||||
|
@ -90,23 +107,27 @@ namespace
|
||||||
|
|
||||||
modifier::modifier(const std::string& name) throw(std::bad_alloc)
|
modifier::modifier(const std::string& name) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
known_modifiers()[modname = name] = this;
|
known_modifiers()[modname = name] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier::modifier(const std::string& name, const std::string& linkgroup) throw(std::bad_alloc)
|
modifier::modifier(const std::string& name, const std::string& linkgroup) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
known_modifiers()[modname = name] = this;
|
known_modifiers()[modname = name] = this;
|
||||||
modifier_linkages()[name] = linkgroup;
|
modifier_linkages()[name] = linkgroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier::~modifier() throw()
|
modifier::~modifier() throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
known_modifiers().erase(modname);
|
known_modifiers().erase(modname);
|
||||||
modifier_linkages().erase(modname);
|
modifier_linkages().erase(modname);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<std::string> modifier::get_set() throw(std::bad_alloc)
|
std::set<std::string> modifier::get_set() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
std::set<std::string> r;
|
std::set<std::string> r;
|
||||||
for(auto i : known_modifiers())
|
for(auto i : known_modifiers())
|
||||||
r.insert(i.first);
|
r.insert(i.first);
|
||||||
|
@ -115,6 +136,7 @@ std::set<std::string> modifier::get_set() throw(std::bad_alloc)
|
||||||
|
|
||||||
modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::runtime_error)
|
modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(!known_modifiers().count(name)) {
|
if(!known_modifiers().count(name)) {
|
||||||
std::ostringstream x;
|
std::ostringstream x;
|
||||||
x << "Invalid modifier '" << name << "'";
|
x << "Invalid modifier '" << name << "'";
|
||||||
|
@ -125,11 +147,13 @@ modifier& modifier::lookup(const std::string& name) throw(std::bad_alloc, std::r
|
||||||
|
|
||||||
std::string modifier::name() const throw(std::bad_alloc)
|
std::string modifier::name() const throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return modname;
|
return modname;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string modifier::linked_name() const throw(std::bad_alloc)
|
std::string modifier::linked_name() const throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
const modifier* p = get_linked_modifier(this);
|
const modifier* p = get_linked_modifier(this);
|
||||||
if(p == this)
|
if(p == this)
|
||||||
return "";
|
return "";
|
||||||
|
@ -139,18 +163,21 @@ std::string modifier::linked_name() const throw(std::bad_alloc)
|
||||||
|
|
||||||
void modifier_set::add(const modifier& mod, bool really) throw(std::bad_alloc)
|
void modifier_set::add(const modifier& mod, bool really) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(really)
|
if(really)
|
||||||
set.insert(&mod);
|
set.insert(&mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void modifier_set::remove(const modifier& mod, bool really) throw(std::bad_alloc)
|
void modifier_set::remove(const modifier& mod, bool really) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(really)
|
if(really)
|
||||||
set.erase(&mod);
|
set.erase(&mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier_set modifier_set::construct(const std::string& _modifiers) throw(std::bad_alloc, std::runtime_error)
|
modifier_set modifier_set::construct(const std::string& _modifiers) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
modifier_set set;
|
modifier_set set;
|
||||||
std::string modifiers = _modifiers;
|
std::string modifiers = _modifiers;
|
||||||
while(modifiers != "") {
|
while(modifiers != "") {
|
||||||
|
@ -169,6 +196,7 @@ modifier_set modifier_set::construct(const std::string& _modifiers) throw(std::b
|
||||||
|
|
||||||
bool modifier_set::valid(const modifier_set& set, const modifier_set& mask) throw(std::bad_alloc)
|
bool modifier_set::valid(const modifier_set& set, const modifier_set& mask) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
//No element can be together with its linkage group.
|
//No element can be together with its linkage group.
|
||||||
for(auto i : set.set) {
|
for(auto i : set.set) {
|
||||||
const modifier* j = get_linked_modifier(i);
|
const modifier* j = get_linked_modifier(i);
|
||||||
|
@ -191,6 +219,7 @@ bool modifier_set::valid(const modifier_set& set, const modifier_set& mask) thro
|
||||||
|
|
||||||
bool modifier_set::operator==(const modifier_set& m) const throw()
|
bool modifier_set::operator==(const modifier_set& m) const throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
for(auto i : set)
|
for(auto i : set)
|
||||||
if(!m.set.count(i))
|
if(!m.set.count(i))
|
||||||
return false;
|
return false;
|
||||||
|
@ -202,6 +231,7 @@ bool modifier_set::operator==(const modifier_set& m) const throw()
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const modifier_set& m)
|
std::ostream& operator<<(std::ostream& os, const modifier_set& m)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
os << "<modset:";
|
os << "<modset:";
|
||||||
for(auto i : m.set)
|
for(auto i : m.set)
|
||||||
os << i->name() << " ";
|
os << i->name() << " ";
|
||||||
|
@ -212,6 +242,7 @@ std::ostream& operator<<(std::ostream& os, const modifier_set& m)
|
||||||
bool modifier_set::triggers(const modifier_set& set, const modifier_set& trigger, const modifier_set& mask)
|
bool modifier_set::triggers(const modifier_set& set, const modifier_set& trigger, const modifier_set& mask)
|
||||||
throw(std::bad_alloc)
|
throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
for(auto i : mask.set) {
|
for(auto i : mask.set) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
//OK iff at least one of:
|
//OK iff at least one of:
|
||||||
|
@ -254,16 +285,19 @@ bool modifier_set::triggers(const modifier_set& set, const modifier_set& trigger
|
||||||
|
|
||||||
std::string keygroup::name() throw(std::bad_alloc)
|
std::string keygroup::name() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return keyname;
|
return keyname;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& keygroup::get_class()
|
const std::string& keygroup::get_class()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct keygroup::parameters keygroup::get_parameters()
|
struct keygroup::parameters keygroup::get_parameters()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
parameters p;
|
parameters p;
|
||||||
p.ktype = ktype;
|
p.ktype = ktype;
|
||||||
p.cal_left = cal_left;
|
p.cal_left = cal_left;
|
||||||
|
@ -276,6 +310,7 @@ struct keygroup::parameters keygroup::get_parameters()
|
||||||
|
|
||||||
std::map<std::string, struct keygroup::parameters> keygroup::get_all_parameters()
|
std::map<std::string, struct keygroup::parameters> keygroup::get_all_parameters()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
std::map<std::string, struct parameters> ret;
|
std::map<std::string, struct parameters> ret;
|
||||||
for(auto i : keygroups())
|
for(auto i : keygroups())
|
||||||
ret[i.first] = i.second->get_parameters();
|
ret[i.first] = i.second->get_parameters();
|
||||||
|
@ -284,6 +319,7 @@ std::map<std::string, struct keygroup::parameters> keygroup::get_all_parameters(
|
||||||
|
|
||||||
keygroup::keygroup(const std::string& name, const std::string& _clazz, enum type t) throw(std::bad_alloc)
|
keygroup::keygroup(const std::string& name, const std::string& _clazz, enum type t) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
keygroups()[keyname = name] = this;
|
keygroups()[keyname = name] = this;
|
||||||
clazz = _clazz;
|
clazz = _clazz;
|
||||||
ktype = t;
|
ktype = t;
|
||||||
|
@ -298,11 +334,13 @@ keygroup::keygroup(const std::string& name, const std::string& _clazz, enum type
|
||||||
|
|
||||||
keygroup::~keygroup() throw()
|
keygroup::~keygroup() throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
keygroups().erase(keyname);
|
keygroups().erase(keyname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void keygroup::change_type(enum type t) throw()
|
void keygroup::change_type(enum type t) throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
ktype = t;
|
ktype = t;
|
||||||
state = 0;
|
state = 0;
|
||||||
if(requests_hook)
|
if(requests_hook)
|
||||||
|
@ -311,6 +349,7 @@ void keygroup::change_type(enum type t) throw()
|
||||||
|
|
||||||
void keygroup::request_hook_callback(bool state)
|
void keygroup::request_hook_callback(bool state)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
requests_hook = state;
|
requests_hook = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,6 +357,7 @@ void keygroup::request_hook_callback(bool state)
|
||||||
std::pair<keygroup*, unsigned> keygroup::lookup(const std::string& name) throw(std::bad_alloc,
|
std::pair<keygroup*, unsigned> keygroup::lookup(const std::string& name) throw(std::bad_alloc,
|
||||||
std::runtime_error)
|
std::runtime_error)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(keygroups().count(name))
|
if(keygroups().count(name))
|
||||||
return std::make_pair(keygroups()[name], 0);
|
return std::make_pair(keygroups()[name], 0);
|
||||||
std::string prefix = name;
|
std::string prefix = name;
|
||||||
|
@ -344,6 +384,7 @@ std::pair<keygroup*, unsigned> keygroup::lookup(const std::string& name) throw(s
|
||||||
|
|
||||||
void keygroup::change_calibration(short left, short center, short right, double tolerance)
|
void keygroup::change_calibration(short left, short center, short right, double tolerance)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
cal_left = left;
|
cal_left = left;
|
||||||
cal_center = center;
|
cal_center = center;
|
||||||
cal_right = right;
|
cal_right = right;
|
||||||
|
@ -354,6 +395,7 @@ void keygroup::change_calibration(short left, short center, short right, double
|
||||||
|
|
||||||
double keygroup::compensate(short value)
|
double keygroup::compensate(short value)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(ktype == KT_HAT || ktype == KT_KEY || ktype == KT_DISABLED || ktype == KT_MOUSE)
|
if(ktype == KT_HAT || ktype == KT_KEY || ktype == KT_DISABLED || ktype == KT_MOUSE)
|
||||||
return value; //These can't be calibrated.
|
return value; //These can't be calibrated.
|
||||||
if(value <= cal_left)
|
if(value <= cal_left)
|
||||||
|
@ -370,6 +412,7 @@ double keygroup::compensate(short value)
|
||||||
|
|
||||||
double keygroup::compensate2(double value)
|
double keygroup::compensate2(double value)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
switch(ktype) {
|
switch(ktype) {
|
||||||
case KT_DISABLED:
|
case KT_DISABLED:
|
||||||
case KT_MOUSE:
|
case KT_MOUSE:
|
||||||
|
@ -398,6 +441,7 @@ double keygroup::compensate2(double value)
|
||||||
|
|
||||||
void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
|
void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
last_rawval = pos;
|
last_rawval = pos;
|
||||||
if(requests_hook)
|
if(requests_hook)
|
||||||
lua_callback_keyhook(keyname, get_parameters());
|
lua_callback_keyhook(keyname, get_parameters());
|
||||||
|
@ -460,10 +504,14 @@ void keygroup::set_position(short pos, const modifier_set& modifiers) throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
void keygroup::run_listeners(const modifier_set& modifiers, unsigned subkey, bool polarity, bool really, double x)
|
void keygroup::run_listeners(const modifier_set& modifiers, unsigned subkey, bool polarity, bool really, double x)
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
modifier_set _modifiers = modifiers;
|
||||||
{
|
{
|
||||||
if(!really)
|
if(!really)
|
||||||
return;
|
return;
|
||||||
std::string name = keyname;
|
kmlock_hold lck;
|
||||||
|
name = keyname;
|
||||||
if(ktype == KT_AXIS_PAIR && subkey == 0)
|
if(ktype == KT_AXIS_PAIR && subkey == 0)
|
||||||
name = name + "+";
|
name = name + "+";
|
||||||
if(ktype == KT_AXIS_PAIR && subkey == 1)
|
if(ktype == KT_AXIS_PAIR && subkey == 1)
|
||||||
|
@ -476,11 +524,13 @@ void keygroup::run_listeners(const modifier_set& modifiers, unsigned subkey, boo
|
||||||
name = name + "s";
|
name = name + "s";
|
||||||
if(ktype == KT_HAT && subkey == 3)
|
if(ktype == KT_HAT && subkey == 3)
|
||||||
name = name + "w";
|
name = name + "w";
|
||||||
information_dispatch::do_key_event(modifiers, *this, subkey, polarity, name);
|
}
|
||||||
|
information_dispatch::do_key_event(_modifiers, *this, subkey, polarity, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
keygroup* keygroup::lookup_by_name(const std::string& name) throw()
|
keygroup* keygroup::lookup_by_name(const std::string& name) throw()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(keygroups().count(name))
|
if(keygroups().count(name))
|
||||||
return keygroups()[name];
|
return keygroups()[name];
|
||||||
else
|
else
|
||||||
|
@ -489,6 +539,7 @@ keygroup* keygroup::lookup_by_name(const std::string& name) throw()
|
||||||
|
|
||||||
std::set<std::string> keygroup::get_axis_set() throw(std::bad_alloc)
|
std::set<std::string> keygroup::get_axis_set() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
std::set<std::string> r;
|
std::set<std::string> r;
|
||||||
for(auto i : keygroups()) {
|
for(auto i : keygroups()) {
|
||||||
keygroup::parameters p = i.second->get_parameters();
|
keygroup::parameters p = i.second->get_parameters();
|
||||||
|
@ -514,6 +565,7 @@ std::set<std::string> keygroup::get_axis_set() throw(std::bad_alloc)
|
||||||
|
|
||||||
std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
|
std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
std::set<std::string> r;
|
std::set<std::string> r;
|
||||||
for(auto i : keygroups()) {
|
for(auto i : keygroups()) {
|
||||||
switch(i.second->ktype) {
|
switch(i.second->ktype) {
|
||||||
|
@ -546,12 +598,12 @@ std::set<std::string> keygroup::get_keys() throw(std::bad_alloc)
|
||||||
|
|
||||||
signed keygroup::get_value()
|
signed keygroup::get_value()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
function_ptr_command<const std::string&> set_axis("set-axis", "Set mode of Joystick axis",
|
function_ptr_command<const std::string&> set_axis("set-axis", "Set mode of Joystick axis",
|
||||||
"Syntax: set-axis <axis> <options>...\nKnown options: disabled, axis, axis-inverse, pressure0-\n"
|
"Syntax: set-axis <axis> <options>...\nKnown options: disabled, axis, axis-inverse, pressure0-\n"
|
||||||
"pressure0+, pressure-0, pressure-+, pressure+0, pressure+-\nminus=<val>, zero=<val>, plus=<val>\n"
|
"pressure0+, pressure-0, pressure-+, pressure+0, pressure+-\nminus=<val>, zero=<val>, plus=<val>\n"
|
||||||
|
@ -721,6 +773,7 @@ namespace
|
||||||
|
|
||||||
std::map<triple, keybind_data*>& keybindings()
|
std::map<triple, keybind_data*>& keybindings()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
static std::map<triple, keybind_data*> x;
|
static std::map<triple, keybind_data*> x;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -729,6 +782,8 @@ namespace
|
||||||
void keymapper::bind(std::string mod, std::string modmask, std::string keyname, std::string command)
|
void keymapper::bind(std::string mod, std::string modmask, std::string keyname, std::string command)
|
||||||
throw(std::bad_alloc, std::runtime_error)
|
throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
triple k(mod, modmask, keyname);
|
triple k(mod, modmask, keyname);
|
||||||
modifier_set _mod = modifier_set::construct(mod);
|
modifier_set _mod = modifier_set::construct(mod);
|
||||||
modifier_set _modmask = modifier_set::construct(modmask);
|
modifier_set _modmask = modifier_set::construct(modmask);
|
||||||
|
@ -743,21 +798,26 @@ void keymapper::bind(std::string mod, std::string modmask, std::string keyname,
|
||||||
keybindings()[k]->subkey = g.second;
|
keybindings()[k]->subkey = g.second;
|
||||||
}
|
}
|
||||||
keybindings()[k]->command = command;
|
keybindings()[k]->command = command;
|
||||||
|
}
|
||||||
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, command);
|
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, command);
|
||||||
}
|
}
|
||||||
void keymapper::unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc,
|
void keymapper::unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc,
|
||||||
std::runtime_error)
|
std::runtime_error)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
triple k(mod, modmask, keyname);
|
triple k(mod, modmask, keyname);
|
||||||
if(!keybindings().count(k))
|
if(!keybindings().count(k))
|
||||||
throw std::runtime_error("Key is not bound");
|
throw std::runtime_error("Key is not bound");
|
||||||
delete keybindings()[k];
|
delete keybindings()[k];
|
||||||
keybindings().erase(k);
|
keybindings().erase(k);
|
||||||
|
}
|
||||||
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, "");
|
inverse_key::notify_update(mod + "/" + modmask + "|" + keyname, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void keymapper::dumpbindings() throw(std::bad_alloc)
|
void keymapper::dumpbindings() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
for(auto i : keybindings()) {
|
for(auto i : keybindings()) {
|
||||||
messages << "bind-key ";
|
messages << "bind-key ";
|
||||||
if(i.first.a != "" || i.first.b != "")
|
if(i.first.a != "" || i.first.b != "")
|
||||||
|
@ -768,6 +828,7 @@ void keymapper::dumpbindings() throw(std::bad_alloc)
|
||||||
|
|
||||||
std::set<std::string> keymapper::get_bindings() throw(std::bad_alloc)
|
std::set<std::string> keymapper::get_bindings() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
std::set<std::string> r;
|
std::set<std::string> r;
|
||||||
for(auto i : keybindings())
|
for(auto i : keybindings())
|
||||||
r.insert(i.first.a + "/" + i.first.b + "|" + i.first.c);
|
r.insert(i.first.a + "/" + i.first.b + "|" + i.first.c);
|
||||||
|
@ -776,6 +837,7 @@ std::set<std::string> keymapper::get_bindings() throw(std::bad_alloc)
|
||||||
|
|
||||||
std::string keymapper::get_command_for(const std::string& keyspec) throw(std::bad_alloc)
|
std::string keymapper::get_command_for(const std::string& keyspec) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
triple k("", "", "");
|
triple k("", "", "");
|
||||||
try {
|
try {
|
||||||
k = parse_to_triple(keyspec);
|
k = parse_to_triple(keyspec);
|
||||||
|
@ -800,6 +862,7 @@ void keymapper::bind_for(const std::string& keyspec, const std::string& cmd) thr
|
||||||
|
|
||||||
inverse_key::inverse_key(const std::string& command, const std::string& name) throw(std::bad_alloc)
|
inverse_key::inverse_key(const std::string& command, const std::string& name) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
cmd = command;
|
cmd = command;
|
||||||
oname = name;
|
oname = name;
|
||||||
ikeys().insert(this);
|
ikeys().insert(this);
|
||||||
|
@ -813,44 +876,52 @@ inverse_key::inverse_key(const std::string& command, const std::string& name) th
|
||||||
|
|
||||||
inverse_key::~inverse_key()
|
inverse_key::~inverse_key()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
ikeys().erase(this);
|
ikeys().erase(this);
|
||||||
forkey().erase(cmd);
|
forkey().erase(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<inverse_key*> inverse_key::get_ikeys() throw(std::bad_alloc)
|
std::set<inverse_key*> inverse_key::get_ikeys() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return ikeys();
|
return ikeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string inverse_key::getname() throw(std::bad_alloc)
|
std::string inverse_key::getname() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return oname;
|
return oname;
|
||||||
}
|
}
|
||||||
|
|
||||||
inverse_key* inverse_key::get_for(const std::string& command) throw(std::bad_alloc)
|
inverse_key* inverse_key::get_for(const std::string& command) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return forkey().count(command) ? forkey()[command] : NULL;
|
return forkey().count(command) ? forkey()[command] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<inverse_key*>& inverse_key::ikeys()
|
std::set<inverse_key*>& inverse_key::ikeys()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
static std::set<inverse_key*> x;
|
static std::set<inverse_key*> x;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, inverse_key*>& inverse_key::forkey()
|
std::map<std::string, inverse_key*>& inverse_key::forkey()
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
static std::map<std::string, inverse_key*> x;
|
static std::map<std::string, inverse_key*> x;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string inverse_key::get(bool primary) throw(std::bad_alloc)
|
std::string inverse_key::get(bool primary) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
return primary ? primary_spec : secondary_spec;
|
return primary ? primary_spec : secondary_spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void inverse_key::clear(bool primary) throw(std::bad_alloc)
|
void inverse_key::clear(bool primary) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(primary) {
|
if(primary) {
|
||||||
if(primary_spec != "")
|
if(primary_spec != "")
|
||||||
keymapper::bind_for(primary_spec, "");
|
keymapper::bind_for(primary_spec, "");
|
||||||
|
@ -870,6 +941,7 @@ void inverse_key::clear(bool primary) throw(std::bad_alloc)
|
||||||
|
|
||||||
void inverse_key::set(std::string keyspec, bool primary) throw(std::bad_alloc)
|
void inverse_key::set(std::string keyspec, bool primary) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(keyspec == "") {
|
if(keyspec == "") {
|
||||||
clear(primary);
|
clear(primary);
|
||||||
return;
|
return;
|
||||||
|
@ -891,6 +963,7 @@ void inverse_key::set(std::string keyspec, bool primary) throw(std::bad_alloc)
|
||||||
|
|
||||||
void inverse_key::addkey(const std::string& keyspec)
|
void inverse_key::addkey(const std::string& keyspec)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
if(primary_spec == "" || primary_spec == keyspec)
|
if(primary_spec == "" || primary_spec == keyspec)
|
||||||
primary_spec = keyspec;
|
primary_spec = keyspec;
|
||||||
else if(secondary_spec == "")
|
else if(secondary_spec == "")
|
||||||
|
@ -899,6 +972,7 @@ void inverse_key::addkey(const std::string& keyspec)
|
||||||
|
|
||||||
void inverse_key::notify_update(const std::string& keyspec, const std::string& command)
|
void inverse_key::notify_update(const std::string& keyspec, const std::string& command)
|
||||||
{
|
{
|
||||||
|
kmlock_hold lck;
|
||||||
for(auto k : ikeys()) {
|
for(auto k : ikeys()) {
|
||||||
bool u = false;
|
bool u = false;
|
||||||
if(k->primary_spec == keyspec || k->secondary_spec == keyspec) {
|
if(k->primary_spec == keyspec || k->secondary_spec == keyspec) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ namespace
|
||||||
}
|
}
|
||||||
operator std::string() throw()
|
operator std::string() throw()
|
||||||
{
|
{
|
||||||
|
lock_holder lck(this);
|
||||||
if(_set)
|
if(_set)
|
||||||
return prefix + "-";
|
return prefix + "-";
|
||||||
else
|
else
|
||||||
|
|
|
@ -50,24 +50,55 @@ namespace
|
||||||
messages << i << ": " << setting::get(i) << std::endl;
|
messages << i << ": " << setting::get(i) << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Return the mutex.
|
||||||
|
mutex& stlock()
|
||||||
|
{
|
||||||
|
static mutex& m = mutex::aquire();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
class stlock_hold
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
stlock_hold() { stlock().lock(); }
|
||||||
|
~stlock_hold() { stlock().unlock(); }
|
||||||
|
private:
|
||||||
|
stlock_hold(const stlock_hold& k);
|
||||||
|
stlock_hold& operator=(const stlock_hold& k);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setting::setting(const std::string& name) throw(std::bad_alloc)
|
setting::setting(const std::string& name) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
|
stlock_hold lck;
|
||||||
|
mut = &mutex::aquire();
|
||||||
settings()[settingname = name] = this;
|
settings()[settingname = name] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting::~setting() throw()
|
setting::~setting() throw()
|
||||||
{
|
{
|
||||||
|
stlock_hold lck;
|
||||||
|
delete mut;
|
||||||
settings().erase(settingname);
|
settings().erase(settingname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setting* setting::get_by_name(const std::string& name)
|
||||||
|
{
|
||||||
|
stlock_hold lck;
|
||||||
|
if(!settings().count(name))
|
||||||
|
throw std::runtime_error("No such setting '" + name + "'");
|
||||||
|
return settings()[name];
|
||||||
|
}
|
||||||
|
|
||||||
void setting::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc, std::runtime_error)
|
void setting::set(const std::string& _setting, const std::string& value) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if(!settings().count(_setting))
|
setting* tochange = get_by_name(_setting);
|
||||||
throw std::runtime_error("No such setting '" + _setting + "'");
|
|
||||||
try {
|
try {
|
||||||
settings()[_setting]->set(value);
|
{
|
||||||
|
lock_holder lck(tochange);
|
||||||
|
tochange->set(value);
|
||||||
|
}
|
||||||
information_dispatch::do_setting_change(_setting, value);
|
information_dispatch::do_setting_change(_setting, value);
|
||||||
} catch(std::bad_alloc& e) {
|
} catch(std::bad_alloc& e) {
|
||||||
throw;
|
throw;
|
||||||
|
@ -83,10 +114,12 @@ bool setting::blank(bool really) throw(std::bad_alloc, std::runtime_error)
|
||||||
|
|
||||||
bool setting::blankable(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
bool setting::blankable(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if(!settings().count(_setting))
|
setting* tochange = get_by_name(_setting);
|
||||||
throw std::runtime_error("No such setting '" + _setting + "'");
|
|
||||||
try {
|
try {
|
||||||
return settings()[_setting]->blank(false);
|
{
|
||||||
|
lock_holder lck(tochange);
|
||||||
|
return tochange->blank(false);
|
||||||
|
}
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -94,11 +127,13 @@ bool setting::blankable(const std::string& _setting) throw(std::bad_alloc, std::
|
||||||
|
|
||||||
void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if(!settings().count(_setting))
|
setting* tochange = get_by_name(_setting);
|
||||||
throw std::runtime_error("No such setting '" + _setting + "'");
|
|
||||||
try {
|
try {
|
||||||
if(!settings()[_setting]->blank(true))
|
{
|
||||||
|
lock_holder lck(tochange);
|
||||||
|
if(!tochange->blank(true))
|
||||||
throw std::runtime_error("This setting can't be cleared");
|
throw std::runtime_error("This setting can't be cleared");
|
||||||
|
}
|
||||||
information_dispatch::do_setting_clear(_setting);
|
information_dispatch::do_setting_clear(_setting);
|
||||||
} catch(std::bad_alloc& e) {
|
} catch(std::bad_alloc& e) {
|
||||||
throw;
|
throw;
|
||||||
|
@ -109,16 +144,20 @@ void setting::blank(const std::string& _setting) throw(std::bad_alloc, std::runt
|
||||||
|
|
||||||
std::string setting::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
std::string setting::get(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if(!settings().count(_setting))
|
setting* tochange = get_by_name(_setting);
|
||||||
throw std::runtime_error("No such setting '" + _setting + "'");
|
{
|
||||||
return settings()[_setting]->get();
|
lock_holder lck(tochange);
|
||||||
|
return tochange->get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setting::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
bool setting::is_set(const std::string& _setting) throw(std::bad_alloc, std::runtime_error)
|
||||||
{
|
{
|
||||||
if(!settings().count(_setting))
|
setting* tochange = get_by_name(_setting);
|
||||||
throw std::runtime_error("No such setting '" + _setting + "'");
|
{
|
||||||
return settings()[_setting]->is_set();
|
lock_holder lck(tochange);
|
||||||
|
return tochange->is_set();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<std::string> setting::get_settings_set() throw(std::bad_alloc)
|
std::set<std::string> setting::get_settings_set() throw(std::bad_alloc)
|
||||||
|
@ -164,6 +203,7 @@ std::string numeric_setting::get() throw(std::bad_alloc)
|
||||||
|
|
||||||
numeric_setting::operator int32_t() throw()
|
numeric_setting::operator int32_t() throw()
|
||||||
{
|
{
|
||||||
|
lock_holder lck(this);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +242,7 @@ std::string boolean_setting::get() throw(std::bad_alloc)
|
||||||
|
|
||||||
boolean_setting::operator bool() throw()
|
boolean_setting::operator bool() throw()
|
||||||
{
|
{
|
||||||
|
lock_holder lck(this);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,5 +285,6 @@ std::string path_setting::get() throw(std::bad_alloc)
|
||||||
|
|
||||||
path_setting::operator std::string()
|
path_setting::operator std::string()
|
||||||
{
|
{
|
||||||
|
lock_holder lck(this);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
|
@ -13,6 +13,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <boost/iostreams/categories.hpp>
|
#include <boost/iostreams/categories.hpp>
|
||||||
#include <boost/iostreams/copy.hpp>
|
#include <boost/iostreams/copy.hpp>
|
||||||
#include <boost/iostreams/stream.hpp>
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
@ -118,6 +120,7 @@ keypress::keypress(modifier_set mod, keygroup& _key, keygroup& _key2, short _val
|
||||||
value = _value;
|
value = _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile bool platform::do_exit_dummy_event_loop = false;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -298,6 +301,7 @@ bool platform::is_sound_enabled() throw()
|
||||||
|
|
||||||
void platform::init()
|
void platform::init()
|
||||||
{
|
{
|
||||||
|
do_exit_dummy_event_loop = false;
|
||||||
msgbuf.register_handler(msg_callback_obj);
|
msgbuf.register_handler(msg_callback_obj);
|
||||||
system_log.open("lsnes.log", std::ios_base::out | std::ios_base::app);
|
system_log.open("lsnes.log", std::ios_base::out | std::ios_base::app);
|
||||||
time_t curtime = time(NULL);
|
time_t curtime = time(NULL);
|
||||||
|
@ -449,6 +453,24 @@ namespace
|
||||||
|
|
||||||
#define MAXWAIT 100000ULL
|
#define MAXWAIT 100000ULL
|
||||||
|
|
||||||
|
void platform::dummy_event_loop() throw()
|
||||||
|
{
|
||||||
|
init_threading();
|
||||||
|
while(!do_exit_dummy_event_loop) {
|
||||||
|
mutex::holder h(*queue_lock);
|
||||||
|
internal_run_queues(true);
|
||||||
|
queue_condition->wait(MAXWAIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void platform::exit_dummy_event_loop() throw()
|
||||||
|
{
|
||||||
|
init_threading();
|
||||||
|
do_exit_dummy_event_loop = true;
|
||||||
|
mutex::holder h(*queue_lock);
|
||||||
|
queue_condition->signal();
|
||||||
|
usleep(200000);
|
||||||
|
}
|
||||||
|
|
||||||
void platform::flush_command_queue() throw()
|
void platform::flush_command_queue() throw()
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,11 @@ mutex& mutex::aquire() throw(std::bad_alloc)
|
||||||
return *new dummy_mutex();
|
return *new dummy_mutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
return *new dummy_mutex();
|
||||||
|
}
|
||||||
|
|
||||||
struct dummy_condition : public condition
|
struct dummy_condition : public condition
|
||||||
{
|
{
|
||||||
dummy_condition(mutex& m);
|
dummy_condition(mutex& m);
|
||||||
|
|
|
@ -208,9 +208,6 @@ namespace
|
||||||
unsigned long axes[(ABS_MAX + div) / div] = {0};
|
unsigned long axes[(ABS_MAX + div) / div] = {0};
|
||||||
unsigned long evtypes[(EV_MAX + div) / div] = {0};
|
unsigned long evtypes[(EV_MAX + div) / div] = {0};
|
||||||
char namebuffer[256];
|
char namebuffer[256];
|
||||||
unsigned button_count = 0;
|
|
||||||
unsigned axis_count = 0;
|
|
||||||
unsigned hat_count = 0;
|
|
||||||
if(ioctl(fd, EVIOCGBIT(0, sizeof(evtypes)), evtypes) < 0) {
|
if(ioctl(fd, EVIOCGBIT(0, sizeof(evtypes)), evtypes) < 0) {
|
||||||
int merrno = errno;
|
int merrno = errno;
|
||||||
messages << "Error probing joystick (evmap; " << filename << "): " << strerror(merrno)
|
messages << "Error probing joystick (evmap; " << filename << "): " << strerror(merrno)
|
||||||
|
@ -240,13 +237,10 @@ namespace
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
joystick_create(fd, namebuffer);
|
joystick_create(fd, namebuffer);
|
||||||
for(unsigned i = 0; i <= KEY_MAX; i++) {
|
for(unsigned i = 0; i <= KEY_MAX; i++)
|
||||||
if(keys[i / div] & (1ULL << (i % div))) {
|
if(keys[i / div] & (1ULL << (i % div)))
|
||||||
joystick_new_button(fd, i, get_button_name(i));
|
joystick_new_button(fd, i, get_button_name(i));
|
||||||
button_count++;
|
for(unsigned i = 0; i <= ABS_MAX; i++)
|
||||||
}
|
|
||||||
}
|
|
||||||
for(unsigned i = 0; i <= ABS_MAX; i++) {
|
|
||||||
if(axes[i / div] & (1ULL << (i % div))) {
|
if(axes[i / div] & (1ULL << (i % div))) {
|
||||||
if(i < ABS_HAT0X || i > ABS_HAT3Y) {
|
if(i < ABS_HAT0X || i > ABS_HAT3Y) {
|
||||||
int32_t V[5];
|
int32_t V[5];
|
||||||
|
@ -258,12 +252,8 @@ namespace
|
||||||
}
|
}
|
||||||
joystick_new_axis(fd, i, V[1], V[2], get_axis_name(i),
|
joystick_new_axis(fd, i, V[1], V[2], get_axis_name(i),
|
||||||
(V[1] < 0) ? keygroup::KT_AXIS_PAIR : keygroup::KT_PRESSURE_MP);
|
(V[1] < 0) ? keygroup::KT_AXIS_PAIR : keygroup::KT_PRESSURE_MP);
|
||||||
axis_count++;
|
} else if(i % 2 == 0)
|
||||||
} else if(i % 2 == 0) {
|
|
||||||
joystick_new_hat(fd, i, i + 1, 1, get_axis_name(i), get_axis_name(i + 1));
|
joystick_new_hat(fd, i, i + 1, 1, get_axis_name(i), get_axis_name(i + 1));
|
||||||
hat_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
joystick_message(fd);
|
joystick_message(fd);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -13,6 +13,18 @@ struct sdl_mutex : public mutex
|
||||||
SDL_mutex* m;
|
SDL_mutex* m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sdl_rec_mutex : public mutex
|
||||||
|
{
|
||||||
|
sdl_rec_mutex() throw(std::bad_alloc);
|
||||||
|
~sdl_rec_mutex() throw();
|
||||||
|
void lock() throw();
|
||||||
|
void unlock() throw();
|
||||||
|
SDL_mutex* m;
|
||||||
|
volatile bool locked;
|
||||||
|
uint32_t owner;
|
||||||
|
uint32_t count;
|
||||||
|
};
|
||||||
|
|
||||||
sdl_mutex::sdl_mutex() throw(std::bad_alloc)
|
sdl_mutex::sdl_mutex() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
m = SDL_CreateMutex();
|
m = SDL_CreateMutex();
|
||||||
|
@ -25,6 +37,21 @@ sdl_mutex::~sdl_mutex() throw()
|
||||||
SDL_DestroyMutex(m);
|
SDL_DestroyMutex(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdl_rec_mutex::sdl_rec_mutex() throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
m = SDL_CreateMutex();
|
||||||
|
if(!m)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
locked = false;
|
||||||
|
owner = 0;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sdl_rec_mutex::~sdl_rec_mutex() throw()
|
||||||
|
{
|
||||||
|
SDL_DestroyMutex(m);
|
||||||
|
}
|
||||||
|
|
||||||
void sdl_mutex::lock() throw()
|
void sdl_mutex::lock() throw()
|
||||||
{
|
{
|
||||||
SDL_mutexP(m);
|
SDL_mutexP(m);
|
||||||
|
@ -35,11 +62,42 @@ void sdl_mutex::unlock() throw()
|
||||||
SDL_mutexV(m);
|
SDL_mutexV(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sdl_rec_mutex::lock() throw()
|
||||||
|
{
|
||||||
|
uint32_t our_id = SDL_ThreadID();
|
||||||
|
if(locked && owner == our_id) {
|
||||||
|
//Owned by us, increment lock count.
|
||||||
|
++count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SDL_mutexP(m);
|
||||||
|
locked = true;
|
||||||
|
owner = our_id;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdl_rec_mutex::unlock() throw()
|
||||||
|
{
|
||||||
|
uint32_t our_id = SDL_ThreadID();
|
||||||
|
if(!locked || owner != our_id)
|
||||||
|
std::cerr << "Warning: Trying to unlock recursive lock locked by another thread!" << std::endl;
|
||||||
|
if(!--count) {
|
||||||
|
locked = false;
|
||||||
|
owner = 0;
|
||||||
|
SDL_mutexV(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex& mutex::aquire() throw(std::bad_alloc)
|
mutex& mutex::aquire() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
return *new sdl_mutex;
|
return *new sdl_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
return *new sdl_rec_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
struct sdl_condition : public condition
|
struct sdl_condition : public condition
|
||||||
{
|
{
|
||||||
sdl_condition(mutex& m) throw(std::bad_alloc);
|
sdl_condition(mutex& m) throw(std::bad_alloc);
|
||||||
|
|
|
@ -283,6 +283,17 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string map_keycode_to_key(int kcode)
|
||||||
|
{
|
||||||
|
key_entry* k = keys;
|
||||||
|
while(k->name) {
|
||||||
|
if(k->keynum == kcode)
|
||||||
|
return k->name;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void handle_wx_keyboard(wxKeyEvent& e, bool polarity)
|
void handle_wx_keyboard(wxKeyEvent& e, bool polarity)
|
||||||
{
|
{
|
||||||
int mods = e.GetModifiers();
|
int mods = e.GetModifiers();
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/control.h>
|
#include <wx/control.h>
|
||||||
#include <wx/combobox.h>
|
#include <wx/combobox.h>
|
||||||
|
#include <wx/cmdline.h>
|
||||||
|
|
||||||
#define UISERV_RESIZED 9991
|
#define UISERV_RESIZED 9991
|
||||||
#define UISERV_UIFUN 9992
|
#define UISERV_UIFUN 9992
|
||||||
|
@ -232,6 +233,13 @@ end:
|
||||||
std::ofstream lsave(get_config_path() + "/" + our_rom_name + ".ls");
|
std::ofstream lsave(get_config_path() + "/" + our_rom_name + ".ls");
|
||||||
lsave << last_save;
|
lsave << last_save;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* eloop_helper(void* x)
|
||||||
|
{
|
||||||
|
platform::dummy_event_loop();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString towxstring(const std::string& str) throw(std::bad_alloc)
|
wxString towxstring(const std::string& str) throw(std::bad_alloc)
|
||||||
|
@ -287,18 +295,53 @@ void graphics_plugin::quit() throw()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const wxCmdLineEntryDesc dummy_descriptor_table[] = {
|
||||||
|
{ wxCMD_LINE_PARAM, NULL, NULL, NULL, wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL |
|
||||||
|
wxCMD_LINE_PARAM_MULTIPLE },
|
||||||
|
{ wxCMD_LINE_NONE }
|
||||||
|
};
|
||||||
|
|
||||||
class lsnes_app : public wxApp
|
class lsnes_app : public wxApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
lsnes_app();
|
||||||
virtual bool OnInit();
|
virtual bool OnInit();
|
||||||
virtual int OnExit();
|
virtual int OnExit();
|
||||||
|
virtual void OnInitCmdLine(wxCmdLineParser& parser);
|
||||||
|
virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
|
||||||
|
private:
|
||||||
|
bool settings_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_APP(lsnes_app)
|
IMPLEMENT_APP(lsnes_app)
|
||||||
|
|
||||||
|
lsnes_app::lsnes_app()
|
||||||
|
{
|
||||||
|
settings_mode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lsnes_app::OnInitCmdLine(wxCmdLineParser& parser)
|
||||||
|
{
|
||||||
|
parser.SetDesc(dummy_descriptor_table);
|
||||||
|
parser.SetSwitchChars(wxT(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lsnes_app::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||||
|
{
|
||||||
|
std::vector<std::string> cmdline;
|
||||||
|
for(size_t i = 0; i< parser.GetParamCount(); i++)
|
||||||
|
cmdline.push_back(tostdstring(parser.GetParam(i)));
|
||||||
|
for(auto i: cmdline) {
|
||||||
|
if(i == "--settings")
|
||||||
|
settings_mode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool lsnes_app::OnInit()
|
bool lsnes_app::OnInit()
|
||||||
{
|
{
|
||||||
|
wxApp::OnInit();
|
||||||
|
|
||||||
reached_main();
|
reached_main();
|
||||||
set_random_seed();
|
set_random_seed();
|
||||||
bring_app_foreground();
|
bring_app_foreground();
|
||||||
|
@ -309,7 +352,6 @@ bool lsnes_app::OnInit()
|
||||||
|
|
||||||
ui_thread = &thread_id::me();
|
ui_thread = &thread_id::me();
|
||||||
platform::init();
|
platform::init();
|
||||||
init_lua();
|
|
||||||
|
|
||||||
messages << "BSNES version: " << emucore_get_version() << std::endl;
|
messages << "BSNES version: " << emucore_get_version() << std::endl;
|
||||||
messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
|
messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
|
||||||
|
@ -323,6 +365,21 @@ bool lsnes_app::OnInit()
|
||||||
command::invokeC("run-script " + cfgpath + "/lsneswxw.rc");
|
command::invokeC("run-script " + cfgpath + "/lsneswxw.rc");
|
||||||
messages << "--- End running lsnesrc --- " << std::endl;
|
messages << "--- End running lsnesrc --- " << std::endl;
|
||||||
|
|
||||||
|
if(settings_mode) {
|
||||||
|
//We got to boot this up quite a bit to get the joystick driver working.
|
||||||
|
//In practicular, we need joystick thread and emulator thread in pause.
|
||||||
|
joystick_thread_handle = &thread::create(joystick_thread, NULL);
|
||||||
|
thread* dummy_loop = &thread::create(eloop_helper, NULL);
|
||||||
|
wxsetingsdialog_display(NULL);
|
||||||
|
platform::exit_dummy_event_loop();
|
||||||
|
joystick_plugin::signal();
|
||||||
|
joystick_thread_handle->join();
|
||||||
|
dummy_loop->join();
|
||||||
|
save_configuration();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
init_lua();
|
||||||
|
|
||||||
joystick_thread_handle = &thread::create(joystick_thread, NULL);
|
joystick_thread_handle = &thread::create(joystick_thread, NULL);
|
||||||
|
|
||||||
msg_window = new wxwin_messages();
|
msg_window = new wxwin_messages();
|
||||||
|
@ -335,12 +392,14 @@ bool lsnes_app::OnInit()
|
||||||
|
|
||||||
int lsnes_app::OnExit()
|
int lsnes_app::OnExit()
|
||||||
{
|
{
|
||||||
|
if(settings_mode)
|
||||||
|
return 0;
|
||||||
//NULL these so no further messages will be sent.
|
//NULL these so no further messages will be sent.
|
||||||
msg_window = NULL;
|
msg_window = NULL;
|
||||||
main_window = NULL;
|
main_window = NULL;
|
||||||
|
save_configuration();
|
||||||
information_dispatch::do_dump_end();
|
information_dispatch::do_dump_end();
|
||||||
rrdata::close();
|
rrdata::close();
|
||||||
save_configuration();
|
|
||||||
joystick_plugin::signal();
|
joystick_plugin::signal();
|
||||||
joystick_thread_handle->join();
|
joystick_thread_handle->join();
|
||||||
platform::quit();
|
platform::quit();
|
||||||
|
|
|
@ -210,9 +210,9 @@ namespace
|
||||||
{
|
{
|
||||||
std::string v = (stringfmt() << target).str();
|
std::string v = (stringfmt() << target).str();
|
||||||
if(target < 0)
|
if(target < 0)
|
||||||
runemufn([]() { setting::set("targetfps", "infinite"); });
|
setting::set("targetfps", "infinite");
|
||||||
else
|
else
|
||||||
runemufn([v]() { setting::set("targetfps", v); });
|
setting::set("targetfps", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
class controller_autohold_menu : public wxMenu
|
class controller_autohold_menu : public wxMenu
|
||||||
|
@ -452,9 +452,7 @@ namespace
|
||||||
|
|
||||||
std::string movie_path()
|
std::string movie_path()
|
||||||
{
|
{
|
||||||
std::string x;
|
return setting::get("moviepath");
|
||||||
runemufn([&x]() { x = setting::get("moviepath"); });
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,13 +960,14 @@ void wxwin_mainwindow::handle_menu_click_cancelable(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case wxID_SET_SPEED: {
|
case wxID_SET_SPEED: {
|
||||||
std::string value;
|
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
runemufn([&value]() { value = setting::is_set("targetfps") ? setting::get("targetfps") : ""; });
|
std::string value = setting::is_set("targetfps") ? setting::get("targetfps") : "";
|
||||||
value = pick_text(this, "Set speed", "Enter percentage speed (or \"infinite\"):", value);
|
value = pick_text(this, "Set speed", "Enter percentage speed (or \"infinite\"):", value);
|
||||||
runemufn([&bad, &value]() { try { setting::set("targetfps", value); } catch(...) { bad = true; } });
|
try {
|
||||||
if(bad)
|
setting::set("targetfps", value);
|
||||||
|
} catch(...) {
|
||||||
wxMessageBox(wxT("Invalid speed"), _T("Error"), wxICON_EXCLAMATION | wxOK, this);
|
wxMessageBox(wxT("Invalid speed"), _T("Error"), wxICON_EXCLAMATION | wxOK, this);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case wxID_SET_VOLUME: {
|
case wxID_SET_VOLUME: {
|
||||||
|
|
|
@ -46,6 +46,154 @@ const char* scalealgo_choices[] = {"Fast Bilinear", "Bilinear", "Bicubic", "Expe
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
class wxdialog_pressbutton;
|
||||||
|
volatile bool keygrab_active = false;
|
||||||
|
std::string pkey;
|
||||||
|
wxdialog_pressbutton* presser = NULL;
|
||||||
|
|
||||||
|
void report_grab_key(const std::string& name);
|
||||||
|
|
||||||
|
class keygrabber : public information_dispatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
keygrabber() : information_dispatch("wxwdigets-key-grabber") { keygrab_active = false; }
|
||||||
|
void on_key_event(const modifier_set& modifiers, keygroup& keygroup, unsigned subkey,
|
||||||
|
bool polarity, const std::string& name)
|
||||||
|
{
|
||||||
|
if(!keygrab_active)
|
||||||
|
return;
|
||||||
|
if(polarity)
|
||||||
|
pkey = name;
|
||||||
|
else {
|
||||||
|
if(pkey == name) {
|
||||||
|
keygrab_active = false;
|
||||||
|
runuifun([pkey]() { report_grab_key(pkey); });
|
||||||
|
} else
|
||||||
|
pkey = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} keygrabber;
|
||||||
|
|
||||||
|
class wxdialog_pressbutton : public wxDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxdialog_pressbutton(wxWindow* parent, const std::string& title);
|
||||||
|
std::string getkey() { return key; }
|
||||||
|
void on_mouse(wxMouseEvent& e);
|
||||||
|
void on_keyboard_up(wxKeyEvent& e);
|
||||||
|
void on_keyboard_down(wxKeyEvent& e);
|
||||||
|
void dismiss_with(const std::string& k);
|
||||||
|
private:
|
||||||
|
bool handle_mousebtn(wxMouseEvent& e, bool(wxMouseEvent::*down)()const, bool(wxMouseEvent::*up)()const,
|
||||||
|
const std::string& k, int flag);
|
||||||
|
std::string key;
|
||||||
|
int mouseflag;
|
||||||
|
int lastkbdkey;
|
||||||
|
};
|
||||||
|
|
||||||
|
void report_grab_key(const std::string& name)
|
||||||
|
{
|
||||||
|
presser->dismiss_with(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vert_padding = 40;
|
||||||
|
int horiz_padding = 60;
|
||||||
|
|
||||||
|
wxdialog_pressbutton::wxdialog_pressbutton(wxWindow* parent, const std::string& title)
|
||||||
|
: wxDialog(parent, wxID_ANY, towxstring(title), wxDefaultPosition, wxSize(-1, -1))
|
||||||
|
{
|
||||||
|
wxStaticText* t;
|
||||||
|
wxBoxSizer* s2 = new wxBoxSizer(wxVERTICAL);
|
||||||
|
wxPanel* p = new wxPanel(this, wxID_ANY);
|
||||||
|
s2->Add(p, 1, wxGROW);
|
||||||
|
lastkbdkey = -1;
|
||||||
|
mouseflag = 0;
|
||||||
|
Centre();
|
||||||
|
wxFlexGridSizer* s = new wxFlexGridSizer(3, 3, 0, 0);
|
||||||
|
p->SetSizer(s);
|
||||||
|
SetSizer(s2);
|
||||||
|
s->Add(horiz_padding, vert_padding);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(t = new wxStaticText(p, wxID_ANY, wxT("Press the key to assign")), 1, wxGROW);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(0, 0);
|
||||||
|
s->Add(horiz_padding, vert_padding);
|
||||||
|
p->SetFocus();
|
||||||
|
p->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(wxdialog_pressbutton::on_keyboard_down), NULL, this);
|
||||||
|
p->Connect(wxEVT_KEY_UP, wxKeyEventHandler(wxdialog_pressbutton::on_keyboard_up), NULL, this);
|
||||||
|
p->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
p->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
p->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
p->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
p->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
p->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(wxdialog_pressbutton::on_keyboard_down), NULL, this);
|
||||||
|
t->Connect(wxEVT_KEY_UP, wxKeyEventHandler(wxdialog_pressbutton::on_keyboard_up), NULL, this);
|
||||||
|
t->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
t->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(wxdialog_pressbutton::on_mouse), NULL, this);
|
||||||
|
presser = this;
|
||||||
|
keygrab_active = true;
|
||||||
|
s->SetSizeHints(this);
|
||||||
|
Fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxdialog_pressbutton::handle_mousebtn(wxMouseEvent& e, bool(wxMouseEvent::*down)()const,
|
||||||
|
bool(wxMouseEvent::*up)()const, const std::string& k, int flag)
|
||||||
|
{
|
||||||
|
if((e.*down)())
|
||||||
|
mouseflag = flag;
|
||||||
|
if((e.*up)()) {
|
||||||
|
if(mouseflag == flag) {
|
||||||
|
dismiss_with(k);
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
mouseflag = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxdialog_pressbutton::on_mouse(wxMouseEvent& e)
|
||||||
|
{
|
||||||
|
handle_mousebtn(e, &wxMouseEvent::LeftDown, &wxMouseEvent::LeftUp, "mouse_left", 1);
|
||||||
|
handle_mousebtn(e, &wxMouseEvent::MiddleDown, &wxMouseEvent::MiddleUp, "mouse_center", 2);
|
||||||
|
handle_mousebtn(e, &wxMouseEvent::RightDown, &wxMouseEvent::RightUp, "mouse_right", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxdialog_pressbutton::on_keyboard_down(wxKeyEvent& e)
|
||||||
|
{
|
||||||
|
lastkbdkey = e.GetKeyCode();
|
||||||
|
mouseflag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxdialog_pressbutton::on_keyboard_up(wxKeyEvent& e)
|
||||||
|
{
|
||||||
|
int kcode = e.GetKeyCode();
|
||||||
|
if(lastkbdkey == kcode) {
|
||||||
|
dismiss_with(map_keycode_to_key(kcode));
|
||||||
|
} else {
|
||||||
|
lastkbdkey = -1;
|
||||||
|
mouseflag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxdialog_pressbutton::dismiss_with(const std::string& k)
|
||||||
|
{
|
||||||
|
if(k == "")
|
||||||
|
return;
|
||||||
|
if(key == "") {
|
||||||
|
keygrab_active = false;
|
||||||
|
key = k;
|
||||||
|
EndModal(wxID_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct keyentry_mod_data
|
struct keyentry_mod_data
|
||||||
{
|
{
|
||||||
wxCheckBox* pressed;
|
wxCheckBox* pressed;
|
||||||
|
@ -62,6 +210,7 @@ namespace
|
||||||
void on_ok(wxCommandEvent& e);
|
void on_ok(wxCommandEvent& e);
|
||||||
void on_cancel(wxCommandEvent& e);
|
void on_cancel(wxCommandEvent& e);
|
||||||
void on_clear(wxCommandEvent& e);
|
void on_clear(wxCommandEvent& e);
|
||||||
|
void on_pressbutton(wxCommandEvent& e);
|
||||||
void on_classchange(wxCommandEvent& e);
|
void on_classchange(wxCommandEvent& e);
|
||||||
std::string getkey();
|
std::string getkey();
|
||||||
private:
|
private:
|
||||||
|
@ -73,11 +222,13 @@ namespace
|
||||||
void set_class(const std::string& _class);
|
void set_class(const std::string& _class);
|
||||||
std::map<std::string, keyentry_mod_data> modifiers;
|
std::map<std::string, keyentry_mod_data> modifiers;
|
||||||
std::map<std::string, std::set<std::string>> classes;
|
std::map<std::string, std::set<std::string>> classes;
|
||||||
|
std::string wtitle;
|
||||||
std::string currentclass;
|
std::string currentclass;
|
||||||
wxFlexGridSizer* top_s;
|
wxFlexGridSizer* top_s;
|
||||||
wxFlexGridSizer* t_s;
|
wxFlexGridSizer* t_s;
|
||||||
wxComboBox* mainclass;
|
wxComboBox* mainclass;
|
||||||
wxComboBox* mainkey;
|
wxComboBox* mainkey;
|
||||||
|
wxButton* press;
|
||||||
wxButton* ok;
|
wxButton* ok;
|
||||||
wxButton* cancel;
|
wxButton* cancel;
|
||||||
wxButton* clear;
|
wxButton* clear;
|
||||||
|
@ -92,8 +243,9 @@ namespace
|
||||||
wxString emptystring;
|
wxString emptystring;
|
||||||
std::set<std::string> mods, keys;
|
std::set<std::string> mods, keys;
|
||||||
|
|
||||||
|
wtitle = title;
|
||||||
|
|
||||||
cleared = false;
|
cleared = false;
|
||||||
runemufn([&mods, &keys, &classes, &classeslist]() {
|
|
||||||
std::set<std::string> x;
|
std::set<std::string> x;
|
||||||
mods = modifier::get_set();
|
mods = modifier::get_set();
|
||||||
keys = keygroup::get_keys();
|
keys = keygroup::get_keys();
|
||||||
|
@ -104,7 +256,6 @@ namespace
|
||||||
x.insert(kclass);
|
x.insert(kclass);
|
||||||
classes[kclass].insert(i);
|
classes[kclass].insert(i);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
Centre();
|
Centre();
|
||||||
top_s = new wxFlexGridSizer(2, 1, 0, 0);
|
top_s = new wxFlexGridSizer(2, 1, 0, 0);
|
||||||
|
@ -135,6 +286,9 @@ namespace
|
||||||
top_s->Add(t_s);
|
top_s->Add(t_s);
|
||||||
|
|
||||||
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
pbutton_s->Add(press = new wxButton(this, wxID_OK, wxT("Prompt key")), 0, wxGROW);
|
||||||
|
press->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
|
||||||
|
wxCommandEventHandler(wxdialog_keyentry::on_pressbutton), NULL, this);
|
||||||
if(clearable)
|
if(clearable)
|
||||||
pbutton_s->Add(clear = new wxButton(this, wxID_OK, wxT("Clear")), 0, wxGROW);
|
pbutton_s->Add(clear = new wxButton(this, wxID_OK, wxT("Clear")), 0, wxGROW);
|
||||||
pbutton_s->Add(ok = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
|
pbutton_s->Add(ok = new wxButton(this, wxID_OK, wxT("OK")), 0, wxGROW);
|
||||||
|
@ -222,9 +376,11 @@ namespace
|
||||||
for(auto i : classes)
|
for(auto i : classes)
|
||||||
if(i.second.count(key))
|
if(i.second.count(key))
|
||||||
_class = i.first;
|
_class = i.first;
|
||||||
|
if(_class != "") {
|
||||||
set_class(_class);
|
set_class(_class);
|
||||||
mainclass->SetValue(towxstring(_class));
|
mainclass->SetValue(towxstring(_class));
|
||||||
mainkey->SetValue(towxstring(key));
|
mainkey->SetValue(towxstring(key));
|
||||||
|
}
|
||||||
t_s->Layout();
|
t_s->Layout();
|
||||||
top_s->Layout();
|
top_s->Layout();
|
||||||
Fit();
|
Fit();
|
||||||
|
@ -281,6 +437,23 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxdialog_keyentry::on_pressbutton(wxCommandEvent& e)
|
||||||
|
{
|
||||||
|
wxdialog_pressbutton* p = new wxdialog_pressbutton(this, wtitle);
|
||||||
|
p->ShowModal();
|
||||||
|
std::string key = p->getkey();
|
||||||
|
p->Destroy();
|
||||||
|
std::string _class;
|
||||||
|
for(auto i : classes)
|
||||||
|
if(i.second.count(key))
|
||||||
|
_class = i.first;
|
||||||
|
if(_class == "")
|
||||||
|
return;
|
||||||
|
set_class(_class);
|
||||||
|
mainclass->SetValue(towxstring(_class));
|
||||||
|
mainkey->SetValue(towxstring(key));
|
||||||
|
}
|
||||||
|
|
||||||
void wxdialog_keyentry::on_ok(wxCommandEvent& e)
|
void wxdialog_keyentry::on_ok(wxCommandEvent& e)
|
||||||
{
|
{
|
||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
|
@ -384,11 +557,9 @@ wxeditor_esettings_joystick_aconfig::wxeditor_esettings_joystick_aconfig(wxWindo
|
||||||
aname = _aname;
|
aname = _aname;
|
||||||
keygroup::parameters params;
|
keygroup::parameters params;
|
||||||
|
|
||||||
runemufn([aname, ¶ms]() {
|
|
||||||
auto k = keygroup::lookup_by_name(aname);
|
auto k = keygroup::lookup_by_name(aname);
|
||||||
if(k)
|
if(k)
|
||||||
params = k->get_parameters();
|
params = k->get_parameters();
|
||||||
});
|
|
||||||
|
|
||||||
switch(params.ktype) {
|
switch(params.ktype) {
|
||||||
case keygroup::KT_DISABLED: didx = 0; break;
|
case keygroup::KT_DISABLED: didx = 0; break;
|
||||||
|
@ -456,12 +627,10 @@ void wxeditor_esettings_joystick_aconfig::on_ok(wxCommandEvent& e)
|
||||||
double ntol;
|
double ntol;
|
||||||
keygroup* k;
|
keygroup* k;
|
||||||
|
|
||||||
runemufn([&k, aname, &_ctype]() {
|
|
||||||
k = keygroup::lookup_by_name(aname);
|
k = keygroup::lookup_by_name(aname);
|
||||||
if(k)
|
if(k)
|
||||||
_ctype = k->get_parameters().ktype;
|
_ctype = k->get_parameters().ktype;
|
||||||
});
|
else {
|
||||||
if(!k) {
|
|
||||||
//Axis gone away?
|
//Axis gone away?
|
||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
return;
|
return;
|
||||||
|
@ -502,11 +671,9 @@ void wxeditor_esettings_joystick_aconfig::on_ok(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
runemufn([&k, _ctype, _ntype, nlow, nmid, nhi, ntol]() {
|
|
||||||
if(_ctype != _ntype)
|
if(_ctype != _ntype)
|
||||||
k->change_type(_ntype);
|
k->change_type(_ntype);
|
||||||
k->change_calibration(nlow, nmid, nhi, ntol);
|
k->change_calibration(nlow, nmid, nhi, ntol);
|
||||||
});
|
|
||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +701,8 @@ namespace
|
||||||
{
|
{
|
||||||
std::string formattype(keygroup::type t)
|
std::string formattype(keygroup::type t)
|
||||||
{
|
{
|
||||||
if(t == keygroup::KT_AXIS_PAIR) return AMODE_AXIS_PAIR;
|
if(t == keygroup::KT_DISABLED) return AMODE_DISABLED;
|
||||||
|
else if(t == keygroup::KT_AXIS_PAIR) return AMODE_AXIS_PAIR;
|
||||||
else if(t == keygroup::KT_AXIS_PAIR_INVERSE) return AMODE_AXIS_PAIR_INVERSE;
|
else if(t == keygroup::KT_AXIS_PAIR_INVERSE) return AMODE_AXIS_PAIR_INVERSE;
|
||||||
else if(t == keygroup::KT_PRESSURE_0M) return AMODE_PRESSURE_0M;
|
else if(t == keygroup::KT_PRESSURE_0M) return AMODE_PRESSURE_0M;
|
||||||
else if(t == keygroup::KT_PRESSURE_0P) return AMODE_PRESSURE_0P;
|
else if(t == keygroup::KT_PRESSURE_0P) return AMODE_PRESSURE_0P;
|
||||||
|
@ -591,14 +759,12 @@ void wxeditor_esettings_joystick::refresh()
|
||||||
{
|
{
|
||||||
//Collect the new settings.
|
//Collect the new settings.
|
||||||
std::map<std::string, keygroup::parameters> x;
|
std::map<std::string, keygroup::parameters> x;
|
||||||
runemufn([&x]() {
|
|
||||||
auto axisnames = keygroup::get_axis_set();
|
auto axisnames = keygroup::get_axis_set();
|
||||||
for(auto i : axisnames) {
|
for(auto i : axisnames) {
|
||||||
keygroup* k = keygroup::lookup_by_name(i);
|
keygroup* k = keygroup::lookup_by_name(i);
|
||||||
if(k)
|
if(k)
|
||||||
x[i] = k->get_parameters();
|
x[i] = k->get_parameters();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
unsigned jcount = 0;
|
unsigned jcount = 0;
|
||||||
for(auto i : x) {
|
for(auto i : x) {
|
||||||
|
@ -709,8 +875,7 @@ void wxeditor_esettings_paths::on_configure(wxCommandEvent& e)
|
||||||
name = SLOTPATH;
|
name = SLOTPATH;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
std::string val;
|
std::string val = setting::get(name);
|
||||||
runemufn([&val, name]() { val = setting::get(name); });
|
|
||||||
try {
|
try {
|
||||||
if(e.GetId() == wxID_HIGHEST + 4)
|
if(e.GetId() == wxID_HIGHEST + 4)
|
||||||
val = pick_text(this, "Change number of slots", "Enter number of slots:", val);
|
val = pick_text(this, "Change number of slots", "Enter number of slots:", val);
|
||||||
|
@ -721,22 +886,22 @@ void wxeditor_esettings_paths::on_configure(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string err;
|
std::string err;
|
||||||
runemufn([val, name, &err]() { try { setting::set(name, val); } catch(std::exception& e) { err = e.what(); }});
|
try {
|
||||||
if(err != "")
|
setting::set(name, val);
|
||||||
|
} catch(std::exception& e) {
|
||||||
wxMessageBox(wxT("Invalid value"), wxT("Can't change value"), wxICON_EXCLAMATION | wxOK);
|
wxMessageBox(wxT("Invalid value"), wxT("Can't change value"), wxICON_EXCLAMATION | wxOK);
|
||||||
|
}
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_paths::refresh()
|
void wxeditor_esettings_paths::refresh()
|
||||||
{
|
{
|
||||||
std::string rpath, fpath, spath, nslot, lpath;
|
std::string rpath, fpath, spath, nslot, lpath;
|
||||||
runemufn([&rpath, &fpath, &spath, &nslot, &lpath]() {
|
|
||||||
fpath = setting::get(FIRMWAREPATH);
|
fpath = setting::get(FIRMWAREPATH);
|
||||||
rpath = setting::get(ROMPATH);
|
rpath = setting::get(ROMPATH);
|
||||||
spath = setting::get(MOVIEPATH);
|
spath = setting::get(MOVIEPATH);
|
||||||
nslot = setting::get(SAVESLOTS);
|
nslot = setting::get(SAVESLOTS);
|
||||||
lpath = setting::get(SLOTPATH);
|
lpath = setting::get(SLOTPATH);
|
||||||
});
|
|
||||||
rompath->SetLabel(towxstring(rpath));
|
rompath->SetLabel(towxstring(rpath));
|
||||||
firmpath->SetLabel(towxstring(fpath));
|
firmpath->SetLabel(towxstring(fpath));
|
||||||
savepath->SetLabel(towxstring(spath));
|
savepath->SetLabel(towxstring(spath));
|
||||||
|
@ -929,11 +1094,10 @@ void wxeditor_esettings_aliases::on_add(wxCommandEvent& e)
|
||||||
show_message_ok(this, "Error", "Not a valid alias name: " + name, wxICON_EXCLAMATION);
|
show_message_ok(this, "Error", "Not a valid alias name: " + name, wxICON_EXCLAMATION);
|
||||||
throw canceled_exception();
|
throw canceled_exception();
|
||||||
}
|
}
|
||||||
std::string old_alias_value;
|
std::string old_alias_value = command::get_alias_for(name);
|
||||||
runemufn([name, &old_alias_value]() { old_alias_value = command::get_alias_for(name); });
|
|
||||||
std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':",
|
std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':",
|
||||||
old_alias_value, true);
|
old_alias_value, true);
|
||||||
runemufn([name, newcmd]() { command::set_alias_for(name, newcmd); });
|
command::set_alias_for(name, newcmd);
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
}
|
}
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -947,11 +1111,10 @@ void wxeditor_esettings_aliases::on_edit(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::string old_alias_value;
|
std::string old_alias_value = command::get_alias_for(name);
|
||||||
runemufn([name, &old_alias_value]() { old_alias_value = command::get_alias_for(name); });
|
|
||||||
std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':",
|
std::string newcmd = pick_text(this, "Edit alias", "Enter new commands for '" + name + "':",
|
||||||
old_alias_value, true);
|
old_alias_value, true);
|
||||||
runemufn([name, newcmd]() { command::set_alias_for(name, newcmd); });
|
command::set_alias_for(name, newcmd);
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
}
|
}
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -964,7 +1127,7 @@ void wxeditor_esettings_aliases::on_delete(wxCommandEvent& e)
|
||||||
refresh();
|
refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runemufn([name]() { command::set_alias_for(name, ""); });
|
command::set_alias_for(name, "");
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +1136,7 @@ void wxeditor_esettings_aliases::refresh()
|
||||||
int n = select->GetSelection();
|
int n = select->GetSelection();
|
||||||
std::set<std::string> bind;
|
std::set<std::string> bind;
|
||||||
std::vector<wxString> choices;
|
std::vector<wxString> choices;
|
||||||
runemufn([&bind]() { bind = command::get_aliases(); });
|
bind = command::get_aliases();
|
||||||
for(auto i : bind) {
|
for(auto i : bind) {
|
||||||
numbers[choices.size()] = i;
|
numbers[choices.size()] = i;
|
||||||
choices.push_back(towxstring(i));
|
choices.push_back(towxstring(i));
|
||||||
|
@ -1007,6 +1170,7 @@ public:
|
||||||
void on_primary(wxCommandEvent& e);
|
void on_primary(wxCommandEvent& e);
|
||||||
void on_secondary(wxCommandEvent& e);
|
void on_secondary(wxCommandEvent& e);
|
||||||
void on_change(wxCommandEvent& e);
|
void on_change(wxCommandEvent& e);
|
||||||
|
void kill_internal_data();
|
||||||
private:
|
private:
|
||||||
std::map<std::string, wxTreeItemId> items;
|
std::map<std::string, wxTreeItemId> items;
|
||||||
std::map<std::string, inverse_key*> realitems;
|
std::map<std::string, inverse_key*> realitems;
|
||||||
|
@ -1060,6 +1224,14 @@ wxeditor_esettings_hotkeys::~wxeditor_esettings_hotkeys()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxeditor_esettings_hotkeys::kill_internal_data()
|
||||||
|
{
|
||||||
|
items.clear();
|
||||||
|
realitems.clear();
|
||||||
|
leafname.clear();
|
||||||
|
true_root = wxTreeItemId();
|
||||||
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
||||||
{
|
{
|
||||||
std::string name = selected();
|
std::string name = selected();
|
||||||
|
@ -1068,13 +1240,12 @@ void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::string key;
|
|
||||||
inverse_key* ik = realitems[name];
|
inverse_key* ik = realitems[name];
|
||||||
if(!ik) {
|
if(!ik) {
|
||||||
refresh();
|
refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runemufn([&key, ik]() { key = ik->get(true); });
|
std::string key = ik->get(true);
|
||||||
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
||||||
if(d->ShowModal() == wxID_CANCEL) {
|
if(d->ShowModal() == wxID_CANCEL) {
|
||||||
d->Destroy();
|
d->Destroy();
|
||||||
|
@ -1083,9 +1254,9 @@ void wxeditor_esettings_hotkeys::on_primary(wxCommandEvent& e)
|
||||||
key = d->getkey();
|
key = d->getkey();
|
||||||
d->Destroy();
|
d->Destroy();
|
||||||
if(key != "")
|
if(key != "")
|
||||||
runemufn([key, ik]() { ik->set(key, true); });
|
ik->set(key, true);
|
||||||
else
|
else
|
||||||
runemufn([key, ik]() { ik->clear(true); });
|
ik->clear(true);
|
||||||
refresh();
|
refresh();
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -1100,13 +1271,12 @@ void wxeditor_esettings_hotkeys::on_secondary(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::string key;
|
|
||||||
inverse_key* ik = realitems[name];
|
inverse_key* ik = realitems[name];
|
||||||
if(!ik) {
|
if(!ik) {
|
||||||
refresh();
|
refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runemufn([&key, ik]() { key = ik->get(false); });
|
std::string key = ik->get(false);
|
||||||
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
wxdialog_keyentry* d = new wxdialog_keyentry(this, "Specify key for " + name, key, true);
|
||||||
if(d->ShowModal() == wxID_CANCEL) {
|
if(d->ShowModal() == wxID_CANCEL) {
|
||||||
d->Destroy();
|
d->Destroy();
|
||||||
|
@ -1115,9 +1285,9 @@ void wxeditor_esettings_hotkeys::on_secondary(wxCommandEvent& e)
|
||||||
key = d->getkey();
|
key = d->getkey();
|
||||||
d->Destroy();
|
d->Destroy();
|
||||||
if(key != "")
|
if(key != "")
|
||||||
runemufn([key, ik]() { ik->set(key, false); });
|
ik->set(key, false);
|
||||||
else
|
else
|
||||||
runemufn([key, ik]() { ik->clear(false); });
|
ik->clear(false);
|
||||||
refresh();
|
refresh();
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
refresh();
|
refresh();
|
||||||
|
@ -1129,13 +1299,11 @@ void wxeditor_esettings_hotkeys::refresh()
|
||||||
std::set<std::string> closure_additional;
|
std::set<std::string> closure_additional;
|
||||||
std::map<std::string, inverse_key*> keyorder;
|
std::map<std::string, inverse_key*> keyorder;
|
||||||
std::map<inverse_key*, std::pair<std::string, std::string>> data;
|
std::map<inverse_key*, std::pair<std::string, std::string>> data;
|
||||||
runemufn([&data, &keyorder]() {
|
|
||||||
auto x = inverse_key::get_ikeys();
|
auto x = inverse_key::get_ikeys();
|
||||||
for(auto y : x) {
|
for(auto y : x) {
|
||||||
keyorder[y->getname()] = y;
|
keyorder[y->getname()] = y;
|
||||||
data[y] = std::make_pair(y->get(true), y->get(false));
|
data[y] = std::make_pair(y->get(true), y->get(false));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
//Close keyorder with respect to parents.
|
//Close keyorder with respect to parents.
|
||||||
for(auto i : keyorder) {
|
for(auto i : keyorder) {
|
||||||
std::string tmp = i.first;
|
std::string tmp = i.first;
|
||||||
|
@ -1282,22 +1450,15 @@ void wxeditor_esettings_bindings::on_add(wxCommandEvent& e)
|
||||||
d->Destroy();
|
d->Destroy();
|
||||||
|
|
||||||
std::string newcommand = pick_text(this, "New binding", "Enter command for binding:", "");
|
std::string newcommand = pick_text(this, "New binding", "Enter command for binding:", "");
|
||||||
bool fault = false;
|
|
||||||
std::string faulttext;
|
|
||||||
runemufn([&fault, &faulttext, name, newcommand]() {
|
|
||||||
try {
|
try {
|
||||||
keymapper::bind_for(name, newcommand);
|
keymapper::bind_for(name, newcommand);
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
fault = true;
|
wxMessageBox(wxT("Error"), towxstring(std::string("Can't bind key: ") + e.what()),
|
||||||
faulttext = e.what();
|
wxICON_EXCLAMATION);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if(fault)
|
|
||||||
wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION);
|
|
||||||
refresh();
|
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
refresh();
|
|
||||||
}
|
}
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e)
|
void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e)
|
||||||
|
@ -1308,26 +1469,18 @@ void wxeditor_esettings_bindings::on_edit(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
std::string old_command_value;
|
std::string old_command_value = keymapper::get_command_for(name);
|
||||||
runemufn([&old_command_value, name]() { old_command_value = keymapper::get_command_for(name); });
|
|
||||||
std::string newcommand = pick_text(this, "Edit binding", "Enter new command for binding:",
|
std::string newcommand = pick_text(this, "Edit binding", "Enter new command for binding:",
|
||||||
old_command_value);
|
old_command_value);
|
||||||
bool fault = false;
|
|
||||||
std::string faulttext;
|
|
||||||
runemufn([&fault, &faulttext, name, newcommand]() {
|
|
||||||
try {
|
try {
|
||||||
keymapper::bind_for(name, newcommand);
|
keymapper::bind_for(name, newcommand);
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
fault = true;
|
wxMessageBox(wxT("Error"), towxstring(std::string("Can't bind key: ") + e.what()),
|
||||||
faulttext = e.what();
|
wxICON_EXCLAMATION);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if(fault)
|
|
||||||
wxMessageBox(wxT("Error"), towxstring("Can't bind key: " + faulttext), wxICON_EXCLAMATION);
|
|
||||||
refresh();
|
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
refresh();
|
|
||||||
}
|
}
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e)
|
void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e)
|
||||||
|
@ -1337,7 +1490,7 @@ void wxeditor_esettings_bindings::on_delete(wxCommandEvent& e)
|
||||||
refresh();
|
refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runemufn([name]() { try { keymapper::bind_for(name, ""); } catch(...) {} });
|
try { keymapper::bind_for(name, ""); } catch(...) {}
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,11 +1499,9 @@ void wxeditor_esettings_bindings::refresh()
|
||||||
int n = select->GetSelection();
|
int n = select->GetSelection();
|
||||||
std::map<std::string, std::string> bind;
|
std::map<std::string, std::string> bind;
|
||||||
std::vector<wxString> choices;
|
std::vector<wxString> choices;
|
||||||
runemufn([&bind]() {
|
|
||||||
std::set<std::string> a = keymapper::get_bindings();
|
std::set<std::string> a = keymapper::get_bindings();
|
||||||
for(auto i : a)
|
for(auto i : a)
|
||||||
bind[i] = keymapper::get_command_for(i);
|
bind[i] = keymapper::get_command_for(i);
|
||||||
});
|
|
||||||
for(auto i : bind) {
|
for(auto i : bind) {
|
||||||
numbers[choices.size()] = i.first;
|
numbers[choices.size()] = i.first;
|
||||||
choices.push_back(towxstring(i.first + " (" + i.second + ")"));
|
choices.push_back(towxstring(i.first + " (" + i.second + ")"));
|
||||||
|
@ -1439,18 +1590,18 @@ void wxeditor_esettings_advanced::on_change(wxCommandEvent& e)
|
||||||
return;
|
return;
|
||||||
std::string value;
|
std::string value;
|
||||||
std::string err;
|
std::string err;
|
||||||
runemufn([name, &value]() { value = setting::get(name); });
|
value = setting::get(name);
|
||||||
try {
|
try {
|
||||||
value = pick_text(this, "Set value to", "Set " + name + " to value:", value);
|
value = pick_text(this, "Set value to", "Set " + name + " to value:", value);
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runemufn([name, value, &err]() {
|
try {
|
||||||
try { setting::set(name, value); } catch(std::exception& e) { err = e.what(); }
|
setting::set(name, value);
|
||||||
});
|
} catch(std::exception& e) {
|
||||||
if(err != "")
|
|
||||||
wxMessageBox(towxstring(err), wxT("Error setting value"), wxICON_EXCLAMATION | wxOK);
|
wxMessageBox(towxstring(err), wxT("Error setting value"), wxICON_EXCLAMATION | wxOK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_advanced::on_selchange(wxCommandEvent& e)
|
void wxeditor_esettings_advanced::on_selchange(wxCommandEvent& e)
|
||||||
{
|
{
|
||||||
|
@ -1466,10 +1617,12 @@ void wxeditor_esettings_advanced::on_clear(wxCommandEvent& e)
|
||||||
if(name == "")
|
if(name == "")
|
||||||
return;
|
return;
|
||||||
bool err = false;
|
bool err = false;
|
||||||
runemufn([name, &err]() { try { setting::blank(name); } catch(...) { err = true; }});
|
try {
|
||||||
if(err)
|
setting::blank(name);
|
||||||
|
} catch(...) {
|
||||||
wxMessageBox(wxT("This setting can't be cleared"), wxT("Error"), wxICON_EXCLAMATION | wxOK);
|
wxMessageBox(wxT("This setting can't be cleared"), wxT("Error"), wxICON_EXCLAMATION | wxOK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wxeditor_esettings_advanced::on_setting_change(const std::string& setting, const std::string& value)
|
void wxeditor_esettings_advanced::on_setting_change(const std::string& setting, const std::string& value)
|
||||||
{
|
{
|
||||||
|
@ -1489,7 +1642,6 @@ void wxeditor_esettings_advanced::on_setting_clear(const std::string& setting)
|
||||||
|
|
||||||
void wxeditor_esettings_advanced::refresh()
|
void wxeditor_esettings_advanced::refresh()
|
||||||
{
|
{
|
||||||
runemufn([&settings, &values, &blankables]() {
|
|
||||||
settings = setting::get_settings_set();
|
settings = setting::get_settings_set();
|
||||||
blankables.clear();
|
blankables.clear();
|
||||||
for(auto i : settings) {
|
for(auto i : settings) {
|
||||||
|
@ -1498,7 +1650,6 @@ void wxeditor_esettings_advanced::refresh()
|
||||||
if(setting::blankable(i))
|
if(setting::blankable(i))
|
||||||
blankables.insert(i);
|
blankables.insert(i);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
_refresh();
|
_refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1537,11 +1688,15 @@ private:
|
||||||
wxWindow* joystick_window;
|
wxWindow* joystick_window;
|
||||||
wxNotebook* tabset;
|
wxNotebook* tabset;
|
||||||
wxButton* closebutton;
|
wxButton* closebutton;
|
||||||
|
wxeditor_esettings_hotkeys* hotkeytab;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxeditor_esettings::wxeditor_esettings(wxWindow* parent)
|
wxeditor_esettings::wxeditor_esettings(wxWindow* parent)
|
||||||
: wxDialog(parent, wxID_ANY, wxT("lsnes: Configure emulator"), wxDefaultPosition, wxSize(-1, -1))
|
: wxDialog(parent, wxID_ANY, wxT("lsnes: Configure emulator"), wxDefaultPosition, wxSize(-1, -1))
|
||||||
{
|
{
|
||||||
|
//Grab keys to prevent the joystick driver from running who knows what commands.
|
||||||
|
keygrabber.grab_keys();
|
||||||
|
|
||||||
Centre();
|
Centre();
|
||||||
wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
|
wxSizer* top_s = new wxBoxSizer(wxVERTICAL);
|
||||||
SetSizer(top_s);
|
SetSizer(top_s);
|
||||||
|
@ -1550,7 +1705,7 @@ wxeditor_esettings::wxeditor_esettings(wxWindow* parent)
|
||||||
tabset->AddPage(new wxeditor_esettings_joystick(tabset), wxT("Joysticks"));
|
tabset->AddPage(new wxeditor_esettings_joystick(tabset), wxT("Joysticks"));
|
||||||
tabset->AddPage(new wxeditor_esettings_paths(tabset), wxT("Paths"));
|
tabset->AddPage(new wxeditor_esettings_paths(tabset), wxT("Paths"));
|
||||||
tabset->AddPage(new wxeditor_esettings_screen(tabset), wxT("Scaling"));
|
tabset->AddPage(new wxeditor_esettings_screen(tabset), wxT("Scaling"));
|
||||||
tabset->AddPage(new wxeditor_esettings_hotkeys(tabset), wxT("Hotkeys"));
|
tabset->AddPage(hotkeytab = new wxeditor_esettings_hotkeys(tabset), wxT("Hotkeys"));
|
||||||
tabset->AddPage(new wxeditor_esettings_aliases(tabset), wxT("Aliases"));
|
tabset->AddPage(new wxeditor_esettings_aliases(tabset), wxT("Aliases"));
|
||||||
tabset->AddPage(new wxeditor_esettings_bindings(tabset), wxT("Bindings"));
|
tabset->AddPage(new wxeditor_esettings_bindings(tabset), wxT("Bindings"));
|
||||||
tabset->AddPage(new wxeditor_esettings_advanced(tabset), wxT("Advanced"));
|
tabset->AddPage(new wxeditor_esettings_advanced(tabset), wxT("Advanced"));
|
||||||
|
@ -1578,6 +1733,8 @@ bool wxeditor_esettings::ShouldPreventAppExit() const
|
||||||
|
|
||||||
void wxeditor_esettings::on_close(wxCommandEvent& e)
|
void wxeditor_esettings::on_close(wxCommandEvent& e)
|
||||||
{
|
{
|
||||||
|
hotkeytab->kill_internal_data();
|
||||||
|
keygrabber.ungrab_keys();
|
||||||
EndModal(wxID_OK);
|
EndModal(wxID_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,18 @@ struct wxw_mutex : public mutex
|
||||||
wxMutex* m;
|
wxMutex* m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wxw_rec_mutex : public mutex
|
||||||
|
{
|
||||||
|
wxw_rec_mutex() throw(std::bad_alloc);
|
||||||
|
~wxw_rec_mutex() throw();
|
||||||
|
void lock() throw();
|
||||||
|
void unlock() throw();
|
||||||
|
wxMutex* m;
|
||||||
|
volatile bool locked;
|
||||||
|
uint32_t owner;
|
||||||
|
uint32_t count;
|
||||||
|
};
|
||||||
|
|
||||||
wxw_mutex::wxw_mutex() throw(std::bad_alloc)
|
wxw_mutex::wxw_mutex() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
m = new wxMutex();
|
m = new wxMutex();
|
||||||
|
@ -31,11 +43,55 @@ void wxw_mutex::unlock() throw()
|
||||||
m->Unlock();
|
m->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxw_rec_mutex::wxw_rec_mutex() throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
m = new wxMutex();
|
||||||
|
locked = false;
|
||||||
|
owner = 0;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxw_rec_mutex::~wxw_rec_mutex() throw()
|
||||||
|
{
|
||||||
|
delete m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxw_rec_mutex::lock() throw()
|
||||||
|
{
|
||||||
|
uint32_t our_id = wxThread::GetCurrentId();
|
||||||
|
if(locked && owner == our_id) {
|
||||||
|
//Owned by us, increment lock count.
|
||||||
|
++count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m->Lock();
|
||||||
|
locked = true;
|
||||||
|
owner = our_id;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxw_rec_mutex::unlock() throw()
|
||||||
|
{
|
||||||
|
uint32_t our_id = wxThread::GetCurrentId();
|
||||||
|
if(!locked || owner != our_id)
|
||||||
|
std::cerr << "Warning: Trying to unlock recursive lock locked by another thread!" << std::endl;
|
||||||
|
if(!--count) {
|
||||||
|
locked = false;
|
||||||
|
owner = 0;
|
||||||
|
m->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex& mutex::aquire() throw(std::bad_alloc)
|
mutex& mutex::aquire() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
return *new wxw_mutex;
|
return *new wxw_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex& mutex::aquire_rec() throw(std::bad_alloc)
|
||||||
|
{
|
||||||
|
return *new wxw_rec_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
struct wxw_condition : public condition
|
struct wxw_condition : public condition
|
||||||
{
|
{
|
||||||
wxw_condition(mutex& m) throw(std::bad_alloc);
|
wxw_condition(mutex& m) throw(std::bad_alloc);
|
||||||
|
|
Loading…
Add table
Reference in a new issue