Skip to content

Commit 8baa1f4

Browse files
committed
recycle random seed when seamlessly setting media items without shuffle order
1 parent 71cb685 commit 8baa1f4

2 files changed

Lines changed: 35 additions & 32 deletions

File tree

app/src/main/java/org/akanework/gramophone/logic/utils/GramophoneShuffleOrder.kt

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import kotlin.random.Random
3232
class CircularShuffleOrder private constructor(
3333
private val listener: EndedWorkaroundPlayer,
3434
private val shuffled: IntArray,
35-
private val random: Random
35+
private val seed: Long,
36+
private val random: Random,
37+
val lastSeed: Long?
3638
) : ShuffleOrder {
3739
private val indexInShuffled = IntArray(shuffled.size)
3840

@@ -65,32 +67,36 @@ class CircularShuffleOrder private constructor(
6567
}
6668
}
6769

68-
constructor(
69-
listener: EndedWorkaroundPlayer,
70-
firstIndex: Int,
71-
length: Int,
72-
randomSeed: Long
73-
) :
74-
this(listener, firstIndex, length, Random(randomSeed))
75-
7670
private constructor(
7771
listener: EndedWorkaroundPlayer,
7872
firstIndex: Int,
7973
length: Int,
80-
random: Random
74+
seed: Long,
75+
random: Random,
76+
lastSeed: Long?
8177
) :
8278
this(
8379
listener,
8480
calculateListWithFirstIndex(calculateShuffledList(0, length, random), firstIndex),
85-
random
81+
seed, random, lastSeed
8682
)
8783

84+
constructor(
85+
listener: EndedWorkaroundPlayer,
86+
firstIndex: Int,
87+
length: Int,
88+
randomSeed: Long,
89+
lastSeed: Long? = null
90+
) :
91+
this(listener, firstIndex, length, randomSeed, Random(randomSeed), lastSeed)
92+
8893
constructor(
8994
listener: EndedWorkaroundPlayer,
9095
shuffledIndices: IntArray,
91-
randomSeed: Long
96+
randomSeed: Long,
97+
lastSeed: Long?
9298
) :
93-
this(listener, shuffledIndices.copyOf(), Random(randomSeed))
99+
this(listener, shuffledIndices.copyOf(), randomSeed, Random(randomSeed), lastSeed)
94100

