diff --git a/CLAUDE.md b/CLAUDE.md index 8c3428b..4688af1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -110,8 +110,13 @@ persistence) → GUI (Qt widgets that read the manager and connect to its signal own child-widget overlay instead. `QAudioOutput` must not be constructed before a `QMainWindow` exists (Qt 6.10 deadlock). Some PyQt signal relays need explicit types/lambdas. -- **Never move or rewrite the user's music files** except deliberate tag edits - via `tagging.py`. The library JSON is the source of truth for everything else. +- **Music files are only touched deliberately:** tag edits via `tagging.py`, + and — since Round 18 — artist/album_artist/album edits relocate the file + inside `LibraryManager.organize_root()` (`/Music`) to keep the + tree organized iTunes-style (`_maybe_move_file`; undoable; files outside the + root are never moved; the new path syncs cross-machine via the `location` + newest-wins merge in `conflict_resolver`). Nothing else may move or rewrite + music files. The library JSON is the source of truth for everything else. - `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. diff --git a/TASKS.md b/TASKS.md index 409f391..487b78b 100644 --- a/TASKS.md +++ b/TASKS.md @@ -3,16 +3,44 @@ Legend: `[ ]` todo · `[~]` in progress · `[x]` done. When a round closes, move its finished items to `tasks-done.md`. -## New backlog (added 2026-07-02, next round) +## Round 18 (current) — the 2026-07-02 backlog batch -- [ ] we might need an equalizer at some point but I'm not sure how it should show up -- [ ] I need to be able to drag a track or tracks from the gnome file browser into a playlist or just into the Library. It should copy the files into the 'itunes music' folder where we store all songs. It should store them where it makes sense for them to go 'artist -> album'. If there is no artist it should go in a standard unknown artist folder. The tracks should show up where they are dragged to in the playlist (if they're being dragged into a playlist) - _(Note: window/table drops + copy-to-`Artist/Album/` + unknown-artist fallback already exist — `file_importer.organized_destination`, `MainWindow.dropEvent`, `playlist_view.files_dropped`. Remaining gap to verify/build: inserting at the exact drop **position** in the playlist rather than appending.)_ -- [ ] if we rename an artist or album we should move the files. Basically we should keep the music folder organized in the same way the library itself is organized inside lintunes. If we add an artist the track moves from the unknown folder to the artist folder (make a folder if we need to) - _(Touches the "never move the user's music files" rule in CLAUDE.md — this would deliberately relax it for metadata renames; needs care around Syncthing + the other machine.)_ -- [ ] one of the sliders in the gray adjustments in preferences should be for the color of the equalizer visualizer. This will set the color of the gray when it's in gray mode. We still toggle between color, gray and off when clicking. Also what mode it's in (gray/color/off) should persist between launches of the app. +Plan reference: `~/.claude/plans/can-you-knock-out-synthetic-horizon.md`. +Tests land in `tests/test_round18.py`. (The equalizer backlog item moved to +Parked / deferred — see there.) -## Round 17 (current) — TASKS.md batch + cruft cleanup +- [x] Drag tracks from the GNOME file browser into a playlist/Library: the + copy-to-`Artist/Album/` + unknown-artist machinery already existed; + the gap was that `playlist_view._on_files_dropped` discarded the drop + row. Position now threads through `files_dropped` → + `MainWindow.import_files` → `import_paths` → + `add_tracks_to_playlist(position)`, so dropped files land at the drop + line (a file already in the library dedups to its existing track and + still inserts in place). +- [x] Renaming artist/album/album_artist moves the file so the music folder + stays organized like the library (`LibraryManager._maybe_move_file` + under `organize_root()` = `/Music`): folders created as + needed, Unknown Artist fallback, collision " 1" suffixes, empty dirs + pruned (never the root), undo/redo moves the file back/forward, a + failed move keeps the edit + old path and reports via + `file_move_failed` in the status bar. Files outside the organize root + are never moved. Cross-machine: `location` now merges + newest-`date_modified`-wins in `conflict_resolver`, covering both + sync-conflict files and live `reload_from_disk`. CLAUDE.md's + never-move rule updated accordingly. +- [x] Visualizer: new "Visualizer (gray mode)" slider in the Preferences + gray adjustments sets the dim-mode bar color (untouched = the old + derived look); the color/gray/off click cycle is unchanged and the + mode now persists across launches (`visualizer_mode` pref). +- [ ] **verify by eye in the running app**: drop files from Nautilus into + the middle of a manual-sort playlist (land at the drop line, Ctrl+Z + removes); Get Info an Unknown Artist track → set artist → watch the + file move in Nautilus (Ctrl+Z moves it back; try once while a track + is playing); bulk album rename + one Ctrl+Z restores all; drag the + visualizer slider while playing in gray mode; cycle modes + relaunch. + (A scripted offscreen run of all of the above passed 2026-07-02.) + +## Round 17 — TASKS.md batch + cruft cleanup Plan reference: `~/.claude/plans/can-you-take-a-drifting-sonnet.md`. Tests land in `tests/test_round17.py`. @@ -105,6 +133,12 @@ Tests land in `tests/test_round17.py`. ## Parked / deferred +- [ ] Equalizer ("maybe just some bass/mid/treble sliders in preferences" — + trav 2026-07-02). Deferred from Round 18: QMediaPlayer has no + audio-effects hooks, so even a 3-band EQ means either a custom + decode→filter→output pipeline (replaces playback; risky for + seek/formats) or leaning on the system (PipeWire filter-chain / + EasyEffects). Needs a design decision before building. - [ ] Smart playlists Phase 2: nested-group editing UI in the criteria dialog (import + evaluation of nested groups already works; imported nested playlists are read-only until then). Big change, on hold.