mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
scrobble: send now playing once per track change
A track transition resets the player position, and the scrobble policy's restart heuristic (same song, position drops to ~0) then re-announced the track we just left and, when the new track's position jittered back to zero, announced it twice. Suppress the now-playing when the restart is the same song; the submission logic still resets so a genuine replay is scrobbled again.
This commit is contained in:
@@ -59,6 +59,7 @@ class ScrobblePolicy(
|
||||
item?.id != songId ||
|
||||
(item != null && item.id == lastItemId && positionMs < previousPosition && positionMs <= RESTART_POSITION_MS)
|
||||
if (restarted) {
|
||||
val sameSong = item != null && item.id == songId
|
||||
songId = item?.id
|
||||
lastItemId = null
|
||||
playedMs = 0
|
||||
@@ -68,7 +69,7 @@ class ScrobblePolicy(
|
||||
if (item == null || !isPlaying) return null
|
||||
nowPlayingSent = true
|
||||
startedAt = now()
|
||||
return Scrobble.NowPlaying(item.id)
|
||||
return if (sameSong) null else Scrobble.NowPlaying(item.id)
|
||||
}
|
||||
lastPositionMs = positionMs
|
||||
lastItemId = item?.id
|
||||
|
||||
@@ -130,15 +130,46 @@ class ScrobblePolicyTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun restartingTheSameTrackScrobblesAgain() {
|
||||
fun restartingTheSameTrackResubmitsWithoutReannouncing() {
|
||||
val item = track(durationMs = 200_000)
|
||||
play(item, toPositionMs = 100_000)
|
||||
clock = 120_000L
|
||||
val repeat = play(item, toPositionMs = 100_000)
|
||||
assertEquals(Scrobble.NowPlaying("s1"), repeat.first())
|
||||
assertEquals(emptyList<Scrobble>(), repeat.filterIsInstance<Scrobble.NowPlaying>())
|
||||
assertEquals(Scrobble.Submission("s1", 120_000L), repeat.last())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doesNotReannounceTheTrackItJustLeftWhenItsPositionResets() {
|
||||
val events = mutableListOf<Scrobble>()
|
||||
events += play(track(id = "s1"), toPositionMs = 100_000)
|
||||
events +=
|
||||
listOfNotNull(
|
||||
policy.advance(track(id = "s1"), 200_000, isPlaying = true, positionMs = 0),
|
||||
policy.advance(track(id = "s2"), 200_000, isPlaying = true, positionMs = 0),
|
||||
)
|
||||
assertEquals(
|
||||
listOf(Scrobble.NowPlaying("s1"), Scrobble.Submission("s1", 1_000L), Scrobble.NowPlaying("s2")),
|
||||
events,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doesNotReannounceWhenTheNewTracksPositionJittersBackToZero() {
|
||||
val events = mutableListOf<Scrobble>()
|
||||
events += play(track(id = "s1"), toPositionMs = 100_000)
|
||||
events +=
|
||||
listOfNotNull(
|
||||
policy.advance(track(id = "s2"), 200_000, isPlaying = true, positionMs = 0),
|
||||
policy.advance(track(id = "s2"), 200_000, isPlaying = true, positionMs = 500),
|
||||
policy.advance(track(id = "s2"), 200_000, isPlaying = true, positionMs = 0),
|
||||
)
|
||||
assertEquals(
|
||||
listOf(Scrobble.NowPlaying("s1"), Scrobble.Submission("s1", 1_000L), Scrobble.NowPlaying("s2")),
|
||||
events,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aTransitionDoesNotReannounceTheNewTrackOnAStaleLowPosition() {
|
||||
val first = track(id = "s1")
|
||||
|
||||
Reference in New Issue
Block a user