95101
override fun getLength(): Int {
96102
return shuffled.size
@@ -119,9 +125,10 @@ class CircularShuffleOrder private constructor(
119125
// B,C,D will be shuffled among themselves to ie D,B,C and then this list will be inserted after
120126
// A so that song list will now be A,D,B,C,...
121127
override fun cloneAndInsert(insertionIndex: Int, insertionCount: Int): ShuffleOrder {
122-
listener.nextShuffleOrder?.let { factory ->
128+
listener.nextShuffleOrder?.let { next ->
123129
listener.nextShuffleOrder = null
124-
val nextShuffleOrder = factory(insertionIndex, shuffled.size + insertionCount, listener)
130+
val nextShuffleOrder = next.create(insertionIndex,
131+
shuffled.size + insertionCount, listener)
125132
if (nextShuffleOrder.length == shuffled.size + insertionCount)
126133
return nextShuffleOrder
127134
// We can't throw here as it would permanently break the ExoPlayer and cause app crash
@@ -155,7 +162,7 @@ class CircularShuffleOrder private constructor(
155162
}
156163
}
157164

158-
return CircularShuffleOrder(listener, newShuffled, Random(random.nextLong()))
165+
return CircularShuffleOrder(listener, newShuffled, random.nextLong(), seed)
159166
}
160167

161168
override fun cloneAndSet(insertionCount: Int, startIndex: Int): ShuffleOrder {
@@ -174,7 +181,7 @@ class CircularShuffleOrder private constructor(
174181
val numberOfElementsToRemove = indexToExclusive - indexFrom
175182
// short-circuit for performance and because this is allowed if nextShuffleOrder is set
176183
if (numberOfElementsToRemove == shuffled.size)
177-
return CircularShuffleOrder(listener, 0, 0, Random(random.nextLong()))
184+
return CircularShuffleOrder(listener, 0, 0, random.nextLong(), seed)
178185
if (listener.nextShuffleOrder != null)
179186
throw IllegalStateException("next shuffle order present but removing some items")
180187
val newShuffled = IntArray(shuffled.size - numberOfElementsToRemove)
@@ -189,7 +196,7 @@ class CircularShuffleOrder private constructor(
189196
}
190197
}
191198

192-
return CircularShuffleOrder(listener, newShuffled, Random(random.nextLong()))
199+
return CircularShuffleOrder(listener, newShuffled, random.nextLong(), seed)
193200
}
194201

195202
override fun cloneAndMove(
@@ -208,6 +215,7 @@ class CircularShuffleOrder private constructor(
208215
@Parcelize
209216
class Persistent private constructor(val seed: Long, val data: IntArray?) : Parcelable {
210217
constructor(order: CircularShuffleOrder) : this(order.random.nextLong(), order.shuffled)
218+
constructor(seed: Long) : this(seed, null)
211219

212220
companion object {
213221
fun deserialize(data: String?): Persistent {
@@ -234,15 +242,11 @@ class CircularShuffleOrder private constructor(
234242
return if (data != null) "$seed;${data.joinToString(",")}" else seed.toString()
235243
}
236244

237-
fun toFactory(): (Int, Int, EndedWorkaroundPlayer) -> CircularShuffleOrder {
238-
if (data == null) {
239-
return { firstIndex, mediaItemCount, it ->
240-
CircularShuffleOrder(it, firstIndex, mediaItemCount, seed)
241-
}
245+
fun create(firstIndex: Int, mediaItemCount: Int, it: EndedWorkaroundPlayer): CircularShuffleOrder {
246+
return if (data == null) {
247+
CircularShuffleOrder(it, firstIndex, mediaItemCount, seed)
242248
} else {
243-
return { _, _, it ->
244-
CircularShuffleOrder(it, data, seed)
245-
}
249+
CircularShuffleOrder(it, data, seed, null)
246250
}
247251
}
248252
}

app/src/main/java/org/akanework/gramophone/logic/utils/exoplayer/EndedWorkaroundPlayer.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ class EndedWorkaroundPlayer(
7070
val exoPlayer
7171
get() = player as ExoPlayer
7272

73-
var nextShuffleOrder:
74-
((firstIndex: Int, mediaItemCount: Int, EndedWorkaroundPlayer) -> CircularShuffleOrder)? =
75-
null
73+
var nextShuffleOrder: CircularShuffleOrder.Persistent? = null
7674
var currentQueueId: Long? = null
7775
var currentTitle: String? = null
7876
var currentIsPinned = false
@@ -204,7 +202,7 @@ class EndedWorkaroundPlayer(
204202
if (repeatMode != null) super.handleSetRepeatMode(repeatMode)
205203
if (shuffleModeEnabled != null) super.handleSetShuffleModeEnabled(shuffleModeEnabled)
206204
if (playbackParameters != null) super.handleSetPlaybackParameters(playbackParameters)
207-
nextShuffleOrder = newShuffleOrder?.toFactory()
205+
nextShuffleOrder = newShuffleOrder
208206
super.handleSetMediaItems(mediaItems, startIndex, startPositionMs)
209207
if (nextShuffleOrder != null)
210208
throw IllegalStateException("shuffleFactory was not consumed during set")
@@ -237,7 +235,8 @@ class EndedWorkaroundPlayer(
237235
val index = currentMediaItemIndex
238236
val isLast = mediaItemCount - index == 1
239237
cloneQueue(generateQueueId(), title, pinned, original)
240-
val newShuffleOrder = newShuffleOrder?.toFactory()
238+
val newShuffleOrder = newShuffleOrder ?: (exoPlayer.shuffleOrder as CircularShuffleOrder
239+
).lastSeed?.let { CircularShuffleOrder.Persistent(it) }
241240
if (repeatMode != null) super.handleSetRepeatMode(repeatMode)
242241
if (shuffleModeEnabled != null) super.handleSetShuffleModeEnabled(shuffleModeEnabled)
243242
if (playbackParameters != null) super.handleSetPlaybackParameters(playbackParameters)
@@ -269,7 +268,7 @@ class EndedWorkaroundPlayer(
269268
)
270269
if (!isLast || mediaItems.size <= startIndex + 1) {
271270
newShuffleOrder?.let {
272-
exoPlayer.shuffleOrder = it.invoke(startIndex,
271+
exoPlayer.shuffleOrder = it.create(startIndex,
273272
exoPlayer.mediaItemCount, this)
274273
}
275274
}

0 commit comments

Comments
 (0)