@@ -8,12 +8,19 @@ import androidx.media3.exoplayer.ExoPlayer
88import androidx.media3.exoplayer.source.ShuffleOrder.DefaultShuffleOrder
99import com.simplemobiletools.musicplayer.extensions.*
1010import com.simplemobiletools.musicplayer.inlines.indexOfFirstOrNull
11+ import kotlinx.coroutines.*
1112
1213private const val DEFAULT_SHUFFLE_ORDER_SEED = 42L
1314
1415@UnstableApi
1516class SimpleMusicPlayer (private val exoPlayer : ExoPlayer ) : ForwardingPlayer(exoPlayer) {
1617
18+ private var seekToNextCount = 0
19+ private var seekToPreviousCount = 0
20+
21+ private val scope = CoroutineScope (Dispatchers .Default )
22+ private var seekJob: Job ? = null
23+
1724 /* *
1825 * The default implementation only advertises the seek to next and previous item in the case
1926 * that it's not the first or last track. We manually advertise that these
@@ -53,28 +60,32 @@ class SimpleMusicPlayer(private val exoPlayer: ExoPlayer) : ForwardingPlayer(exo
5360 override fun seekToNext () {
5461 play()
5562 if (! maybeForceNext()) {
56- super .seekToNext()
63+ seekToNextCount + = 1
64+ seekWithDelay()
5765 }
5866 }
5967
6068 override fun seekToPrevious () {
6169 play()
6270 if (! maybeForcePrevious()) {
63- super .seekToPrevious()
71+ seekToPreviousCount + = 1
72+ seekWithDelay()
6473 }
6574 }
6675
6776 override fun seekToNextMediaItem () {
6877 play()
6978 if (! maybeForceNext()) {
70- super .seekToNextMediaItem()
79+ seekToNextCount + = 1
80+ seekWithDelay()
7181 }
7282 }
7383
7484 override fun seekToPreviousMediaItem () {
7585 play()
7686 if (! maybeForcePrevious()) {
77- super .seekToPreviousMediaItem()
87+ seekToPreviousCount + = 1
88+ seekWithDelay()
7889 }
7990 }
8091
@@ -122,4 +133,36 @@ class SimpleMusicPlayer(private val exoPlayer: ExoPlayer) : ForwardingPlayer(exo
122133 exoPlayer.setShuffleOrder(DefaultShuffleOrder (shuffledIndices.toIntArray(), DEFAULT_SHUFFLE_ORDER_SEED ))
123134 }
124135 }
136+
137+ /* *
138+ * This is here so the player can quickly seek next/previous without doing too much work.
139+ * It probably won't be needed once https://github.com/androidx/media/issues/81 is resolved.
140+ */
141+ private fun seekWithDelay () {
142+ seekJob?.cancel()
143+ seekJob = scope.launch {
144+ delay(timeMillis = 400 )
145+ if (seekToNextCount > 0 || seekToPreviousCount > 0 ) {
146+ runOnPlayerThread {
147+ if (currentMediaItem != null ) {
148+ if (seekToNextCount > 0 ) {
149+ seekTo(rotateIndex(currentMediaItemIndex + seekToNextCount), 0 )
150+ }
151+
152+ if (seekToPreviousCount > 0 ) {
153+ seekTo(rotateIndex(currentMediaItemIndex - seekToPreviousCount), 0 )
154+ }
155+
156+ seekToNextCount = 0
157+ seekToPreviousCount = 0
158+ }
159+ }
160+ }
161+ }
162+ }
163+
164+ private fun rotateIndex (index : Int ): Int {
165+ val count = mediaItemCount
166+ return (index % count + count) % count
167+ }
125168}
0 commit comments