Commit 1 Initial commit:
Initial commit - MusicDriveSync
MusicDriveSync is a wxPython desktop application for managing music on car
thumb drives. The user maintains a large FLAC library on a NAS, organized as
Artist/Album/Tracks. Rather than physically inserting drives to update them,
each thumb drive has a corresponding folder on the NAS. The app lets the user
browse the NAS library, see which tracks are already on a given drive
(highlighted green), copy missing tracks to the drive folder, and remove
tracks from it. Syncing to the physical drive is done separately via rsync.
This initial commit includes a working application with the following:
- config.py: reads and validates musicdrivesync.ini
- MusicDriveSync_Lib.py: NAS library scanning with cache, drive folder
scanning with progress callback, comparison index, copy and remove stubs
- panels/LibraryPanel.py: wx.TreeCtrl-based library tree with green
highlighting for tracks present on the active drive, Show Missing Only
filter, and Copy Selected button
- panels/DrivePanel.py: wx.TreeCtrl-based drive folder tree with Remove
Selected button and confirmation dialog
- main.py: top-level frame wiring drive selector, both panels, status bar
progress during library and drive scans, path accessibility checks on startup
---
Commit 2 Changelog and CLAUDE.md:
Add changelog system, fix CLAUDE.md conflicts, and apply session bug fixes
Introduces a changelog/ folder to track bugs, architectural decisions, and
lessons learned across the life of the project.
- changelog/CHANGELOG_INDEX.md: master index table for all entries
- changelog/00001_arch.md: DataViewTreeCtrl to wx.TreeCtrl migration
- changelog/00002_bug.md: missing drive scan progress feedback fix
- changelog/00003_arch.md: library panel color logic reversal
- CLAUDE.md: corrected two conflicts with the current codebase:
color coding description updated (green = on drive, normal = needs copying);
DataViewCtrl note replaced with TreeCtrl decision with pointer to changelog;
UI layout diagram corrected; changelog folder added to project structure
- panels/DrivePanel.py: converted from DataViewTreeCtrl to wx.TreeCtrl
- MusicDriveSync_Lib.py: added progress_callback to ScanDriveFolder()
- main.py: wired drive scan progress to status bar; added path accessibility
checks at startup
---
Commit 3 Fix Remove Selected:
Fix Remove Selected, add safety guard, and document NAS read-only rule
- Fixed "No tracks selected" on Remove and Copy buttons. Both panels were
using TreeItemId.GetID() as a dict key which is unreliable across the wx
layer. Replaced with wx.TreeCtrl's native SetItemData/GetItemData. The
separate _item_data dict was removed from both panels entirely.
See changelog/00004_bug.md.
- Fixed 5-minute UI freeze after removing tracks. OnRemoveTracks was calling
ScanDriveFolder() on the UI thread after every remove. Replaced with an
in-memory filter of _drive_tracks using the list of removed relative paths.
- Silent remove failures now surface as a warning dialog.
- Added path prefix guard to RemoveTracksFromDrive(). Any file whose path
does not begin with drive_path is unconditionally skipped.
- Added Absolute Rules section to CLAUDE.md: the NAS music library is
strictly read-only. The app may never delete or modify files there.
- changelog/00004_bug.md: documents the SetItemData fix and lessons learned.
---
Commit 4 Copy and Tools menu:
Implement CopyTracksToDrive, add Tools menu with Empty Folder Report
CopyTracksToDrive (MusicDriveSync_Lib.py):
- Copies files preserving full folder structure relative to music_library_path
(e.g. Compilations/Album/track.flac mirrors exactly on the drive folder)
- Uses shutil.copy2 to preserve file timestamps and metadata
- Skips files that already exist at the destination
- Accepts a progress_callback(done, total) for status bar updates
OnCopyTracks / _on_copy_complete (main.py):
- Copy now runs in a background thread, no UI freeze for large selections
- Status bar updates as each file is copied (e.g. "Copying to Taco... 3/12")
- After completion, newly copied files are added to _drive_tracks in memory
by reading their tags directly, no full rescan needed
- Both panels disabled during copy and re-enabled on completion
Tools menu (main.py):
- Added Tools menu to the right of File in the menu bar
- Empty Folder Report: scans the active drive folder and lists all
subdirectories that contain no FLAC files (may still contain jpg/png etc.)
- Results shown relative to drive root for readability
- EmptyFolderReportDialog class added to main.py
FindFoldersWithoutFlac (MusicDriveSync_Lib.py):
- Two-pass walk: marks all dirs containing FLACs and their ancestors, then
collects highest-level dirs with no FLACs using topdown pruning
Added the changelog files.
Initial commit MusicDriveSync
MusicDriveSync is a wxPython desktop application for managing music on car thumb drives. The user maintains a large
FLAC library on a NAS, organized as Artist/Album/Tracks. Rather than physically inserting drives to update them, each
thumb drive has a corresponding folder on the NAS. The app lets the user browse the NAS library, see which tracks
are already on a given drive (highlighted green), copy missing tracks to the drive folder, and remove tracks from it.
Syncing to the physical drive is done separately via rsync.
This initial commit includes a working application with the following components:
- config.py: reads and validates musicdrivesync.ini; single config source for all modules
- MusicDriveSync_Lib.py: NAS library scanning with cache, drive folder scanning with progress callback, comparison
index, copy and remove stubs
- panels/LibraryPanel.py: wx.TreeCtrl-based library tree with green highlighting for tracks present on the active
drive, "Show missing only" filter, and Copy Selected button
- panels/DrivePanel.py: wx.TreeCtrl-based drive folder tree with Remove Selected button and confirmation dialog
- main.py: top-level frame wiring drive selector, both panels, status bar progress during library and drive scans,
and path accessibility checks on startup
This form allows you to request diffs between any two revisions of this file. For each of the two "sides" of the diff, enter a numeric revision.