From 9fdf94e9cee5a5180ffefc2b8314f7a9879ebbc6 Mon Sep 17 00:00:00 2001 From: ayumi Date: Sat, 15 Feb 2025 02:25:27 +0100 Subject: [PATCH] Allow manually unmounting the SD card --- lua/images.lua | 1 + lua/img/unmount.png | Bin 0 -> 107 bytes lua/main_menu.lua | 21 +++++++ lua/settings.lua | 77 ++++++++++++++++++++++- src/tangara/audio/audio_events.hpp | 4 ++ src/tangara/audio/audio_fsm.cpp | 7 +-- src/tangara/audio/audio_fsm.hpp | 4 +- src/tangara/system_fsm/running.cpp | 15 ++++- src/tangara/system_fsm/system_events.hpp | 3 + src/tangara/system_fsm/system_fsm.hpp | 5 ++ src/tangara/ui/ui_fsm.cpp | 5 ++ src/tangara/ui/ui_fsm.hpp | 2 + 12 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 lua/img/unmount.png diff --git a/lua/images.lua b/lua/images.lua index 21a1aa9a..a492b9a2 100644 --- a/lua/images.lua +++ b/lua/images.lua @@ -29,6 +29,7 @@ local img = { unlistened = lvgl.ImgData("//lua/img/unlistened.png"), info = lvgl.ImgData("//lua/img/info.png"), menu = lvgl.ImgData("//lua/img/menu.png"), + unmount = lvgl.ImgData("//lua/img/unmount.png"), file_directory = lvgl.ImgData("//lua/img/file_icons/directory.png"), file_playlist = lvgl.ImgData("//lua/img/file_icons/playlist.png"), file_music = lvgl.ImgData("//lua/img/file_icons/music.png"), diff --git a/lua/img/unmount.png b/lua/img/unmount.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd8a6744dacb48641b6b7ed1f40cdfb957e010e GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh0wlLOK8*rWMxHK?Ar-ggp4-UFV8Frb_ track; diff --git a/src/tangara/audio/audio_fsm.cpp b/src/tangara/audio/audio_fsm.cpp index 7854818d..27c29eee 100644 --- a/src/tangara/audio/audio_fsm.cpp +++ b/src/tangara/audio/audio_fsm.cpp @@ -534,10 +534,7 @@ auto Standby::entry() -> void { updateOutputMode(); } -void Standby::react(const system_fsm::KeyLockChanged& ev) { - if (!ev.locking) { - return; - } +void Standby::react(const system_fsm::UnmountRequest& ev) { auto current = sStreamCues.current(); sServices->bg_worker().Dispatch([=]() { auto db = sServices->database().lock(); @@ -548,6 +545,7 @@ void Standby::react(const system_fsm::KeyLockChanged& ev) { if (queue.totalSize() <= queue.currentPosition()) { // Nothing is playing, so don't bother saving the queue. db->put(kQueueKey, ""); + events::System().Dispatch(UnmountReady{.idle = ev.idle}); return; } db->put(kQueueKey, queue.serialise()); @@ -562,6 +560,7 @@ void Standby::react(const system_fsm::KeyLockChanged& ev) { }; db->put(kCurrentFileKey, current_track.toString()); } + events::System().Dispatch(UnmountReady{.idle = ev.idle}); }); } diff --git a/src/tangara/audio/audio_fsm.hpp b/src/tangara/audio/audio_fsm.hpp index fb42e387..c30012d9 100644 --- a/src/tangara/audio/audio_fsm.hpp +++ b/src/tangara/audio/audio_fsm.hpp @@ -65,7 +65,7 @@ class AudioState : public tinyfsm::Fsm { void react(const OutputModeChanged&); virtual void react(const system_fsm::BootComplete&) {} - virtual void react(const system_fsm::KeyLockChanged&){}; + virtual void react(const system_fsm::UnmountRequest&) {} virtual void react(const system_fsm::SdStateChanged&) {} virtual void react(const system_fsm::BluetoothEvent&); virtual void react(const system_fsm::HasPhonesChanged&); @@ -114,7 +114,7 @@ class Uninitialised : public AudioState { class Standby : public AudioState { public: void entry() override; - void react(const system_fsm::KeyLockChanged&) override; + void react(const system_fsm::UnmountRequest&) override; void react(const system_fsm::SdStateChanged&) override; using AudioState::react; diff --git a/src/tangara/system_fsm/running.cpp b/src/tangara/system_fsm/running.cpp index 13f58ef9..87b7f1ac 100644 --- a/src/tangara/system_fsm/running.cpp +++ b/src/tangara/system_fsm/running.cpp @@ -59,9 +59,22 @@ void Running::react(const database::event::UpdateFinished&) { checkIdle(); } +void Running::react(const ui::UnmountRequest& ev) { + events::Audio().Dispatch(audio::TogglePlayPause{.set_to = false}); + events::Audio().Dispatch(UnmountRequest{.idle = false}); +} + +void Running::react(const audio::UnmountReady& ev) { + if (ev.idle) { + transit(); + } else { + unmountStorage(); + } +} + void Running::react(const internal::UnmountTimeout&) { if (IdleCondition()) { - transit(); + events::Audio().Dispatch(UnmountRequest{.idle = true}); } } diff --git a/src/tangara/system_fsm/system_events.hpp b/src/tangara/system_fsm/system_events.hpp index c2e3a2ab..b96846e0 100644 --- a/src/tangara/system_fsm/system_events.hpp +++ b/src/tangara/system_fsm/system_events.hpp @@ -40,6 +40,9 @@ struct FatalError : tinyfsm::Event {}; struct OnIdle : tinyfsm::Event {}; struct SdStateChanged : tinyfsm::Event {}; +struct UnmountRequest : tinyfsm::Event { + bool idle; +}; struct StorageError : tinyfsm::Event { FRESULT error; diff --git a/src/tangara/system_fsm/system_fsm.hpp b/src/tangara/system_fsm/system_fsm.hpp index 40009781..398a0b9b 100644 --- a/src/tangara/system_fsm/system_fsm.hpp +++ b/src/tangara/system_fsm/system_fsm.hpp @@ -27,6 +27,7 @@ #include "drivers/touchwheel.hpp" #include "system_fsm/service_locator.hpp" #include "system_fsm/system_events.hpp" +#include "ui/ui_fsm.hpp" #include "tinyfsm.hpp" namespace system_fsm { @@ -64,6 +65,8 @@ class SystemState : public tinyfsm::Fsm { virtual void react(const internal::IdleTimeout&) {} virtual void react(const internal::UnmountTimeout&) {} virtual void react(const internal::Mount&) {} + virtual void react(const ui::UnmountRequest&) {} + virtual void react(const audio::UnmountReady&) {} protected: auto IdleCondition() -> bool; @@ -103,6 +106,8 @@ class Running : public SystemState { void react(const database::event::UpdateFinished&) override; void react(const SamdUsbMscChanged&) override; void react(const StorageError&) override; + void react(const ui::UnmountRequest&) override; + void react(const audio::UnmountReady&) override; void react(const internal::UnmountTimeout&) override; void react(const internal::Mount&) override; diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp index a22c704b..ebc4b635 100644 --- a/src/tangara/ui/ui_fsm.cpp +++ b/src/tangara/ui/ui_fsm.cpp @@ -714,6 +714,11 @@ void Lua::entry() { }); registry.AddPropertyModule("sd_card", { {"mounted", &sSdMounted}, + {"unmount", [&](lua_State*) { + events::System().Dispatch( + UnmountRequest{}); + return 0; + }}, }); registry.AddPropertyModule("usb", { diff --git a/src/tangara/ui/ui_fsm.hpp b/src/tangara/ui/ui_fsm.hpp index aae69f94..d4354bec 100644 --- a/src/tangara/ui/ui_fsm.hpp +++ b/src/tangara/ui/ui_fsm.hpp @@ -37,6 +37,8 @@ namespace ui { +struct UnmountRequest : tinyfsm::Event {}; + class UiState : public tinyfsm::Fsm { public: static auto InitBootSplash(drivers::IGpios&, drivers::NvsStorage&) -> bool;