fix(player): lockscreen skip scrubs instead of advancing in background audio
onSkipToNext/onSkipToPrevious forwarded a bare next/previous to Rust, which always advanced the queue. Correct for music, wrong for a video whose audio is running through a background-audio handoff (UR-040): pressing skip to re-hear a line jumped to the next episode instead of scrubbing. resolve_skip_action in player/seek.rs maps the command to Advance or SeekTo, and is_background_audio_active() is the whole test — the handoff exists only for video, and an episode played through it reports MediaType::Audio, so media type cannot distinguish the case. Forward 30s, back 10s, both clamped to [0, duration] so a skip near either end cannot seek negative or read as EOF and advance. Routed through the same spawn-then-seek_absolute path as the scrubber, because a handoff seek re-opens the stream and must not run under the blocking lock (DR-159). Kotlin keeps sending the opaque command; it only gains FAST_FORWARD/ REWIND in the PlaybackStateCompat so the system stops drawing skip arrows for a control that scrubs. The remote-volume action block is deliberately untouched: the handoff never applies to cast sessions, where skip really does mean advance. Tests written first and watched fail (left: Advance, right: SeekTo). 706 Rust tests pass, clippy 0, coverage 90%.
This commit is contained in:
+23
@@ -239,6 +239,21 @@ class JellyTauPlaybackService : MediaSessionService() {
|
||||
nativeOnMediaCommand("previous")
|
||||
}
|
||||
|
||||
// Fast-forward/rewind map onto the same two commands on purpose.
|
||||
// Rust decides whether a skip advances the queue or scrubs
|
||||
// +30s/-10s, based on whether a background-audio handoff owns
|
||||
// playback (DR-201); routing these separately would put that
|
||||
// decision in two places and let them disagree.
|
||||
override fun onFastForward() {
|
||||
android.util.Log.d("JellyTauPlaybackService", "Lock screen: Fast-forward pressed")
|
||||
nativeOnMediaCommand("next")
|
||||
}
|
||||
|
||||
override fun onRewind() {
|
||||
android.util.Log.d("JellyTauPlaybackService", "Lock screen: Rewind pressed")
|
||||
nativeOnMediaCommand("previous")
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
android.util.Log.d("JellyTauPlaybackService", "Lock screen: Stop pressed")
|
||||
nativeOnMediaCommand("stop")
|
||||
@@ -543,6 +558,14 @@ class JellyTauPlaybackService : MediaSessionService() {
|
||||
PlaybackStateCompat.ACTION_STOP or
|
||||
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
|
||||
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
|
||||
// Advertised so the system draws seek affordances alongside the
|
||||
// skip arrows: during a background-audio handoff the backend
|
||||
// resolves skip to a +30s/-10s scrub rather than a queue advance
|
||||
// (DR-201), and a control that scrubs should not look like one
|
||||
// that changes track. Rust owns which of the two a press means;
|
||||
// these only describe what the session can do.
|
||||
PlaybackStateCompat.ACTION_FAST_FORWARD or
|
||||
PlaybackStateCompat.ACTION_REWIND or
|
||||
PlaybackStateCompat.ACTION_SEEK_TO
|
||||
)
|
||||
.setState(
|
||||
|
||||
Reference in New Issue
Block a user