From f6269a2f7abd35eed39651359c781986cb7dfb1a Mon Sep 17 00:00:00 2001 From: philippe44 Date: Mon, 30 Oct 2023 01:06:37 -0700 Subject: [PATCH] gap when changing queue workaround --- .../spotify/cspot/include/TrackPlayer.h | 1 - components/spotify/cspot/include/TrackQueue.h | 3 +- components/spotify/cspot/src/SpircHandler.cpp | 14 ++++++---- components/spotify/cspot/src/TrackPlayer.cpp | 2 ++ components/spotify/cspot/src/TrackQueue.cpp | 28 +++++++++++++++---- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/components/spotify/cspot/include/TrackPlayer.h b/components/spotify/cspot/include/TrackPlayer.h index 31f98939..1577c476 100644 --- a/components/spotify/cspot/include/TrackPlayer.h +++ b/components/spotify/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/components/spotify/cspot/include/TrackQueue.h b/components/spotify/cspot/include/TrackQueue.h index 174d51af..60c1d318 100644 --- a/components/spotify/cspot/include/TrackQueue.h +++ b/components/spotify/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/components/spotify/cspot/src/SpircHandler.cpp b/components/spotify/cspot/src/SpircHandler.cpp index 8f225b76..92531a64 100644 --- a/components/spotify/cspot/src/SpircHandler.cpp +++ b/components/spotify/cspot/src/SpircHandler.cpp @@ -205,16 +205,18 @@ void SpircHandler::handleFrame(std::vector& data) { 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, - false); + ctx->timeProvider->getSyncedTimestamp() - + playbackState->innerFrame.state.position_measured_at); 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/components/spotify/cspot/src/TrackPlayer.cpp b/components/spotify/cspot/src/TrackPlayer.cpp index a252b3cb..c96f2ec7 100644 --- a/components/spotify/cspot/src/TrackPlayer.cpp +++ b/components/spotify/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/components/spotify/cspot/src/TrackQueue.cpp b/components/spotify/cspot/src/TrackQueue.cpp index b859539f..5c416bbe 100644 --- a/components/spotify/cspot/src/TrackQueue.cpp +++ b/components/spotify/cspot/src/TrackQueue.cpp @@ -587,8 +587,9 @@ 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; if (initial) { // Clear preloaded tracks @@ -609,13 +610,28 @@ void TrackQueue::updateTracks(uint32_t requestedPosition, bool initial) { playableSemaphore->give(); } else { - // Clear preloaded tracks - preloadedTracks.clear(); - // Copy requested track list currentTracks = playbackState->remoteTracks; - // Push a song on the preloaded queue - queueNextTrack(0, requestedPosition); + // try to not re-load track if we are still loading it + if (preloadedTracks[0]->loading) { + // 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"); + queueNextTrack(1); + + cleared = false; + } else { + // Clear preloaded tracks + preloadedTracks.clear(); + + // Push a song on the preloaded queue + CSPOT_LOG(info, "Re-loading current track"); + queueNextTrack(0, requestedPosition); + } } + + return cleared; }