summaryrefslogtreecommitdiff
path: root/src/ui/ui_fsm.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-01-05 10:38:35 +1100
committerjacqueline <me@jacqueline.id.au>2024-01-05 10:38:35 +1100
commit34cae4e6e4bb00b3453bcdab084368a949c908a4 (patch)
tree024caadd70ea35ab2c73cc782f3a37c93a90702f /src/ui/ui_fsm.cpp
parent938ba62f57ed2c002bae4aec236eeaeb200e4cba (diff)
downloadtangara-fw-34cae4e6e4bb00b3453bcdab084368a949c908a4.tar.gz
add an alerts module for lua, and implement a volume indicator with it
Diffstat (limited to 'src/ui/ui_fsm.cpp')
-rw-r--r--src/ui/ui_fsm.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/ui/ui_fsm.cpp b/src/ui/ui_fsm.cpp
index 8e355fd1..740383a4 100644
--- a/src/ui/ui_fsm.cpp
+++ b/src/ui/ui_fsm.cpp
@@ -9,6 +9,8 @@
#include <memory>
#include <variant>
+#include "freertos/portmacro.h"
+#include "freertos/projdefs.h"
#include "lua.h"
#include "lua.hpp"
@@ -44,6 +46,7 @@
#include "spiffs.hpp"
#include "storage.hpp"
#include "system_events.hpp"
+#include "tinyfsm.hpp"
#include "touchwheel.hpp"
#include "track_queue.hpp"
#include "ui_events.hpp"
@@ -70,6 +73,13 @@ models::TopBar UiState::sTopBarModel{{},
UiState::sPlaybackModel.is_playing,
UiState::sPlaybackModel.current_track};
+static TimerHandle_t sAlertTimer;
+static lv_obj_t* sAlertContainer;
+
+static void alert_timer_callback(TimerHandle_t timer) {
+ events::Ui().Dispatch(internal::DismissAlerts{});
+}
+
auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool {
// Init LVGL first, since the display driver registers itself with LVGL.
lv_init();
@@ -89,6 +99,7 @@ void UiState::PushScreen(std::shared_ptr<Screen> screen) {
sScreens.push(sCurrentScreen);
}
sCurrentScreen = screen;
+ lv_obj_set_parent(sAlertContainer, sCurrentScreen->alert());
}
int UiState::PopScreen() {
@@ -96,6 +107,8 @@ int UiState::PopScreen() {
return 0;
}
sCurrentScreen = sScreens.top();
+ lv_obj_set_parent(sAlertContainer, sCurrentScreen->alert());
+
sScreens.pop();
return sScreens.size();
}
@@ -127,6 +140,10 @@ void UiState::react(const internal::ControlSchemeChanged&) {
sInput->mode(sServices->nvs().PrimaryInput());
}
+void UiState::react(const internal::DismissAlerts&) {
+ lv_obj_clean(sAlertContainer);
+}
+
namespace states {
void Splash::exit() {
@@ -164,6 +181,10 @@ void Splash::react(const system_fsm::StorageMounted&) {
void Lua::entry() {
if (!sLua) {
+ sAlertTimer = xTimerCreate("ui_alerts", pdMS_TO_TICKS(1000), false, NULL,
+ alert_timer_callback);
+ sAlertContainer = lv_obj_create(sCurrentScreen->alert());
+
auto bat =
sServices->battery().State().value_or(battery::Battery::BatteryState{});
battery_pct_ =
@@ -184,6 +205,9 @@ void Lua::entry() {
playback_track_ = std::make_shared<lua::Property>();
playback_position_ = std::make_shared<lua::Property>();
+ volume_current_pct_ = std::make_shared<lua::Property>(0);
+ volume_current_db_ = std::make_shared<lua::Property>(0);
+
sLua.reset(lua::LuaThread::Start(*sServices, sCurrentScreen->content()));
sLua->bridge().AddPropertyModule("power",
{
@@ -208,12 +232,23 @@ void Lua::entry() {
{"replay", queue_repeat_},
{"random", queue_random_},
});
+ sLua->bridge().AddPropertyModule("volume",
+ {
+ {"current_pct", volume_current_pct_},
+ {"current_db", volume_current_db_},
+ });
+
sLua->bridge().AddPropertyModule(
"backstack",
{
{"push", [&](lua_State* s) { return PushLuaScreen(s); }},
{"pop", [&](lua_State* s) { return PopLuaScreen(s); }},
});
+ sLua->bridge().AddPropertyModule(
+ "alerts", {
+ {"show", [&](lua_State* s) { return ShowAlert(s); }},
+ {"hide", [&](lua_State* s) { return HideAlert(s); }},
+ });
sCurrentScreen.reset();
sLua->RunScript("/lua/main.lua");
@@ -265,6 +300,38 @@ auto Lua::SetPlaying(const lua::LuaValue& val) -> bool {
return true;
}
+auto Lua::ShowAlert(lua_State* s) -> int {
+ if (!sCurrentScreen) {
+ return 0;
+ }
+ xTimerReset(sAlertTimer, portMAX_DELAY);
+ tinyfsm::FsmList<UiState>::dispatch(internal::DismissAlerts{});
+
+ lv_group_t* prev_group = lv_group_get_default();
+
+ luavgl_set_root(s, sAlertContainer);
+ lv_group_t* catchall = lv_group_create();
+ lv_group_set_default(catchall);
+
+ // Call the constructor for the alert.
+ lua_settop(s, 1); // Make sure the function is actually at top of stack
+ lua::CallProtected(s, 0, 1);
+
+ // Restore the previous group and default object.
+ luavgl_set_root(s, sCurrentScreen->content());
+ lv_group_set_default(prev_group);
+
+ lv_group_del(catchall);
+
+ return 0;
+}
+
+auto Lua::HideAlert(lua_State* s) -> int {
+ xTimerStop(sAlertTimer, portMAX_DELAY);
+ tinyfsm::FsmList<UiState>::dispatch(internal::DismissAlerts{});
+ return 0;
+}
+
auto Lua::SetRandom(const lua::LuaValue& val) -> bool {
if (!std::holds_alternative<bool>(val)) {
return false;
@@ -327,6 +394,11 @@ void Lua::react(const audio::PlaybackFinished&) {
playback_playing_->Update(false);
}
+void Lua::react(const audio::VolumeChanged& ev) {
+ volume_current_pct_->Update(static_cast<int>(ev.percent));
+ volume_current_db_->Update(static_cast<int>(ev.db));
+}
+
void Lua::react(const internal::BackPressed& ev) {
PopLuaScreen(sLua->state());
}