summaryrefslogtreecommitdiff
path: root/src/ui/screen_playing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/screen_playing.cpp')
-rw-r--r--src/ui/screen_playing.cpp338
1 files changed, 0 insertions, 338 deletions
diff --git a/src/ui/screen_playing.cpp b/src/ui/screen_playing.cpp
deleted file mode 100644
index c29d342e..00000000
--- a/src/ui/screen_playing.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#include "screen_playing.hpp"
-#include <sys/_stdint.h>
-#include <memory>
-
-#include "audio_events.hpp"
-#include "bindey/binding.h"
-#include "core/lv_event.h"
-#include "core/lv_obj.h"
-#include "core/lv_obj_scroll.h"
-#include "core/lv_obj_tree.h"
-#include "database.hpp"
-#include "esp_log.h"
-#include "extra/layouts/flex/lv_flex.h"
-#include "extra/layouts/grid/lv_grid.h"
-#include "font/lv_symbol_def.h"
-#include "future_fetcher.hpp"
-#include "lvgl.h"
-
-#include "core/lv_group.h"
-#include "core/lv_obj_pos.h"
-#include "event_queue.hpp"
-#include "extra/widgets/list/lv_list.h"
-#include "extra/widgets/menu/lv_menu.h"
-#include "extra/widgets/spinner/lv_spinner.h"
-#include "future_fetcher.hpp"
-#include "hal/lv_hal_disp.h"
-#include "index.hpp"
-#include "misc/lv_anim.h"
-#include "misc/lv_area.h"
-#include "misc/lv_color.h"
-#include "misc/lv_txt.h"
-#include "model_playback.hpp"
-#include "model_top_bar.hpp"
-#include "track.hpp"
-#include "ui_events.hpp"
-#include "ui_fsm.hpp"
-#include "widget_top_bar.hpp"
-#include "widgets/lv_btn.h"
-#include "widgets/lv_img.h"
-#include "widgets/lv_label.h"
-#include "widgets/lv_slider.h"
-
-namespace ui {
-namespace screens {
-
-static void above_fold_focus_cb(lv_event_t* ev) {
- if (ev->user_data == NULL) {
- return;
- }
- Playing* instance = reinterpret_cast<Playing*>(ev->user_data);
- instance->OnFocusAboveFold();
-}
-
-static void below_fold_focus_cb(lv_event_t* ev) {
- if (ev->user_data == NULL) {
- return;
- }
- Playing* instance = reinterpret_cast<Playing*>(ev->user_data);
- instance->OnFocusBelowFold();
-}
-
-static lv_style_t scrubber_style;
-
-auto info_label(lv_obj_t* parent) -> lv_obj_t* {
- lv_obj_t* label = lv_label_create(parent);
- lv_obj_set_size(label, lv_pct(100), LV_SIZE_CONTENT);
- lv_label_set_text(label, "");
- lv_label_set_long_mode(label, LV_LABEL_LONG_DOT);
- lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
- lv_obj_center(label);
-
- lv_obj_set_style_bg_color(label, lv_color_black(), LV_STATE_FOCUSED);
- return label;
-}
-
-auto Playing::control_button(lv_obj_t* parent, char* icon) -> lv_obj_t* {
- lv_obj_t* button = lv_btn_create(parent);
- lv_obj_set_size(button, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
-
- lv_obj_clear_flag(button, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
- lv_obj_add_event_cb(button, above_fold_focus_cb, LV_EVENT_FOCUSED, this);
-
- lv_obj_t* icon_obj = lv_img_create(button);
- lv_img_set_src(icon_obj, icon);
-
- return button;
-}
-
-auto Playing::next_up_label(lv_obj_t* parent, const std::pmr::string& text)
- -> lv_obj_t* {
- lv_obj_t* button = lv_list_add_btn(parent, NULL, text.c_str());
- lv_label_set_long_mode(lv_obj_get_child(button, -1), LV_LABEL_LONG_DOT);
- lv_obj_add_event_cb(button, below_fold_focus_cb, LV_EVENT_FOCUSED, this);
- lv_group_add_obj(group_, button);
- return button;
-}
-
-Playing::Playing(models::TopBar& top_bar_model,
- models::Playback& playback_model,
- std::weak_ptr<database::Database> db,
- audio::TrackQueue& queue)
- : db_(db),
- queue_(queue),
- current_track_(),
- next_tracks_(),
- new_track_(),
- new_next_tracks_() {
- lv_obj_set_layout(content_, LV_LAYOUT_FLEX);
- lv_group_set_wrap(group_, false);
-
- lv_obj_set_size(content_, lv_pct(100), lv_disp_get_ver_res(NULL));
- lv_obj_set_flex_flow(content_, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(content_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START,
- LV_FLEX_ALIGN_START);
-
- lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF);
-
- lv_obj_t* above_fold_container = lv_obj_create(content_);
- lv_obj_set_layout(above_fold_container, LV_LAYOUT_FLEX);
- lv_obj_set_size(above_fold_container, lv_pct(100), lv_disp_get_ver_res(NULL));
- lv_obj_set_flex_flow(above_fold_container, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(above_fold_container, LV_FLEX_ALIGN_START,
- LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
-
- widgets::TopBar::Configuration config{
- .show_back_button = true,
- .title = "Now Playing",
- };
- CreateTopBar(above_fold_container, config, top_bar_model);
-
- lv_obj_t* now_playing_container = lv_obj_create(above_fold_container);
- lv_obj_set_layout(now_playing_container, LV_LAYOUT_FLEX);
- lv_obj_set_width(now_playing_container, lv_pct(100));
- lv_obj_set_flex_grow(now_playing_container, 1);
- lv_obj_set_flex_flow(now_playing_container, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(now_playing_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
- LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
-
- lv_obj_set_style_pad_left(now_playing_container, 4, LV_PART_MAIN);
- lv_obj_set_style_pad_right(now_playing_container, 4, LV_PART_MAIN);
-
- lv_obj_t* info_container = lv_obj_create(now_playing_container);
- lv_obj_set_layout(info_container, LV_LAYOUT_FLEX);
- lv_obj_set_width(info_container, lv_pct(100));
- lv_obj_set_flex_grow(info_container, 1);
- lv_obj_set_flex_flow(info_container, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(info_container, LV_FLEX_ALIGN_CENTER,
- LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
-
- lv_obj_t* artist_label = info_label(info_container);
- lv_obj_t* album_label = info_label(info_container);
- lv_obj_t* title_label = info_label(info_container);
-
- lv_obj_t* scrubber = lv_slider_create(now_playing_container);
- lv_obj_set_size(scrubber, lv_pct(100), 5);
-
- lv_style_init(&scrubber_style);
- lv_style_set_bg_color(&scrubber_style, lv_color_black());
- lv_obj_add_style(scrubber, &scrubber_style, LV_PART_INDICATOR);
-
- lv_group_add_obj(group_, scrubber);
-
- data_bindings_.emplace_back(playback_model.current_track.onChangedAndNow(
- [=, this](const std::optional<database::TrackId>& id) {
- if (!id) {
- return;
- }
- if (current_track_.get() && current_track_.get()->data().id == *id) {
- return;
- }
- auto db = db_.lock();
- if (!db) {
- return;
- }
- // Clear the playback progress whilst we're waiting for the next
- // track's data to load.
- lv_slider_set_value(scrubber, 0, LV_ANIM_OFF);
- new_track_.reset(
- new database::FutureFetcher<std::shared_ptr<database::Track>>(
- db->GetTrack(*id)));
- }));
-
- data_bindings_.emplace_back(current_track_.onChangedAndNow(
- [=](const std::shared_ptr<database::Track>& t) {
- if (!t) {
- return;
- }
- lv_label_set_text(
- artist_label,
- t->tags().at(database::Tag::kArtist).value_or("").c_str());
- lv_label_set_text(
- album_label,
- t->tags().at(database::Tag::kAlbum).value_or("").c_str());
- lv_label_set_text(title_label, t->TitleOrFilename().c_str());
- }));
-
- data_bindings_.emplace_back(
- playback_model.current_track_duration.onChangedAndNow([=](uint32_t d) {
- lv_slider_set_range(scrubber, 0, std::max<uint32_t>(1, d));
- }));
- data_bindings_.emplace_back(
- playback_model.current_track_position.onChangedAndNow(
- [=](uint32_t p) { lv_slider_set_value(scrubber, p, LV_ANIM_OFF); }));
-
- lv_obj_t* spacer = lv_obj_create(now_playing_container);
- lv_obj_set_size(spacer, 1, 4);
-
- lv_obj_t* controls_container = lv_obj_create(now_playing_container);
- lv_obj_set_size(controls_container, lv_pct(100), 20);
- lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW);
- lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_EVENLY,
- LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
-
- lv_obj_t* play_pause_control =
- control_button(controls_container, LV_SYMBOL_PLAY);
- lv_group_add_obj(group_, play_pause_control);
- lv_bind(play_pause_control, LV_EVENT_CLICKED, [=](lv_obj_t*) {
- events::Audio().Dispatch(audio::TogglePlayPause{});
- });
-
- lv_obj_t* track_prev = control_button(controls_container, LV_SYMBOL_PREV);
- lv_group_add_obj(group_, track_prev);
- lv_bind(track_prev, LV_EVENT_CLICKED, [=](lv_obj_t*) { queue_.Previous(); });
-
- lv_obj_t* track_next = control_button(controls_container, LV_SYMBOL_NEXT);
- lv_group_add_obj(group_, track_next);
- lv_bind(track_next, LV_EVENT_CLICKED, [=](lv_obj_t*) { queue_.Next(); });
-
- lv_obj_t* shuffle = control_button(controls_container, LV_SYMBOL_SHUFFLE);
- lv_group_add_obj(group_, shuffle);
- // lv_bind(shuffle, LV_EVENT_CLICKED, [=](lv_obj_t*) { queue_ });
-
- lv_group_add_obj(group_, control_button(controls_container, LV_SYMBOL_LOOP));
-
- next_up_header_ = lv_obj_create(now_playing_container);
- lv_obj_set_size(next_up_header_, lv_pct(100), 15);
- lv_obj_set_flex_flow(next_up_header_, LV_FLEX_FLOW_ROW);
- lv_obj_set_flex_align(next_up_header_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END,
- LV_FLEX_ALIGN_END);
-
- next_up_label_ = lv_label_create(next_up_header_);
- lv_label_set_text(next_up_label_, "");
- lv_obj_set_height(next_up_label_, lv_pct(100));
- lv_obj_set_flex_grow(next_up_label_, 1);
-
- next_up_hint_ = lv_label_create(next_up_header_);
- lv_label_set_text(next_up_hint_, "");
- lv_obj_set_size(next_up_hint_, LV_SIZE_CONTENT, lv_pct(100));
-
- next_up_container_ = lv_list_create(content_);
- lv_obj_set_layout(next_up_container_, LV_LAYOUT_FLEX);
- lv_obj_set_size(next_up_container_, lv_pct(100), lv_disp_get_ver_res(NULL));
- lv_obj_set_flex_flow(next_up_container_, LV_FLEX_FLOW_COLUMN);
- lv_obj_set_flex_align(next_up_container_, LV_FLEX_ALIGN_START,
- LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
-
- data_bindings_.emplace_back(playback_model.upcoming_tracks.onChangedAndNow(
- [=, this](const std::vector<database::TrackId>& ids) {
- auto db = db_.lock();
- if (!db) {
- return;
- }
- lv_label_set_text(next_up_label_, "Next up");
-
- new_next_tracks_.reset(new database::FutureFetcher<
- std::vector<std::shared_ptr<database::Track>>>(
- db->GetBulkTracks(ids)));
- }));
-
- data_bindings_.emplace_back(next_tracks_.onChangedAndNow(
- [=](const std::vector<std::shared_ptr<database::Track>>& tracks) {
- // TODO(jacqueline): Do a proper diff to maintain selection.
- int children = lv_obj_get_child_cnt(next_up_container_);
- while (children > 0) {
- lv_obj_del(lv_obj_get_child(next_up_container_, 0));
- children--;
- }
-
- if (tracks.empty()) {
- lv_label_set_text(next_up_label_, "Nothing queued");
- lv_label_set_text(next_up_hint_, "");
- return;
- } else {
- lv_label_set_text(next_up_label_, "Next up");
- lv_label_set_text(next_up_hint_, "");
- }
-
- for (const auto& track : tracks) {
- lv_group_add_obj(group_, next_up_label(next_up_container_,
- track->TitleOrFilename()));
- }
- }));
-}
-
-Playing::~Playing() {}
-
-auto Playing::Tick() -> void {
- if (new_track_ && new_track_->Finished()) {
- auto res = new_track_->Result();
- new_track_.reset();
- if (res) {
- current_track_(*res);
- }
- }
- if (new_next_tracks_ && new_next_tracks_->Finished()) {
- auto res = new_next_tracks_->Result();
- new_next_tracks_.reset();
- if (res) {
- std::vector<std::shared_ptr<database::Track>> filtered;
- for (const auto& t : *res) {
- if (t) {
- filtered.push_back(t);
- }
- }
- next_tracks_.set(filtered);
- }
- }
-}
-
-auto Playing::OnFocusAboveFold() -> void {
- lv_obj_scroll_to_y(content_, 0, LV_ANIM_ON);
-}
-
-auto Playing::OnFocusBelowFold() -> void {
- if (lv_obj_get_scroll_y(content_) < lv_obj_get_y(next_up_header_) + 20) {
- lv_obj_scroll_to_y(content_, lv_obj_get_y(next_up_header_) + 20,
- LV_ANIM_ON);
- }
-}
-
-} // namespace screens
-} // namespace ui