From 7e3930d247902921c0ba2ee42d8dc847b7908733 Mon Sep 17 00:00:00 2001 From: philippe44 Date: Mon, 20 Nov 2023 12:40:26 -0800 Subject: [PATCH] do not reload track when changing queue (if possible) (#164) * do not reload track when changing queue (if possible) * simpler solution * replace frame of further tracks * buffer rollback * feat: Update bell, fix formatting --------- Co-authored-by: Filip Grzywok --- cspot/bell | 2 +- cspot/include/TrackPlayer.h | 1 - cspot/include/TrackQueue.h | 3 ++- cspot/src/SpircHandler.cpp | 12 ++++++++---- cspot/src/TrackPlayer.cpp | 2 ++ cspot/src/TrackQueue.cpp | 29 ++++++++++++++++++++--------- targets/cli/CliPlayer.cpp | 4 ++++ 7 files changed, 37 insertions(+), 16 deletions(-) diff --git a/cspot/bell b/cspot/bell index 51d57213..33612f42 160000 --- a/cspot/bell +++ b/cspot/bell @@ -1 +1 @@ -Subproject commit 51d572132dc5b8b521c39987fc34b1915d4126aa +Subproject commit 33612f425489c552a71fddb175581049e4a75af1 diff --git a/cspot/include/TrackPlayer.h b/cspot/include/TrackPlayer.h index 31f98939..1577c476 100644 --- a/cspot/include/TrackPlayer.h +++ b/cspot/include/TrackPlayer.h @@ -37,7 +37,6 @@ class TrackPlayer : bell::Task { typedef std::function DataCallback; typedef std::function EOFCallback; - typedef std::function isAiringCallback; TrackPlayer(std::shared_ptr ctx, std::shared_ptr trackQueue, diff --git a/cspot/include/TrackQueue.h b/cspot/include/TrackQueue.h index 174d51af..60c1d318 100644 --- a/cspot/include/TrackQueue.h +++ b/cspot/include/TrackQueue.h @@ -54,6 +54,7 @@ class QueuedTrack { uint32_t requestedPosition; std::string identifier; + bool loading = false; // Will return nullptr if the track is not ready std::shared_ptr getAudioFile(); @@ -100,7 +101,7 @@ class TrackQueue : public bell::Task { bool hasTracks(); bool isFinished(); bool skipTrack(SkipDirection dir, bool expectNotify = true); - void updateTracks(uint32_t requestedPosition = 0, bool initial = false); + bool updateTracks(uint32_t requestedPosition = 0, bool initial = false); TrackInfo getTrackInfo(std::string_view identifier); std::shared_ptr consumeTrack( std::shared_ptr prevSong, int& offset); diff --git a/cspot/src/SpircHandler.cpp b/cspot/src/SpircHandler.cpp index 8f225b76..8d8add6a 100644 --- a/cspot/src/SpircHandler.cpp +++ b/cspot/src/SpircHandler.cpp @@ -201,11 +201,12 @@ void SpircHandler::handleFrame(std::vector& data) { break; } case MessageType_kMessageTypeReplace: { - CSPOT_LOG(debug, "Got replace frame"); + CSPOT_LOG(debug, "Got replace frame %d", + playbackState->remoteTracks.size()); playbackState->syncWithRemote(); // 1st track is the current one, but update the position - trackQueue->updateTracks( + bool cleared = trackQueue->updateTracks( playbackState->remoteFrame.state.position_ms + ctx->timeProvider->getSyncedTimestamp() - playbackState->innerFrame.state.position_measured_at, @@ -213,8 +214,11 @@ void SpircHandler::handleFrame(std::vector& data) { this->notify(); - sendEvent(EventType::FLUSH); - trackPlayer->resetState(); + // need to re-load all if streaming track is completed + if (cleared) { + sendEvent(EventType::FLUSH); + trackPlayer->resetState(); + } break; } case MessageType_kMessageTypeShuffle: { diff --git a/cspot/src/TrackPlayer.cpp b/cspot/src/TrackPlayer.cpp index a252b3cb..c96f2ec7 100644 --- a/cspot/src/TrackPlayer.cpp +++ b/cspot/src/TrackPlayer.cpp @@ -201,6 +201,7 @@ void TrackPlayer::runTask() { } eof = false; + track->loading = true; CSPOT_LOG(info, "Playing"); @@ -255,6 +256,7 @@ void TrackPlayer::runTask() { // always move back to LOADING (ensure proper seeking after last track has been loaded) currentTrackStream = nullptr; + track->loading = false; } if (eof) { diff --git a/cspot/src/TrackQueue.cpp b/cspot/src/TrackQueue.cpp index b859539f..f2860387 100644 --- a/cspot/src/TrackQueue.cpp +++ b/cspot/src/TrackQueue.cpp @@ -587,18 +587,18 @@ bool TrackQueue::isFinished() { return currentTracksIndex >= currentTracks.size() - 1; } -void TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { +bool TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { std::scoped_lock lock(tracksMutex); + bool cleared = true; + + // Copy requested track list + currentTracks = playbackState->remoteTracks; + currentTracksIndex = playbackState->innerFrame.state.playing_track_index; if (initial) { // Clear preloaded tracks preloadedTracks.clear(); - // Copy requested track list - currentTracks = playbackState->remoteTracks; - - currentTracksIndex = playbackState->innerFrame.state.playing_track_index; - if (currentTracksIndex < currentTracks.size()) { // Push a song on the preloaded queue queueNextTrack(0, requestedPosition); @@ -608,14 +608,25 @@ void TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { notifyPending = true; playableSemaphore->give(); + } else if (preloadedTracks[0]->loading) { + // try to not re-load track if we are still loading it + + // remove everything except first track + preloadedTracks.erase(preloadedTracks.begin() + 1, preloadedTracks.end()); + + // Push a song on the preloaded queue + CSPOT_LOG(info, "Keeping current track %d", currentTracksIndex); + queueNextTrack(1); + + cleared = false; } else { // Clear preloaded tracks preloadedTracks.clear(); - // Copy requested track list - currentTracks = playbackState->remoteTracks; - // Push a song on the preloaded queue + CSPOT_LOG(info, "Re-loading current track"); queueNextTrack(0, requestedPosition); } + + return cleared; } diff --git a/targets/cli/CliPlayer.cpp b/targets/cli/CliPlayer.cpp index 4c3ddd99..1642c4ec 100644 --- a/targets/cli/CliPlayer.cpp +++ b/targets/cli/CliPlayer.cpp @@ -72,6 +72,10 @@ CliPlayer::CliPlayer(std::unique_ptr sink, case cspot::SpircHandler::EventType::DEPLETED: this->playlistEnd = true; break; + case cspot::SpircHandler::EventType::VOLUME: { + int volume = std::get(event->data); + break; + } default: break; }