summaryrefslogtreecommitdiff
path: root/src/lua/lua_thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/lua_thread.cpp')
-rw-r--r--src/lua/lua_thread.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/lua/lua_thread.cpp b/src/lua/lua_thread.cpp
new file mode 100644
index 00000000..cb7066a5
--- /dev/null
+++ b/src/lua/lua_thread.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "lua_thread.hpp"
+#include <memory>
+
+#include "esp_heap_caps.h"
+#include "esp_log.h"
+#include "lua.h"
+#include "lua.hpp"
+#include "luavgl.h"
+#include "service_locator.hpp"
+
+namespace lua {
+
+[[maybe_unused]] static constexpr char kTag[] = "lua";
+
+class Allocator {
+ public:
+ Allocator() : total_allocated_(0) {}
+
+ auto alloc(void* ptr, size_t osize, size_t nsize) -> void* {
+ total_allocated_ = total_allocated_ - osize + nsize;
+ // ESP_LOGI(kTag, "lua realloc -> %u KiB", total_allocated_ / 1024);
+ if (nsize == 0) {
+ heap_caps_free(ptr);
+ return NULL;
+ } else {
+ return heap_caps_realloc(ptr, nsize, MALLOC_CAP_SPIRAM);
+ }
+ }
+
+ private:
+ size_t total_allocated_;
+};
+
+static auto lua_alloc(void* ud, void* ptr, size_t osize, size_t nsize)
+ -> void* {
+ Allocator* instance = reinterpret_cast<Allocator*>(ud);
+ return instance->alloc(ptr, osize, nsize);
+}
+
+static int lua_panic(lua_State* L) {
+ ESP_LOGE(kTag, "!! PANIC !! %s", lua_tostring(L, -1));
+ return 0;
+}
+
+auto LuaThread::Start(system_fsm::ServiceLocator& services, lv_obj_t* lvgl_root)
+ -> LuaThread* {
+ auto alloc = std::make_unique<Allocator>();
+ lua_State* state = lua_newstate(lua_alloc, alloc.get());
+ if (!state) {
+ return nullptr;
+ }
+
+ luaL_openlibs(state);
+ lua_atpanic(state, lua_panic);
+
+ auto bridge = std::make_unique<Bridge>(services, *state);
+
+ // FIXME: luavgl init should probably be a part of the bridge.
+ if (lvgl_root) {
+ luavgl_set_root(state, lvgl_root);
+ luaL_requiref(state, "lvgl", luaopen_lvgl, true);
+ lua_pop(state, 1);
+ }
+
+ return new LuaThread(alloc, bridge, state);
+}
+
+LuaThread::LuaThread(std::unique_ptr<Allocator>& alloc,
+ std::unique_ptr<Bridge>& bridge,
+ lua_State* state)
+ : alloc_(std::move(alloc)), bridge_(std::move(bridge)), state_(state) {}
+
+LuaThread::~LuaThread() {
+ lua_close(state_);
+}
+
+auto LuaThread::RunScript(const std::string& path) -> bool {
+ int res = luaL_loadfilex(state_, path.c_str(), NULL);
+ if (res != LUA_OK) {
+ return false;
+ }
+ res = lua_pcall(state_, 0, 0, 0);
+ if (res) {
+ const char* msg = lua_tostring(state_, -1);
+ lua_writestring(msg, strlen(msg));
+ lua_writeline();
+ lua_pop(state_, 1);
+ }
+ return true;
+}
+
+} // namespace lua