The first half of andTunes, a music player for the Rabbit R1. Auxio re-reads Android's MediaStore on every launch, which is the "your songs will show up here" hang — so the answer isn't a faster scanner, it's not scanning at all. LinTunes already knows the artist, album and year of every file it just copied, so it writes them into Music/andTunes/library.json and the app reads one file instead of indexing a filesystem. New lintunes/andtunes/: layout.py (a de-duplicated Media/<Artist>/<Album>/ tree, so a song in three playlists is stored once), manifest.py (pure, Qt-free), art.py (one 480 px cover per album via QImage, cached and invalidated by the audio file's mtime — which is exactly what embedding new art moves), and sync.py, a third sibling of plan_export/ExportWorker. Three rules the code depends on: planning never renders art (a mutagen open per album, and planning runs on the GUI thread); the index is written last and after a cancel lists only tracks whose files actually landed; and every delete goes through layout.assert_inside, which is why the old Music/<Playlist>/ folders are structurally unreachable rather than merely un-referenced. Connections gains "Sync to Rabbit" and "Rabbit Sync Settings…" — the ticked set is the device's contents, so unticking is how a playlist comes off, which nothing could do before. The selection rides preferences.json so both machines agree. The old per-playlist sync stays, renamed "(Auxio)": removing it now would leave the device full of files and nothing able to open them until the app exists. The app itself is rounds 48-50; its board is andtunes/TASKS.md, including the measured screen facts (480x640 px at density override 160 — one dp is half its usual physical size on a 2.88" panel). Claude-Session: https://claude.ai/code/session_015wrTys5U1fLb4pBD2LKWzV
22 lines
913 B
Python
22 lines
913 B
Python
"""The andTunes side of the house: what the Rabbit R1 app expects to find.
|
|
|
|
`device_sync.py` is the transport — how bytes cross the MTP mount. This
|
|
package is the *format*: where files live under ``Music/andTunes/`` on the
|
|
device, what the library index looks like, and how album art is rendered for a
|
|
2.88" screen. Keeping them apart means the app's on-device contract can change
|
|
without touching the copy loop, and vice versa.
|
|
"""
|
|
|
|
from .layout import (
|
|
ART_DIR, BUTTONS_DIR, FORMAT_VERSION, MANIFEST_NAME, MEDIA_DIR,
|
|
PLAYLISTS_DIR, ROOT_NAME, DeviceLayoutError, album_key, art_relpath,
|
|
assert_inside, media_relpath, playlist_relpath, root_for,
|
|
)
|
|
|
|
__all__ = [
|
|
"ART_DIR", "BUTTONS_DIR", "FORMAT_VERSION", "MANIFEST_NAME", "MEDIA_DIR",
|
|
"PLAYLISTS_DIR", "ROOT_NAME", "DeviceLayoutError", "album_key",
|
|
"art_relpath", "assert_inside", "media_relpath", "playlist_relpath",
|
|
"root_for",
|
|
]
|