diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-01-17 11:48:40 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-01-17 11:48:40 +1100 |
| commit | 71b46730394979ea528d152dbe884cc35c368759 (patch) | |
| tree | 516b3af32f8822a5f900ea10fd6ffba2e3de1ebb /src/lua | |
| parent | 7cdcd44e0ca10ebdc796638190ed1d9b45d99ef0 (diff) | |
| download | tangara-fw-71b46730394979ea528d152dbe884cc35c368759.tar.gz | |
all screens basically working, but bluetooth is rough
Diffstat (limited to 'src/lua')
| -rw-r--r-- | src/lua/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/lua/bridge.cpp | 2 | ||||
| -rw-r--r-- | src/lua/include/lua_controls.hpp | 15 | ||||
| -rw-r--r-- | src/lua/include/property.hpp | 13 | ||||
| -rw-r--r-- | src/lua/lua_controls.cpp | 58 | ||||
| -rw-r--r-- | src/lua/property.cpp | 78 |
6 files changed, 164 insertions, 4 deletions
diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt index 7174757a..d89b22e8 100644 --- a/src/lua/CMakeLists.txt +++ b/src/lua/CMakeLists.txt @@ -4,7 +4,7 @@ idf_component_register( SRCS "lua_thread.cpp" "bridge.cpp" "property.cpp" "lua_database.cpp" - "lua_queue.cpp" "lua_version.cpp" + "lua_queue.cpp" "lua_version.cpp" "lua_controls.cpp" INCLUDE_DIRS "include" REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer" "battery" "esp-idf-lua" "luavgl" "lua-linenoise" "lua-term" diff --git a/src/lua/bridge.cpp b/src/lua/bridge.cpp index 82721d4e..a680a521 100644 --- a/src/lua/bridge.cpp +++ b/src/lua/bridge.cpp @@ -16,6 +16,7 @@ #include "lauxlib.h" #include "lua.h" #include "lua.hpp" +#include "lua_controls.hpp" #include "lua_database.hpp" #include "lua_queue.hpp" #include "lua_version.hpp" @@ -55,6 +56,7 @@ Bridge::Bridge(system_fsm::ServiceLocator& services, lua_State& s) luaL_requiref(&s, "term.core", luaopen_term_core, true); lua_pop(&s, 1); + RegisterControlsModule(&s); RegisterDatabaseModule(&s); RegisterQueueModule(&s); RegisterVersionModule(&s); diff --git a/src/lua/include/lua_controls.hpp b/src/lua/include/lua_controls.hpp new file mode 100644 index 00000000..18ad261d --- /dev/null +++ b/src/lua/include/lua_controls.hpp @@ -0,0 +1,15 @@ +/* + * Copyright 2023 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include "lua.hpp" + +namespace lua { + +auto RegisterControlsModule(lua_State*) -> void; + +} // namespace lua diff --git a/src/lua/include/property.hpp b/src/lua/include/property.hpp index a8a88125..9c5129ae 100644 --- a/src/lua/include/property.hpp +++ b/src/lua/include/property.hpp @@ -6,18 +6,27 @@ #pragma once +#include <stdint.h> #include <memory> #include <string> #include "audio_events.hpp" +#include "bluetooth_types.hpp" #include "lua.hpp" #include "lvgl.h" #include "service_locator.hpp" namespace lua { -using LuaValue = - std::variant<std::monostate, int, bool, std::string, audio::Track>; +// FIXME: We should use some kind of interface for this instead. +using LuaValue = std::variant<std::monostate, + int, + bool, + std::string, + audio::Track, + drivers::bluetooth::Device, + std::vector<drivers::bluetooth::Device>>; + using LuaFunction = std::function<int(lua_State*)>; class Property { diff --git a/src/lua/lua_controls.cpp b/src/lua/lua_controls.cpp new file mode 100644 index 00000000..2da0ed11 --- /dev/null +++ b/src/lua/lua_controls.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2023 jacqueline <me@jacqueline.id.au> + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "lua_controls.hpp" + +#include <memory> +#include <string> + +#include "lua.hpp" + +#include "esp_log.h" +#include "lauxlib.h" +#include "lua.h" +#include "lvgl.h" + +#include "nvs.hpp" +#include "ui_events.hpp" + +namespace lua { + +[[maybe_unused]] static constexpr char kTag[] = "lua_controls"; + +static auto controls_schemes(lua_State* L) -> int { + lua_newtable(L); + + lua_pushliteral(L, "Buttons Only"); + lua_rawseti(L, -2, + static_cast<int>(drivers::NvsStorage::InputModes::kButtonsOnly)); + + lua_pushliteral(L, "D-Pad"); + lua_rawseti( + L, -2, + static_cast<int>(drivers::NvsStorage::InputModes::kDirectionalWheel)); + + lua_pushliteral(L, "Touchwheel"); + lua_rawseti( + L, -2, static_cast<int>(drivers::NvsStorage::InputModes::kRotatingWheel)); + + return 1; +} + +static const struct luaL_Reg kControlsFuncs[] = {{"schemes", controls_schemes}, + {NULL, NULL}}; + +static auto lua_controls(lua_State* state) -> int { + luaL_newlib(state, kControlsFuncs); + return 1; +} + +auto RegisterControlsModule(lua_State* s) -> void { + luaL_requiref(s, "controls", lua_controls, true); + lua_pop(s, 1); +} + +} // namespace lua diff --git a/src/lua/property.cpp b/src/lua/property.cpp index 89351579..2d702447 100644 --- a/src/lua/property.cpp +++ b/src/lua/property.cpp @@ -10,7 +10,9 @@ #include <cmath> #include <memory> #include <string> +#include <variant> +#include "bluetooth_types.hpp" #include "lua.h" #include "lua.hpp" #include "lua_thread.hpp" @@ -185,6 +187,35 @@ static auto pushTagValue(lua_State* L, const database::TagValue& val) -> void { val); } +static void pushDevice(lua_State* L, const drivers::bluetooth::Device& dev) { + lua_createtable(L, 0, 4); + + lua_pushliteral(L, "address"); + auto* mac = reinterpret_cast<drivers::bluetooth::mac_addr_t*>( + lua_newuserdata(L, sizeof(drivers::bluetooth::mac_addr_t))); + *mac = dev.address; + lua_rawset(L, -3); + + // What I just did there was perfectly safe. Look, I can prove it: + static_assert( + std::is_trivially_copy_assignable<drivers::bluetooth::mac_addr_t>()); + static_assert( + std::is_trivially_destructible<drivers::bluetooth::mac_addr_t>()); + + lua_pushliteral(L, "name"); + lua_pushlstring(L, dev.name.data(), dev.name.size()); + lua_rawset(L, -3); + + // FIXME: This field deserves a little more structure. + lua_pushliteral(L, "class"); + lua_pushinteger(L, dev.class_of_device); + lua_rawset(L, -3); + + lua_pushliteral(L, "signal_strength"); + lua_pushinteger(L, dev.signal_strength); + lua_rawset(L, -3); +} + auto Property::PushValue(lua_State& s) -> int { std::visit( [&](auto&& arg) { @@ -222,6 +253,16 @@ auto Property::PushValue(lua_State& s) -> int { lua_pushliteral(&s, "encoding"); lua_pushstring(&s, codecs::StreamTypeToString(arg.encoding).c_str()); lua_settable(&s, table); + } else if constexpr (std::is_same_v<T, drivers::bluetooth::Device>) { + pushDevice(&s, arg); + } else if constexpr (std::is_same_v< + T, std::vector<drivers::bluetooth::Device>>) { + lua_createtable(&s, arg.size(), 0); + size_t i = 1; + for (const auto& dev : arg) { + pushDevice(&s, dev); + lua_rawseti(&s, -2, i++); + } } else { static_assert(always_false_v<T>, "PushValue missing type"); } @@ -230,6 +271,34 @@ auto Property::PushValue(lua_State& s) -> int { return 1; } +auto popRichType(lua_State* L) -> LuaValue { + lua_pushliteral(L, "address"); + lua_gettable(L, -2); + + if (lua_isuserdata(L, -1)) { + // This must be a bt device! + drivers::bluetooth::mac_addr_t mac = + *reinterpret_cast<drivers::bluetooth::mac_addr_t*>( + lua_touserdata(L, -1)); + lua_pop(L, 1); + + lua_pushliteral(L, "name"); + lua_gettable(L, -2); + + std::pmr::string name = lua_tostring(L, -1); + lua_pop(L, 1); + + return drivers::bluetooth::Device{ + .address = mac, + .name = name, + .class_of_device = 0, + .signal_strength = 0, + }; + } + + return std::monostate{}; +} + auto Property::PopValue(lua_State& s) -> bool { LuaValue new_val; switch (lua_type(&s, 2)) { @@ -250,7 +319,14 @@ auto Property::PopValue(lua_State& s) -> bool { new_val = lua_tostring(&s, 2); break; default: - return false; + if (lua_istable(&s, 2)) { + new_val = popRichType(&s); + if (std::holds_alternative<std::monostate>(new_val)) { + return false; + } + } else { + return false; + } } if (cb_ && std::invoke(*cb_, new_val)) { |
