From 71b46730394979ea528d152dbe884cc35c368759 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 17 Jan 2024 11:48:40 +1100 Subject: all screens basically working, but bluetooth is rough --- src/lua/property.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'src/lua/property.cpp') 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 #include #include +#include +#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( + 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()); + static_assert( + std::is_trivially_destructible()); + + 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) { + pushDevice(&s, arg); + } else if constexpr (std::is_same_v< + T, std::vector>) { + 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, "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( + 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(new_val)) { + return false; + } + } else { + return false; + } } if (cb_ && std::invoke(*cb_, new_val)) { -- cgit v1.2.3