v0.17.1: a library to break
Round 47 was verified by loading trav's real 21,531-track library. Nothing was written and nothing was at risk, but it's the wrong habit and he said so. The alternative is better for development anyway: reproducible, in-repo, and full of the awkward cases on purpose rather than by luck. scripts/make_dev_library.py builds a complete synthetic library — data dir and music tree — from ffmpeg sine waves in six containers, with art on some albums and not others, every playlist type (regular, folder, live/non-live/ unsupported/limited+nested smart, system, empty, duplicates), a play journal and a tombstone. ~4 MB, gitignored; the generator is the artifact worth keeping, not the sine waves. The edge cases are the point. A collision pair identical in artist/album/title/ number, slashes and colons in every name, a track with no artist, a multi-disc release, a compilation whose album_artist differs, a dangling location, a 208-character title, and non-ASCII plus an emoji all the way out to the m3u filename. CLAUDE.md now carries the rule: never develop against the real library, and when a feature needs a shape the fixture lacks, add it here. Using it found two bugs in it — a relative --out made every location resolve against the wrong root, and four-minute uncompressed clips made it 62 MB. andTunes is paused on a weak connection (the Android SDK is a ~1-1.5 GB one-time download; after that --offline builds need nothing). andtunes/ README.md now carries everything needed to resume cold: measured device facts, the dp trap, exact toolchain commands, locked design decisions, and the library.json contract. JDK 21 is installed and ticked off. Also answers the scroll wheel question: it reads as volume because the ROM's key layout maps the wheel's KEY_UP/KEY_DOWN to KEYCODE_VOLUME_UP/DOWN, but a focused activity sees key events first — so andTunes can claim it by consuming both those and DPAD_UP/DOWN, in onKeyDown and onKeyUp. No system file touched, no other app affected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015wrTys5U1fLb4pBD2LKWzV
This commit is contained in:
@@ -415,6 +415,20 @@ persistence) → GUI (Qt widgets that read the manager and connect to its signal
|
||||
AND push** (trav's standing request, 2026-07-03: both machines ride the
|
||||
bleeding edge, sync as often as possible) — so never leave master in a
|
||||
half-working state between commits you push.
|
||||
- **Never develop or verify against trav's real library.** It is 21,531 tracks
|
||||
of irreplaceable music and no amount of read-only care makes it the right
|
||||
thing to point a half-finished feature at. `scripts/make_dev_library.py`
|
||||
builds a synthetic one that has the same *shapes* — every playlist type
|
||||
(regular, folder, live/non-live/unsupported smart, system, empty,
|
||||
duplicates), six container formats, art on some albums and not others, a
|
||||
play journal, a tombstone, and a deliberate pile of naming edge cases (a
|
||||
collision pair differing only by id, an emoji album, a 208-character title,
|
||||
forbidden characters, a dangling location). Build it with
|
||||
`python3 scripts/make_dev_library.py --out dev-library` and run against it
|
||||
with `--data-dir dev-library/data`; it's gitignored, the generator isn't.
|
||||
When a feature needs a shape the fixture lacks, **add it to the generator**
|
||||
rather than reaching for the real library.
|
||||
|
||||
- `scripts/` holds one-off maintenance tools (`audit_artwork.py`,
|
||||
`recover_artwork.py`, `clear_computed_ratings.py`) run manually against a data
|
||||
dir; most default to dry-run and need `--write` to mutate files.
|
||||
|
||||
Reference in New Issue
Block a user