Everything written this session that has not been through the device: rounds 43 to 48 (each patch adversarially verified, 43's transient-notice expectation fixed), a partial round 49, the pipeline scripts, the Android Auto design and the icon comparison mock. Also the two harness changes that were never A/B'd — adaptive waits, which may only shorten a declared wait and never lengthen it, and a ship that runs the mock walk and the deploy at the same time. The A/B and its 255-step baseline are in handoff/tools; main stays at what the phone has actually walked.
43 lines
2.9 KiB
Plaintext
43 lines
2.9 KiB
Plaintext
Every update also carries a **queue window** that nothing reads. `NowPlaying`
|
|
(Rust) and `NowPlayingArgs` (Kotlin) hold a `queue` of at most twenty-one
|
|
entries — the current item and ten either side, each with its id, title,
|
|
artist, album, duration and art key — plus `queueIndex`, where the current one
|
|
sits *within that window* rather than within the whole queue.
|
|
`src/mobile/media.svelte.js` fills both from `player.queue` and `player.qi`;
|
|
`MediaService` ignores them completely, so the card is byte for byte the card
|
|
it was. The reason is media3: `SimpleBasePlayer.getState()` wants a playlist
|
|
and an index into it, and the data that migration needs should have been
|
|
running on the phone for a while before anything depends on it. Ten either
|
|
side because one covers the card's own prev and next and nothing else, while a
|
|
queue *list* — which is what Auto asks for — wants a screenful plus a scroll
|
|
in both directions; and it is a cap, not a length, so a two-thousand-track
|
|
queue crosses the bridge as twenty-one entries exactly like a twenty-one-track
|
|
one does. Measured at two kilobytes of JSON for twenty-one short titles and
|
|
six with long ones and real Android cover paths, against the thirty to eighty
|
|
kilobytes of base64 cover that already ride the same call once per record —
|
|
and an update is a track change, a transport change or the thirty-second
|
|
top-up, never a position tick.
|
|
|
|
Because it is on no screen, the walk reads it out of `logcat`:
|
|
`MediaSessionPlugin.update` logs one `media window n=… i=… art=… at=…` line
|
|
per update under the tag `SoulStream`, and the phone walk's `queue-window`
|
|
check holds that against `__ss.card` — the mirror `media.svelte.js` keeps of
|
|
what it last sent, beside xfernote's — field for field, through a next and a
|
|
previous. Field for field is deliberate: a key spelled snake_case where the
|
|
bridge wants camelCase arrives as nothing at all on both hops, with no error
|
|
anywhere, which is why the art-key count is compared and not just the size and
|
|
the index.
|
|
|
|
Three things in that check are load-bearing and easy to undo by accident. It
|
|
arms at queue index **one** rather than wherever the walk left off, which buys
|
|
a row on either side (`prev()` seeks to zero at the top of a queue and
|
|
`next()` stops at the end), a track that has just started (`prev()` is a seek
|
|
again past five seconds), and the fact that while the queue index is at most
|
|
ten nothing is clamped off the front of the window — so the window's index IS
|
|
the queue index, which is what lets the logged index be compared against the
|
|
queue's directly. It requires each reading to be a FRESH one at both ends, the
|
|
push counter up and a new line in the log, because a `prev()` that lands back
|
|
on the row it started from reads exactly like a stale line otherwise. And it
|
|
FAILS rather than skips when it cannot be armed — a queue under three rows, or
|
|
repeat-one, under which `next()` seeks instead of stepping — with the reason
|
|
in the message. |