You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
7.6KB

  1. #include "ScriptEngine.hpp"
  2. #include <luajit-2.0/lua.hpp>
  3. struct LuaJITEngine : ScriptEngine {
  4. lua_State* L = NULL;
  5. struct SafeArray {
  6. void* p;
  7. size_t len;
  8. };
  9. ~LuaJITEngine() {
  10. if (L)
  11. lua_close(L);
  12. }
  13. std::string getEngineName() override {
  14. return "Lua";
  15. }
  16. int run(const std::string& path, const std::string& script) override {
  17. ProcessBlock* block = getProcessBlock();
  18. L = luaL_newstate();
  19. if (!L) {
  20. display("Could not create LuaJIT context");
  21. return -1;
  22. }
  23. // Import a subset of the standard library
  24. luaopen_base(L);
  25. luaopen_string(L);
  26. luaopen_table(L);
  27. luaopen_math(L);
  28. // Set user pointer
  29. lua_pushlightuserdata(L, this);
  30. lua_setglobal(L, "_engine");
  31. // Set global functions
  32. // lua_pushcfunction(L, native_print);
  33. // lua_setglobal(L, "print");
  34. lua_pushcfunction(L, native_display);
  35. lua_setglobal(L, "display");
  36. // Set config
  37. lua_newtable(L);
  38. {
  39. // frameDivider
  40. lua_pushinteger(L, 32);
  41. lua_setfield(L, -2, "frameDivider");
  42. // bufferSize
  43. lua_pushinteger(L, 1);
  44. lua_setfield(L, -2, "bufferSize");
  45. }
  46. lua_setglobal(L, "config");
  47. // Compile script
  48. if (luaL_loadbuffer(L, script.c_str(), script.size(), path.c_str())) {
  49. const char* s = lua_tostring(L, -1);
  50. WARN("LuaJIT: %s", s);
  51. display(s);
  52. lua_pop(L, 1);
  53. return -1;
  54. }
  55. // Run script
  56. if (lua_pcall(L, 0, 0, 0)) {
  57. const char* s = lua_tostring(L, -1);
  58. WARN("LuaJIT: %s", s);
  59. display(s);
  60. lua_pop(L, 1);
  61. return -1;
  62. }
  63. // Get config
  64. lua_getglobal(L, "config");
  65. {
  66. // frameDivider
  67. lua_getfield(L, -1, "frameDivider");
  68. int frameDivider = lua_tointeger(L, -1);
  69. setFrameDivider(frameDivider);
  70. lua_pop(L, 1);
  71. // bufferSize
  72. lua_getfield(L, -1, "bufferSize");
  73. int bufferSize = lua_tointeger(L, -1);
  74. setBufferSize(bufferSize);
  75. lua_pop(L, 1);
  76. }
  77. lua_pop(L, 1);
  78. // Get process function
  79. lua_getglobal(L, "process");
  80. if (!lua_isfunction(L, -1)) {
  81. display("No process() function");
  82. return -1;
  83. }
  84. // FloatArray metatable
  85. lua_newtable(L);
  86. {
  87. // __index
  88. lua_pushcfunction(L, native_FloatArray_index);
  89. lua_setfield(L, -2, "__index");
  90. // __newindex
  91. lua_pushcfunction(L, native_FloatArray_newindex);
  92. lua_setfield(L, -2, "__newindex");
  93. // __len
  94. lua_pushcfunction(L, native_FloatArray_len);
  95. lua_setfield(L, -2, "__len");
  96. }
  97. lua_setglobal(L, "FloatArray");
  98. // BoolArray metatable
  99. lua_newtable(L);
  100. {
  101. // __index
  102. lua_pushcfunction(L, native_BoolArray_index);
  103. lua_setfield(L, -2, "__index");
  104. // __newindex
  105. lua_pushcfunction(L, native_BoolArray_newindex);
  106. lua_setfield(L, -2, "__newindex");
  107. // __len
  108. lua_pushcfunction(L, native_BoolArray_len);
  109. lua_setfield(L, -2, "__len");
  110. }
  111. lua_setglobal(L, "BoolArray");
  112. // Create block object
  113. lua_newtable(L);
  114. {
  115. // inputs
  116. lua_newtable(L);
  117. for (int i = 0; i < NUM_ROWS; i++) {
  118. SafeArray* input = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  119. input->p = &block->inputs[i];
  120. input->len = block->bufferSize;
  121. lua_getglobal(L, "FloatArray");
  122. lua_setmetatable(L, -2);
  123. lua_rawseti(L, -2, i + 1);
  124. }
  125. lua_setfield(L, -2, "inputs");
  126. // outputs
  127. lua_newtable(L);
  128. for (int i = 0; i < NUM_ROWS; i++) {
  129. SafeArray* output = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  130. output->p = &block->outputs[i];
  131. output->len = block->bufferSize;
  132. lua_getglobal(L, "FloatArray");
  133. lua_setmetatable(L, -2);
  134. lua_rawseti(L, -2, i + 1);
  135. }
  136. lua_setfield(L, -2, "outputs");
  137. // knobs
  138. SafeArray* knobs = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  139. knobs->p = &block->knobs;
  140. knobs->len = 6;
  141. lua_getglobal(L, "FloatArray");
  142. lua_setmetatable(L, -2);
  143. lua_setfield(L, -2, "knobs");
  144. // switches
  145. SafeArray* switches = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  146. switches->p = &block->switches;
  147. switches->len = 6;
  148. lua_getglobal(L, "BoolArray");
  149. lua_setmetatable(L, -2);
  150. lua_setfield(L, -2, "switches");
  151. // lights
  152. lua_newtable(L);
  153. for (int i = 0; i < NUM_ROWS; i++) {
  154. SafeArray* light = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  155. light->p = &block->lights[i];
  156. light->len = 3;
  157. lua_getglobal(L, "FloatArray");
  158. lua_setmetatable(L, -2);
  159. lua_rawseti(L, -2, i + 1);
  160. }
  161. lua_setfield(L, -2, "lights");
  162. // switchLights
  163. lua_newtable(L);
  164. for (int i = 0; i < NUM_ROWS; i++) {
  165. SafeArray* switchLight = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray));
  166. switchLight->p = &block->switchLights[i];
  167. switchLight->len = 3;
  168. lua_getglobal(L, "FloatArray");
  169. lua_setmetatable(L, -2);
  170. lua_rawseti(L, -2, i + 1);
  171. }
  172. lua_setfield(L, -2, "switchLights");
  173. }
  174. return 0;
  175. }
  176. int process() override {
  177. ProcessBlock* block = getProcessBlock();
  178. // Set block
  179. {
  180. // sampleRate
  181. lua_pushnumber(L, block->sampleRate);
  182. lua_setfield(L, -2, "sampleRate");
  183. // sampleTime
  184. lua_pushnumber(L, block->sampleTime);
  185. lua_setfield(L, -2, "sampleTime");
  186. // bufferSize
  187. lua_pushinteger(L, block->bufferSize);
  188. lua_setfield(L, -2, "bufferSize");
  189. }
  190. // Duplicate process function
  191. lua_pushvalue(L, -2);
  192. // Duplicate block
  193. lua_pushvalue(L, -2);
  194. // Call process function
  195. if (lua_pcall(L, 1, 0, 0)) {
  196. const char* err = lua_tostring(L, -1);
  197. WARN("LuaJIT: %s", err);
  198. display(err);
  199. return -1;
  200. }
  201. return 0;
  202. }
  203. static LuaJITEngine* getEngine(lua_State* L) {
  204. lua_getglobal(L, "_engine");
  205. LuaJITEngine* engine = (LuaJITEngine*) lua_touserdata(L, -1);
  206. lua_pop(L, 1);
  207. return engine;
  208. }
  209. // static int native_print(lua_State* L) {
  210. // lua_getglobal(L, "tostring");
  211. // lua_pushvalue(L, 1);
  212. // lua_call(L, 1, 1);
  213. // const char* s = lua_tostring(L, 1);
  214. // INFO("LuaJIT: %s", s);
  215. // return 0;
  216. // }
  217. static int native_display(lua_State* L) {
  218. lua_getglobal(L, "tostring");
  219. lua_pushvalue(L, 1);
  220. lua_call(L, 1, 1);
  221. const char* s = lua_tostring(L, -1);
  222. if (!s)
  223. s = "(null)";
  224. getEngine(L)->display(s);
  225. return 0;
  226. }
  227. static int native_FloatArray_index(lua_State* L) {
  228. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  229. float* data = (float*) a->p;
  230. size_t index = lua_tointeger(L, 2) - 1;
  231. if (index >= a->len) {
  232. lua_pushstring(L, "Array out of bounds");
  233. lua_error(L);
  234. }
  235. lua_pushnumber(L, data[index]);
  236. return 1;
  237. }
  238. static int native_FloatArray_newindex(lua_State* L) {
  239. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  240. float* data = (float*) a->p;
  241. size_t index = lua_tointeger(L, 2) - 1;
  242. if (index >= a->len) {
  243. lua_pushstring(L, "Array out of bounds");
  244. lua_error(L);
  245. }
  246. data[index] = lua_tonumber(L, 3);
  247. return 0;
  248. }
  249. static int native_FloatArray_len(lua_State* L) {
  250. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  251. lua_pushinteger(L, a->len);
  252. return 1;
  253. }
  254. static int native_BoolArray_index(lua_State* L) {
  255. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  256. bool* data = (bool*) a->p;
  257. size_t index = lua_tointeger(L, 2) - 1;
  258. if (index >= a->len) {
  259. lua_pushstring(L, "Array out of bounds");
  260. lua_error(L);
  261. }
  262. lua_pushboolean(L, data[index]);
  263. return 1;
  264. }
  265. static int native_BoolArray_newindex(lua_State* L) {
  266. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  267. bool* data = (bool*) a->p;
  268. size_t index = lua_tointeger(L, 2) - 1;
  269. if (index >= a->len) {
  270. lua_pushstring(L, "Array out of bounds");
  271. lua_error(L);
  272. }
  273. data[index] = lua_toboolean(L, 3);
  274. return 0;
  275. }
  276. static int native_BoolArray_len(lua_State* L) {
  277. SafeArray* a = (SafeArray*) lua_touserdata(L, 1);
  278. lua_pushinteger(L, a->len);
  279. return 1;
  280. }
  281. };
  282. __attribute__((constructor(1000)))
  283. static void constructor() {
  284. addScriptEngine<LuaJITEngine>("lua");
  285. }