diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp index c99aa1e3..83b26a78 100644 --- a/src/components/ble/MusicService.cpp +++ b/src/components/ble/MusicService.cpp @@ -152,12 +152,20 @@ int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_ albumName = s; } else if (ble_uuid_cmp(ctxt->chr->uuid, &msStatusCharUuid.u) == 0) { playing = s[0]; + // These variables need to be updated, because the progress may not be updated immediately, + // leading to getProgress() returning an incorrect position. + if (playing) { + trackProgressUpdateTime = xTaskGetTickCount(); + } else { + trackProgress += static_cast((static_cast(xTaskGetTickCount() - trackProgressUpdateTime) / 1024.0f) * getPlaybackSpeed()); + } } else if (ble_uuid_cmp(ctxt->chr->uuid, &msRepeatCharUuid.u) == 0) { repeat = s[0]; } else if (ble_uuid_cmp(ctxt->chr->uuid, &msShuffleCharUuid.u) == 0) { shuffle = s[0]; } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPositionCharUuid.u) == 0) { trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + trackProgressUpdateTime = xTaskGetTickCount(); } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTotalLengthCharUuid.u) == 0) { trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackNumberCharUuid.u) == 0) { @@ -191,7 +199,10 @@ float Pinetime::Controllers::MusicService::getPlaybackSpeed() const { return playbackSpeed; } -int Pinetime::Controllers::MusicService::getProgress() const { +int Pinetime::Controllers::MusicService::getProgress() { + if (isPlaying()) { + return trackProgress + static_cast((static_cast(xTaskGetTickCount() - trackProgressUpdateTime) / 1024.0f) * getPlaybackSpeed()); + } return trackProgress; } diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h index 1ad9a420..6c1a6edb 100644 --- a/src/components/ble/MusicService.h +++ b/src/components/ble/MusicService.h @@ -47,7 +47,7 @@ namespace Pinetime { std::string getAlbum() const; - int getProgress() const; + int getProgress(); int getTrackLength() const; @@ -81,6 +81,7 @@ namespace Pinetime { int trackLength {0}; int trackNumber {}; int tracksTotal {}; + TickType_t trackProgressUpdateTime {0}; float playbackSpeed {1.0f}; diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 6c91c1e0..b789224b 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -152,32 +152,27 @@ Music::~Music() { void Music::Refresh() { if (artist != musicService.getArtist()) { artist = musicService.getArtist(); - currentLength = 0; + currentPosition = 0; lv_label_set_text(txtArtist, artist.data()); } if (track != musicService.getTrack()) { track = musicService.getTrack(); - currentLength = 0; + currentPosition = 0; lv_label_set_text(txtTrack, track.data()); } if (album != musicService.getAlbum()) { album = musicService.getAlbum(); - currentLength = 0; + currentPosition = 0; } if (playing != musicService.isPlaying()) { playing = musicService.isPlaying(); } - // Because we increment this ourselves, - // we can't compare with the old data directly - // have to update it when there's actually new data - // just to avoid unnecessary draws that make UI choppy - if (lastLength != musicService.getProgress()) { - currentLength = musicService.getProgress(); - lastLength = currentLength; + if (currentPosition != musicService.getProgress()) { + currentPosition = musicService.getProgress(); UpdateLength(); } @@ -186,7 +181,7 @@ void Music::Refresh() { UpdateLength(); } - if (playing == Pinetime::Controllers::MusicService::MusicStatus::Playing) { + if (playing) { lv_label_set_text_static(txtPlayPause, Symbols::pause); if (xTaskGetTickCount() - 1024 >= lastIncrement) { @@ -197,18 +192,12 @@ void Music::Refresh() { } frameB = !frameB; - if (currentLength < totalLength) { - currentLength += - static_cast((static_cast(xTaskGetTickCount() - lastIncrement) / 1024.0f) * musicService.getPlaybackSpeed()); - } else { + if (currentPosition >= totalLength) { // Let's assume the getTrack finished, paused when the timer ends // and there's no new getTrack being sent to us - // TODO: ideally this would be configurable playing = false; } lastIncrement = xTaskGetTickCount(); - - UpdateLength(); } } else { lv_label_set_text_static(txtPlayPause, Symbols::play); @@ -221,15 +210,15 @@ void Music::UpdateLength() { } else if (totalLength > (99 * 60)) { lv_label_set_text_fmt(txtTrackDuration, "%02d:%02d/%02d:%02d", - (currentLength / (60 * 60)) % 100, - ((currentLength % (60 * 60)) / 60) % 100, + (currentPosition / (60 * 60)) % 100, + ((currentPosition % (60 * 60)) / 60) % 100, (totalLength / (60 * 60)) % 100, ((totalLength % (60 * 60)) / 60) % 100); } else { lv_label_set_text_fmt(txtTrackDuration, "%02d:%02d/%02d:%02d", - (currentLength / 60) % 100, - (currentLength % 60) % 100, + (currentPosition / 60) % 100, + (currentPosition % 60) % 100, (totalLength / 60) % 100, (totalLength % 60) % 100); } diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 27b2d3d2..258a4020 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -70,10 +70,8 @@ namespace Pinetime { /** Total length in seconds */ int totalLength = 0; - /** Current length in seconds */ - int currentLength; - /** Last length */ - int lastLength; + /** Current position in seconds */ + int currentPosition; /** Last time an animation update or timer was incremented */ TickType_t lastIncrement = 0;