summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-07-12 14:40:54 +1000
committerjacqueline <me@jacqueline.id.au>2024-07-12 14:40:54 +1000
commitf78de39a750d58bfe883a789aa6cc4b0a5d9b9e7 (patch)
treebd7c20afd43745a0648aa36b83f8414f0fe5ba42
parenta3eb2dd9dc2399ce9c22cd3b07f482f080976440 (diff)
downloadtangara-fw-f78de39a750d58bfe883a789aa6cc4b0a5d9b9e7.tar.gz
Give Bluetooth settings a bit of a refresh
It's now a bit more responsive to stuff happening, gives you more information, and remembers your previously paired devices for faster switching between them.
-rw-r--r--lua/settings.lua46
-rw-r--r--lua/widgets.lua9
-rw-r--r--src/drivers/bluetooth.cpp24
-rw-r--r--src/drivers/include/drivers/nvs.hpp2
-rw-r--r--src/drivers/nvs.cpp2
-rw-r--r--src/tangara/lua/property.cpp51
6 files changed, 79 insertions, 55 deletions
diff --git a/lua/settings.lua b/lua/settings.lua
index 0691f2d1..3751a12a 100644
--- a/lua/settings.lua
+++ b/lua/settings.lua
@@ -46,6 +46,7 @@ local BluetoothPairing = SettingsScreen:new {
for _, dev in pairs(devs) do
devices:add_btn(nil, dev.name):onClicked(function()
bluetooth.paired_device:set(dev)
+ backstack.pop()
end)
end
end)
@@ -101,16 +102,15 @@ local BluetoothSettings = SettingsScreen:new {
theme.set_style(paired_label, "settings_title")
self.bindings = self.bindings + {
- bluetooth.connected:bind(function(conn)
- if conn then
- paired_label:set { text = "Connected to:" }
- else
- paired_label:set { text = "Paired with:" }
- end
- end),
bluetooth.connecting:bind(function(conn)
if conn then
paired_label:set { text = "Connecting to:" }
+ else
+ if bluetooth.connected:get() then
+ paired_label:set { text = "Connected to:" }
+ else
+ paired_label:set { text = "Paired with:" }
+ end
end
end),
}
@@ -159,22 +159,42 @@ local BluetoothSettings = SettingsScreen:new {
h = lvgl.SIZE_CONTENT,
}
+ -- 'Pair new device' button that goes to the discovery screen.
+
+ local button_container = self.content:Object {
+ w = lvgl.PCT(100),
+ h = lvgl.SIZE_CONTENT,
+ flex = {
+ flex_direction = "row",
+ justify_content = "center",
+ align_items = "space-evenly",
+ align_content = "center",
+ },
+ pad_top = 4,
+ pad_column = 4,
+ }
+ button_container:add_style(styles.list_item)
+
+ local pair_new = button_container:Button {}
+ pair_new:Label { text = "Pair new device" }
+ pair_new:onClicked(function()
+ backstack.push(BluetoothPairing:new())
+ end)
+
+
self.bindings = self.bindings + {
bluetooth.known_devices:bind(function(devs)
+ local group = lvgl.group.get_default()
+ group.remove_obj(pair_new)
devices:clean()
for _, dev in pairs(devs) do
devices:add_btn(nil, dev.name):onClicked(function()
bluetooth.paired_device:set(dev)
end)
end
+ group:add_obj(pair_new)
end)
}
-
- local pair_new = self.content:Button {}
- pair_new:Label { text = "Pair new device" }
- pair_new:onClicked(function()
- backstack.push(BluetoothPairing:new())
- end)
end
}
diff --git a/lua/widgets.lua b/lua/widgets.lua
index c3573c0b..c7a24576 100644
--- a/lua/widgets.lua
+++ b/lua/widgets.lua
@@ -79,11 +79,10 @@ function widgets.Row(parent, left, right)
}
end
-local bindings_meta = {
- __add = function(a, b)
- return table.move(a, 1, #a, #b + 1, b)
- end
-}
+local bindings_meta = {}
+bindings_meta["__add"] = function(a, b)
+ return setmetatable(table.move(a, 1, #a, #b + 1, b), bindings_meta)
+end
function widgets.StatusBar(parent, opts)
local root = parent.root:Object {
diff --git a/src/drivers/bluetooth.cpp b/src/drivers/bluetooth.cpp
index 2edf5ad9..a0a318e9 100644
--- a/src/drivers/bluetooth.cpp
+++ b/src/drivers/bluetooth.cpp
@@ -603,16 +603,21 @@ void Disabled::react(const events::Enable&) {
void Idle::entry() {
ESP_LOGI(kTag, "bt is idle");
+ std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
}
-void Idle::exit() {}
+void Idle::exit() {
+ std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
+}
void Idle::react(const events::Disable& ev) {
transit<Disabled>();
}
void Idle::react(const events::PairedDeviceChanged& ev) {
- connect(*sPairedWith_);
+ if (sPairedWith_) {
+ connect(*sPairedWith_);
+ }
}
void Idle::react(events::internal::Gap ev) {
@@ -633,18 +638,10 @@ void Connecting::entry() {
sTimeoutTimer = xTimerCreate("bt_timeout", pdMS_TO_TICKS(15000), false, NULL,
timeoutCallback);
xTimerStart(sTimeoutTimer, portMAX_DELAY);
-
- if (sEventHandler_) {
- std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
- }
}
void Connecting::exit() {
xTimerDelete(sTimeoutTimer, portMAX_DELAY);
-
- if (sEventHandler_) {
- std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
- }
}
void Connecting::react(const events::ConnectTimedOut& ev) {
@@ -751,12 +748,16 @@ void Connected::entry() {
sStorage_->PreferredBluetoothDevice(sPairedWith_);
}
+ std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
+
// TODO: if we already have a source, immediately start playing
}
void Connected::exit() {
ESP_LOGI(kTag, "exiting connected state");
esp_a2d_source_disconnect(connected_to_.data());
+
+ std::invoke(sEventHandler_, SimpleEvent::kConnectionStateChanged);
}
void Connected::react(const events::Disable& ev) {
@@ -765,6 +766,9 @@ void Connected::react(const events::Disable& ev) {
void Connected::react(const events::PairedDeviceChanged& ev) {
transit<Idle>();
+ if (sPairedWith_) {
+ connect(*sPairedWith_);
+ }
}
void Connected::react(const events::SourceChanged& ev) {
diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp
index 2bc77a31..8eb28cc9 100644
--- a/src/drivers/include/drivers/nvs.hpp
+++ b/src/drivers/include/drivers/nvs.hpp
@@ -34,7 +34,7 @@ class Setting {
dirty_ = true;
}
}
- auto get() -> std::optional<T>& { return val_; }
+ auto get() -> std::optional<T> { return val_; }
/* Reads the stored value from NVS and parses it into the correct type. */
auto load(nvs_handle_t) -> std::optional<T>;
diff --git a/src/drivers/nvs.cpp b/src/drivers/nvs.cpp
index c4d8dedc..e3c4aa06 100644
--- a/src/drivers/nvs.cpp
+++ b/src/drivers/nvs.cpp
@@ -391,7 +391,7 @@ auto NvsStorage::BluetoothNames() -> std::vector<bluetooth::MacAndName> {
auto NvsStorage::BluetoothName(const bluetooth::mac_addr_t& mac,
std::optional<std::string> name) -> void {
std::lock_guard<std::mutex> lock{mutex_};
- auto& val = bt_names_.get();
+ auto val = bt_names_.get();
if (!val) {
val.emplace();
}
diff --git a/src/tangara/lua/property.cpp b/src/tangara/lua/property.cpp
index 7b4f0b97..1be1fd2d 100644
--- a/src/tangara/lua/property.cpp
+++ b/src/tangara/lua/property.cpp
@@ -371,33 +371,34 @@ auto popRichType(lua_State* L) -> LuaValue {
}
auto Property::popValue(lua_State& s) -> bool {
- LuaValue new_val;
- switch (lua_type(&s, 2)) {
- case LUA_TNIL:
- new_val = std::monostate{};
- break;
- case LUA_TNUMBER:
- if (lua_isinteger(&s, 2)) {
- new_val = lua_tointeger(&s, 2);
- } else {
- new_val = static_cast<lua_Integer>(std::round(lua_tonumber(&s, 2)));
- }
- break;
- case LUA_TBOOLEAN:
- new_val = static_cast<bool>(lua_toboolean(&s, 2));
- break;
- case LUA_TSTRING:
- new_val = lua_tostring(&s, 2);
- break;
- default:
- if (lua_istable(&s, 2)) {
- new_val = popRichType(&s);
- if (std::holds_alternative<std::monostate>(new_val)) {
+ LuaValue new_val{std::monostate{}};
+ if (lua_gettop(&s) >= 2) {
+ switch (lua_type(&s, 2)) {
+ case LUA_TNIL:
+ break;
+ case LUA_TNUMBER:
+ if (lua_isinteger(&s, 2)) {
+ new_val = lua_tointeger(&s, 2);
+ } else {
+ new_val = static_cast<lua_Integer>(std::round(lua_tonumber(&s, 2)));
+ }
+ break;
+ case LUA_TBOOLEAN:
+ new_val = static_cast<bool>(lua_toboolean(&s, 2));
+ break;
+ case LUA_TSTRING:
+ new_val = lua_tostring(&s, 2);
+ break;
+ default:
+ if (lua_istable(&s, 2)) {
+ new_val = popRichType(&s);
+ if (std::holds_alternative<std::monostate>(new_val)) {
+ return false;
+ }
+ } else {
return false;
}
- } else {
- return false;
- }
+ }
}
return set(new_val);