Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c73f016
Merge pull request #26 from InfiniTimeOrg/main
tituscmd Jan 21, 2025
3a79fc6
music app redesign
tituscmd May 11, 2025
bf83698
Merge branch 'InfiniTimeOrg:main' into music_redesign
tituscmd May 11, 2025
5ccbaad
removed an empty line
tituscmd May 11, 2025
c85e99c
Merge branch 'music_redesign' of github.com:tituscmd/InfiniTime into …
tituscmd May 11, 2025
e97cb58
Some tweaks for the default texts, as well as adding a different appr…
tituscmd May 12, 2025
db1a0ad
formatting
tituscmd May 12, 2025
e633015
more formatting
tituscmd May 12, 2025
441399e
Merge branch 'main' into music_redesign
tituscmd May 14, 2025
ee276b5
revert back to swiping as a gesture to switch between skip and volume…
tituscmd May 14, 2025
43aa932
remove all unneccessary references to the motor controller
tituscmd May 14, 2025
29cc0eb
formatting
tituscmd May 14, 2025
ba976b6
Merge branch 'main' into music_redesign
tituscmd May 16, 2025
18894a6
removed accidental change
tituscmd May 30, 2025
6b1e277
Merge branch 'music_redesign' of github.com:tituscmd/InfiniTime into …
tituscmd May 30, 2025
012fa8d
Merge branch 'main' into music_redesign
tituscmd May 30, 2025
1ad75d0
Merge branch 'main' into music_redesign
tituscmd Jun 1, 2025
cbc9625
correct color of the buttons
tituscmd Jun 6, 2025
e44aac1
remove redundant initialisers for trackName and albumName
tituscmd Jun 12, 2025
f76c9d4
Merge branch 'main' into music_redesign
tituscmd Jun 12, 2025
73f991d
Merge branch 'main' into music_redesign
tituscmd Jun 28, 2025
628fd16
Merge branch 'main' into music_redesign
tituscmd Jun 29, 2025
ef74a00
add progress bar
tituscmd Jul 26, 2025
fcea150
Update settings.json
tituscmd Jul 26, 2025
8eb080e
Merge branch 'main' into music_redesign_2
tituscmd Jul 26, 2025
052dad2
formatting
tituscmd Jul 28, 2025
b691fe3
Merge branch 'music_redesign_2' of github.com:tituscmd/InfiniTime int…
tituscmd Jul 28, 2025
65ae129
formatting
tituscmd Jul 28, 2025
ed30e53
more formatting
tituscmd Jul 28, 2025
c634bf2
different design for music.cpp
tituscmd Aug 6, 2025
b27c4f2
renaming to camelCase, time top center, some visual tweaks
tituscmd Aug 11, 2025
afe65d6
tweak code for much easier alignment testing
tituscmd Aug 18, 2025
d87126a
tweak code for much easier alignment testing
tituscmd Aug 18, 2025
d11a71b
change controls button
tituscmd Aug 18, 2025
8d036ee
tweaks to the new swap controls button
tituscmd Aug 18, 2025
4ed2d18
Different version of the music app, where all buttons are on one screen
tituscmd Aug 22, 2025
e02a795
another UI iteration, my favorite (volume buttons above track buttons)
tituscmd Aug 22, 2025
e2514b0
version with buttons up top
tituscmd Aug 23, 2025
1f902b1
clean up code
tituscmd Aug 25, 2025
2201ee8
finally got a formatting extension, so this is hopefully the last for…
tituscmd Aug 25, 2025
3e18fcb
finally got a formatting extension, so this is hopefully the last for…
tituscmd Aug 25, 2025
0b3427e
some final spacing optimizations
tituscmd Aug 25, 2025
b965144
remove some more (now) unused lines
tituscmd Aug 25, 2025
a1cef42
lots of code optimization, mainly to get the reconnection smoother
tituscmd Aug 25, 2025
4d34f70
remove unused emoji
tituscmd Sep 13, 2025
9483662
Merge branch 'main' into music_redesign_2
tituscmd Sep 13, 2025
6fcf5e0
Merge branch 'main' into music_redesign_2
tituscmd Sep 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
"typeinfo": "cpp",
"span": "cpp"
}
}
208 changes: 109 additions & 99 deletions src/displayapp/screens/Music.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
#include <cstdint>
#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"

using namespace Pinetime::Applications::Screens;

Expand All @@ -48,7 +46,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, const Controllers::Ble& bleController, Controllers::DateTime& dateTimeController)
: musicService(music), bleController {bleController}, dateTimeController {dateTimeController} {

lv_obj_t* label;

lv_style_init(&btn_style);
Expand All @@ -58,22 +58,20 @@ Music::Music(Pinetime::Controllers::MusicService& music) : 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_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
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);
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_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
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);
lv_obj_set_hidden(btnVolUp, true);

btnPrev = lv_btn_create(lv_scr_act(), nullptr);
btnPrev->user_data = this;
Expand Down Expand Up @@ -102,41 +100,51 @@ 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_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID);
lv_obj_set_width(txtArtist, LV_HOR_RES - 12);
lv_label_set_text_static(txtArtist, "");
lv_obj_set_style_local_text_color(txtArtist, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);
// 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 = -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);
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, BASE_Y);
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, "");

/** 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);
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);
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);

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);
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, txtArtist, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
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, 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);
lv_obj_set_style_local_text_color(txtCurrentPosition, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray);

frameB = false;
txtTrackDuration = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_long_mode(txtTrackDuration, LV_LABEL_LONG_SROLL);
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);

musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN);

Expand All @@ -150,74 +158,94 @@ Music::~Music() {
}

void Music::Refresh() {
if (artist != musicService.getArtist()) {
bleState = bleController.IsConnected();
if (bleState.Get() == false) {
SetDisconnectedUI();
lastConnected = false;
} else {
if (!lastConnected) {
// just reconnected
musicService.event(Controllers::MusicService::EVENT_MUSIC_OPEN);
SetConnectedUI();
RefreshTrackInfo(true);
} else {
RefreshTrackInfo(false);
}
lastConnected = true;
}
}

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);
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);
}
}

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",
(currentPosition / (60 * 60)) % 100,
((currentPosition % (60 * 60)) / 60) % 100,
(totalLength / (60 * 60)) % 100,
((totalLength % (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(txtTrackDuration,
"%02d:%02d/%02d:%02d",
(currentPosition / 60) % 100,
(currentPosition % 60) % 100,
(totalLength / 60) % 100,
(totalLength % 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 > 0 ? totalLength : 1);
lv_bar_set_value(barTrackDuration, currentPosition, LV_ANIM_OFF);
}
}

Expand Down Expand Up @@ -250,24 +278,6 @@ 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);

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;
Expand Down
26 changes: 19 additions & 7 deletions src/displayapp/screens/Music.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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, Controllers::DateTime& dateTimeController);

~Music() override;

Expand All @@ -47,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;
Expand All @@ -59,13 +67,14 @@ namespace Pinetime {
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;
const Controllers::Ble& bleController;
Pinetime::Controllers::DateTime& dateTimeController;

std::string artist;
std::string album;
Expand All @@ -75,13 +84,16 @@ 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;

bool lastConnected = false;

lv_task_t* taskRefresh;

Utility::DirtyValue<bool> bleState {};
Utility::DirtyValue<bool> bleRadioEnabled {};

/** Watchapp */
};
}
Expand All @@ -92,7 +104,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.bleController, controllers.dateTimeController);
};

static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
Expand Down
1 change: 1 addition & 0 deletions src/displayapp/screens/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,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";
Expand Down