v0.5.2: custom start times survive a track change
Playing a track with an iTunes start time (e.g. "Pretty Girls is a Motherfucker", 0:40) began at 0:00 whenever another track was already loaded. QMediaPlayer.setSource() synchronously emits two status changes before returning: a LoadedMedia still reporting the *outgoing* source, then LoadingMedia for the new one. The stale first event consumed the one-shot _pending_start_ms armed in Round 22 and seeked the dying pipeline, so the new track's real LoadedMedia ~5 ms later found nothing armed. Only the first track after launch worked. The armed seek now carries the URL it belongs to and is consumed only when source() matches. tests/test_round32.py models the real Qt event sequence, which Round 22's plain MagicMock never emitted; the test_round8/test_round22 stubs now report the new source by the time its LoadedMedia arrives, as Qt does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,32 @@
|
||||
## Done
|
||||
|
||||
### Round 32 (2026-08-14) — Custom start times survive a track change (v0.5.2)
|
||||
|
||||
trav reported "Pretty Girls is a Motherfucker" starting at 0:00 despite its
|
||||
imported 0:40 start time. Import and storage were fine (70 tracks carry a start
|
||||
time, 72 a stop time); the seek was being thrown away. `QMediaPlayer.setSource()`
|
||||
synchronously emits *two* status changes before it returns — a `LoadedMedia`
|
||||
still reporting the **outgoing** source, then `LoadingMedia` for the new one —
|
||||
and the stale first event consumed the one-shot `_pending_start_ms` armed by
|
||||
Round 22, leaving nothing for the new track's real `LoadedMedia` ~5 ms later.
|
||||
So it misfired on every track change; only the first track after launch worked,
|
||||
which is why Round 22 looked green.
|
||||
|
||||
- [x] The armed seek is tagged with the URL it belongs to
|
||||
(`_pending_start_url`), and `_on_media_status` consumes it only when
|
||||
`source()` matches — a status change fired for other media can't eat it.
|
||||
- [x] `LocalSink.load` restructured so the pending seek is armed only on the
|
||||
new-source branch; Round 22's same-source replay path still seeks directly
|
||||
and arms nothing.
|
||||
- [x] `tests/test_round32.py` models the real Qt event sequence (a `setSource`
|
||||
side effect that fires the stale `LoadedMedia` before switching `source()`),
|
||||
which Round 22's plain `MagicMock` never did. All three behavioral tests fail
|
||||
on the old code. `test_round8` / `test_round22` stubs updated to report the
|
||||
new source by the time its `LoadedMedia` arrives, as real Qt does.
|
||||
- [x] Verified against the real files headless: switching from a playing track
|
||||
to the Psychic Vagina mp3 with `start_ms=40000` now lands at 40.1 s and
|
||||
climbs; a track with no start time still starts at 0.
|
||||
|
||||
### Round 31 (2026-08-13) — One cast control, not two (v0.5.1)
|
||||
|
||||
The cast glyph appeared both under the volume slider and inside the visualizer,
|
||||
|
||||
Reference in New Issue
Block a user