diff --git a/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/ExoPlayerPlaybackEngine.kt b/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/ExoPlayerPlaybackEngine.kt index c9cdb020..59736f02 100644 --- a/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/ExoPlayerPlaybackEngine.kt +++ b/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/ExoPlayerPlaybackEngine.kt @@ -460,7 +460,7 @@ internal class ExoPlayerPlaybackEngine( } else { Action.Type.PLAYBACK_STOP } - currentPlaybackSession?.actions?.add( + currentPlaybackSession?.tryAddAction( Action( trueTimeWrapper.currentTimeMillis, positionInSeconds, @@ -594,9 +594,15 @@ internal class ExoPlayerPlaybackEngine( }.toDouble() / MS_IN_SECOND startStall(Stall.Reason.SEEK, stallPositionSeconds, invokedAtMillis) } - currentPlaybackSession?.actions?.apply { - add(Action(invokedAtMillis, oldPositionSeconds, Action.Type.PLAYBACK_STOP)) - add(Action(invokedAtMillis, newPositionSeconds, Action.Type.PLAYBACK_START)) + currentPlaybackSession?.apply { + tryAddAction(Action(invokedAtMillis, oldPositionSeconds, Action.Type.PLAYBACK_STOP)) + tryAddAction( + Action( + invokedAtMillis, + newPositionSeconds, + Action.Type.PLAYBACK_START, + ), + ) } } } @@ -674,7 +680,7 @@ internal class ExoPlayerPlaybackEngine( } else { eventTime.currentPlaybackPositionMs }.toDouble() / MS_IN_SECOND - currentPlaybackSession?.actions?.add( + currentPlaybackSession?.tryAddAction( Action( trueTimeWrapper.currentTimeMillis, positionInSeconds, diff --git a/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/mediasource/streamingsession/PlaybackSession.kt b/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/mediasource/streamingsession/PlaybackSession.kt index 0e78bb06..03b27ac1 100644 --- a/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/mediasource/streamingsession/PlaybackSession.kt +++ b/player/playback-engine/src/main/kotlin/com/tidal/sdk/player/playbackengine/mediasource/streamingsession/PlaybackSession.kt @@ -17,7 +17,7 @@ internal sealed class PlaybackSession { abstract val actualQuality: ProductQuality abstract val sourceType: String? abstract val sourceId: String? - abstract val actions: MutableList + val actions: List = mutableListOf() var startTimestamp = 0L var startAssetPosition by @@ -25,6 +25,17 @@ internal sealed class PlaybackSession { oldValue == START_ASSET_POSITION_UNASSIGNED && newValue >= 0 } + fun tryAddAction(action: Action) { + if (actions.lastOrNull()?.actionType == action.actionType) { + /** + * PlayLog-wise, we can't start while started or stop while stopped. However, + * ExoPlayer-wise, it can happen for example when a discontinuity occurs while paused. + */ + return + } + (actions as MutableList).add(action) + } + @Suppress("LongParameterList") class Audio( override val playbackSessionId: UUID, @@ -35,10 +46,7 @@ internal sealed class PlaybackSession { override val actualQuality: AudioQuality, override val sourceType: String?, override val sourceId: String?, - ) : PlaybackSession() { - - override val actions = mutableListOf() - } + ) : PlaybackSession() @Suppress("LongParameterList") class Video( @@ -49,10 +57,7 @@ internal sealed class PlaybackSession { override val actualQuality: VideoQuality, override val sourceType: String?, override val sourceId: String?, - ) : PlaybackSession() { - - override val actions = mutableListOf() - } + ) : PlaybackSession() class Broadcast( override val playbackSessionId: UUID, @@ -61,10 +66,7 @@ internal sealed class PlaybackSession { override val actualQuality: AudioQuality, override val sourceType: String?, override val sourceId: String?, - ) : PlaybackSession() { - - override val actions = mutableListOf() - } + ) : PlaybackSession() @Suppress("LongParameterList") class UC( @@ -76,7 +78,6 @@ internal sealed class PlaybackSession { ) : PlaybackSession() { override val actualQuality = AudioQuality.LOW - override val actions = mutableListOf() } companion object {