lsnes rr2-β24
[lsnes.git] / src / lua / ibind.cpp
blobae1278613841f940db05ab4eeac1bdd052f0b7fa
1 #include "lua/internal.hpp"
2 #include "core/instance.hpp"
3 #include "core/keymapper.hpp"
4 #include "core/messages.hpp"
5 #include "core/command.hpp"
6 #include <vector>
8 class lua_inverse_bind
10 public:
11 lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd);
12 static size_t overcommit(const std::string& name, const std::string& cmd) { return 0; }
13 std::string print()
15 return ikey.getname();
17 static int create(lua::state& L, lua::parameters& P);
18 private:
19 keyboard::invbind ikey;
22 class lua_command_binding : public command::base
24 public:
25 lua_command_binding(lua::state& _L, const std::string& cmd, int idx)
26 : command::base(*CORE().command, cmd, false), L(_L)
28 L.pushlightuserdata(this);
29 L.pushvalue(idx);
30 L.rawset(LUA_REGISTRYINDEX);
32 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
34 L.pushlightuserdata(this);
35 L.rawget(LUA_REGISTRYINDEX);
36 L.pushstring(arguments.c_str());
37 int r = L.pcall(1, 0, 0);
38 std::string err;
39 if(r == LUA_ERRRUN)
40 err = L.get_string(-1, "Lua command callback");
41 else if(r == LUA_ERRMEM)
42 err = "Out of memory";
43 else if(r == LUA_ERRERR)
44 err = "Double fault";
45 else
46 err = "Unknown error";
47 if(r) {
48 messages << "Error running lua command hook: " << err << std::endl;
51 private:
52 lua::state& L;
55 class lua_command_bind
57 public:
58 lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2);
59 static size_t overcommit(const std::string& cmd, int idx1, int idx2) { return 0; }
60 ~lua_command_bind();
61 std::string print()
63 if(b)
64 return a->get_name() + "," + b->get_name();
65 else
66 return a->get_name();
68 static int create(lua::state& L, lua::parameters& P);
69 private:
70 lua_command_binding* a;
71 lua_command_binding* b;
74 lua_inverse_bind::lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd)
75 : ikey(*CORE().mapper, cmd, "Lua‣" + name)
79 lua_command_bind::lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2)
81 if(L.type(idx2) == LUA_TFUNCTION) {
82 a = new lua_command_binding(L, "+" + cmd, idx1);
83 b = new lua_command_binding(L, "-" + cmd, idx2);
84 } else {
85 a = new lua_command_binding(L, cmd, idx1);
86 b = NULL;
90 lua_command_bind::~lua_command_bind()
92 delete a;
93 delete b;
96 namespace
98 int list_bindings(lua::state& L, lua::parameters& P)
100 auto& core = CORE();
101 std::string target;
103 P(P.optional(target, ""));
105 L.newtable();
106 for(auto key : core.mapper->get_bindings()) {
107 std::string _key = key;
108 std::string cmd = core.mapper->get(key);
109 if(target != "" && cmd != target)
110 continue;
111 L.pushlstring(_key.c_str(), _key.length());
112 L.pushlstring(cmd.c_str(), cmd.length());
113 L.rawset(-3);
115 for(auto key : core.mapper->get_controller_keys()) {
116 for(unsigned i = 0;; i++) {
117 std::string _key = key->get_string(i);
118 if(_key == "")
119 break;
120 std::string cmd = key->get_command();
121 _key = "|/" + _key;
122 if(target != "" && cmd != target)
123 continue;
124 L.pushlstring(_key.c_str(), _key.length());
125 L.pushlstring(cmd.c_str(), cmd.length());
126 L.rawset(-3);
129 return 1;
132 int get_alias(lua::state& L, lua::parameters& P)
134 std::string name;
136 P(name);
138 std::string a = CORE().command->get_alias_for(name);
139 if(a != "")
140 L.pushlstring(a);
141 else
142 L.pushnil();
143 return 1;
146 int set_alias(lua::state& L, lua::parameters& P)
148 auto& core = CORE();
149 std::string name, value;
151 P(name, P.optional(value, ""));
153 core.command->set_alias_for(name, value);
154 (*core.abindmanager)();
155 return 0;
158 lua::functions LUA_alias_fns(lua_func_misc, "", {
159 {"list_bindings", list_bindings},
160 {"get_alias", get_alias},
161 {"set_alias", set_alias},
164 lua::_class<lua_inverse_bind> LUA_class_inverse_bind(lua_class_bind, "INVERSEBIND", {
165 {"new", lua_inverse_bind::create},
166 }, {}, &lua_inverse_bind::print);
167 lua::_class<lua_command_bind> LUA_class_command_bind(lua_class_bind, "COMMANDBIND", {
168 {"new", lua_command_bind::create},
169 }, {}, &lua_command_bind::print);
172 int lua_inverse_bind::create(lua::state& L, lua::parameters& P)
174 std::string name, command;
176 P(name, command);
178 lua::_class<lua_inverse_bind>::create(L, name, command);
179 return 1;
182 int lua_command_bind::create(lua::state& L, lua::parameters& P)
184 std::string name;
185 int lfn1 = 0, lfn2 = 0;
187 P(name, P.function(lfn1));
188 if(P.is_function() || P.is_novalue())
189 lfn2 = P.skip();
190 else
191 P.expected("function or nil");
192 lua::_class<lua_command_bind>::create(L.get_master(), name, lfn1, lfn2);
193 return 1;