Update track progress in MusicService. Fix #127

This commit is contained in:
Riku Isokoski 2022-03-28 17:00:23 +03:00
parent f82aa71eb0
commit 34858d0a6c
4 changed files with 27 additions and 28 deletions

View file

@ -152,12 +152,20 @@ int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_
albumName = s; albumName = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, &msStatusCharUuid.u) == 0) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msStatusCharUuid.u) == 0) {
playing = s[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<int>((static_cast<float>(xTaskGetTickCount() - trackProgressUpdateTime) / 1024.0f) * getPlaybackSpeed());
}
} else if (ble_uuid_cmp(ctxt->chr->uuid, &msRepeatCharUuid.u) == 0) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msRepeatCharUuid.u) == 0) {
repeat = s[0]; repeat = s[0];
} else if (ble_uuid_cmp(ctxt->chr->uuid, &msShuffleCharUuid.u) == 0) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msShuffleCharUuid.u) == 0) {
shuffle = s[0]; shuffle = s[0];
} else if (ble_uuid_cmp(ctxt->chr->uuid, &msPositionCharUuid.u) == 0) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPositionCharUuid.u) == 0) {
trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; 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) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTotalLengthCharUuid.u) == 0) {
trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
} else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackNumberCharUuid.u) == 0) { } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackNumberCharUuid.u) == 0) {
@ -191,7 +199,10 @@ float Pinetime::Controllers::MusicService::getPlaybackSpeed() const {
return playbackSpeed; return playbackSpeed;
} }
int Pinetime::Controllers::MusicService::getProgress() const { int Pinetime::Controllers::MusicService::getProgress() {
if (isPlaying()) {
return trackProgress + static_cast<int>((static_cast<float>(xTaskGetTickCount() - trackProgressUpdateTime) / 1024.0f) * getPlaybackSpeed());
}
return trackProgress; return trackProgress;
} }

View file

@ -47,7 +47,7 @@ namespace Pinetime {
std::string getAlbum() const; std::string getAlbum() const;
int getProgress() const; int getProgress();
int getTrackLength() const; int getTrackLength() const;
@ -81,6 +81,7 @@ namespace Pinetime {
int trackLength {0}; int trackLength {0};
int trackNumber {}; int trackNumber {};
int tracksTotal {}; int tracksTotal {};
TickType_t trackProgressUpdateTime {0};
float playbackSpeed {1.0f}; float playbackSpeed {1.0f};

View file

@ -152,32 +152,27 @@ Music::~Music() {
void Music::Refresh() { void Music::Refresh() {
if (artist != musicService.getArtist()) { if (artist != musicService.getArtist()) {
artist = musicService.getArtist(); artist = musicService.getArtist();
currentLength = 0; currentPosition = 0;
lv_label_set_text(txtArtist, artist.data()); lv_label_set_text(txtArtist, artist.data());
} }
if (track != musicService.getTrack()) { if (track != musicService.getTrack()) {
track = musicService.getTrack(); track = musicService.getTrack();
currentLength = 0; currentPosition = 0;
lv_label_set_text(txtTrack, track.data()); lv_label_set_text(txtTrack, track.data());
} }
if (album != musicService.getAlbum()) { if (album != musicService.getAlbum()) {
album = musicService.getAlbum(); album = musicService.getAlbum();
currentLength = 0; currentPosition = 0;
} }
if (playing != musicService.isPlaying()) { if (playing != musicService.isPlaying()) {
playing = musicService.isPlaying(); playing = musicService.isPlaying();
} }
// Because we increment this ourselves, if (currentPosition != musicService.getProgress()) {
// we can't compare with the old data directly currentPosition = musicService.getProgress();
// 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;
UpdateLength(); UpdateLength();
} }
@ -186,7 +181,7 @@ void Music::Refresh() {
UpdateLength(); UpdateLength();
} }
if (playing == Pinetime::Controllers::MusicService::MusicStatus::Playing) { if (playing) {
lv_label_set_text_static(txtPlayPause, Symbols::pause); lv_label_set_text_static(txtPlayPause, Symbols::pause);
if (xTaskGetTickCount() - 1024 >= lastIncrement) { if (xTaskGetTickCount() - 1024 >= lastIncrement) {
@ -197,18 +192,12 @@ void Music::Refresh() {
} }
frameB = !frameB; frameB = !frameB;
if (currentLength < totalLength) { if (currentPosition >= totalLength) {
currentLength +=
static_cast<int>((static_cast<float>(xTaskGetTickCount() - lastIncrement) / 1024.0f) * musicService.getPlaybackSpeed());
} else {
// Let's assume the getTrack finished, paused when the timer ends // Let's assume the getTrack finished, paused when the timer ends
// and there's no new getTrack being sent to us // and there's no new getTrack being sent to us
// TODO: ideally this would be configurable
playing = false; playing = false;
} }
lastIncrement = xTaskGetTickCount(); lastIncrement = xTaskGetTickCount();
UpdateLength();
} }
} else { } else {
lv_label_set_text_static(txtPlayPause, Symbols::play); lv_label_set_text_static(txtPlayPause, Symbols::play);
@ -221,15 +210,15 @@ void Music::UpdateLength() {
} else if (totalLength > (99 * 60)) { } else if (totalLength > (99 * 60)) {
lv_label_set_text_fmt(txtTrackDuration, lv_label_set_text_fmt(txtTrackDuration,
"%02d:%02d/%02d:%02d", "%02d:%02d/%02d:%02d",
(currentLength / (60 * 60)) % 100, (currentPosition / (60 * 60)) % 100,
((currentLength % (60 * 60)) / 60) % 100, ((currentPosition % (60 * 60)) / 60) % 100,
(totalLength / (60 * 60)) % 100, (totalLength / (60 * 60)) % 100,
((totalLength % (60 * 60)) / 60) % 100); ((totalLength % (60 * 60)) / 60) % 100);
} else { } else {
lv_label_set_text_fmt(txtTrackDuration, lv_label_set_text_fmt(txtTrackDuration,
"%02d:%02d/%02d:%02d", "%02d:%02d/%02d:%02d",
(currentLength / 60) % 100, (currentPosition / 60) % 100,
(currentLength % 60) % 100, (currentPosition % 60) % 100,
(totalLength / 60) % 100, (totalLength / 60) % 100,
(totalLength % 60) % 100); (totalLength % 60) % 100);
} }

View file

@ -70,10 +70,8 @@ namespace Pinetime {
/** Total length in seconds */ /** Total length in seconds */
int totalLength = 0; int totalLength = 0;
/** Current length in seconds */ /** Current position in seconds */
int currentLength; int currentPosition;
/** Last length */
int lastLength;
/** Last time an animation update or timer was incremented */ /** Last time an animation update or timer was incremented */
TickType_t lastIncrement = 0; TickType_t lastIncrement = 0;