mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 15:29:15 +01:00
address fourth review: reset the saved position per track and serialize cursor writes
This commit is contained in:
@@ -10,6 +10,8 @@ import com.subtracks.data.model.QueueEntry
|
|||||||
import com.subtracks.data.model.QueueKind
|
import com.subtracks.data.model.QueueKind
|
||||||
import com.subtracks.data.model.ShuffleOrder
|
import com.subtracks.data.model.ShuffleOrder
|
||||||
import com.subtracks.data.model.SongListItem
|
import com.subtracks.data.model.SongListItem
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
|
|
||||||
const val QUEUE_CHUNK = 60
|
const val QUEUE_CHUNK = 60
|
||||||
@@ -71,6 +73,8 @@ class QueueRepository(
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var cachedFlatVersion = -1L
|
private var cachedFlatVersion = -1L
|
||||||
|
|
||||||
|
private val cursorMutex = Mutex()
|
||||||
|
|
||||||
fun playlistEntry(
|
fun playlistEntry(
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
playlistId: String,
|
playlistId: String,
|
||||||
@@ -94,7 +98,7 @@ class QueueRepository(
|
|||||||
) {
|
) {
|
||||||
write(entries)
|
write(entries)
|
||||||
setShuffle(shuffleOrder != null, shuffleOrder)
|
setShuffle(shuffleOrder != null, shuffleOrder)
|
||||||
dao.setCursor(cursorRow().copy(queuePosition = 0))
|
cursorMutex.withLock { dao.setCursor(cursorRow().copy(queuePosition = 0, positionMs = 0)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun snapshot(): QueueSnapshot {
|
suspend fun snapshot(): QueueSnapshot {
|
||||||
@@ -124,6 +128,7 @@ class QueueRepository(
|
|||||||
order: LongArray?,
|
order: LongArray?,
|
||||||
) {
|
) {
|
||||||
val seed = if (enabled && order != null) System.nanoTime() else 0L
|
val seed = if (enabled && order != null) System.nanoTime() else 0L
|
||||||
|
cursorMutex.withLock {
|
||||||
db.useWriterConnection { transactor ->
|
db.useWriterConnection { transactor ->
|
||||||
transactor.immediateTransaction {
|
transactor.immediateTransaction {
|
||||||
dao.clearShuffleOrder()
|
dao.clearShuffleOrder()
|
||||||
@@ -133,6 +138,7 @@ class QueueRepository(
|
|||||||
dao.setCursor(cursorRow().copy(shuffleEnabled = enabled, shuffleSeed = seed))
|
dao.setCursor(cursorRow().copy(shuffleEnabled = enabled, shuffleSeed = seed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cachedShuffleSeed = 0
|
cachedShuffleSeed = 0
|
||||||
cachedShuffleOrder = null
|
cachedShuffleOrder = null
|
||||||
}
|
}
|
||||||
@@ -142,7 +148,7 @@ class QueueRepository(
|
|||||||
queueVersion.incrementAndGet()
|
queueVersion.incrementAndGet()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setRepeat(mode: Int) = dao.setCursor(cursorRow().copy(repeatMode = mode))
|
suspend fun setRepeat(mode: Int) = cursorMutex.withLock { dao.setCursor(cursorRow().copy(repeatMode = mode)) }
|
||||||
|
|
||||||
private suspend fun loadShuffleOrder(
|
private suspend fun loadShuffleOrder(
|
||||||
seed: Long,
|
seed: Long,
|
||||||
@@ -272,9 +278,16 @@ class QueueRepository(
|
|||||||
|
|
||||||
suspend fun cursorPositionMs(): Long = dao.cursor()?.positionMs ?: 0
|
suspend fun cursorPositionMs(): Long = dao.cursor()?.positionMs ?: 0
|
||||||
|
|
||||||
suspend fun setPosition(positionMs: Long) = dao.setCursor(cursorRow().copy(positionMs = positionMs.coerceAtLeast(0)))
|
suspend fun setPosition(positionMs: Long) =
|
||||||
|
cursorMutex.withLock {
|
||||||
|
dao.setCursor(cursorRow().copy(positionMs = positionMs.coerceAtLeast(0)))
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun setCursor(position: Long) = dao.setCursor(cursorRow().copy(queuePosition = position))
|
suspend fun setCursor(position: Long) =
|
||||||
|
cursorMutex.withLock {
|
||||||
|
val row = cursorRow()
|
||||||
|
dao.setCursor(row.copy(queuePosition = position, positionMs = if (row.queuePosition == position) row.positionMs else 0))
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun cursorRow(): PlaybackCursor = dao.cursor() ?: PlaybackCursor(queuePosition = 0)
|
private suspend fun cursorRow(): PlaybackCursor = dao.cursor() ?: PlaybackCursor(queuePosition = 0)
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ class PlaybackController(
|
|||||||
val order = withContext(Dispatchers.Default) { shuffledOrder(snap.size, start) }
|
val order = withContext(Dispatchers.Default) { shuffledOrder(snap.size, start) }
|
||||||
queueRepository.setShuffle(true, order)
|
queueRepository.setShuffle(true, order)
|
||||||
shuffleEnabled = true
|
shuffleEnabled = true
|
||||||
|
queueSourceId = entry.sourceId
|
||||||
queueRepository.setCursor(0)
|
queueRepository.setCursor(0)
|
||||||
snap = queueRepository.snapshot()
|
snap = queueRepository.snapshot()
|
||||||
this@PlaybackController.snapshot = snap
|
this@PlaybackController.snapshot = snap
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class QueueViewModel(
|
|||||||
rows.addAll(queueRepository.range(snapshot, start, end).map(::newRow))
|
rows.addAll(queueRepository.range(snapshot, start, end).map(::newRow))
|
||||||
first = rows.firstOrNull()?.position ?: 0
|
first = rows.firstOrNull()?.position ?: 0
|
||||||
last = rows.lastOrNull()?.position ?: -1
|
last = rows.lastOrNull()?.position ?: -1
|
||||||
initialIndex = (cursor - first).toInt().coerceAtLeast(0)
|
initialIndex = rows.indexOfFirst { it.position == cursor }.coerceAtLeast(0)
|
||||||
}
|
}
|
||||||
ready = true
|
ready = true
|
||||||
generation++
|
generation++
|
||||||
|
|||||||
@@ -932,6 +932,26 @@ class PlaybackControllerTest {
|
|||||||
restored.close()
|
restored.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun changingTrackResetsTheSavedPosition() {
|
||||||
|
seedAlbum(3, sourceId = 1)
|
||||||
|
controller.playAlbum(1, "al1", 0)
|
||||||
|
await {
|
||||||
|
controller.state.value.item
|
||||||
|
?.id == "s1"
|
||||||
|
}
|
||||||
|
|
||||||
|
runBlocking { queues.setPosition(60_000L) }
|
||||||
|
|
||||||
|
controller.next()
|
||||||
|
await {
|
||||||
|
controller.state.value.item
|
||||||
|
?.id == "s2"
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0L, runBlocking { queues.cursorPositionMs() })
|
||||||
|
}
|
||||||
|
|
||||||
private fun seedAlbum(
|
private fun seedAlbum(
|
||||||
count: Int,
|
count: Int,
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
|
|||||||
Reference in New Issue
Block a user