diff --git a/src/ui/include/screen_playing.hpp b/src/ui/include/screen_playing.hpp index cf1ddaa2..3eae32a7 100644 --- a/src/ui/include/screen_playing.hpp +++ b/src/ui/include/screen_playing.hpp @@ -21,8 +21,19 @@ class Playing : public Screen { explicit Playing(database::Track t); ~Playing(); + auto BindTrack(database::Track t) -> void; + private: database::Track track_; + + lv_obj_t* artist_label_; + lv_obj_t* album_label_; + lv_obj_t* title_label_; + + lv_obj_t* scrubber_; + lv_obj_t* play_pause_control_; + + lv_obj_t* next_up_container_; }; } // namespace screens diff --git a/src/ui/lvgl_task.cpp b/src/ui/lvgl_task.cpp index 3ffaea03..853b3280 100644 --- a/src/ui/lvgl_task.cpp +++ b/src/ui/lvgl_task.cpp @@ -22,6 +22,7 @@ #include "core/lv_obj_tree.h" #include "esp_log.h" #include "event_queue.hpp" +#include "extra/themes/basic/lv_theme_basic.h" #include "font/lv_font.h" #include "freertos/portmacro.h" #include "freertos/projdefs.h" @@ -53,6 +54,9 @@ void LvglMain(std::weak_ptr weak_touch_wheel, ESP_LOGI(kTag, "init lvgl"); lv_init(); + lv_theme_t* theme = lv_theme_basic_init(NULL); + lv_disp_set_theme(NULL, theme); + TouchWheelEncoder encoder(weak_touch_wheel); std::shared_ptr current_screen; diff --git a/src/ui/screen_playing.cpp b/src/ui/screen_playing.cpp index 053f324c..1ac8ad5a 100644 --- a/src/ui/screen_playing.cpp +++ b/src/ui/screen_playing.cpp @@ -6,7 +6,11 @@ #include "screen_playing.hpp" +#include "core/lv_obj.h" #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 "lvgl.h" #include "core/lv_group.h" @@ -18,26 +22,133 @@ #include "hal/lv_hal_disp.h" #include "index.hpp" #include "misc/lv_area.h" +#include "misc/lv_color.h" #include "track.hpp" #include "ui_events.hpp" #include "ui_fsm.hpp" +#include "widgets/lv_bar.h" +#include "widgets/lv_btn.h" +#include "widgets/lv_img.h" #include "widgets/lv_label.h" namespace ui { namespace screens { +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_long_mode(label, LV_LABEL_LONG_DOT); + lv_obj_center(label); + return label; +} + +auto control_button(lv_obj_t* parent, char* icon) -> lv_obj_t* { + lv_obj_t* button = lv_img_create(parent); + lv_obj_set_size(button, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_img_set_src(button, icon); + return button; +} + +auto next_up_label(lv_obj_t* parent, const std::string& text) -> lv_obj_t* { + lv_obj_t* label = lv_label_create(parent); + lv_label_set_text(label, text.c_str()); + lv_obj_set_size(label, lv_pct(100), LV_SIZE_CONTENT); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + return label; +} + Playing::Playing(database::Track track) : track_(track) { - lv_obj_t* container = lv_obj_create(root_); - lv_obj_set_align(container, LV_ALIGN_CENTER); - lv_obj_set_size(container, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - - // bro idk - lv_obj_t* label = lv_label_create(container); - lv_label_set_text_static(label, track.TitleOrFilename().c_str()); - lv_obj_set_align(label, LV_ALIGN_CENTER); + lv_obj_set_layout(root_, LV_LAYOUT_FLEX); + lv_obj_set_size(root_, lv_pct(100), lv_pct(200)); + lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, + LV_FLEX_ALIGN_START); + + lv_obj_t* above_fold_container = lv_obj_create(root_); + 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_CENTER, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_END); + + lv_obj_t* info_container = lv_obj_create(above_fold_container); + lv_obj_set_layout(info_container, LV_LAYOUT_FLEX); + lv_obj_set_size(info_container, lv_pct(100), 80); + 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_END); + + artist_label_ = info_label(info_container); + album_label_ = info_label(info_container); + title_label_ = info_label(info_container); + + scrubber_ = lv_bar_create(above_fold_container); + lv_obj_set_size(scrubber_, lv_pct(100), 5); + lv_bar_set_range(scrubber_, 0, 100); + lv_bar_set_value(scrubber_, 0, LV_ANIM_OFF); + + 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_obj_t* controls_container = lv_obj_create(above_fold_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); + + play_pause_control_ = control_button(controls_container, LV_SYMBOL_PLAY); + lv_group_add_obj(group_, play_pause_control_); + lv_group_add_obj(group_, control_button(controls_container, LV_SYMBOL_PREV)); + lv_group_add_obj(group_, control_button(controls_container, LV_SYMBOL_NEXT)); + lv_group_add_obj(group_, + control_button(controls_container, LV_SYMBOL_SHUFFLE)); + lv_group_add_obj(group_, control_button(controls_container, LV_SYMBOL_LOOP)); + + lv_obj_t* next_up_header = lv_obj_create(above_fold_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); + + lv_obj_t* next_up_title = lv_label_create(next_up_header); + lv_label_set_text(next_up_title, "Next up..."); + lv_obj_set_height(next_up_title, lv_pct(100)); + lv_obj_set_flex_grow(next_up_title, 1); + + lv_obj_t* next_up_hint = lv_label_create(next_up_header); + lv_label_set_text(next_up_hint, LV_SYMBOL_DOWN); + lv_obj_set_size(next_up_hint, LV_SIZE_CONTENT, lv_pct(100)); + + next_up_container_ = lv_obj_create(root_); + lv_obj_set_layout(next_up_container_, LV_LAYOUT_FLEX); + lv_obj_set_width(next_up_container_, lv_pct(100)); + lv_obj_set_flex_grow(next_up_container_, 1); + lv_obj_set_flex_flow(next_up_container_, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(next_up_container_, LV_FLEX_ALIGN_CENTER, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_END); + + lv_group_add_obj(group_, next_up_label(root_, "Song 2")); + lv_group_add_obj(group_, next_up_label(root_, "Song 3")); + lv_group_add_obj( + group_, next_up_label(root_, "Another song that has a very long name")); + + BindTrack(track); } Playing::~Playing() {} +auto Playing::BindTrack(database::Track t) -> void { + track_ = t; + + 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()); +} + } // namespace screens } // namespace ui diff --git a/src/ui/screen_track_browser.cpp b/src/ui/screen_track_browser.cpp index 17b7dc46..93ca277e 100644 --- a/src/ui/screen_track_browser.cpp +++ b/src/ui/screen_track_browser.cpp @@ -7,8 +7,11 @@ #include #include +#include "core/lv_obj.h" #include "database.hpp" #include "event_queue.hpp" +#include "extra/layouts/flex/lv_flex.h" +#include "font/lv_symbol_def.h" #include "lvgl.h" #include "screen_menu.hpp" @@ -61,11 +64,31 @@ TrackBrowser::TrackBrowser( loading_pos_(END), loading_page_(std::move(initial_page)), current_pages_() { - lv_obj_t* title_obj = lv_label_create(root_); - lv_label_set_text(title_obj, title.c_str()); + lv_obj_set_layout(root_, LV_LAYOUT_FLEX); + lv_obj_set_size(root_, lv_pct(100), lv_pct(100)); + lv_obj_set_flex_flow(root_, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(root_, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, + LV_FLEX_ALIGN_START); + + lv_obj_t* header = lv_obj_create(root_); + lv_obj_set_size(header, lv_pct(100), 15); + lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(header, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, + LV_FLEX_ALIGN_CENTER); + + lv_obj_t* title_label = lv_label_create(header); + lv_label_set_text(title_label, title.c_str()); + lv_obj_set_flex_grow(title_label, 1); + + lv_obj_t* playback_label = lv_label_create(header); + lv_label_set_text(playback_label, LV_SYMBOL_PAUSE); + + lv_obj_t* battery_label = lv_label_create(header); + lv_label_set_text(battery_label, LV_SYMBOL_BATTERY_2); list_ = lv_list_create(root_); - lv_obj_set_size(list_, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL)); + lv_obj_set_width(list_, lv_pct(100)); + lv_obj_set_flex_grow(list_, 1); lv_obj_center(list_); } diff --git a/src/ui/wheel_encoder.cpp b/src/ui/wheel_encoder.cpp index 62e88065..243772d7 100644 --- a/src/ui/wheel_encoder.cpp +++ b/src/ui/wheel_encoder.cpp @@ -41,7 +41,6 @@ auto TouchWheelEncoder::Read(lv_indev_data_t* data) -> void { lock->Update(); - auto ticks = lock->ticks(); if (ticks > 0) { data->key = LV_KEY_PREV;