Conversation
This was referenced Aug 3, 2026
palchrb
force-pushed
the
claude/upstream-skip-debounce
branch
from
August 4, 2026 05:14
c7fade9 to
70376a8
Compare
palchrb
force-pushed
the
claude/upstream-skip-debounce
branch
from
September 1, 2026 10:01
70376a8 to
b5e20c4
Compare
Contributor
Author
|
Aligning with upstream as of today |
Owner
|
I did a big refactor, heavy rebase needed |
Every next or prev press moved the pointer and started a load at once. A load cannot be recalled once started: NewStream has already asked for the audio key before its context is checked, and the pump writes that request out regardless, so cancelling the load on the next press still costs the request. Mashing the button spent one key request per press, and a long enough burst had Spotify answering 429 and refusing the track the listener finally stopped on. Give relative navigation a lane class of its own. A step forward or back is not a destination: it is queued rather than dropped, so a burst of twenty presses ends twenty tracks on, while it still cancels and drops the loads and prefetches ahead of it, whose track the pointer is leaving. That fixes a bug the old classification had on its own: a skip that arrived while the previous one was still queued dropped its walk, and its pointer step with it, so a burst could end short of where it was pressed to. Then hold the load a skip ends in. A press that follows another within skip_debounce_ms queues its load with a time before which the lane will not take it; the next press drops it unstarted, so a burst pays for the one load it ends on. The first press of a burst loads immediately, so a lone skip is as quick as before. Stopping playback, loading a context, or a transfer drop a held load the same way they drop any other, and a held load still queued at shutdown is answered like the rest. Two consequences are handled on the loop. A second prev during a load no longer reads the outgoing stream's position and restarts it; it goes to the track before. And the outgoing stream keeps playing until the load lands, so if it runs out meanwhile its end is among the events held for the load: those are dropped when the load lands, since handling them against the stream that just started would advance straight past it. The state is still published per press. The connect-state PUTs it raises are throttled and coalesced on the push lane, so there is nothing to gate here, and will_play is emitted for every stop along the way. Configured with skip_debounce_ms, defaulting to 600; 0 loads every skip immediately. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019FHWG4ossSBydy7jbVFWho
palchrb
force-pushed
the
claude/upstream-skip-debounce
branch
from
September 12, 2026 22:08
b5e20c4 to
0bc93f9
Compare
Contributor
Author
|
You think this is still needed, or did you address the fast skipping in your big refactor? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the first half of #346.
A burst of next/prev presses currently loads every track it passes through — one audio-key request per press — and Spotify answers 429 well before the listener finds their song. This splits the skip into a pointer move and a deferred load: presses move the selection immediately (published via will_play and a new pending_track_uri in /status), and only the track the user stops on gets loaded.
The window (skip_debounce_ms, default 600, 0 disables) was measured, not guessed: across two sessions of continuous skipping from the Spotify iOS app, gaps between Connect commands ranged 74–495ms. Deferred pointer moves also skip the connect-state PUT (only the first of a burst publishes) — the burst otherwise outruns the endpoint's tolerance and reproduces the same 429 on a different endpoint. Field-tested on a Pi Zero 2 W: a 20-press burst now costs 2 loads and no rate limiting.