| @@ -1,28 +1,6 @@ | |||||
| #include "ScriptEngine.hpp" | #include "ScriptEngine.hpp" | ||||
| #include <luajit-2.0/lua.hpp> | #include <luajit-2.0/lua.hpp> | ||||
| static const luaL_Reg lj_lib_load[] = { | |||||
| { "", luaopen_base }, | |||||
| { LUA_LOADLIBNAME, luaopen_package }, | |||||
| { LUA_TABLIBNAME, luaopen_table }, | |||||
| { LUA_STRLIBNAME, luaopen_string }, | |||||
| { LUA_MATHLIBNAME, luaopen_math }, | |||||
| { LUA_BITLIBNAME, luaopen_bit }, | |||||
| { LUA_JITLIBNAME, luaopen_jit }, | |||||
| { LUA_FFILIBNAME, luaopen_ffi }, | |||||
| { NULL, NULL } | |||||
| }; | |||||
| LUALIB_API void custom_openlibs(lua_State *L) | |||||
| { | |||||
| const luaL_Reg *lib; | |||||
| for (lib = lj_lib_load; lib->func; lib++) { | |||||
| lua_pushcfunction(L, lib->func); | |||||
| lua_pushstring(L, lib->name); | |||||
| lua_call(L, 1, 0); | |||||
| } | |||||
| lua_pop(L, 1); | |||||
| } | |||||
| struct LuaJITEngine : ScriptEngine { | struct LuaJITEngine : ScriptEngine { | ||||
| lua_State* L = NULL; | lua_State* L = NULL; | ||||
| @@ -33,15 +11,15 @@ struct LuaJITEngine : ScriptEngine { | |||||
| float sampleRate; | float sampleRate; | ||||
| float sampleTime; | float sampleTime; | ||||
| int bufferSize; | int bufferSize; | ||||
| float* inputs[NUM_ROWS+1]; | |||||
| float* outputs[NUM_ROWS+1]; | |||||
| float* inputs[NUM_ROWS + 1]; | |||||
| float* outputs[NUM_ROWS + 1]; | |||||
| float* knobs; | float* knobs; | ||||
| bool* switches; | bool* switches; | ||||
| float* lights[NUM_ROWS+1]; | |||||
| float* switchLights[NUM_ROWS+1]; | |||||
| float* lights[NUM_ROWS + 1]; | |||||
| float* switchLights[NUM_ROWS + 1]; | |||||
| }; | }; | ||||
| LuaProcessBlock block; | |||||
| LuaProcessBlock luaBlock; | |||||
| ~LuaJITEngine() { | ~LuaJITEngine() { | ||||
| if (L) | if (L) | ||||
| @@ -53,22 +31,21 @@ struct LuaJITEngine : ScriptEngine { | |||||
| } | } | ||||
| int run(const std::string& path, const std::string& script) override { | int run(const std::string& path, const std::string& script) override { | ||||
| ProcessBlock* original_block = getProcessBlock(); | |||||
| block.sampleRate = original_block->sampleRate; | |||||
| block.sampleTime = original_block->sampleTime; | |||||
| block.bufferSize = original_block->bufferSize; | |||||
| ProcessBlock* block = getProcessBlock(); | |||||
| // Initialize all the pointers with an offset of -1 | // Initialize all the pointers with an offset of -1 | ||||
| block.knobs = (float*)&(original_block->knobs[-1]); | |||||
| block.switches = (bool*)&(original_block->switches[-1]); | |||||
| for(int i = 1; i < NUM_ROWS + 1; i++) { | |||||
| block.inputs[i] = (float*)&(original_block->inputs[i-1][-1]); | |||||
| block.outputs[i] = (float*)&(original_block->outputs[i-1][-1]); | |||||
| block.lights[i] = (float*)&(original_block->lights[i-1][-1]); | |||||
| block.switchLights[i] = (float*)&(original_block->switchLights[i-1][-1]); | |||||
| #pragma GCC diagnostic push | |||||
| #pragma GCC diagnostic ignored "-Warray-bounds" | |||||
| luaBlock.knobs = &block->knobs[-1]; | |||||
| luaBlock.switches = &block->switches[-1]; | |||||
| for (int i = 0; i < NUM_ROWS; i++) { | |||||
| luaBlock.inputs[i + 1] = &block->inputs[i][-1]; | |||||
| luaBlock.outputs[i + 1] = &block->outputs[i][-1]; | |||||
| luaBlock.lights[i + 1] = &block->lights[i][-1]; | |||||
| luaBlock.switchLights[i + 1] = &block->switchLights[i][-1]; | |||||
| } | } | ||||
| #pragma GCC diagnostic pop | |||||
| L = luaL_newstate(); | L = luaL_newstate(); | ||||
| if (!L) { | if (!L) { | ||||
| @@ -77,7 +54,22 @@ struct LuaJITEngine : ScriptEngine { | |||||
| } | } | ||||
| // Import a subset of the standard library | // Import a subset of the standard library | ||||
| custom_openlibs(L); | |||||
| static const luaL_Reg lj_lib_load[] = { | |||||
| {"", luaopen_base}, | |||||
| {LUA_LOADLIBNAME, luaopen_package}, | |||||
| {LUA_TABLIBNAME, luaopen_table}, | |||||
| {LUA_STRLIBNAME, luaopen_string}, | |||||
| {LUA_MATHLIBNAME, luaopen_math}, | |||||
| {LUA_BITLIBNAME, luaopen_bit}, | |||||
| {LUA_JITLIBNAME, luaopen_jit}, | |||||
| {LUA_FFILIBNAME, luaopen_ffi}, | |||||
| {NULL, NULL} | |||||
| }; | |||||
| for (const luaL_Reg* lib = lj_lib_load; lib->func; lib++) { | |||||
| lua_pushcfunction(L, lib->func); | |||||
| lua_pushstring(L, lib->name); | |||||
| lua_call(L, 1, 0); | |||||
| } | |||||
| // Set user pointer | // Set user pointer | ||||
| lua_pushlightuserdata(L, this); | lua_pushlightuserdata(L, this); | ||||
| @@ -102,11 +94,11 @@ struct LuaJITEngine : ScriptEngine { | |||||
| } | } | ||||
| lua_setglobal(L, "config"); | lua_setglobal(L, "config"); | ||||
| // Loads the FFI auxiliary functions. | |||||
| // Load the FFI auxiliary functions. | |||||
| std::stringstream ffi_stream; | std::stringstream ffi_stream; | ||||
| ffi_stream | ffi_stream | ||||
| << "local ffi = require('ffi')" << std::endl | << "local ffi = require('ffi')" << std::endl | ||||
| // Describes the struct 'LuaProcessBlock' that way LuaJIT knows how to access the data | |||||
| // Describe the struct `LuaProcessBlock` so that LuaJIT knows how to access the data | |||||
| << "ffi.cdef[[" << std::endl | << "ffi.cdef[[" << std::endl | ||||
| << "struct LuaProcessBlock {" << std::endl | << "struct LuaProcessBlock {" << std::endl | ||||
| << "float sampleRate;" << std::endl | << "float sampleRate;" << std::endl | ||||
| @@ -118,9 +110,9 @@ struct LuaJITEngine : ScriptEngine { | |||||
| << "bool *switches;" << std::endl | << "bool *switches;" << std::endl | ||||
| << "float *lights[" << NUM_ROWS + 1 << "];" << std::endl | << "float *lights[" << NUM_ROWS + 1 << "];" << std::endl | ||||
| << "float *switchLights[" << NUM_ROWS + 1 << "];" << std::endl | << "float *switchLights[" << NUM_ROWS + 1 << "];" << std::endl | ||||
| <<"};]]" << std::endl | |||||
| // Declares the function 'castBlock' used to transform the 'block' pointer into a LuaJIT cdata | |||||
| << "function castBlock(b) return ffi.cast('struct LuaProcessBlock*', b) end"; | |||||
| << "};]]" << std::endl | |||||
| // Declare the function `_castBlock` used to transform `luaBlock` pointer into a LuaJIT cdata | |||||
| << "function _castBlock(b) return ffi.cast('struct LuaProcessBlock*', b) end"; | |||||
| std::string ffi_script = ffi_stream.str(); | std::string ffi_script = ffi_stream.str(); | ||||
| // Compile the ffi script | // Compile the ffi script | ||||
| @@ -183,21 +175,27 @@ struct LuaJITEngine : ScriptEngine { | |||||
| } | } | ||||
| // Create block object | // Create block object | ||||
| lua_getglobal(L, "castBlock"); | |||||
| lua_pushlightuserdata(L, (void *)&block); | |||||
| if (lua_pcall(L, 1, 1, 0) != 0) | |||||
| printf("error running function 'castBlock': %s", lua_tostring(L, -1)); | |||||
| lua_getglobal(L, "_castBlock"); | |||||
| lua_pushlightuserdata(L, (void*) &luaBlock); | |||||
| if (lua_pcall(L, 1, 1, 0)) { | |||||
| const char* s = lua_tostring(L, -1); | |||||
| WARN("LuaJIT: Error casting block: %s", s); | |||||
| display(s); | |||||
| lua_pop(L, 1); | |||||
| return -1; | |||||
| } | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int process() override { | int process() override { | ||||
| ProcessBlock* original_block = getProcessBlock(); | |||||
| ProcessBlock* block = getProcessBlock(); | |||||
| // Update the values of the block (the pointers should not change) | |||||
| block.sampleRate = original_block->sampleRate; | |||||
| block.sampleTime = original_block->sampleTime; | |||||
| block.bufferSize = original_block->bufferSize; | |||||
| // Update the values of the block. | |||||
| // The pointer values do not change. | |||||
| luaBlock.sampleRate = block->sampleRate; | |||||
| luaBlock.sampleTime = block->sampleTime; | |||||
| luaBlock.bufferSize = block->bufferSize; | |||||
| // Duplicate process function | // Duplicate process function | ||||
| lua_pushvalue(L, -2); | lua_pushvalue(L, -2); | ||||