From 8a0a167adbf3d9b6f8b6f16aaf20ca39ad5549de Mon Sep 17 00:00:00 2001 From: jacqueline Date: Sun, 12 Nov 2023 19:14:09 +1100 Subject: Convert the main menu screen to lua lol --- src/lua/lua_thread.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/lua/lua_thread.cpp (limited to 'src/lua/lua_thread.cpp') 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 + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "lua_thread.hpp" +#include + +#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(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(); + 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(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& alloc, + std::unique_ptr& 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 -- cgit v1.2.3