@@ -22,11 +22,11 @@ import com.lasthopesoftware.bluewater.client.playback.nowplaying.storage.ManageN
2222import com.lasthopesoftware.bluewater.client.playback.nowplaying.storage.NowPlaying
2323import com.lasthopesoftware.bluewater.client.playback.playlist.ManagePlaylistPlayback
2424import com.lasthopesoftware.bluewater.shared.lazyLogger
25- import com.lasthopesoftware.policies.ratelimiting.PromisingRateLimiter
2625import com.lasthopesoftware.promises.ContinuingResult
2726import com.lasthopesoftware.promises.extensions.ProgressingPromise
2827import com.lasthopesoftware.promises.extensions.keepPromise
2928import com.lasthopesoftware.promises.extensions.onEachEventually
29+ import com.lasthopesoftware.promises.extensions.regardless
3030import com.lasthopesoftware.promises.extensions.toPromise
3131import com.lasthopesoftware.promises.extensions.unitResponse
3232import com.namehillsoftware.handoff.errors.RejectionDropper
@@ -69,7 +69,10 @@ class PlaybackEngine(
6969
7070 private val activeLibraryId = AtomicReference (markerLibraryId)
7171
72- private val nowPlayingStateSync = PromisingRateLimiter <NowPlaying ?>(1 )
72+ private val promisedNowPlayingStateSync = Any ()
73+
74+ @Volatile
75+ private var promisedNowPlayingState = Promise .empty<NowPlaying ?>()
7376
7477 private val promisedPlayback = AtomicReference <ProgressingPromise <PositionedPlayingFile , Unit >? > (null )
7578
@@ -480,13 +483,9 @@ class PlaybackEngine(
480483 return playlistPlayback.resume()
481484 }
482485
483- private fun serializedPlayerUpdate () = nowPlayingStateSync.limit {
484- playbackBootstrapper.updateFromState(activeLibraryId.get())
485- }
486+ private fun serializedPlayerUpdate () = updateStateSynchronously { playbackBootstrapper.updateFromState(activeLibraryId.get()) }
486487
487- private fun promiseActiveNowPlaying () = nowPlayingStateSync.limit {
488- nowPlayingRepository.promiseNowPlaying(activeLibraryId.get())
489- }
488+ private fun promiseActiveNowPlaying () = updateStateSynchronously { nowPlayingRepository.promiseNowPlaying(activeLibraryId.get()) }
490489
491490 private fun saveState (
492491 libraryId : LibraryId ,
@@ -508,7 +507,7 @@ class PlaybackEngine(
508507 private inline fun saveState (
509508 libraryId : LibraryId ,
510509 crossinline updateFunc : NowPlaying .() -> NowPlaying
511- ): Promise <NowPlaying ?> = nowPlayingStateSync.limit {
510+ ): Promise <NowPlaying ?> = updateStateSynchronously {
512511 nowPlayingRepository.promiseNowPlaying(libraryId).eventually {
513512 it?.let { np ->
514513 val updatedNowPlaying = updateFunc(np)
@@ -519,7 +518,25 @@ class PlaybackEngine(
519518 }
520519
521520 @Suppress(" UNCHECKED_CAST" )
522- private fun saveState (nowPlaying : NowPlaying ): Promise <NowPlaying ?> = nowPlayingStateSync.limit {
521+ private fun saveState (nowPlaying : NowPlaying ): Promise <NowPlaying ?> = updateStateSynchronously {
523522 nowPlayingRepository.updateNowPlaying(nowPlaying) as Promise <NowPlaying ?>
524523 }
524+
525+ /* *
526+ * Updates the `promisedNowPlayingState` with the result of the provided `updateFunc`.
527+ *
528+ * This function ensures that the `promisedNowPlayingState` is updated synchronously.
529+ * Each new update is chained to the previous promise, guaranteeing that state
530+ * updates are applied in the order they are initiated.
531+ *
532+ * @param updateFunc A function that returns a [Promise] for a nullable [NowPlaying] state.
533+ * This function is responsible for fetching or modifying the state.
534+ * @return A [Promise] that resolves with the current [NowPlaying] state after the update
535+ * function has been scheduled. To wait for the update to complete, chain to the returned promise.
536+ */
537+ private inline fun updateStateSynchronously (crossinline updateFunc : () -> Promise <NowPlaying ?>): Promise <NowPlaying ?> = synchronized(promisedNowPlayingStateSync) {
538+ promisedNowPlayingState
539+ .regardless { updateFunc() }
540+ .also { promisedNowPlayingState = it }
541+ }
525542}
0 commit comments