From 3a79fc6ff78465ced19020432cc6367f40ca5a04 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 12 May 2025 01:22:05 +0200 Subject: [PATCH 01/32] music app redesign --- src/displayapp/screens/Music.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0763da0fe3..0369f28a38 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -23,6 +23,8 @@ #include "displayapp/icons/music/disc.c" #include "displayapp/icons/music/disc_f_1.c" #include "displayapp/icons/music/disc_f_2.c" +#include "displayapp/InfiniTimeTheme.h" + using namespace Pinetime::Applications::Screens; @@ -52,7 +54,7 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_style_init(&btn_style); lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 20); - lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_AQUA); + lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, Colors::bgAlt); lv_style_set_bg_opa(&btn_style, LV_STATE_DEFAULT, LV_OPA_50); btnVolDown = lv_btn_create(lv_scr_act(), nullptr); @@ -114,15 +116,15 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { constexpr int8_t MIDDLE_OFFSET = -25; txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT); + lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtArtist, LV_HOR_RES - 12); lv_label_set_text_static(txtArtist, "Artist Name"); + lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD); - + lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES - 12); lv_label_set_text_static(txtTrack, "This is a very long getTrack name"); From 5ccbaad83e981fde19eb83e8cc16bfbc6200c12b Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 12 May 2025 01:41:58 +0200 Subject: [PATCH 02/32] removed an empty line --- src/displayapp/screens/Music.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0369f28a38..6be76fb010 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -25,7 +25,6 @@ #include "displayapp/icons/music/disc_f_2.c" #include "displayapp/InfiniTimeTheme.h" - using namespace Pinetime::Applications::Screens; static void event_handler(lv_obj_t* obj, lv_event_t event) { From e97cb58fbbeb1f2cc283b93a9ba2f5277a6e4a39 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 12 May 2025 19:25:30 +0200 Subject: [PATCH 03/32] Some tweaks for the default texts, as well as adding a different approach to switching between skipping and volume buttons --- .vscode/settings.json | 4 +++- src/components/ble/MusicService.h | 6 +++--- src/displayapp/screens/Music.cpp | 36 ++++++++++++++++++------------- src/displayapp/screens/Music.h | 8 +++++-- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a7b04eea3c..70643b0798 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,6 +65,8 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "ios": "cpp", + "disc.c": "cpp" } } diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h index 93d94a346e..9257e13514 100644 --- a/src/components/ble/MusicService.h +++ b/src/components/ble/MusicService.h @@ -71,9 +71,9 @@ namespace Pinetime { uint16_t eventHandle {}; - std::string artistName {"Waiting for"}; - std::string albumName {}; - std::string trackName {"track information.."}; + std::string trackName {""}; + std::string albumName {""}; + std::string artistName {"Not Playing"}; bool playing {false}; diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 6be76fb010..e7d7b1cf6c 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -48,7 +48,9 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { +Music::Music(Pinetime::Controllers::MusicService& music, + Pinetime::Controllers::MotorController& motor) + : musicService(music), motor(motor) { lv_obj_t* label; lv_style_init(&btn_style); @@ -118,7 +120,7 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtArtist, LV_HOR_RES - 12); - lv_label_set_text_static(txtArtist, "Artist Name"); + lv_label_set_text_static(txtArtist, ""); lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); txtTrack = lv_label_create(lv_scr_act(), nullptr); @@ -126,7 +128,7 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES - 12); - lv_label_set_text_static(txtTrack, "This is a very long getTrack name"); + lv_label_set_text_static(txtTrack, ""); /** Init animation */ imgDisc = lv_img_create(lv_scr_act(), nullptr); @@ -250,24 +252,28 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - switch (event) { - case TouchEvents::SwipeUp: { - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); + static bool isVolumeMode = false; // T-flip-flop state - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - return true; - } - case TouchEvents::SwipeDown: { - if (lv_obj_get_hidden(btnNext)) { + switch (event) { + case TouchEvents::DoubleTap: { + isVolumeMode = !isVolumeMode; // Toggle state + + if (isVolumeMode) { + motor.RunForDuration(35); + // Show volume controls, hide track controls + lv_obj_set_hidden(btnVolDown, false); + lv_obj_set_hidden(btnVolUp, false); + lv_obj_set_hidden(btnNext, true); + lv_obj_set_hidden(btnPrev, true); + } else { + motor.RunForDuration(35); + // Show track controls, hide volume controls lv_obj_set_hidden(btnNext, false); lv_obj_set_hidden(btnPrev, false); lv_obj_set_hidden(btnVolDown, true); lv_obj_set_hidden(btnVolUp, true); - return true; } - return false; + return true; } case TouchEvents::SwipeLeft: { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 522533215b..e9aa2c8bf1 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -34,7 +34,8 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music); + Music(Pinetime::Controllers::MusicService& music, + Pinetime::Controllers::MotorController& motor); ~Music() override; @@ -82,6 +83,9 @@ namespace Pinetime { lv_task_t* taskRefresh; + Controllers::MotorController& motor; + + /** Watchapp */ }; } @@ -92,7 +96,7 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService); + return new Screens::Music(*controllers.musicService, controllers.motorController); }; }; } From db1a0add8d27e5997babab4d8287d2967c55a7db Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 12 May 2025 19:28:32 +0200 Subject: [PATCH 04/32] formatting --- src/displayapp/screens/Music.cpp | 9 ++++----- src/displayapp/screens/Music.h | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index e7d7b1cf6c..cd3f1af3b8 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -48,9 +48,8 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music, - Pinetime::Controllers::MotorController& motor) - : musicService(music), motor(motor) { +Music::Music(Pinetime::Controllers::MusicService& music, Pinetime::Controllers::MotorController& motor) +: musicService(music), motor(motor) { lv_obj_t* label; lv_style_init(&btn_style); @@ -252,11 +251,11 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - static bool isVolumeMode = false; // T-flip-flop state + static bool isVolumeMode = false; // T-flip-flop state switch (event) { case TouchEvents::DoubleTap: { - isVolumeMode = !isVolumeMode; // Toggle state + isVolumeMode = !isVolumeMode; // Toggle state if (isVolumeMode) { motor.RunForDuration(35); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index e9aa2c8bf1..4b9992715e 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -34,8 +34,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music, - Pinetime::Controllers::MotorController& motor); + Music(Pinetime::Controllers::MusicService& music, Pinetime::Controllers::MotorController& motor); ~Music() override; From e633015375cd478a1d9f8c26fec74bd6ffb6d651 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 12 May 2025 19:30:25 +0200 Subject: [PATCH 05/32] more formatting --- src/displayapp/screens/Music.cpp | 2 +- src/displayapp/screens/Music.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index cd3f1af3b8..db2033bce6 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -49,7 +49,7 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ Music::Music(Pinetime::Controllers::MusicService& music, Pinetime::Controllers::MotorController& motor) -: musicService(music), motor(motor) { + : musicService(music), motor(motor) { lv_obj_t* label; lv_style_init(&btn_style); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 4b9992715e..924931f3df 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -84,7 +84,6 @@ namespace Pinetime { Controllers::MotorController& motor; - /** Watchapp */ }; } From ee276b5cd0545bcb9d0bbe4781c50513991f05af Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Wed, 14 May 2025 18:47:32 +0200 Subject: [PATCH 06/32] revert back to swiping as a gesture to switch between skip and volume buttons --- src/displayapp/screens/Music.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index db2033bce6..3fa2a8c938 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -251,28 +251,24 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - static bool isVolumeMode = false; // T-flip-flop state - switch (event) { - case TouchEvents::DoubleTap: { - isVolumeMode = !isVolumeMode; // Toggle state - - if (isVolumeMode) { - motor.RunForDuration(35); - // Show volume controls, hide track controls - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - } else { - motor.RunForDuration(35); - // Show track controls, hide volume controls + case TouchEvents::SwipeUp: { + lv_obj_set_hidden(btnVolDown, false); + lv_obj_set_hidden(btnVolUp, false); + + lv_obj_set_hidden(btnNext, true); + lv_obj_set_hidden(btnPrev, true); + return true; + } + case TouchEvents::SwipeDown: { + if (lv_obj_get_hidden(btnNext)) { lv_obj_set_hidden(btnNext, false); lv_obj_set_hidden(btnPrev, false); lv_obj_set_hidden(btnVolDown, true); lv_obj_set_hidden(btnVolUp, true); + return true; } - return true; + return false; } case TouchEvents::SwipeLeft: { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); From 43aa9323428eb79218390e1fe2c84a41170a7549 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Wed, 14 May 2025 18:50:52 +0200 Subject: [PATCH 07/32] remove all unneccessary references to the motor controller --- src/displayapp/screens/Music.cpp | 4 ++-- src/displayapp/screens/Music.h | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 3fa2a8c938..a534b70061 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -48,8 +48,8 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music, Pinetime::Controllers::MotorController& motor) - : musicService(music), motor(motor) { +Music::Music(Pinetime::Controllers::MusicService& music) + : musicService(music){ lv_obj_t* label; lv_style_init(&btn_style); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 924931f3df..522533215b 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -34,7 +34,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music, Pinetime::Controllers::MotorController& motor); + Music(Pinetime::Controllers::MusicService& music); ~Music() override; @@ -82,8 +82,6 @@ namespace Pinetime { lv_task_t* taskRefresh; - Controllers::MotorController& motor; - /** Watchapp */ }; } @@ -94,7 +92,7 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService, controllers.motorController); + return new Screens::Music(*controllers.musicService); }; }; } From 29cc0eb21525f7aa9674717612cb015fdaa5d7b8 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Wed, 14 May 2025 18:53:10 +0200 Subject: [PATCH 08/32] formatting --- src/displayapp/screens/Music.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index a534b70061..29b8e45688 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -48,8 +48,7 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music) - : musicService(music){ +Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_obj_t* label; lv_style_init(&btn_style); From 18894a6e0348dfd0c0cdd8b0dffb1f6b04e1b264 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Fri, 30 May 2025 15:39:38 +0200 Subject: [PATCH 09/32] removed accidental change --- .vscode/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 70643b0798..a7b04eea3c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,8 +65,6 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp", - "ios": "cpp", - "disc.c": "cpp" + "typeinfo": "cpp" } } From cbc9625aa9706dae414936fa4ea002ac3dc333de Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 7 Jun 2025 00:33:01 +0200 Subject: [PATCH 10/32] correct color of the buttons --- src/displayapp/screens/Music.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 29b8e45688..0bd0965ff9 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -54,7 +54,6 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { lv_style_init(&btn_style); lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 20); lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, Colors::bgAlt); - lv_style_set_bg_opa(&btn_style, LV_STATE_DEFAULT, LV_OPA_50); btnVolDown = lv_btn_create(lv_scr_act(), nullptr); btnVolDown->user_data = this; From e44aac1f25117e17c485bc498e9427e8e88bb86f Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Thu, 12 Jun 2025 17:33:29 +0200 Subject: [PATCH 11/32] remove redundant initialisers for trackName and albumName --- src/components/ble/MusicService.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h index 9257e13514..e32980b42c 100644 --- a/src/components/ble/MusicService.h +++ b/src/components/ble/MusicService.h @@ -71,8 +71,8 @@ namespace Pinetime { uint16_t eventHandle {}; - std::string trackName {""}; - std::string albumName {""}; + std::string trackName; + std::string albumName; std::string artistName {"Not Playing"}; bool playing {false}; From ef74a001d320cd1bab7bb29afaa474c5362e0f37 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 26 Jul 2025 18:47:59 +0200 Subject: [PATCH 12/32] add progress bar --- .vscode/settings.json | 3 +- src/displayapp/screens/Music.cpp | 103 +++++++++++++++++++++++-------- src/displayapp/screens/Music.h | 17 ++++- 3 files changed, 94 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a7b04eea3c..f0414bac40 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,6 +65,7 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "disc_f_1.c": "cpp" } } diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0bd0965ff9..ace12f2638 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -24,6 +24,7 @@ #include "displayapp/icons/music/disc_f_1.c" #include "displayapp/icons/music/disc_f_2.c" #include "displayapp/InfiniTimeTheme.h" +#include "components/ble/BleController.h" using namespace Pinetime::Applications::Screens; @@ -48,7 +49,7 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { +Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController): musicService(music), bleController {bleController}{ lv_obj_t* label; lv_style_init(&btn_style); @@ -102,19 +103,12 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text_static(txtPlayPause, Symbols::play); - txtTrackDuration = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_long_mode(txtTrackDuration, LV_LABEL_LONG_SROLL); - lv_obj_align(txtTrackDuration, nullptr, LV_ALIGN_IN_TOP_LEFT, 12, 20); - lv_label_set_text_static(txtTrackDuration, "--:--/--:--"); - lv_label_set_align(txtTrackDuration, LV_ALIGN_IN_LEFT_MID); - lv_obj_set_width(txtTrackDuration, LV_HOR_RES); - constexpr uint8_t FONT_HEIGHT = 12; constexpr uint8_t LINE_PAD = 15; constexpr int8_t MIDDLE_OFFSET = -25; txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD); + lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 2 * FONT_HEIGHT + LINE_PAD); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtArtist, LV_HOR_RES - 12); lv_label_set_text_static(txtArtist, ""); @@ -122,19 +116,53 @@ Music::Music(Pinetime::Controllers::MusicService& music) : musicService(music) { txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT); + lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 1 * FONT_HEIGHT); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES - 12); lv_label_set_text_static(txtTrack, ""); - /** Init animation */ + barTrackDuration = lv_bar_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::lightGray); + lv_obj_set_style_local_bg_opa(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100); + lv_obj_set_style_local_radius(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_size(barTrackDuration, 240, 10); + lv_obj_align(barTrackDuration, nullptr, LV_ALIGN_CENTER, 0, 5); + lv_bar_set_range(barTrackDuration, 0, 1000); + lv_bar_set_value(barTrackDuration, 0, LV_ANIM_OFF); + + txtCurrentPosition = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(txtCurrentPosition, LV_LABEL_LONG_SROLL); + lv_obj_align(txtCurrentPosition, nullptr, LV_ALIGN_IN_LEFT_MID, 0, 25); + lv_label_set_text_static(txtCurrentPosition, "--:--"); + lv_label_set_align(txtCurrentPosition, LV_ALIGN_IN_LEFT_MID); + lv_obj_set_width(txtCurrentPosition, LV_HOR_RES); + lv_obj_set_style_local_text_color(txtCurrentPosition, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + + txtTrackDuration = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(txtTrackDuration, LV_LABEL_LONG_SROLL); + lv_obj_align(txtTrackDuration, nullptr, LV_ALIGN_IN_RIGHT_MID, -13, 25); + lv_label_set_text_static(txtTrackDuration, "--:--"); + lv_label_set_align(txtTrackDuration, LV_ALIGN_IN_RIGHT_MID); + lv_obj_set_width(txtTrackDuration, LV_HOR_RES); + lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + + bluetoothInfo = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_fmt(bluetoothInfo, "%s ???", Screens::Symbols::bluetooth); + lv_obj_set_style_local_text_color(bluetoothInfo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_align(bluetoothInfo, nullptr, LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_auto_realign(bluetoothInfo, true); + + + /* Init animation imgDisc = lv_img_create(lv_scr_act(), nullptr); lv_img_set_src_arr(imgDisc, &disc); - lv_obj_align(imgDisc, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15, 15); + lv_obj_align(imgDisc, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); imgDiscAnim = lv_img_create(lv_scr_act(), nullptr); lv_img_set_src_arr(imgDiscAnim, &disc_f_1); - lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15 - 32, 15); + lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0 - 32, 0); + */ frameB = false; @@ -178,16 +206,27 @@ void Music::Refresh() { UpdateLength(); } + bleState = bleController.IsConnected(); + bleRadioEnabled = bleController.IsRadioEnabled(); + if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { + if (bleState.Get() == false) { + lv_label_set_text_fmt(bluetoothInfo, "%s Disconnected", Screens::Symbols::bluetooth); + } else { + lv_label_set_text_fmt(bluetoothInfo, "%s Connected", Screens::Symbols::bluetooth); + } + } + if (playing) { lv_label_set_text_static(txtPlayPause, Symbols::pause); if (xTaskGetTickCount() - 1024 >= lastIncrement) { - if (frameB) { + /*if (frameB) { lv_img_set_src(imgDiscAnim, &disc_f_1); } else { lv_img_set_src(imgDiscAnim, &disc_f_2); } frameB = !frameB; + */ if (currentPosition >= totalLength) { // Let's assume the getTrack finished, paused when the timer ends @@ -202,22 +241,36 @@ void Music::Refresh() { } void Music::UpdateLength() { + int remaining = totalLength - currentPosition; + if (remaining < 0) remaining = 0; + if (totalLength > (99 * 60 * 60)) { - lv_label_set_text_static(txtTrackDuration, "Inf/Inf"); + lv_label_set_text_static(txtCurrentPosition, "Inf"); + lv_label_set_text_static(txtTrackDuration, "Inf"); } else if (totalLength > (99 * 60)) { - lv_label_set_text_fmt(txtTrackDuration, - "%02d:%02d/%02d:%02d", + lv_label_set_text_fmt(txtCurrentPosition, + "%d:%02d", (currentPosition / (60 * 60)) % 100, - ((currentPosition % (60 * 60)) / 60) % 100, - (totalLength / (60 * 60)) % 100, - ((totalLength % (60 * 60)) / 60) % 100); - } else { + ((currentPosition % (60 * 60)) / 60) % 100); + lv_label_set_text_fmt(txtTrackDuration, - "%02d:%02d/%02d:%02d", + "-%d:%02d", + (remaining / (60 * 60)) % 100, + ((remaining % (60 * 60)) / 60) % 100); + lv_bar_set_range(barTrackDuration, 0, totalLength > 0 ? totalLength : 1); + lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF); + } else { + lv_label_set_text_fmt(txtCurrentPosition, + "%d:%02d", (currentPosition / 60) % 100, - (currentPosition % 60) % 100, - (totalLength / 60) % 100, - (totalLength % 60) % 100); + (currentPosition % 60) % 100); + + lv_label_set_text_fmt(txtTrackDuration, + "-%d:%02d", + (remaining / 60) % 100, + (remaining % 60) % 100); + lv_bar_set_range(barTrackDuration, 0, totalLength); + lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF); } } diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 522533215b..c801ae9773 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -24,6 +24,8 @@ #include "displayapp/apps/Apps.h" #include "displayapp/Controllers.h" #include "Symbols.h" +#include "components/ble/BleController.h" +#include "utility/DirtyValue.h" namespace Pinetime { namespace Controllers { @@ -34,7 +36,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music); + Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController); ~Music() override; @@ -55,17 +57,22 @@ namespace Pinetime { lv_obj_t* txtArtist; lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; + lv_obj_t* bluetoothInfo; lv_obj_t* imgDisc; lv_obj_t* imgDiscAnim; lv_obj_t* txtTrackDuration; + lv_obj_t* txtCurrentPosition; + lv_obj_t* barTrackDuration; + lv_style_t btn_style; /** For the spinning disc animation */ bool frameB; - Pinetime::Controllers::MusicService& musicService; + Pinetime::Controllers::MusicService& musicService; + const Controllers::Ble& bleController; std::string artist; std::string album; @@ -82,6 +89,9 @@ namespace Pinetime { lv_task_t* taskRefresh; + Utility::DirtyValue bleState {}; + Utility::DirtyValue bleRadioEnabled {}; + /** Watchapp */ }; } @@ -92,7 +102,8 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService); + return new Screens::Music(*controllers.musicService, + controllers.bleController); }; }; } From fcea150959e429bbfff0aa8b76fe4e6b1957514a Mon Sep 17 00:00:00 2001 From: Titus <154823939+tituscmd@users.noreply.github.com> Date: Sat, 26 Jul 2025 21:19:38 +0200 Subject: [PATCH 13/32] Update settings.json --- .vscode/settings.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f0414bac40..a7b04eea3c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,7 +65,6 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp", - "disc_f_1.c": "cpp" + "typeinfo": "cpp" } } From 052dad29a229081d774f43de379eb0adc990bdd6 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 28 Jul 2025 22:43:27 +0200 Subject: [PATCH 14/32] formatting --- src/displayapp/screens/Music.cpp | 30 +++++++++--------------------- src/displayapp/screens/Music.h | 3 +-- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index ace12f2638..bbbf4f8cd1 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -49,7 +49,8 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController): musicService(music), bleController {bleController}{ +Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController) + : musicService(music), bleController {bleController}{ lv_obj_t* label; lv_style_init(&btn_style); @@ -212,7 +213,7 @@ void Music::Refresh() { if (bleState.Get() == false) { lv_label_set_text_fmt(bluetoothInfo, "%s Disconnected", Screens::Symbols::bluetooth); } else { - lv_label_set_text_fmt(bluetoothInfo, "%s Connected", Screens::Symbols::bluetooth); + lv_label_set_text_fmt(bluetoothInfo, "%s Connected", Screens::Symbols::bluetooth); } } @@ -242,33 +243,20 @@ void Music::Refresh() { void Music::UpdateLength() { int remaining = totalLength - currentPosition; - if (remaining < 0) remaining = 0; + if (remaining < 0) + remaining = 0; if (totalLength > (99 * 60 * 60)) { lv_label_set_text_static(txtCurrentPosition, "Inf"); lv_label_set_text_static(txtTrackDuration, "Inf"); } else if (totalLength > (99 * 60)) { - lv_label_set_text_fmt(txtCurrentPosition, - "%d:%02d", - (currentPosition / (60 * 60)) % 100, - ((currentPosition % (60 * 60)) / 60) % 100); - - lv_label_set_text_fmt(txtTrackDuration, - "-%d:%02d", - (remaining / (60 * 60)) % 100, - ((remaining % (60 * 60)) / 60) % 100); + lv_label_set_text_fmt(txtCurrentPosition, "%d:%02d", (currentPosition / (60 * 60)) % 100, ((currentPosition % (60 * 60)) / 60) % 100); + lv_label_set_text_fmt(txtTrackDuration, "-%d:%02d", (remaining / (60 * 60)) % 100, ((remaining % (60 * 60)) / 60) % 100); lv_bar_set_range(barTrackDuration, 0, totalLength > 0 ? totalLength : 1); lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF); } else { - lv_label_set_text_fmt(txtCurrentPosition, - "%d:%02d", - (currentPosition / 60) % 100, - (currentPosition % 60) % 100); - - lv_label_set_text_fmt(txtTrackDuration, - "-%d:%02d", - (remaining / 60) % 100, - (remaining % 60) % 100); + lv_label_set_text_fmt(txtCurrentPosition, "%d:%02d", (currentPosition / 60) % 100, (currentPosition % 60) % 100); + lv_label_set_text_fmt(txtTrackDuration, "-%d:%02d", (remaining / 60) % 100, (remaining % 60) % 100); lv_bar_set_range(barTrackDuration, 0, totalLength); lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF); } diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index c801ae9773..e94fe8db3b 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -102,8 +102,7 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService, - controllers.bleController); + return new Screens::Music(*controllers.musicService, controllers.bleController); }; }; } From 65ae1293b0454edcd2f69ca4a03f5f446ce1f14f Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 28 Jul 2025 22:48:36 +0200 Subject: [PATCH 15/32] formatting --- src/displayapp/screens/Music.cpp | 2 +- src/displayapp/screens/Music.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index c8b9079f63..39be58c0b4 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -51,7 +51,7 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController) - : musicService(music), bleController {bleController}{ + : musicService(music), bleController {bleController} { lv_obj_t* label; lv_style_init(&btn_style); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index f8e8c9f05f..f4504c2f58 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -71,7 +71,7 @@ namespace Pinetime { /** For the spinning disc animation */ bool frameB; - Pinetime::Controllers::MusicService& musicService; + Pinetime::Controllers::MusicService& musicService; const Controllers::Ble& bleController; std::string artist; From ed30e539fdf2b0dfa2a312deb227ef1ac648b60f Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Tue, 29 Jul 2025 00:16:44 +0200 Subject: [PATCH 16/32] more formatting --- src/displayapp/screens/Music.cpp | 1 - src/displayapp/screens/Music.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 39be58c0b4..52538cf6ac 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -26,7 +26,6 @@ #include "displayapp/InfiniTimeTheme.h" #include "components/ble/BleController.h" - using namespace Pinetime::Applications::Screens; static void event_handler(lv_obj_t* obj, lv_event_t event) { diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index f4504c2f58..7d60f6c8e8 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -65,7 +65,6 @@ namespace Pinetime { lv_obj_t* txtCurrentPosition; lv_obj_t* barTrackDuration; - lv_style_t btn_style; /** For the spinning disc animation */ From c634bf21339f95097ef1372b797a3ccdcf5834bc Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Wed, 6 Aug 2025 14:54:59 +0200 Subject: [PATCH 17/32] different design for music.cpp --- src/displayapp/screens/Music.cpp | 30 +++++++++++++++++++++++++----- src/displayapp/screens/Music.h | 10 ++++++++-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 52538cf6ac..0b88d640ed 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -49,8 +49,12 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController) - : musicService(music), bleController {bleController} { +Music::Music(Pinetime::Controllers::MusicService& music, + const Controllers::Ble& bleController, + Controllers::DateTime& dateTimeController) + : musicService(music), bleController {bleController}, + dateTimeController {dateTimeController} { + lv_obj_t* label; lv_style_init(&btn_style); @@ -149,11 +153,13 @@ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + /* bluetoothInfo = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(bluetoothInfo, "%s ???", Screens::Symbols::bluetooth); lv_obj_set_style_local_text_color(bluetoothInfo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_align(bluetoothInfo, nullptr, LV_ALIGN_IN_TOP_MID, 0, 0); lv_obj_set_auto_realign(bluetoothInfo, true); + */ /* Init animation imgDisc = lv_img_create(lv_scr_act(), nullptr); @@ -165,6 +171,11 @@ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0 - 32, 0); */ + label_time = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_auto_realign(label_time, true); + frameB = false; musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); @@ -207,15 +218,24 @@ void Music::Refresh() { UpdateLength(); } + lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str()); + bleState = bleController.IsConnected(); bleRadioEnabled = bleController.IsRadioEnabled(); if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { if (bleState.Get() == false) { - lv_label_set_text_fmt(bluetoothInfo, "%s Disconnected", Screens::Symbols::bluetooth); - } else { - lv_label_set_text_fmt(bluetoothInfo, "%s Connected", Screens::Symbols::bluetooth); + lv_label_set_text_fmt(txtArtist, "Disconnected"); + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + } + else { + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); } } + if (playing) { lv_label_set_text_static(txtPlayPause, Symbols::pause); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 7d60f6c8e8..97ecb2ec49 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -36,7 +36,9 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController); + Music(Pinetime::Controllers::MusicService& music, + const Controllers::Ble& bleController, + Controllers::DateTime& dateTimeController); ~Music() override; @@ -58,6 +60,7 @@ namespace Pinetime { lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; lv_obj_t* bluetoothInfo; + lv_obj_t* label_time; lv_obj_t* imgDisc; lv_obj_t* imgDiscAnim; @@ -72,6 +75,7 @@ namespace Pinetime { Pinetime::Controllers::MusicService& musicService; const Controllers::Ble& bleController; + Pinetime::Controllers::DateTime& dateTimeController; std::string artist; std::string album; @@ -101,7 +105,9 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService, controllers.bleController); + return new Screens::Music(*controllers.musicService, + controllers.bleController, + controllers.dateTimeController); }; static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { From b27c4f2b7e86be5efd7d96a358b2bbb713fab886 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 11 Aug 2025 02:09:50 +0200 Subject: [PATCH 18/32] renaming to camelCase, time top center, some visual tweaks --- src/displayapp/screens/Music.cpp | 27 ++++++++++----------------- src/displayapp/screens/Music.h | 3 +-- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0b88d640ed..591e485ae8 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -115,16 +115,15 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 2 * FONT_HEIGHT + LINE_PAD); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); - lv_obj_set_width(txtArtist, LV_HOR_RES - 12); + lv_obj_set_width(txtArtist, LV_HOR_RES); lv_label_set_text_static(txtArtist, ""); lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 1 * FONT_HEIGHT); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); - lv_obj_set_width(txtTrack, LV_HOR_RES - 12); + lv_obj_set_width(txtTrack, LV_HOR_RES); lv_label_set_text_static(txtTrack, ""); barTrackDuration = lv_bar_create(lv_scr_act(), nullptr); @@ -153,14 +152,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); - /* - bluetoothInfo = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_text_fmt(bluetoothInfo, "%s ???", Screens::Symbols::bluetooth); - lv_obj_set_style_local_text_color(bluetoothInfo, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_align(bluetoothInfo, nullptr, LV_ALIGN_IN_TOP_MID, 0, 0); - lv_obj_set_auto_realign(bluetoothInfo, true); - */ - /* Init animation imgDisc = lv_img_create(lv_scr_act(), nullptr); lv_img_set_src_arr(imgDisc, &disc); @@ -171,10 +162,11 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0 - 32, 0); */ - label_time = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER); - lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); - lv_obj_set_auto_realign(label_time, true); + labelTime = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_align(labelTime, LV_LABEL_ALIGN_CENTER); + lv_obj_align(labelTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_auto_realign(labelTime, true); + lv_label_set_text_static(labelTime, "09:41"); frameB = false; @@ -218,7 +210,7 @@ void Music::Refresh() { UpdateLength(); } - lv_label_set_text(label_time, dateTimeController.FormattedTime().c_str()); + lv_label_set_text(labelTime, dateTimeController.FormattedTime().c_str()); bleState = bleController.IsConnected(); bleRadioEnabled = bleController.IsRadioEnabled(); @@ -241,7 +233,8 @@ void Music::Refresh() { lv_label_set_text_static(txtPlayPause, Symbols::pause); if (xTaskGetTickCount() - 1024 >= lastIncrement) { - /*if (frameB) { + /* + if (frameB) { lv_img_set_src(imgDiscAnim, &disc_f_1); } else { lv_img_set_src(imgDiscAnim, &disc_f_2); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 97ecb2ec49..eccfb138e6 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -59,8 +59,7 @@ namespace Pinetime { lv_obj_t* txtArtist; lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; - lv_obj_t* bluetoothInfo; - lv_obj_t* label_time; + lv_obj_t* labelTime; lv_obj_t* imgDisc; lv_obj_t* imgDiscAnim; From afe65d69dbd2d873cb7c2541753c86b4405eccfe Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 18 Aug 2025 19:30:00 +0200 Subject: [PATCH 19/32] tweak code for much easier alignment testing --- src/displayapp/screens/Music.cpp | 45 ++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 591e485ae8..0db5a3da6e 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -108,37 +108,40 @@ Music::Music(Pinetime::Controllers::MusicService& music, txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text_static(txtPlayPause, Symbols::play); - constexpr uint8_t FONT_HEIGHT = 12; - constexpr uint8_t LINE_PAD = 15; - constexpr int8_t MIDDLE_OFFSET = -25; - txtArtist = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 2 * FONT_HEIGHT + LINE_PAD); - lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); - lv_obj_set_width(txtArtist, LV_HOR_RES); - lv_label_set_text_static(txtArtist, ""); - lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + // top anchor for the whole stack, move this and everything follows + constexpr int16_t BASE_Y = -70; // was txtTrack's previous y, 70 looks good for current default txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, (MIDDLE_OFFSET - 45) + 1 * FONT_HEIGHT); + lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, BASE_Y); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES); lv_label_set_text_static(txtTrack, ""); + // 27px below txtTrack (12 + 15 previously), hard coded + txtArtist = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); + lv_obj_align(txtArtist, txtTrack, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 27); + lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); + lv_obj_set_width(txtArtist, LV_HOR_RES); + lv_label_set_text_static(txtArtist, ""); + lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + + // bar sits 36px below txtArtist (to match old layout) barTrackDuration = lv_bar_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::lightGray); lv_obj_set_style_local_bg_opa(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100); lv_obj_set_style_local_radius(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); lv_obj_set_size(barTrackDuration, 240, 10); - lv_obj_align(barTrackDuration, nullptr, LV_ALIGN_CENTER, 0, 5); + lv_obj_align(barTrackDuration, txtArtist, LV_ALIGN_OUT_BOTTOM_MID, 0, 14); lv_bar_set_range(barTrackDuration, 0, 1000); lv_bar_set_value(barTrackDuration, 0, LV_ANIM_OFF); + // time labels 20px below the bar, left and right aligned txtCurrentPosition = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtCurrentPosition, LV_LABEL_LONG_SROLL); - lv_obj_align(txtCurrentPosition, nullptr, LV_ALIGN_IN_LEFT_MID, 0, 25); + lv_obj_align(txtCurrentPosition, barTrackDuration, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); lv_label_set_text_static(txtCurrentPosition, "--:--"); lv_label_set_align(txtCurrentPosition, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtCurrentPosition, LV_HOR_RES); @@ -146,12 +149,20 @@ Music::Music(Pinetime::Controllers::MusicService& music, txtTrackDuration = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrackDuration, LV_LABEL_LONG_SROLL); - lv_obj_align(txtTrackDuration, nullptr, LV_ALIGN_IN_RIGHT_MID, -13, 25); + lv_obj_align(txtTrackDuration, barTrackDuration, LV_ALIGN_OUT_BOTTOM_RIGHT, -13, 0); lv_label_set_text_static(txtTrackDuration, "--:--"); lv_label_set_align(txtTrackDuration, LV_ALIGN_IN_RIGHT_MID); lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + // status time at the very top, keep independent of the chain + labelTime = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_align(labelTime, LV_LABEL_ALIGN_CENTER); + lv_obj_align(labelTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); + lv_obj_set_auto_realign(labelTime, true); + lv_label_set_text_static(labelTime, "09:41"); + lv_obj_set_hidden(labelTime, true); + /* Init animation imgDisc = lv_img_create(lv_scr_act(), nullptr); lv_img_set_src_arr(imgDisc, &disc); @@ -162,12 +173,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0 - 32, 0); */ - labelTime = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_align(labelTime, LV_LABEL_ALIGN_CENTER); - lv_obj_align(labelTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); - lv_obj_set_auto_realign(labelTime, true); - lv_label_set_text_static(labelTime, "09:41"); - frameB = false; musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); From d87126a955855ca0306b72ebe206da38f39644fb Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 18 Aug 2025 19:30:18 +0200 Subject: [PATCH 20/32] tweak code for much easier alignment testing --- src/displayapp/screens/Music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0db5a3da6e..14042a4ddd 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -116,7 +116,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, BASE_Y); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES); - lv_label_set_text_static(txtTrack, ""); + lv_label_set_text_static(txtTrack, "Some Track"); // 27px below txtTrack (12 + 15 previously), hard coded txtArtist = lv_label_create(lv_scr_act(), nullptr); From d11a71b0c32bfa63e9d4c2eb447a34f80c5311a0 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 18 Aug 2025 20:19:02 +0200 Subject: [PATCH 21/32] change controls button --- src/displayapp/fonts/fonts.json | 2 +- src/displayapp/screens/Music.cpp | 37 ++++++++++++++++++++++++++++++-- src/displayapp/screens/Music.h | 4 ++++ src/displayapp/screens/Symbols.h | 1 + 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index fea3160572..f6567f3f6e 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" + "range": "0xf079, 0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" } ], "bpp": 1, diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 14042a4ddd..017dcce6d7 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -109,7 +109,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_label_set_text_static(txtPlayPause, Symbols::play); // top anchor for the whole stack, move this and everything follows - constexpr int16_t BASE_Y = -70; // was txtTrack's previous y, 70 looks good for current default + constexpr int16_t BASE_Y = -90; // was txtTrack's previous y, 70 looks good for current default txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); @@ -121,7 +121,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, // 27px below txtTrack (12 + 15 previously), hard coded txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_align(txtArtist, txtTrack, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 27); + lv_obj_align(txtArtist, txtTrack, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtArtist, LV_HOR_RES); lv_label_set_text_static(txtArtist, ""); @@ -163,6 +163,19 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_label_set_text_static(labelTime, "09:41"); lv_obj_set_hidden(labelTime, true); + btnSwapControls = lv_btn_create(lv_scr_act(), nullptr); + btnSwapControls->user_data = this; + lv_obj_set_event_cb(btnSwapControls, event_handler); + lv_obj_set_style_local_radius(btnSwapControls, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); + lv_obj_set_style_local_bg_color(btnSwapControls, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + txtSwapControls = lv_label_create(btnSwapControls, nullptr); + lv_label_set_text_fmt(txtSwapControls, "%s Volume Controls", Symbols::swap); + lv_obj_set_style_local_text_color(txtSwapControls, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding + lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding + lv_obj_align(btnSwapControls, nullptr, LV_ALIGN_CENTER, 0, 20); + + /* Init animation imgDisc = lv_img_create(lv_scr_act(), nullptr); lv_img_set_src_arr(imgDisc, &disc); @@ -303,12 +316,31 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } } else if (obj == btnNext) { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); + } else if (obj == btnSwapControls) { + showingVolumeControls = !showingVolumeControls; // flip the state + + if (showingVolumeControls) { + // show volume buttons, hide track buttons + lv_obj_set_hidden(btnVolDown, false); + lv_obj_set_hidden(btnVolUp, false); + lv_obj_set_hidden(btnNext, true); + lv_obj_set_hidden(btnPrev, true); + lv_label_set_text_fmt(txtSwapControls, "%s Track Controls", Symbols::swap); + } else { + // show track buttons, hide volume buttons + lv_obj_set_hidden(btnNext, false); + lv_obj_set_hidden(btnPrev, false); + lv_obj_set_hidden(btnVolDown, true); + lv_obj_set_hidden(btnVolUp, true); + lv_label_set_text_fmt(txtSwapControls, "%s Volume Controls", Symbols::swap); + } } } } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { + /* case TouchEvents::SwipeUp: { lv_obj_set_hidden(btnVolDown, false); lv_obj_set_hidden(btnVolUp, false); @@ -327,6 +359,7 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } return false; } + */ case TouchEvents::SwipeLeft: { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); return true; diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index eccfb138e6..ff2fd2ea51 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -56,9 +56,11 @@ namespace Pinetime { lv_obj_t* btnNext; lv_obj_t* btnVolDown; lv_obj_t* btnVolUp; + lv_obj_t* btnSwapControls; lv_obj_t* txtArtist; lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; + lv_obj_t* txtSwapControls; lv_obj_t* labelTime; lv_obj_t* imgDisc; @@ -67,6 +69,8 @@ namespace Pinetime { lv_obj_t* txtCurrentPosition; lv_obj_t* barTrackDuration; + bool showingVolumeControls = false; + lv_style_t btn_style; /** For the spinning disc animation */ diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 40699b3d65..4482fb0be2 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -41,6 +41,7 @@ namespace Pinetime { static constexpr const char* sleep = "\xEE\xBD\x84"; static constexpr const char* calculator = "\xEF\x87\xAC"; static constexpr const char* backspace = "\xEF\x95\x9A"; + static constexpr const char* swap = "\xef\x81\xb9"; // fontawesome_weathericons.c // static constexpr const char* sun = "\xEF\x86\x85"; From 8d036eecdb593b23fd910ab7f6c01e5aec027318 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 18 Aug 2025 20:47:28 +0200 Subject: [PATCH 22/32] tweaks to the new swap controls button --- src/displayapp/screens/Music.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 017dcce6d7..ea9af54ddc 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -116,7 +116,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, BASE_Y); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES); - lv_label_set_text_static(txtTrack, "Some Track"); + lv_label_set_text_static(txtTrack, ""); // 27px below txtTrack (12 + 15 previously), hard coded txtArtist = lv_label_create(lv_scr_act(), nullptr); @@ -174,6 +174,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding lv_obj_align(btnSwapControls, nullptr, LV_ALIGN_CENTER, 0, 20); + lv_obj_set_auto_realign(btnSwapControls, true); /* Init animation @@ -234,15 +235,20 @@ void Music::Refresh() { bleRadioEnabled = bleController.IsRadioEnabled(); if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { if (bleState.Get() == false) { - lv_label_set_text_fmt(txtArtist, "Disconnected"); + lv_label_set_text_static(txtArtist, "Disconnected"); + lv_label_set_text_static(txtTrack, ""); lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); } else { lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); } } @@ -326,6 +332,8 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { lv_obj_set_hidden(btnNext, true); lv_obj_set_hidden(btnPrev, true); lv_label_set_text_fmt(txtSwapControls, "%s Track Controls", Symbols::swap); + lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding + lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding } else { // show track buttons, hide volume buttons lv_obj_set_hidden(btnNext, false); @@ -333,6 +341,9 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { lv_obj_set_hidden(btnVolDown, true); lv_obj_set_hidden(btnVolUp, true); lv_label_set_text_fmt(txtSwapControls, "%s Volume Controls", Symbols::swap); + lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding + lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding + } } } From 4ed2d1872ed4925a55cc9bdf4aa0f19f09e85e9f Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Fri, 22 Aug 2025 18:21:39 +0200 Subject: [PATCH 23/32] Different version of the music app, where all buttons are on one screen --- src/displayapp/screens/Music.cpp | 28 +++++++++++++++++----------- src/displayapp/screens/Music.h | 4 ++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index ea9af54ddc..c06f857eae 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -64,28 +64,26 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnVolDown = lv_btn_create(lv_scr_act(), nullptr); btnVolDown->user_data = this; lv_obj_set_event_cb(btnVolDown, event_handler); - lv_obj_set_size(btnVolDown, 76, 76); + lv_obj_set_size(btnVolDown, 115, 50); lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_add_style(btnVolDown, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolDown, nullptr); lv_label_set_text_static(label, Symbols::volumDown); - lv_obj_set_hidden(btnVolDown, true); btnVolUp = lv_btn_create(lv_scr_act(), nullptr); btnVolUp->user_data = this; lv_obj_set_event_cb(btnVolUp, event_handler); - lv_obj_set_size(btnVolUp, 76, 76); + lv_obj_set_size(btnVolUp, 115, 50); lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); lv_obj_add_style(btnVolUp, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolUp, nullptr); lv_label_set_text_static(label, Symbols::volumUp); - lv_obj_set_hidden(btnVolUp, true); btnPrev = lv_btn_create(lv_scr_act(), nullptr); btnPrev->user_data = this; lv_obj_set_event_cb(btnPrev, event_handler); lv_obj_set_size(btnPrev, 76, 76); - lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, -56); lv_obj_add_style(btnPrev, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnPrev, nullptr); lv_label_set_text_static(label, Symbols::stepBackward); @@ -94,7 +92,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnNext->user_data = this; lv_obj_set_event_cb(btnNext, event_handler); lv_obj_set_size(btnNext, 76, 76); - lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -56); lv_obj_add_style(btnNext, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnNext, nullptr); lv_label_set_text_static(label, Symbols::stepForward); @@ -103,13 +101,15 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, event_handler); lv_obj_set_size(btnPlayPause, 76, 76); - lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -56); lv_obj_add_style(btnPlayPause, LV_STATE_DEFAULT, &btn_style); txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text_static(txtPlayPause, Symbols::play); - // top anchor for the whole stack, move this and everything follows - constexpr int16_t BASE_Y = -90; // was txtTrack's previous y, 70 looks good for current default + // I'm using the txtTrack label as the top anchor for the whole lot + // of song, artist, progress bar and duration text (0:00 and -0:00) so + // its much easier to move that around and mess with the buttons + constexpr int16_t BASE_Y = -100; txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); @@ -118,7 +118,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_width(txtTrack, LV_HOR_RES); lv_label_set_text_static(txtTrack, ""); - // 27px below txtTrack (12 + 15 previously), hard coded txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); lv_obj_align(txtArtist, txtTrack, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); @@ -127,7 +126,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_label_set_text_static(txtArtist, ""); lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); - // bar sits 36px below txtArtist (to match old layout) barTrackDuration = lv_bar_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(barTrackDuration, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::lightGray); @@ -155,6 +153,9 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); + // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that + + /* // status time at the very top, keep independent of the chain labelTime = lv_label_create(lv_scr_act(), nullptr); lv_label_set_align(labelTime, LV_LABEL_ALIGN_CENTER); @@ -175,6 +176,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding lv_obj_align(btnSwapControls, nullptr, LV_ALIGN_CENTER, 0, 20); lv_obj_set_auto_realign(btnSwapControls, true); + */ /* Init animation @@ -322,6 +324,8 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } } else if (obj == btnNext) { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); + // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that + /* } else if (obj == btnSwapControls) { showingVolumeControls = !showingVolumeControls; // flip the state @@ -345,12 +349,14 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding } + */ } } } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { + // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that /* case TouchEvents::SwipeUp: { lv_obj_set_hidden(btnVolDown, false); diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index ff2fd2ea51..e0f6a936a3 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -56,11 +56,11 @@ namespace Pinetime { lv_obj_t* btnNext; lv_obj_t* btnVolDown; lv_obj_t* btnVolUp; - lv_obj_t* btnSwapControls; + // lv_obj_t* btnSwapControls; lv_obj_t* txtArtist; lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; - lv_obj_t* txtSwapControls; + // lv_obj_t* txtSwapControls; lv_obj_t* labelTime; lv_obj_t* imgDisc; From e02a795a1a05eb4127a217b887a86b50c0bc50db Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Fri, 22 Aug 2025 22:50:38 +0200 Subject: [PATCH 24/32] another UI iteration, my favorite (volume buttons above track buttons) --- src/displayapp/screens/Music.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index c06f857eae..63d55d5c74 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -65,7 +65,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnVolDown->user_data = this; lv_obj_set_event_cb(btnVolDown, event_handler); lv_obj_set_size(btnVolDown, 115, 50); - lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, -86); lv_obj_add_style(btnVolDown, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolDown, nullptr); lv_label_set_text_static(label, Symbols::volumDown); @@ -74,7 +74,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnVolUp->user_data = this; lv_obj_set_event_cb(btnVolUp, event_handler); lv_obj_set_size(btnVolUp, 115, 50); - lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -86); lv_obj_add_style(btnVolUp, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolUp, nullptr); lv_label_set_text_static(label, Symbols::volumUp); @@ -83,7 +83,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnPrev->user_data = this; lv_obj_set_event_cb(btnPrev, event_handler); lv_obj_set_size(btnPrev, 76, 76); - lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, -56); + lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); lv_obj_add_style(btnPrev, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnPrev, nullptr); lv_label_set_text_static(label, Symbols::stepBackward); @@ -92,7 +92,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnNext->user_data = this; lv_obj_set_event_cb(btnNext, event_handler); lv_obj_set_size(btnNext, 76, 76); - lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -56); + lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); lv_obj_add_style(btnNext, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnNext, nullptr); lv_label_set_text_static(label, Symbols::stepForward); @@ -101,7 +101,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnPlayPause->user_data = this; lv_obj_set_event_cb(btnPlayPause, event_handler); lv_obj_set_size(btnPlayPause, 76, 76); - lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -56); + lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_add_style(btnPlayPause, LV_STATE_DEFAULT, &btn_style); txtPlayPause = lv_label_create(btnPlayPause, nullptr); lv_label_set_text_static(txtPlayPause, Symbols::play); @@ -109,7 +109,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, // I'm using the txtTrack label as the top anchor for the whole lot // of song, artist, progress bar and duration text (0:00 and -0:00) so // its much easier to move that around and mess with the buttons - constexpr int16_t BASE_Y = -100; + constexpr int16_t BASE_Y = -110; txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); @@ -231,7 +231,7 @@ void Music::Refresh() { UpdateLength(); } - lv_label_set_text(labelTime, dateTimeController.FormattedTime().c_str()); + //lv_label_set_text(labelTime, dateTimeController.FormattedTime().c_str()); bleState = bleController.IsConnected(); bleRadioEnabled = bleController.IsRadioEnabled(); From e2514b05d1345bc1dbac1c60edaefc5be275a5b5 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 23 Aug 2025 18:41:05 +0200 Subject: [PATCH 25/32] version with buttons up top --- src/displayapp/screens/Music.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 63d55d5c74..7027172298 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -64,8 +64,8 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnVolDown = lv_btn_create(lv_scr_act(), nullptr); btnVolDown->user_data = this; lv_obj_set_event_cb(btnVolDown, event_handler); - lv_obj_set_size(btnVolDown, 115, 50); - lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, -86); + lv_obj_set_size(btnVolDown, 117, 60); + lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0); lv_obj_add_style(btnVolDown, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolDown, nullptr); lv_label_set_text_static(label, Symbols::volumDown); @@ -73,8 +73,8 @@ Music::Music(Pinetime::Controllers::MusicService& music, btnVolUp = lv_btn_create(lv_scr_act(), nullptr); btnVolUp->user_data = this; lv_obj_set_event_cb(btnVolUp, event_handler); - lv_obj_set_size(btnVolUp, 115, 50); - lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, -86); + lv_obj_set_size(btnVolUp, 117, 60); + lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); lv_obj_add_style(btnVolUp, LV_STATE_DEFAULT, &btn_style); label = lv_label_create(btnVolUp, nullptr); lv_label_set_text_static(label, Symbols::volumUp); @@ -109,14 +109,14 @@ Music::Music(Pinetime::Controllers::MusicService& music, // I'm using the txtTrack label as the top anchor for the whole lot // of song, artist, progress bar and duration text (0:00 and -0:00) so // its much easier to move that around and mess with the buttons - constexpr int16_t BASE_Y = -110; + constexpr int16_t BASE_Y = -45; // -45 for buttons at the top txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, BASE_Y); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES); - lv_label_set_text_static(txtTrack, ""); + lv_label_set_text_static(txtTrack, "Some Track"); txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); From 1f902b165ed31f04ac0d6e39f2e965690861a749 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 20:25:24 +0200 Subject: [PATCH 26/32] clean up code --- src/displayapp/screens/Music.cpp | 152 +++++-------------------------- 1 file changed, 24 insertions(+), 128 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 7027172298..0b5e16f3b0 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -108,7 +108,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, // I'm using the txtTrack label as the top anchor for the whole lot // of song, artist, progress bar and duration text (0:00 and -0:00) so - // its much easier to move that around and mess with the buttons + // its much easier to move that around and mess with the buttons separately constexpr int16_t BASE_Y = -45; // -45 for buttons at the top txtTrack = lv_label_create(lv_scr_act(), nullptr); @@ -116,7 +116,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 0, BASE_Y); lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID); lv_obj_set_width(txtTrack, LV_HOR_RES); - lv_label_set_text_static(txtTrack, "Some Track"); + lv_label_set_text_static(txtTrack, ""); txtArtist = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC); @@ -136,7 +136,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_bar_set_range(barTrackDuration, 0, 1000); lv_bar_set_value(barTrackDuration, 0, LV_ANIM_OFF); - // time labels 20px below the bar, left and right aligned txtCurrentPosition = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtCurrentPosition, LV_LABEL_LONG_SROLL); lv_obj_align(txtCurrentPosition, barTrackDuration, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0); @@ -153,42 +152,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); - // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that - - /* - // status time at the very top, keep independent of the chain - labelTime = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_align(labelTime, LV_LABEL_ALIGN_CENTER); - lv_obj_align(labelTime, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0); - lv_obj_set_auto_realign(labelTime, true); - lv_label_set_text_static(labelTime, "09:41"); - lv_obj_set_hidden(labelTime, true); - - btnSwapControls = lv_btn_create(lv_scr_act(), nullptr); - btnSwapControls->user_data = this; - lv_obj_set_event_cb(btnSwapControls, event_handler); - lv_obj_set_style_local_radius(btnSwapControls, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20); - lv_obj_set_style_local_bg_color(btnSwapControls, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - txtSwapControls = lv_label_create(btnSwapControls, nullptr); - lv_label_set_text_fmt(txtSwapControls, "%s Volume Controls", Symbols::swap); - lv_obj_set_style_local_text_color(txtSwapControls, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); - lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding - lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding - lv_obj_align(btnSwapControls, nullptr, LV_ALIGN_CENTER, 0, 20); - lv_obj_set_auto_realign(btnSwapControls, true); - */ - - - /* Init animation - imgDisc = lv_img_create(lv_scr_act(), nullptr); - lv_img_set_src_arr(imgDisc, &disc); - lv_obj_align(imgDisc, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0); - - imgDiscAnim = lv_img_create(lv_scr_act(), nullptr); - lv_img_set_src_arr(imgDiscAnim, &disc_f_1); - lv_obj_align(imgDiscAnim, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0 - 32, 0); - */ - frameB = false; musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); @@ -203,6 +166,27 @@ Music::~Music() { } void Music::Refresh() { + bleState = bleController.IsConnected(); + bleRadioEnabled = bleController.IsRadioEnabled(); + if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { + if (bleState.Get() == false) { + lv_label_set_text_static(txtArtist, "Disconnected"); + lv_label_set_text_static(txtTrack, ""); + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + } + else { + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + } + } + if (artist != musicService.getArtist()) { artist = musicService.getArtist(); lv_label_set_text(txtArtist, artist.data()); @@ -230,51 +214,10 @@ void Music::Refresh() { totalLength = musicService.getTrackLength(); UpdateLength(); } - - //lv_label_set_text(labelTime, dateTimeController.FormattedTime().c_str()); - - bleState = bleController.IsConnected(); - bleRadioEnabled = bleController.IsRadioEnabled(); - if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { - if (bleState.Get() == false) { - lv_label_set_text_static(txtArtist, "Disconnected"); - lv_label_set_text_static(txtTrack, ""); - lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - } - else { - lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - } - } if (playing) { lv_label_set_text_static(txtPlayPause, Symbols::pause); - if (xTaskGetTickCount() - 1024 >= lastIncrement) { - - /* - if (frameB) { - lv_img_set_src(imgDiscAnim, &disc_f_1); - } else { - lv_img_set_src(imgDiscAnim, &disc_f_2); - } - frameB = !frameB; - */ - - if (currentPosition >= totalLength) { - // Let's assume the getTrack finished, paused when the timer ends - // and there's no new getTrack being sent to us - playing = false; - } - lastIncrement = xTaskGetTickCount(); - } } else { lv_label_set_text_static(txtPlayPause, Symbols::play); } @@ -296,7 +239,7 @@ void Music::UpdateLength() { } else { lv_label_set_text_fmt(txtCurrentPosition, "%d:%02d", (currentPosition / 60) % 100, (currentPosition % 60) % 100); lv_label_set_text_fmt(txtTrackDuration, "-%d:%02d", (remaining / 60) % 100, (remaining % 60) % 100); - lv_bar_set_range(barTrackDuration, 0, totalLength); + lv_bar_set_range(barTrackDuration, 0, totalLength > 0 ? totalLength : 1); lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF); } } @@ -324,59 +267,12 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) { } } else if (obj == btnNext) { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); - // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that - /* - } else if (obj == btnSwapControls) { - showingVolumeControls = !showingVolumeControls; // flip the state - - if (showingVolumeControls) { - // show volume buttons, hide track buttons - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - lv_label_set_text_fmt(txtSwapControls, "%s Track Controls", Symbols::swap); - lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding - lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding - } else { - // show track buttons, hide volume buttons - lv_obj_set_hidden(btnNext, false); - lv_obj_set_hidden(btnPrev, false); - lv_obj_set_hidden(btnVolDown, true); - lv_obj_set_hidden(btnVolUp, true); - lv_label_set_text_fmt(txtSwapControls, "%s Volume Controls", Symbols::swap); - lv_obj_set_width(btnSwapControls, lv_obj_get_width(txtSwapControls) + 18); // +padding - lv_obj_set_height(btnSwapControls, lv_obj_get_height(txtSwapControls) + 8); // +padding - - } - */ } } } bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { - // Only commented out until we figure out the final version of this over on GitHub. Can be fully removed after that - /* - case TouchEvents::SwipeUp: { - lv_obj_set_hidden(btnVolDown, false); - lv_obj_set_hidden(btnVolUp, false); - - lv_obj_set_hidden(btnNext, true); - lv_obj_set_hidden(btnPrev, true); - return true; - } - case TouchEvents::SwipeDown: { - if (lv_obj_get_hidden(btnNext)) { - lv_obj_set_hidden(btnNext, false); - lv_obj_set_hidden(btnPrev, false); - lv_obj_set_hidden(btnVolDown, true); - lv_obj_set_hidden(btnVolUp, true); - return true; - } - return false; - } - */ case TouchEvents::SwipeLeft: { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); return true; From 2201ee8ee10240bc85db1048935527adab63bf4c Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 20:39:58 +0200 Subject: [PATCH 27/32] finally got a formatting extension, so this is hopefully the last formatting commit --- src/displayapp/screens/Music.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 0b5e16f3b0..efb661346e 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -49,12 +49,9 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) { * * TODO: Investigate Apple Media Service and AVRCPv1.6 support for seamless integration */ -Music::Music(Pinetime::Controllers::MusicService& music, - const Controllers::Ble& bleController, - Controllers::DateTime& dateTimeController) - : musicService(music), bleController {bleController}, - dateTimeController {dateTimeController} { - +Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController, Controllers::DateTime& dateTimeController) + : musicService(music), bleController {bleController}, dateTimeController {dateTimeController} { + lv_obj_t* label; lv_style_init(&btn_style); @@ -177,8 +174,7 @@ void Music::Refresh() { lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - } - else { + } else { lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); @@ -214,7 +210,6 @@ void Music::Refresh() { totalLength = musicService.getTrackLength(); UpdateLength(); } - if (playing) { lv_label_set_text_static(txtPlayPause, Symbols::pause); From 3e18fcb836d941cbb6775f3b0f21c224d061ef4c Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 20:40:19 +0200 Subject: [PATCH 28/32] finally got a formatting extension, so this is hopefully the last formatting commit (ironically one more) --- src/displayapp/screens/Music.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index e0f6a936a3..29a0ef4a4e 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -36,9 +36,7 @@ namespace Pinetime { namespace Screens { class Music : public Screen { public: - Music(Pinetime::Controllers::MusicService& music, - const Controllers::Ble& bleController, - Controllers::DateTime& dateTimeController); + Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& bleController, Controllers::DateTime& dateTimeController); ~Music() override; @@ -108,9 +106,7 @@ namespace Pinetime { static constexpr const char* icon = Screens::Symbols::music; static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::Music(*controllers.musicService, - controllers.bleController, - controllers.dateTimeController); + return new Screens::Music(*controllers.musicService, controllers.bleController, controllers.dateTimeController); }; static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { From 0b3427e00b69e55a2b610d2da514fb2729e8f66d Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 20:55:36 +0200 Subject: [PATCH 29/32] some final spacing optimizations --- src/displayapp/screens/Music.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index efb661346e..776b592d3e 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -106,7 +106,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& // I'm using the txtTrack label as the top anchor for the whole lot // of song, artist, progress bar and duration text (0:00 and -0:00) so // its much easier to move that around and mess with the buttons separately - constexpr int16_t BASE_Y = -45; // -45 for buttons at the top + constexpr int16_t BASE_Y = -40; // -45 for buttons at the top txtTrack = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC); @@ -129,7 +129,7 @@ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& lv_obj_set_style_local_bg_opa(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100); lv_obj_set_style_local_radius(barTrackDuration, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); lv_obj_set_size(barTrackDuration, 240, 10); - lv_obj_align(barTrackDuration, txtArtist, LV_ALIGN_OUT_BOTTOM_MID, 0, 14); + lv_obj_align(barTrackDuration, txtArtist, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); lv_bar_set_range(barTrackDuration, 0, 1000); lv_bar_set_value(barTrackDuration, 0, LV_ANIM_OFF); From b965144ad3ee13535e6cc263232d9a12fd337935 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 21:01:35 +0200 Subject: [PATCH 30/32] remove some more (now) unused lines --- src/displayapp/screens/Music.cpp | 3 --- src/displayapp/screens/Music.h | 10 ---------- 2 files changed, 13 deletions(-) diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 776b592d3e..ce0a83f96d 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -20,9 +20,6 @@ #include #include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" -#include "displayapp/icons/music/disc.c" -#include "displayapp/icons/music/disc_f_1.c" -#include "displayapp/icons/music/disc_f_2.c" #include "displayapp/InfiniTimeTheme.h" #include "components/ble/BleController.h" diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 29a0ef4a4e..4171a83ea3 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -54,12 +54,9 @@ namespace Pinetime { lv_obj_t* btnNext; lv_obj_t* btnVolDown; lv_obj_t* btnVolUp; - // lv_obj_t* btnSwapControls; lv_obj_t* txtArtist; lv_obj_t* txtTrack; lv_obj_t* txtPlayPause; - // lv_obj_t* txtSwapControls; - lv_obj_t* labelTime; lv_obj_t* imgDisc; lv_obj_t* imgDiscAnim; @@ -67,13 +64,8 @@ namespace Pinetime { lv_obj_t* txtCurrentPosition; lv_obj_t* barTrackDuration; - bool showingVolumeControls = false; - lv_style_t btn_style; - /** For the spinning disc animation */ - bool frameB; - Pinetime::Controllers::MusicService& musicService; const Controllers::Ble& bleController; Pinetime::Controllers::DateTime& dateTimeController; @@ -86,8 +78,6 @@ namespace Pinetime { int totalLength = 0; /** Current position in seconds */ int currentPosition; - /** Last time an animation update or timer was incremented */ - TickType_t lastIncrement = 0; bool playing; From a1cef42322e5ac17c057dc9a8c98d6d691dc6ceb Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Mon, 25 Aug 2025 23:29:07 +0200 Subject: [PATCH 31/32] lots of code optimization, mainly to get the reconnection smoother --- .vscode/settings.json | 3 +- src/displayapp/screens/Music.cpp | 77 +++++++++++++++++++------------- src/displayapp/screens/Music.h | 8 ++++ 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index a7b04eea3c..519d4471f9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,6 +65,7 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "span": "cpp" } } diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index ce0a83f96d..176f68af82 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -146,8 +146,6 @@ Music::Music(Pinetime::Controllers::MusicService& music, const Controllers::Ble& lv_obj_set_width(txtTrackDuration, LV_HOR_RES); lv_obj_set_style_local_text_color(txtTrackDuration, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); - frameB = false; - musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); @@ -161,58 +159,73 @@ Music::~Music() { void Music::Refresh() { bleState = bleController.IsConnected(); - bleRadioEnabled = bleController.IsRadioEnabled(); - if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { - if (bleState.Get() == false) { - lv_label_set_text_static(txtArtist, "Disconnected"); - lv_label_set_text_static(txtTrack, ""); - lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); - lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + if (bleState.Get() == false) { + SetDisconnectedUI(); + lastConnected = false; + } else { + if (!lastConnected) { + // just reconnected + musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN); + SetConnectedUI(); + RefreshTrackInfo(true); } else { - lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); - lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + RefreshTrackInfo(false); } + lastConnected = true; } +} - if (artist != musicService.getArtist()) { +void Music::SetDisconnectedUI() { + lv_label_set_text_static(txtArtist, "Disconnected"); + lv_label_set_text_static(txtTrack, ""); + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgDark); + lv_label_set_text_static(txtCurrentPosition, "--:--"); + lv_label_set_text_static(txtTrackDuration, "--:--"); + lv_bar_set_range(barTrackDuration, 0, 1000); + lv_bar_set_value(barTrackDuration, 0, LV_ANIM_OFF); +} + +void Music::SetConnectedUI() { + lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); + lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt); +} + +void Music::RefreshTrackInfo(bool force) { + if (force || playing != musicService.isPlaying()) { + playing = musicService.isPlaying(); + lv_label_set_text_static(txtPlayPause, playing ? Symbols::pause : Symbols::play); + } + + if (force || artist != musicService.getArtist()) { artist = musicService.getArtist(); lv_label_set_text(txtArtist, artist.data()); } - if (track != musicService.getTrack()) { + if (force || track != musicService.getTrack()) { track = musicService.getTrack(); lv_label_set_text(txtTrack, track.data()); } - if (album != musicService.getAlbum()) { + if (force || album != musicService.getAlbum()) { album = musicService.getAlbum(); } - if (playing != musicService.isPlaying()) { - playing = musicService.isPlaying(); - } - - if (currentPosition != musicService.getProgress()) { + if (force || currentPosition != musicService.getProgress()) { currentPosition = musicService.getProgress(); UpdateLength(); } - if (totalLength != musicService.getTrackLength()) { + if (force || totalLength != musicService.getTrackLength()) { totalLength = musicService.getTrackLength(); UpdateLength(); } - - if (playing) { - lv_label_set_text_static(txtPlayPause, Symbols::pause); - } else { - lv_label_set_text_static(txtPlayPause, Symbols::play); - } } void Music::UpdateLength() { diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 4171a83ea3..8d2bbe110e 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -49,6 +49,12 @@ namespace Pinetime { void UpdateLength(); + void RefreshTrackInfo(bool force); + + void SetDisconnectedUI(); + + void SetConnectedUI(); + lv_obj_t* btnPrev; lv_obj_t* btnPlayPause; lv_obj_t* btnNext; @@ -81,6 +87,8 @@ namespace Pinetime { bool playing; + bool lastConnected = false; + lv_task_t* taskRefresh; Utility::DirtyValue bleState {}; From 4d34f706d65efaf2c018462f5cd65d72faacf9c5 Mon Sep 17 00:00:00 2001 From: Titus Kendzorra Date: Sat, 13 Sep 2025 13:48:38 +0200 Subject: [PATCH 32/32] remove unused emoji --- src/displayapp/fonts/fonts.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index f6567f3f6e..fea3160572 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -7,7 +7,7 @@ }, { "file": "FontAwesome5-Solid+Brands+Regular.woff", - "range": "0xf079, 0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" + "range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743, 0xf1ec, 0xf55a" } ], "bpp": 1,