Skip to content

fix(music): skip on the player instead of rebuilding the queue - #1797

Merged
A-EDev merged 5 commits into
mainfrom
fix/music-next-gap
Nov 7, 2026
Merged

A-EDev merged 5 commits into
mainfrom
fix/music-next-gap

Conversation

@A-EDev

@A-EDev A-EDev commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • In-app Next and Previous seek on the player when the target is already queued, instead of stopping and rebuilding the queue. Anything out of step still takes the old path: a restored queue, a saved resume position, a changed download, Play on, or a stopped player.
  • Every in-app skip now keeps the old song playing on a short-lived tail player until that tail is heard, then the song changes under it. With crossfade off they overlap for 250 ms, otherwise for the chosen fade. If the tail isn't playing within 1.5 s the skip is plain.
  • With crossfade off, the tail starts at the nearest sync point, because a mid-song start first decodes from the sync point before it (about 500 ms).
  • Notification and headset skips have already changed the song when they arrive, so they only get a tail while Fade when you skip is on, and the next song stays muted until the tail plays.
  • Fast repeat presses move the target and never replace the queue. A stale LaunchedEffect in FullMusicPlayerContent could replay a song as a one-song queue, and it now only loads lyrics.
  • The play button follows Media3's shouldShowPlayButton, so Pause works while the next song buffers.

Related issue

Closes #1761

Change type

  • Bug fix
  • Feature
  • Refactor or maintenance
  • Build, packaging, or CI
  • Documentation

Validation

  • ./gradlew :app:assembleGithubDebug: passed
  • ./gradlew :app:testGithubDebugUnitTest: 5352 tests, 0 failures, 46 skipped
  • I ran any additional flavor-specific build or test tasks affected by this change. :app:compileFossDebugKotlin, ktlintCheck and nightly_notes.py --check pass
  • I manually tested the affected behavior on an Android device or emulator.

Test device and Android version: Xiaomi 2311DRK48G, Android 16, debug builds. Audio was recorded from the phone with scrcpy; silence means samples at or below 8 of 32767 for at least 30 ms. Presses were adb input tap, 9 s apart, so press times include its delay.

Skip main This PR
In-app Next, crossfade off 0.58 to 1.40 s silence on 24 of 24 presses, median 0.74 s none on 11 of 16 presses, 0.14 to 0.40 s on 5
Press to new song, crossfade off, full player 1.07 s 1.23 s
In-app Next, 3 s crossfade silence on 8 of 8, 0.28 to 1.43 s none on 8 of 8
Media key Next, 3 s crossfade 0.88 to 1.13 s silence, fades on 6 of 6 0.32 to 0.43 s silence, fades on 6 of 6

Fast presses, Pause straight after Next, and Next then Previous behaved correctly. Song order varied a little between runs, and a song's quiet intro counts as silence.

Not tested: the notification and headset buttons themselves (media keys were sent with cmd media_session dispatch), Bluetooth, a release build, and data or battery cost.

Screenshots or recordings

Risk and compatibility

Player path. With crossfade off, the old song jumps forward during a skip: 1.1 to 1.5 s, up to 4.9 s on the first skip after opening a song. It is heard for about half a second before the new song takes over. Each in-app skip briefly runs a second player, which loads about 3 s of the old song. During a hold the notification shows the old song while the app already shows the new one.

These change with Next and Previous and now match auto-advance and the notification: "Playing from" stays the queue's source instead of turning into "Radio", a named radio station stays active, play context genre is kept, skipping onto a song from Add to queue no longer reseeds radio, a repeated song plays its own queue entry, and player items keep their existing metadata. Tapping the spinner while buffering now pauses. Auto crossfade's line-up moved to TailAligner as it was. A debug log line was added for each skip route. No preference or database changes.

  • The change does not introduce secrets, private data, or unexpected telemetry.
  • New user-facing text uses Android string resources.
  • Dependency and lockfile changes are intentional and limited to this PR.
  • Room schema changes include the required version bump and migration, or this PR does not change the Room schema.
  • Breaking changes and upgrade steps are clearly documented.

@github-actions github-actions Bot added documentation Improvements or additions to documentation player Video and audio playback ui Compose UI, theming, or Material 3 surfaces labels Nov 6, 2026
@A-EDev
A-EDev force-pushed the fix/music-next-gap branch from 1e32646 to cb79ad6 Compare November 6, 2026 17:37
@A-EDev
A-EDev force-pushed the fix/music-next-gap branch from cb79ad6 to f261f94 Compare November 7, 2026 09:27
@A-EDev
A-EDev marked this pull request as ready for review November 7, 2026 09:57
Copilot AI balanced review requested due to automatic review settings November 7, 2026 09:57
@A-EDev
A-EDev merged commit a48171b into main Nov 7, 2026
9 checks passed
@A-EDev
A-EDev deleted the fix/music-next-gap branch November 7, 2026 09:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation player Video and audio playback ui Compose UI, theming, or Material 3 surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Corssfade bug

2 participants