Refactor some generic reading/writing routines out of moviefile.cpp
[lsnes.git] / src / lua / ibind.cpp
blobaccff189f02a023f28109b97fd275a58f91b27ec
1 #include "lua/internal.hpp"
2 #include "core/keymapper.hpp"
3 #include "core/command.hpp"
4 #include <vector>
6 class lua_inverse_bind
8 public:
9 lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd);
10 std::string print()
12 return ikey.getname();
14 static int create(lua::state& L, lua::parameters& P);
15 private:
16 keyboard::invbind ikey;
19 class lua_command_binding : public command::base
21 public:
22 lua_command_binding(lua::state& _L, const std::string& cmd, int idx)
23 : command::base(lsnes_cmd, cmd), L(_L)
25 L.pushlightuserdata(this);
26 L.pushvalue(idx);
27 L.rawset(LUA_REGISTRYINDEX);
29 void invoke(const std::string& arguments) throw(std::bad_alloc, std::runtime_error)
31 L.pushlightuserdata(this);
32 L.rawget(LUA_REGISTRYINDEX);
33 L.pushstring(arguments.c_str());
34 int r = L.pcall(1, 0, 0);
35 std::string err;
36 if(r == LUA_ERRRUN)
37 err = L.get_string(-1, "Lua command callback");
38 else if(r == LUA_ERRMEM)
39 err = "Out of memory";
40 else if(r == LUA_ERRERR)
41 err = "Double fault";
42 else
43 err = "Unknown error";
44 if(r) {
45 messages << "Error running lua command hook: " << err << std::endl;
48 private:
49 lua::state& L;
52 class lua_command_bind
54 public:
55 lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2);
56 ~lua_command_bind();
57 std::string print()
59 if(b)
60 return a->get_name() + "," + b->get_name();
61 else
62 return a->get_name();
64 static int create(lua::state& L, lua::parameters& P);
65 private:
66 lua_command_binding* a;
67 lua_command_binding* b;
70 lua_inverse_bind::lua_inverse_bind(lua::state& L, const std::string& name, const std::string& cmd)
71 : ikey(lsnes_mapper, cmd, "Lua‣" + name)
75 lua_command_bind::lua_command_bind(lua::state& L, const std::string& cmd, int idx1, int idx2)
77 if(L.type(idx2) == LUA_TFUNCTION) {
78 a = new lua_command_binding(L, "+" + cmd, idx1);
79 b = new lua_command_binding(L, "-" + cmd, idx2);
80 } else {
81 a = new lua_command_binding(L, cmd, idx1);
82 b = NULL;
86 lua_command_bind::~lua_command_bind()
88 delete a;
89 delete b;
92 namespace
94 lua::fnptr2 input_bindings(lua_func_misc, "list_bindings", [](lua::state& L, lua::parameters& P) -> int {
95 std::string target;
97 P(P.optional(target, ""));
99 L.newtable();
100 for(auto key : lsnes_mapper.get_bindings()) {
101 std::string _key = key;
102 std::string cmd = lsnes_mapper.get(key);
103 if(target != "" && cmd != target)
104 continue;
105 L.pushlstring(_key.c_str(), _key.length());
106 L.pushlstring(cmd.c_str(), cmd.length());
107 L.rawset(-3);
109 for(auto key : lsnes_mapper.get_controller_keys()) {
110 for(unsigned i = 0;; i++) {
111 std::string _key = key->get_string(i);
112 if(_key == "")
113 break;
114 std::string cmd = key->get_command();
115 _key = "|/" + _key;
116 if(target != "" && cmd != target)
117 continue;
118 L.pushlstring(_key.c_str(), _key.length());
119 L.pushlstring(cmd.c_str(), cmd.length());
120 L.rawset(-3);
123 return 1;
126 lua::fnptr2 get_alias(lua_func_misc, "get_alias", [](lua::state& L, lua::parameters& P) -> int {
127 std::string name;
129 P(name);
131 std::string a = lsnes_cmd.get_alias_for(name);
132 if(a != "")
133 L.pushlstring(a);
134 else
135 L.pushnil();
136 return 1;
139 lua::fnptr2 set_alias(lua_func_misc, "set_alias", [](lua::state& L, lua::parameters& P) -> int {
140 std::string name, value;
142 P(name, P.optional(value, ""));
144 lsnes_cmd.set_alias_for(name, value);
145 refresh_alias_binds();
146 return 0;
149 lua::_class<lua_inverse_bind> class_inverse_bind(lua_class_bind, "INVERSEBIND", {
150 {"new", lua_inverse_bind::create},
151 }, {}, &lua_inverse_bind::print);
152 lua::_class<lua_command_bind> class_command_bind(lua_class_bind, "COMMANDBIND", {
153 {"new", lua_command_bind::create},
154 }, {}, &lua_command_bind::print);
157 int lua_inverse_bind::create(lua::state& L, lua::parameters& P)
159 std::string name, command;
161 P(name, command);
163 lua_inverse_bind* b = lua::_class<lua_inverse_bind>::create(L, name, command);
164 return 1;
167 int lua_command_bind::create(lua::state& L, lua::parameters& P)
169 std::string name;
170 int lfn1 = 0, lfn2 = 0;
172 P(name, P.function(lfn1));
173 if(P.is_function() || P.is_novalue())
174 lfn2 = P.skip();
175 else
176 P.expected("function or nil");
177 lua_command_bind* b = lua::_class<lua_command_bind>::create(L.get_master(), name, lfn1, lfn2);
178 return 1;