diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-01-05 10:38:35 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-01-05 10:38:35 +1100 |
| commit | 34cae4e6e4bb00b3453bcdab084368a949c908a4 (patch) | |
| tree | 024caadd70ea35ab2c73cc782f3a37c93a90702f /src/ui/ui_fsm.cpp | |
| parent | 938ba62f57ed2c002bae4aec236eeaeb200e4cba (diff) | |
| download | tangara-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.cpp | 72 |
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()); } |
