From 7c85b803337b855d021de7f5e9c7e1082a29da06 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 3 Feb 2024 20:56:02 -0500 Subject: [PATCH] Add basic runtime for Lua --- lua/camlua.h | 17 ++++++ lua/lua.c | 12 +++++ lua/runtime.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 lua/camlua.h create mode 100644 lua/runtime.c diff --git a/lua/camlua.h b/lua/camlua.h new file mode 100644 index 0000000..ba5335d --- /dev/null +++ b/lua/camlua.h @@ -0,0 +1,17 @@ +#ifndef CAM_LUA_H +#define CAM_LUA_H + +#include +#include +#include + +LUALIB_API int luaopen_ptp(lua_State *L); + +lua_State *cam_new_task(int *id); +int lua_script_run_loop(int id); +int cam_run_lua_script(const char *buffer); +int cam_run_lua_script_async(const char *buffer); + +const char *cam_lua_get_error(); + +#endif \ No newline at end of file diff --git a/lua/lua.c b/lua/lua.c index ba6db9c..e3d1060 100644 --- a/lua/lua.c +++ b/lua/lua.c @@ -11,6 +11,8 @@ #include struct PtpRuntime *luaptp_get_runtime(lua_State *L); + +// lua-cjson void lua_json_decode(lua_State *l, const char *json_text, int json_len); void json_create_config(lua_State *l); @@ -137,12 +139,22 @@ static int mylua_test(lua_State *L) { return 1; } +static int mylua_connect(lua_State *L) { + struct PtpRuntime *r = luaptp_get_runtime(L); + + lua_pushinteger(L, 0); + + return 1; +} + + static const luaL_Reg ptplib[] = { {"test", mylua_test}, {"getDeviceInfo", mylua_device_info}, {"takePicture", mylua_take_picture}, {"setProperty", mylua_set_property}, {"sendOperation", mylua_send_operation}, + {"connect", mylua_connect}, {NULL, NULL} }; diff --git a/lua/runtime.c b/lua/runtime.c new file mode 100644 index 0000000..4fcaf19 --- /dev/null +++ b/lua/runtime.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_LUA_CONCURRENT 5 + +// Must be provided +int cam_lua_setup(lua_State *L); + +static char error_buffer[64]; + +static struct CamLuaTasks { + int tasks; + struct lua_State *L[MAX_LUA_CONCURRENT]; +}lua_tasks = {0}; + +const char *cam_lua_get_error() { + return error_buffer; +} + +int lua_script_run_loop(int id) { + if (id >= MAX_LUA_CONCURRENT || id < 0) { + snprintf(error_buffer, sizeof(error_buffer), "Script: out of bounds ID: %d\n", id); + return 1; + } + + struct lua_State *L = lua_tasks.L[(int)id]; + + if (L == NULL) return -1; + + lua_getglobal(L, "eventLoop"); + + if (lua_isfunction(L, -1)) { + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + snprintf(error_buffer, sizeof(error_buffer), "Failed to run Lua: %s", lua_tostring(L, -1)); + return -1; + } + } else { + snprintf(error_buffer, sizeof(error_buffer), "eventLoop is not a function: %s", lua_tostring(L, -1)); + return -1; + } + + return 0; +} + +static int lua_script_print(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + ptp_verbose_log("Lua: %s\n", str); + return 1; +} + +static int lua_script_toast(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + ptp_verbose_log("Lua: %s\n", str); + return 1; +} + +static int lua_script_set_status(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + //ui_send_text("status", (char *)str); + return 1; +} + +static int mylua_itoa(lua_State* L) { + int number = luaL_checkinteger(L, 1); + char buffer[20]; + snprintf(buffer, sizeof(buffer), "%d", number); + lua_pushstring(L, buffer); + return 1; +} + +lua_State *cam_lua_state() { + lua_State *L = luaL_newstate(); + luaopen_ptp(L); + luaopen_base(L); + luaL_requiref(L, "ptp", luaopen_ptp, 1); + lua_register(L, "print", lua_script_print); + lua_register(L, "setStatusText", lua_script_set_status); + cam_lua_setup(L); + return L; +} + +int cam_run_lua_script(const char *buffer) { + lua_State *L = cam_lua_state(); + if (L == NULL) { + snprintf(error_buffer, sizeof(error_buffer), "Reached max concurrent Lua tasks"); + return -1; + } + + if (luaL_loadbuffer(L, buffer, strlen(buffer), "script") != LUA_OK) { + snprintf(error_buffer, sizeof(error_buffer), "Failed to run Lua: %s", lua_tostring(L, -1)); + lua_close(L); + return -1; + } + + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + snprintf(error_buffer, sizeof(error_buffer), "Failed to run Lua: %s", lua_tostring(L, -1)); + lua_close(L); + return -1; + } + + lua_close(L); + return 0; +} + +lua_State *cam_new_task(int *id) { + if (lua_tasks.tasks >= MAX_LUA_CONCURRENT) { + return NULL; + } + + lua_State *L = cam_lua_state(); + + *id = lua_tasks.tasks; + lua_tasks.L[lua_tasks.tasks] = L; + lua_tasks.tasks++; + + return L; +} + +int cam_run_lua_script_async(const char *buffer) { + int id = 0; + lua_State *L = cam_new_task(&id); + if (L == NULL) { + snprintf(error_buffer, sizeof(error_buffer), "Reached max concurrent Lua tasks"); + return -1; + } + + if (luaL_loadbuffer(L, buffer, strlen(buffer), "script") != LUA_OK) { + snprintf(error_buffer, sizeof(error_buffer), "Failed to run Lua: %s", lua_tostring(L, -1)); + lua_close(L); + return -1; + } + + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + snprintf(error_buffer, sizeof(error_buffer), "Failed to run Lua: %s", lua_tostring(L, -1)); + lua_close(L); + return -1; + } + + return id; +}