| @@ -15,8 +15,8 @@ include $(RACK_DIR)/arch.mk | |||
| DUKTAPE ?= 0 | |||
| QUICKJS ?= 1 | |||
| LUAJIT ?= 1 | |||
| PYTHON ?= 1 | |||
| LUA ?= 1 | |||
| # Entropia File System Watcher | |||
| efsw := dep/lib/libefsw-static-release.a | |||
| @@ -60,36 +60,52 @@ $(quickjs): | |||
| cd QuickJS && $(MAKE) $(QUICKJS_MAKE_FLAGS) install | |||
| endif | |||
| # LuaJIT | |||
| ifeq ($(LUAJIT), 1) | |||
| SOURCES += src/LuaJITEngine.cpp | |||
| luajit := dep/lib/libluajit-5.1.a | |||
| OBJECTS += $(luajit) | |||
| DEPS += $(luajit) | |||
| $(luajit): | |||
| $(WGET) "http://luajit.org/download/LuaJIT-2.0.5.tar.gz" | |||
| $(SHA256) LuaJIT-2.0.5.tar.gz 874b1f8297c697821f561f9b73b57ffd419ed8f4278c82e05b48806d30c1e979 | |||
| cd dep && $(UNTAR) ../LuaJIT-2.0.5.tar.gz | |||
| cd dep/LuaJIT-2.0.5 && $(MAKE) | |||
| cd dep/LuaJIT-2.0.5 && $(MAKE) PREFIX="$(DEP_PATH)" install | |||
| endif | |||
| # Python | |||
| ifeq ($(PYTHON), 1) | |||
| SOURCES += src/PythonEngine.cpp | |||
| # Note this is a dynamic library, not static. | |||
| python := dep/lib/libpython3.7m.so.1.0 | |||
| python := dep/lib/libpython3.8.so.1.0 | |||
| DEPS += $(python) $(numpy) | |||
| FLAGS += -Idep/include/python3.7m | |||
| FLAGS += -Idep/include/python3.8 | |||
| # TODO Test these flags on all platforms | |||
| # Make dynamic linker look in the plugin folder for libpython. | |||
| LDFLAGS += -Wl,-rpath,'$$ORIGIN'/dep/lib | |||
| LDFLAGS += -Ldep/lib -lpython3.7m | |||
| LDFLAGS += -Ldep/lib -lpython3.8 | |||
| LDFLAGS += -lcrypt -lpthread -ldl -lutil -lm | |||
| DISTRIBUTABLES += $(python) | |||
| DISTRIBUTABLES += dep/lib/python3.7 | |||
| DISTRIBUTABLES += dep/lib/python3.8 | |||
| $(python): | |||
| $(WGET) "https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz" | |||
| $(SHA256) Python-3.7.4.tar.xz fb799134b868199930b75f26678f18932214042639cd52b16da7fd134cd9b13f | |||
| cd dep && $(UNTAR) ../Python-3.7.4.tar.xz | |||
| cd dep/Python-3.7.4 && $(CONFIGURE) --build=$(MACHINE) --enable-shared --enable-optimizations | |||
| cd dep/Python-3.7.4 && $(MAKE) build_all | |||
| cd dep/Python-3.7.4 && $(MAKE) install | |||
| numpy := dep/lib/python3.7/site-packages/numpy-1.17.2-py3.7-linux-x86_64.egg | |||
| FLAGS += -Idep/lib/python3.7/site-packages/numpy-1.17.2-py3.7-linux-x86_64.egg/numpy/core/include | |||
| $(WGET) "https://www.python.org/ftp/python/3.8.0/Python-3.8.0rc1.tar.xz" | |||
| $(SHA256) Python-3.8.0rc1.tar.xz ae44df6ccf5d70059dd4d04c97156f5fcace74384a6f3cfb2fdf9baddb90a821 | |||
| cd dep && $(UNTAR) ../Python-3.8.0rc1.tar.xz | |||
| cd dep/Python-3.8.0rc1 && $(CONFIGURE) --build=$(MACHINE) --enable-shared --enable-optimizations | |||
| cd dep/Python-3.8.0rc1 && $(MAKE) build_all | |||
| cd dep/Python-3.8.0rc1 && $(MAKE) install | |||
| numpy := dep/lib/python3.8/site-packages/numpy | |||
| FLAGS += -Idep/lib/python3.8/site-packages/numpy/core/include | |||
| $(numpy): $(python) | |||
| $(WGET) "https://github.com/numpy/numpy/releases/download/v1.17.2/numpy-1.17.2.tar.gz" | |||
| $(SHA256) numpy-1.17.2.tar.gz 81a4f748dcfa80a7071ad8f3d9f8edb9f8bc1f0a9bdd19bfd44fd42c02bd286c | |||
| cd dep && $(UNTAR) ../numpy-1.17.2.tar.gz | |||
| # Don't try to find an external BLAS and LAPACK library. | |||
| cd dep/numpy-1.17.2 && LD_LIBRARY_PATH=../lib NPY_BLAS_ORDER= NPY_LAPACK_ORDER= "$(DEP_PATH)"/bin/python3.7 setup.py build -j4 install | |||
| # Don't install to an egg folder. | |||
| # Make sure to use our built Python. | |||
| cd dep/numpy-1.17.2 && LD_LIBRARY_PATH=../lib NPY_BLAS_ORDER= NPY_LAPACK_ORDER= "$(DEP_PATH)"/bin/python3.8 setup.py build -j4 install --single-version-externally-managed --root=/ | |||
| # scipy: $(numpy) | |||
| # $(WGET) "https://github.com/scipy/scipy/releases/download/v1.3.1/scipy-1.3.1.tar.xz" | |||
| @@ -98,20 +114,6 @@ $(numpy): $(python) | |||
| # cd dep/scipy-1.3.1 && "$(DEP_PATH)"/bin/python3.7 setup.py build -j4 install | |||
| endif | |||
| # LuaJIT | |||
| ifeq ($(LUA), 1) | |||
| SOURCES += src/LuaJITEngine.cpp | |||
| luajit := dep/lib/libluajit-5.1.a | |||
| OBJECTS += $(luajit) | |||
| DEPS += $(luajit) | |||
| $(luajit): | |||
| $(WGET) "http://luajit.org/download/LuaJIT-2.0.5.tar.gz" | |||
| $(SHA256) LuaJIT-2.0.5.tar.gz 874b1f8297c697821f561f9b73b57ffd419ed8f4278c82e05b48806d30c1e979 | |||
| cd dep && $(UNTAR) ../LuaJIT-2.0.5.tar.gz | |||
| cd dep/LuaJIT-2.0.5 && $(MAKE) | |||
| cd dep/LuaJIT-2.0.5 && $(MAKE) PREFIX="$(DEP_PATH)" install | |||
| endif | |||
| # # Julia | |||
| # julia := dep/lib/libjulia.a | |||
| # DEPS += $(julia) | |||
| @@ -5,6 +5,11 @@ | |||
| struct LuaJITEngine : ScriptEngine { | |||
| lua_State* L = NULL; | |||
| struct SafeArray { | |||
| void* p; | |||
| size_t len; | |||
| }; | |||
| ~LuaJITEngine() { | |||
| if (L) | |||
| lua_close(L); | |||
| @@ -34,8 +39,8 @@ struct LuaJITEngine : ScriptEngine { | |||
| lua_setglobal(L, "_engine"); | |||
| // Set global functions | |||
| lua_pushcfunction(L, native_print); | |||
| lua_setglobal(L, "print"); | |||
| // lua_pushcfunction(L, native_print); | |||
| // lua_setglobal(L, "print"); | |||
| lua_pushcfunction(L, native_display); | |||
| lua_setglobal(L, "display"); | |||
| @@ -93,64 +98,99 @@ struct LuaJITEngine : ScriptEngine { | |||
| return -1; | |||
| } | |||
| // FloatArray metatable | |||
| lua_newtable(L); | |||
| { | |||
| // __index | |||
| lua_pushcfunction(L, native_FloatArray_index); | |||
| lua_setfield(L, -2, "__index"); | |||
| // __newindex | |||
| lua_pushcfunction(L, native_FloatArray_newindex); | |||
| lua_setfield(L, -2, "__newindex"); | |||
| // __len | |||
| lua_pushcfunction(L, native_FloatArray_len); | |||
| lua_setfield(L, -2, "__len"); | |||
| } | |||
| lua_setglobal(L, "FloatArray"); | |||
| // BoolArray metatable | |||
| lua_newtable(L); | |||
| { | |||
| // __index | |||
| lua_pushcfunction(L, native_BoolArray_index); | |||
| lua_setfield(L, -2, "__index"); | |||
| // __newindex | |||
| lua_pushcfunction(L, native_BoolArray_newindex); | |||
| lua_setfield(L, -2, "__newindex"); | |||
| // __len | |||
| lua_pushcfunction(L, native_BoolArray_len); | |||
| lua_setfield(L, -2, "__len"); | |||
| } | |||
| lua_setglobal(L, "BoolArray"); | |||
| // Create block object | |||
| lua_newtable(L); | |||
| { | |||
| // inputs | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_newtable(L); | |||
| for (int j = 0; j < block->bufferSize; j++) { | |||
| lua_pushnumber(L, 0.0); | |||
| lua_rawseti(L, -2, j + 1); | |||
| } | |||
| SafeArray* input = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| input->p = &block->inputs[i]; | |||
| input->len = block->bufferSize; | |||
| lua_getglobal(L, "FloatArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_setfield(L, -2, "inputs"); | |||
| // outputs | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_newtable(L); | |||
| for (int j = 0; j < block->bufferSize; j++) { | |||
| lua_pushnumber(L, 0.0); | |||
| lua_rawseti(L, -2, j + 1); | |||
| } | |||
| SafeArray* output = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| output->p = &block->outputs[i]; | |||
| output->len = block->bufferSize; | |||
| lua_getglobal(L, "FloatArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_setfield(L, -2, "outputs"); | |||
| // knobs | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_pushnumber(L, 0.0); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| SafeArray* knobs = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| knobs->p = &block->knobs; | |||
| knobs->len = 6; | |||
| lua_getglobal(L, "FloatArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_setfield(L, -2, "knobs"); | |||
| // switches | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_pushboolean(L, false); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| SafeArray* switches = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| switches->p = &block->switches; | |||
| switches->len = 6; | |||
| lua_getglobal(L, "BoolArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_setfield(L, -2, "switches"); | |||
| // lights | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_newtable(L); | |||
| for (int c = 0; c < 3; c++) { | |||
| lua_pushnumber(L, 0.0); | |||
| lua_rawseti(L, -2, c + 1); | |||
| } | |||
| SafeArray* light = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| light->p = &block->lights[i]; | |||
| light->len = 3; | |||
| lua_getglobal(L, "FloatArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_setfield(L, -2, "lights"); | |||
| // switchLights | |||
| lua_newtable(L); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_newtable(L); | |||
| for (int c = 0; c < 3; c++) { | |||
| lua_pushnumber(L, 0.0); | |||
| lua_rawseti(L, -2, c + 1); | |||
| } | |||
| SafeArray* switchLight = (SafeArray*) lua_newuserdata(L, sizeof(SafeArray)); | |||
| switchLight->p = &block->switchLights[i]; | |||
| switchLight->len = 3; | |||
| lua_getglobal(L, "FloatArray"); | |||
| lua_setmetatable(L, -2); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_setfield(L, -2, "switchLights"); | |||
| @@ -175,32 +215,6 @@ struct LuaJITEngine : ScriptEngine { | |||
| // bufferSize | |||
| lua_pushinteger(L, block->bufferSize); | |||
| lua_setfield(L, -2, "bufferSize"); | |||
| // inputs | |||
| lua_getfield(L, -1, "inputs"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_rawgeti(L, -1, i + 1); | |||
| for (int j = 0; j < block->bufferSize; j++) { | |||
| lua_pushnumber(L, block->inputs[i][j]); | |||
| lua_rawseti(L, -2, j + 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| // knobs | |||
| lua_getfield(L, -1, "knobs"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_pushnumber(L, block->knobs[i]); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| // switches | |||
| lua_getfield(L, -1, "switches"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_pushboolean(L, block->switches[i]); | |||
| lua_rawseti(L, -2, i + 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| // Duplicate process function | |||
| @@ -215,54 +229,6 @@ struct LuaJITEngine : ScriptEngine { | |||
| return -1; | |||
| } | |||
| // Get block | |||
| { | |||
| // outputs | |||
| lua_getfield(L, -1, "outputs"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_rawgeti(L, -1, i + 1); | |||
| for (int j = 0; j < block->bufferSize; j++) { | |||
| lua_rawgeti(L, -1, j + 1); | |||
| block->outputs[i][j] = lua_tonumber(L, -1); | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| // knobs | |||
| lua_getfield(L, -1, "knobs"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_rawgeti(L, -1, i + 1); | |||
| block->knobs[i] = lua_tonumber(L, -1); | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| // lights | |||
| lua_getfield(L, -1, "lights"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_rawgeti(L, -1, i + 1); | |||
| for (int c = 0; c < 3; c++) { | |||
| lua_rawgeti(L, -1, c + 1); | |||
| block->lights[i][c] = lua_tonumber(L, -1); | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| // switchLights | |||
| lua_getfield(L, -1, "switchLights"); | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| lua_rawgeti(L, -1, i + 1); | |||
| for (int c = 0; c < 3; c++) { | |||
| lua_rawgeti(L, -1, c + 1); | |||
| block->switchLights[i][c] = lua_tonumber(L, -1); | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -273,14 +239,14 @@ struct LuaJITEngine : ScriptEngine { | |||
| return engine; | |||
| } | |||
| static int native_print(lua_State* L) { | |||
| lua_getglobal(L, "tostring"); | |||
| lua_pushvalue(L, 1); | |||
| lua_call(L, 1, 1); | |||
| const char* s = lua_tostring(L, 1); | |||
| INFO("LuaJIT: %s", s); | |||
| return 0; | |||
| } | |||
| // static int native_print(lua_State* L) { | |||
| // lua_getglobal(L, "tostring"); | |||
| // lua_pushvalue(L, 1); | |||
| // lua_call(L, 1, 1); | |||
| // const char* s = lua_tostring(L, 1); | |||
| // INFO("LuaJIT: %s", s); | |||
| // return 0; | |||
| // } | |||
| static int native_display(lua_State* L) { | |||
| lua_getglobal(L, "tostring"); | |||
| @@ -292,6 +258,62 @@ struct LuaJITEngine : ScriptEngine { | |||
| getEngine(L)->display(s); | |||
| return 0; | |||
| } | |||
| static int native_FloatArray_index(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| float* data = (float*) a->p; | |||
| size_t index = lua_tointeger(L, 2) - 1; | |||
| if (index >= a->len) { | |||
| lua_pushstring(L, "Array out of bounds"); | |||
| lua_error(L); | |||
| } | |||
| lua_pushnumber(L, data[index]); | |||
| return 1; | |||
| } | |||
| static int native_FloatArray_newindex(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| float* data = (float*) a->p; | |||
| size_t index = lua_tointeger(L, 2) - 1; | |||
| if (index >= a->len) { | |||
| lua_pushstring(L, "Array out of bounds"); | |||
| lua_error(L); | |||
| } | |||
| data[index] = lua_tonumber(L, 3); | |||
| return 0; | |||
| } | |||
| static int native_FloatArray_len(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| lua_pushinteger(L, a->len); | |||
| return 1; | |||
| } | |||
| static int native_BoolArray_index(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| bool* data = (bool*) a->p; | |||
| size_t index = lua_tointeger(L, 2) - 1; | |||
| if (index >= a->len) { | |||
| lua_pushstring(L, "Array out of bounds"); | |||
| lua_error(L); | |||
| } | |||
| lua_pushboolean(L, data[index]); | |||
| return 1; | |||
| } | |||
| static int native_BoolArray_newindex(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| bool* data = (bool*) a->p; | |||
| size_t index = lua_tointeger(L, 2) - 1; | |||
| if (index >= a->len) { | |||
| lua_pushstring(L, "Array out of bounds"); | |||
| lua_error(L); | |||
| } | |||
| data[index] = lua_toboolean(L, 3); | |||
| return 0; | |||
| } | |||
| static int native_BoolArray_len(lua_State* L) { | |||
| SafeArray* a = (SafeArray*) lua_touserdata(L, 1); | |||
| lua_pushinteger(L, a->len); | |||
| return 1; | |||
| } | |||
| }; | |||
| @@ -298,11 +298,10 @@ void ScriptEngine::display(const std::string& message) { | |||
| module->message = message; | |||
| } | |||
| void ScriptEngine::setFrameDivider(int frameDivider) { | |||
| module->frameDivider = frameDivider; | |||
| module->frameDivider = std::max(frameDivider, 1); | |||
| } | |||
| void ScriptEngine::setBufferSize(int bufferSize) { | |||
| bufferSize = clamp(bufferSize, 1, MAX_BUFFER_SIZE); | |||
| module->block->bufferSize = bufferSize; | |||
| module->block->bufferSize = clamp(bufferSize, 1, MAX_BUFFER_SIZE); | |||
| } | |||
| ProcessBlock* ScriptEngine::getProcessBlock() { | |||
| return module->block; | |||
| @@ -9,6 +9,14 @@ extern "C" { | |||
| #include <thread> | |||
| /* | |||
| TODO: | |||
| - Allow multiple instances with GIL. | |||
| - Fix destructors. | |||
| - Add config object. | |||
| */ | |||
| extern rack::Plugin* pluginInstance; | |||
| @@ -16,13 +24,12 @@ static void initPython() { | |||
| if (Py_IsInitialized()) | |||
| return; | |||
| std::string pythonDir = rack::asset::plugin(pluginInstance, "dep/lib/python3.7"); | |||
| std::string pythonDir = rack::asset::plugin(pluginInstance, "dep/lib/python3.8"); | |||
| // Set python path | |||
| std::string sep = ":"; | |||
| std::string pythonPath = pythonDir; | |||
| pythonPath += sep + pythonDir + "/lib-dynload"; | |||
| // TODO Don't install to egg | |||
| pythonPath += sep + pythonDir + "/site-packages/numpy-1.17.2-py3.7-linux-x86_64.egg"; | |||
| pythonPath += sep + pythonDir + "/site-packages"; | |||
| wchar_t* pythonPathW = Py_DecodeLocale(pythonPath.c_str(), NULL); | |||
| Py_SetPath(pythonPathW); | |||
| PyMem_RawFree(pythonPathW); | |||
| @@ -30,10 +37,13 @@ static void initPython() { | |||
| Py_InitializeEx(0); | |||
| assert(Py_IsInitialized()); | |||
| PyEval_InitThreads(); | |||
| // PyEval_InitThreads(); | |||
| // Import numpy | |||
| assert(_import_array() == 0); | |||
| if (_import_array()) { | |||
| PyErr_Print(); | |||
| abort(); | |||
| } | |||
| } | |||
| @@ -59,6 +69,7 @@ struct PythonEngine : ScriptEngine { | |||
| } | |||
| int run(const std::string& path, const std::string& script) override { | |||
| ProcessBlock* block = getProcessBlock(); | |||
| initPython(); | |||
| // PyThreadState* tstate = PyThreadState_Get(); | |||
| @@ -73,8 +84,8 @@ struct PythonEngine : ScriptEngine { | |||
| assert(mainDict); | |||
| // Set context pointer | |||
| PyObject* thisO = PyCapsule_New(this, NULL, NULL); | |||
| PyDict_SetItemString(mainDict, "this", thisO); | |||
| PyObject* engineObj = PyCapsule_New(this, NULL, NULL); | |||
| PyDict_SetItemString(mainDict, "_engine", engineObj); | |||
| // Add functions to globals | |||
| static PyMethodDef native_functions[] = { | |||
| @@ -86,6 +97,25 @@ struct PythonEngine : ScriptEngine { | |||
| return -1; | |||
| } | |||
| // Set config | |||
| static PyStructSequence_Field configFields[] = { | |||
| {"frameDivider", ""}, | |||
| {"bufferSize", ""}, | |||
| {NULL, NULL}, | |||
| }; | |||
| static PyStructSequence_Desc configDesc = {"Config", "", configFields, LENGTHOF(configFields) - 1}; | |||
| PyTypeObject* configType = PyStructSequence_NewType(&configDesc); | |||
| assert(configType); | |||
| PyObject* configObj = PyStructSequence_New(configType); | |||
| assert(configObj); | |||
| PyDict_SetItemString(mainDict, "config", configObj); | |||
| // frameDivider | |||
| PyStructSequence_SetItem(configObj, 0, PyLong_FromLong(32)); | |||
| // bufferSize | |||
| PyStructSequence_SetItem(configObj, 1, PyLong_FromLong(1)); | |||
| // Compile string | |||
| PyObject* code = Py_CompileString(script.c_str(), path.c_str(), Py_file_input); | |||
| if (!code) { | |||
| @@ -103,7 +133,6 @@ struct PythonEngine : ScriptEngine { | |||
| DEFER({Py_DECREF(result);}); | |||
| // Create block | |||
| ProcessBlock* block = getProcessBlock(); | |||
| static PyStructSequence_Field blockFields[] = { | |||
| {"inputs", ""}, | |||
| {"outputs", ""}, | |||
| @@ -197,10 +226,10 @@ struct PythonEngine : ScriptEngine { | |||
| static PyObject* nativeDisplay(PyObject* self, PyObject* args) { | |||
| PyObject* mainDict = PyEval_GetGlobals(); | |||
| assert(mainDict); | |||
| PyObject* thatO = PyDict_GetItemString(mainDict, "this"); | |||
| assert(thatO); | |||
| PythonEngine* that = (PythonEngine*) PyCapsule_GetPointer(thatO, NULL); | |||
| assert(that); | |||
| PyObject* engineObj = PyDict_GetItemString(mainDict, "_engine"); | |||
| assert(engineObj); | |||
| PythonEngine* engine = (PythonEngine*) PyCapsule_GetPointer(engineObj, NULL); | |||
| assert(engine); | |||
| PyObject* msgO = PyTuple_GetItem(args, 0); | |||
| if (!msgO) | |||
| @@ -210,7 +239,7 @@ struct PythonEngine : ScriptEngine { | |||
| DEFER({Py_DECREF(msgS);}); | |||
| const char* msg = PyUnicode_AsUTF8(msgS); | |||
| that->display(msg); | |||
| engine->display(msg); | |||
| Py_INCREF(Py_None); | |||
| return Py_None; | |||
| @@ -3,8 +3,10 @@ config.frameDivider = 1 | |||
| config.bufferSize = 16 | |||
| function process(block) | |||
| for j=1,block.bufferSize do | |||
| block.outputs[1][j] = math.random() | |||
| for i=1,6 do | |||
| for j=1,block.bufferSize do | |||
| block.outputs[i][j] = block.inputs[i][j] | |||
| end | |||
| end | |||
| end | |||
| @@ -1,9 +1,13 @@ | |||
| frame = 0 | |||
| print(config) | |||
| print(config.frameDivider) | |||
| print(config.bufferSize) | |||
| def process(block): | |||
| global frame | |||
| frame += 1 | |||
| print(frame) | |||
| display(frame) | |||
| # print(block) | |||
| # block.switch_lights[:, 2] = 1 | |||
| print(block.inputs) | |||
| @@ -12,6 +16,6 @@ def process(block): | |||
| print(block.switches) | |||
| print(block.lights) | |||
| print(block.switch_lights) | |||
| print("===") | |||
| # print("===") | |||
| print("Hello, world!") | |||