v0.20.0: the Rabbit's plays come home
andTunes phase 3. The R1 is now one more machine in the Round 38 play-count model, and nothing lands on it that Android can't play. Play counts: andTunes 0.2.0 counts a play on a natural finish (LinTunes' rule) and keeps Music/andTunes/plays/andtunes-<install id>.json in exactly the per-machine-totals journal shape, written beside the old one and renamed over it. Each sync first folds it into <data_dir>/plays/ with a new play_journal.merge_totals, the per-track max: the file now has two homes and both desktops may bring it back, so the max converges and an older copy can never pull a count down. Nothing is written when nothing moved, and PlayJournal.load needed no change. Format gate: the planner reuses export/web_support.conversion_for outright, since Android's MediaPlayer decodes the browser's set. FairPlay is refused and reported; ALAC, AIFF and oddities land as FLAC, converted once into a per-track cache and size-diffed after that. With no ffmpeg, the export's "sync without them?" question. A file ffmpeg can't read costs that song, not the sync. "Sync Playlist to Rabbit (Auxio)" is retired from the menu; device_sync's helpers stay because export and andTunes import them. The dev fixture grew a real ALAC track, a Protected AAC .m4p and an "Odd Formats" playlist. Verified on the R1 with it: AIFF and ALAC arrived as FLAC and played, the FairPlay track was refused, four plays came back on the next sync and each track's effective count rose by exactly one, and a third sync copied nothing. Found along the way: USB re-enumeration can wedge gvfsd-mtp, after which anything touching the mount (find_device, the GUI tests) hangs in an uninterruptible wait. CLAUDE.md now has the recovery. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ZCVBTJRFJ2XfMshu2gtUv
This commit is contained in:
@@ -1,5 +1,54 @@
|
||||
## Done
|
||||
|
||||
### Round 51 (2026-09-11) — counts come home, and only playable files go (v0.20.0)
|
||||
|
||||
andTunes phase 3. The Rabbit is now one more machine in the play-count
|
||||
model, and nothing lands on it that Android can't play.
|
||||
|
||||
- [x] **Play counts come back** (andTunes 0.2.0). A natural finish counts a
|
||||
play, which is LinTunes' rule, and LinTunes records no skips either.
|
||||
The app keeps `Music/andTunes/plays/andtunes-<install id>.json` in the
|
||||
Round 38 per-machine-totals shape and writes it beside the old one then
|
||||
renames it over, so a sync never reads half a file. Each sync first
|
||||
folds it into `<data_dir>/plays/` (`andtunes/plays.py`), using a new
|
||||
`play_journal.merge_totals` (the per-track max). That file now has two
|
||||
homes and both desktops may bring it back, so the max converges and an
|
||||
older copy can never pull a count down. Nothing is written when nothing
|
||||
moved, and `PlayJournal.load` needed no change at all.
|
||||
- [x] **Format gate.** The planner reuses `export/web_support.conversion_for`
|
||||
outright, because Android's MediaPlayer decodes the browser's set.
|
||||
FairPlay is refused and reported, and ALAC, AIFF and oddities land as
|
||||
`.flac`. Each conversion is cached at
|
||||
`$XDG_CACHE_HOME/lintunes/andtunes-flac/<track id>.flac`, so after the
|
||||
first sync it's an ordinary size diff and is never re-copied. With no
|
||||
ffmpeg, the same "sync without them?" question as export. A file
|
||||
ffmpeg can't read costs that song, not the sync.
|
||||
- [x] **"Sync Playlist to Rabbit (Auxio)" retired** from the Connections
|
||||
menu, along with its handlers and worker plumbing. `device_sync`'s
|
||||
helpers stay, because export and andTunes import them.
|
||||
- [x] **The dev fixture grew the shapes the gate needs**: a real ALAC
|
||||
`.m4a`, a "Protected AAC" `.m4p`, and an "Odd Formats" playlist (AIFF,
|
||||
WAV, OGG, ALAC, FairPlay), ticked for sync by default.
|
||||
- [x] **Found while verifying: a wedged gvfs-MTP mount hangs everything that
|
||||
touches it.** A USB re-enumeration left `gvfsd-mtp` holding a dead
|
||||
session. Every `ls` then sat in an uninterruptible FUSE wait that even
|
||||
`timeout` couldn't kill. The dev sync and the GUI tests (which call the
|
||||
real `find_device()`) both hung with it. Recovery was killing
|
||||
`gvfsd-mtp` and running `gio mount mtp://…/`; the steps are now in
|
||||
CLAUDE.md. It also explains the earlier 3-minute test runs: the full
|
||||
suite takes 11 s against a healthy mount.
|
||||
- [x] Verified with the dev library on the R1:
|
||||
- AIFF → `01 Reel One.flac` and ALAC → `03 Reel Three.flac` on the
|
||||
device; the FairPlay track was refused; 18 stale files from the old
|
||||
fixture were pruned; the default buttons were shipped.
|
||||
- All four Odd Formats songs played through on the R1.
|
||||
- The next sync brought back `plays: 4`, and each track's effective
|
||||
count went up by exactly one, with the device's `last_played`.
|
||||
- A third sync copied nothing.
|
||||
- Cold start 338–347 ms.
|
||||
`tests/test_round51.py` covers the gate, the cache, `bring_back` and
|
||||
the fold; the full suite passes.
|
||||
|
||||
### Round 50 (2026-09-11) — andTunes plays music on the Rabbit (v0.19.0)
|
||||
|
||||
The Android half of andTunes had been paused on a 1 GB toolchain download.
|
||||
|
||||
Reference in New Issue
Block a user