From 2f16d230025c3173cfbecc58b38d6a52b6b0f5f2 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 5 Jul 2023 20:09:03 +1000 Subject: Start on wiring up playback screen to real data --- src/ui/include/screen_playing.hpp | 7 +++++++ src/ui/include/ui_fsm.hpp | 13 ++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src/ui/include') diff --git a/src/ui/include/screen_playing.hpp b/src/ui/include/screen_playing.hpp index 3eae32a7..5ccfe391 100644 --- a/src/ui/include/screen_playing.hpp +++ b/src/ui/include/screen_playing.hpp @@ -6,12 +6,15 @@ #pragma once +#include #include +#include #include "lvgl.h" #include "database.hpp" #include "screen.hpp" +#include "track.hpp" namespace ui { namespace screens { @@ -23,6 +26,9 @@ class Playing : public Screen { auto BindTrack(database::Track t) -> void; + auto UpdateTime(uint32_t) -> void; + auto UpdateNextUp(std::vector tracks) -> void; + private: database::Track track_; @@ -34,6 +40,7 @@ class Playing : public Screen { lv_obj_t* play_pause_control_; lv_obj_t* next_up_container_; + std::vector next_tracks_; }; } // namespace screens diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp index 32275fab..cd1ec492 100644 --- a/src/ui/include/ui_fsm.hpp +++ b/src/ui/include/ui_fsm.hpp @@ -9,7 +9,9 @@ #include #include +#include "audio_events.hpp" #include "relative_wheel.hpp" +#include "screen_playing.hpp" #include "tinyfsm.hpp" #include "display.hpp" @@ -37,6 +39,8 @@ class UiState : public tinyfsm::Fsm { /* Fallback event handler. Does nothing. */ void react(const tinyfsm::Event& ev) {} + virtual void react(const audio::PlaybackUpdate){}; + virtual void react(const system_fsm::KeyLockChanged&){}; virtual void react(const internal::RecordSelected&){}; @@ -57,6 +61,7 @@ class UiState : public tinyfsm::Fsm { static std::stack> sScreens; static std::shared_ptr sCurrentScreen; + static std::unique_ptr sPlayingScreen; }; namespace states { @@ -68,7 +73,7 @@ class Splash : public UiState { using UiState::react; }; -class Interactive : public UiState { +class Browse : public UiState { void entry() override; void react(const internal::RecordSelected&) override; @@ -78,6 +83,12 @@ class Interactive : public UiState { void react(const system_fsm::StorageMounted&) override; }; +class Playing : public UiState { + void entry() override; + + void react(const audio::PlaybackUpdate) override; +}; + class FatalError : public UiState {}; } // namespace states -- cgit v1.2.3 From 39f7545cd5ef7a30bbd482f3579df7744c6b688d Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 7 Jul 2023 15:29:47 +1000 Subject: wire up the playing screen with some real data Includes implementing song duration calculation for CBR MP3 files --- src/ui/include/screen.hpp | 10 ++++++++++ src/ui/include/screen_playing.hpp | 35 +++++++++++++++++++++++++++++------ src/ui/include/ui_fsm.hpp | 24 +++++++++++++++++------- 3 files changed, 56 insertions(+), 13 deletions(-) (limited to 'src/ui/include') diff --git a/src/ui/include/screen.hpp b/src/ui/include/screen.hpp index 7ff06fbd..13b92a09 100644 --- a/src/ui/include/screen.hpp +++ b/src/ui/include/screen.hpp @@ -15,14 +15,24 @@ namespace ui { +/* + * Base class for ever discrete screen in the app. Provides a consistent + * interface that can be used for transitioning between screens, adding them to + * back stacks, etc. + */ class Screen { public: Screen() : root_(lv_obj_create(NULL)), group_(lv_group_create()) {} + virtual ~Screen() { lv_obj_del(root_); lv_group_del(group_); } + /* + * Called periodically to allow the screen to update itself, e.g. to handle + * std::futures that are still loading in. + */ virtual auto Tick() -> void {} auto root() -> lv_obj_t* { return root_; } diff --git a/src/ui/include/screen_playing.hpp b/src/ui/include/screen_playing.hpp index 5ccfe391..148f2774 100644 --- a/src/ui/include/screen_playing.hpp +++ b/src/ui/include/screen_playing.hpp @@ -7,30 +7,54 @@ #pragma once #include +#include #include #include #include "lvgl.h" #include "database.hpp" +#include "future_fetcher.hpp" #include "screen.hpp" #include "track.hpp" +#include "track_queue.hpp" namespace ui { namespace screens { +/* + * The 'Now Playing' / 'Currently Playing' screen that contains information + * about the current track, as well as playback controls. + */ class Playing : public Screen { public: - explicit Playing(database::Track t); + explicit Playing(std::weak_ptr db, + audio::TrackQueue* queue); ~Playing(); - auto BindTrack(database::Track t) -> void; + auto Tick() -> void override; - auto UpdateTime(uint32_t) -> void; - auto UpdateNextUp(std::vector tracks) -> void; + // Callbacks invoked by the UI state machine in response to audio events. + + auto OnTrackUpdate() -> void; + auto OnPlaybackUpdate(uint32_t, uint32_t) -> void; + auto OnQueueUpdate() -> void; private: - database::Track track_; + auto BindTrack(const database::Track& track) -> void; + auto ApplyNextUp(const std::vector& tracks) -> void; + + std::weak_ptr db_; + audio::TrackQueue* queue_; + + std::optional track_; + std::vector next_tracks_; + + std::unique_ptr>> + new_track_; + std::unique_ptr< + database::FutureFetcher>>> + new_next_tracks_; lv_obj_t* artist_label_; lv_obj_t* album_label_; @@ -40,7 +64,6 @@ class Playing : public Screen { lv_obj_t* play_pause_control_; lv_obj_t* next_up_container_; - std::vector next_tracks_; }; } // namespace screens diff --git a/src/ui/include/ui_fsm.hpp b/src/ui/include/ui_fsm.hpp index cd1ec492..2fc6db4e 100644 --- a/src/ui/include/ui_fsm.hpp +++ b/src/ui/include/ui_fsm.hpp @@ -19,13 +19,14 @@ #include "storage.hpp" #include "system_events.hpp" #include "touchwheel.hpp" +#include "track_queue.hpp" #include "ui_events.hpp" namespace ui { class UiState : public tinyfsm::Fsm { public: - static auto Init(drivers::IGpios* gpio_expander) -> bool; + static auto Init(drivers::IGpios*, audio::TrackQueue*) -> bool; virtual ~UiState() {} @@ -39,12 +40,14 @@ class UiState : public tinyfsm::Fsm { /* Fallback event handler. Does nothing. */ void react(const tinyfsm::Event& ev) {} - virtual void react(const audio::PlaybackUpdate){}; + virtual void react(const audio::PlaybackStarted&) {} + virtual void react(const audio::PlaybackUpdate&) {} + virtual void react(const audio::QueueUpdate&) {} - virtual void react(const system_fsm::KeyLockChanged&){}; + virtual void react(const system_fsm::KeyLockChanged&) {} - virtual void react(const internal::RecordSelected&){}; - virtual void react(const internal::IndexSelected&){}; + virtual void react(const internal::RecordSelected&) {} + virtual void react(const internal::IndexSelected&) {} virtual void react(const system_fsm::DisplayReady&) {} virtual void react(const system_fsm::BootComplete&) {} @@ -52,8 +55,11 @@ class UiState : public tinyfsm::Fsm { protected: void PushScreen(std::shared_ptr); + void PopScreen(); static drivers::IGpios* sIGpios; + static audio::TrackQueue* sQueue; + static std::shared_ptr sTouchWheel; static std::shared_ptr sRelativeWheel; static std::shared_ptr sDisplay; @@ -61,7 +67,6 @@ class UiState : public tinyfsm::Fsm { static std::stack> sScreens; static std::shared_ptr sCurrentScreen; - static std::unique_ptr sPlayingScreen; }; namespace states { @@ -81,12 +86,17 @@ class Browse : public UiState { void react(const system_fsm::KeyLockChanged&) override; void react(const system_fsm::StorageMounted&) override; + using UiState::react; }; class Playing : public UiState { void entry() override; + void exit() override; - void react(const audio::PlaybackUpdate) override; + void react(const audio::PlaybackStarted&) override; + void react(const audio::PlaybackUpdate&) override; + void react(const audio::QueueUpdate&) override; + using UiState::react; }; class FatalError : public UiState {}; -- cgit v1.2.3