summaryrefslogtreecommitdiff
path: root/src/lua
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-01-17 11:48:40 +1100
committerjacqueline <me@jacqueline.id.au>2024-01-17 11:48:40 +1100
commit71b46730394979ea528d152dbe884cc35c368759 (patch)
tree516b3af32f8822a5f900ea10fd6ffba2e3de1ebb /src/lua
parent7cdcd44e0ca10ebdc796638190ed1d9b45d99ef0 (diff)
downloadtangara-fw-71b46730394979ea528d152dbe884cc35c368759.tar.gz
all screens basically working, but bluetooth is rough
Diffstat (limited to 'src/lua')
-rw-r--r--src/lua/CMakeLists.txt2
-rw-r--r--src/lua/bridge.cpp2
-rw-r--r--src/lua/include/lua_controls.hpp15
-rw-r--r--src/lua/include/property.hpp13
-rw-r--r--src/lua/lua_controls.cpp58
-rw-r--r--src/lua/property.cpp78
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)) {