Fork of Tangara with customizations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
tangara-fw/src/tangara/lua/bridge.cpp

146 lines
3.6 KiB

/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "lua/bridge.hpp"
#include <cstdint>
#include <memory>
#include <string>
#include "database/database.hpp"
#include "database/index.hpp"
#include "esp_log.h"
#include "lauxlib.h"
#include "lua.h"
#include "lua.hpp"
#include "lua/lua_controls.hpp"
#include "lua/lua_database.hpp"
#include "lua/lua_filesystem.hpp"
#include "lua/lua_queue.hpp"
#include "lua/lua_screen.hpp"
#include "lua/lua_testing.hpp"
#include "lua/lua_theme.hpp"
#include "lua/lua_version.hpp"
#include "lvgl.h"
#include "luavgl.h"
#include "events/event_queue.hpp"
#include "lua/property.hpp"
#include "system_fsm/service_locator.hpp"
#include "ui/ui_events.hpp"
extern "C" {
int luaopen_linenoise(lua_State* L);
int luaopen_term_core(lua_State* L);
}
LV_FONT_DECLARE(font_fusion_12);
LV_FONT_DECLARE(font_fusion_10);
namespace lua {
[[maybe_unused]] static constexpr char kTag[] = "lua_bridge";
static constexpr char kBridgeKey[] = "bridge";
static auto make_font_cb(const char* name, int size, int weight)
-> const lv_font_t* {
if (std::string{"fusion"} == name) {
if (size == 12) {
return &font_fusion_12;
}
if (size == 10) {
return &font_fusion_10;
}
}
return NULL;
}
static auto delete_font_cb(const lv_font_t* font) -> void {}
auto Bridge::Get(lua_State* state) -> Bridge* {
lua_pushstring(state, kBridgeKey);
lua_gettable(state, LUA_REGISTRYINDEX);
return reinterpret_cast<Bridge*>(lua_touserdata(state, -1));
}
Bridge::Bridge(system_fsm::ServiceLocator& services) : services_(services) {}
auto Bridge::installBaseModules(lua_State* L) -> void {
lua_pushstring(L, kBridgeKey);
lua_pushlightuserdata(L, this);
lua_settable(L, LUA_REGISTRYINDEX);
bindings_.install(L);
luaL_requiref(L, "linenoise", luaopen_linenoise, true);
lua_pop(L, 1);
luaL_requiref(L, "term.core", luaopen_term_core, true);
lua_pop(L, 1);
RegisterControlsModule(L);
RegisterDatabaseModule(L);
RegisterQueueModule(L);
RegisterTestingModule(L);
RegisterFileSystemModule(L);
RegisterVersionModule(L);
RegisterThemeModule(L);
RegisterScreenModule(L);
}
auto Bridge::installLvgl(lua_State* L) -> void {
luavgl_set_pcall(L, CallProtected);
luavgl_set_font_extension(L, make_font_cb, delete_font_cb);
luaL_requiref(L, "lvgl", luaopen_lvgl, true);
lua_pop(L, 1);
}
static auto new_property_module(lua_State* state) -> int {
const char* name = luaL_checkstring(state, 1);
luaL_newmetatable(state, name);
lua_pushstring(state, "__index");
lua_pushvalue(state, -2);
lua_settable(state, -3); // metatable.__index = metatable
return 1;
}
template <class... Ts>
inline constexpr bool always_false_v = false;
auto Bridge::installPropertyModule(
lua_State* L,
const std::string& name,
std::vector<std::pair<std::string, std::variant<LuaFunction, Property*>>>&
props) -> void {
// Create the module (or retrieve it if one with this name already exists)
luaL_requiref(L, name.c_str(), new_property_module, true);
for (const auto& prop : props) {
lua_pushstring(L, prop.first.c_str());
std::visit(
[&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, LuaFunction>) {
bindings_.Register(L, arg);
} else if constexpr (std::is_same_v<T, Property*>) {
bindings_.Register(L, arg);
} else {
static_assert(always_false_v<T>, "missing case");
}
},
prop.second);
lua_settable(L, -3); // metatable.propname = property
}
lua_pop(L, 1); // pop the module off the stack
}
} // namespace lua