29 Commits

Author SHA1 Message Date
Maksim Totmin
cc429eed31 Add _ensure_schema() to create SQLite tables if missing
- Creates all required tables (item, artist, album, avformat_info,
  store_info, item_to_container, track_size_calc) in Library.itdb
- Creates location table in Locations.itdb
- Called from Nano7Database.__init__(), so empty DB is always valid
- Fixes 'no such table: item' error on iPod with wiped DB
2026-05-31 18:31:26 +07:00
Maksim Totmin
8c9e146a6c Add wasmtime to AppImage build for HASHAB signing 2026-05-31 18:24:07 +07:00
Maksim Totmin
7d371e2fbf Fix ithmb append mode: preserve existing data across transfer sessions
- Change ithmb file open from 'wb' (truncate) to 'ab' (append)
- Compute write offset from actual file position via seek(0,2)
- Prevents losing all previous artwork data on each transfer
2026-05-31 18:17:03 +07:00
Maksim Totmin
803f0c4d9a Update README with current features and project structure
- Cover art pipeline, iTunes-style player, Nano 7G DB
- AppImage build, config in ~/.config/, reembed script
- Accurate directory structure
2026-05-31 18:06:43 +07:00
Maksim Totmin
59865169e6 Remove old config.ini (migrated to ~/.config/), add *.AppImage to gitignore, fix build script 2026-05-31 18:02:21 +07:00
Maksim Totmin
8a1f6811c0 Move config to ~/.config/neo-pod-desktop/config.ini with migration
- Config is now in XDG_CONFIG_HOME (~/.config/) for write access in AppImage
- Auto-migrates existing config.ini from project root on first run
- Creates directory on save() if not exists
2026-05-31 18:01:55 +07:00
Maksim Totmin
7a86732953 Fix build-appimage.sh: use venv for PyInstaller, set proper paths
- Create venv with --copies to avoid system pip restrictions (PEP 668)
- Install deps into venv before PyInstaller run
- Use absolute paths for --add-data
2026-05-31 17:48:54 +07:00
Maksim Totmin
81b2ab2173 Add AppImage build script and scripts/ directory
- scripts/build-appimage.sh: builds portable x86_64 AppImage
  via PyInstaller (onedir) + appimagetool
  - Bundles Python + PyQt6 + all dependencies
  - Excludes unused Qt modules to reduce size
  - Auto-downloads appimagetool if missing
  - Generates app icon via Pillow
- .gitignore: add build/
2026-05-31 17:45:51 +07:00
Maksim Totmin
489d99c068 Add cover art pipeline (extract/encode/cache) and iTunes-style player
- New src/artwork/ module with iPod Nano 7G cover art support
  - codecs: RGB565/RGB555/UYVY/JPEG encode/decode via numpy
  - presets: 50+ iPod artwork format definitions
  - chunks: ArtworkDB binary parser/writer (MHFD→MHSD→MHLI→MHII→MHNI)
  - writer: ithmb file generation + ArtworkDB assembly
  - extractor: cover extraction from audio files (APIC/covr/FLAC pictures)
  - cache: local JPEG cache for player UI
- iTunes-style playback bar with 60x60 cover art display
- Scan library now caches cover art by artist+album
- iPod Nano7 transfer writes artwork to ArtworkDB + ithmb
- FFmpeg conversion preserves embedded cover art (-map 0:t?)
- One-time reembed_covers.py script in /tmp
- MetadataHandler process_file() fallback to cover_path
- Bug fixes: missing read_existing_artwork import, signed PID in Q format
2026-05-31 17:45:01 +07:00
Maksim Totmin
8c576232b1 Redesign Library tab and add Download tab toggle
Library tab redesign:
- Merge 'Ready to Transfer' table and 'Source Files' list into one unified table
- Replace bottom buttons with top toolbar (Add Files, Convert, Transfer, Remove, Refresh, Search)
- Add search/filter bar to filter tracks by title
- Add context menu (right-click): Play, Convert/Transfer, Show in File Manager, Remove
- Source tracks shown in gray (dimmed), ready tracks in normal color
- Remove status column with emoji — clean iTunes-like layout

Settings:
- Add 'Show YouTube Download Tab' checkbox in Advanced section
- Download tab hidden by default, can be enabled in Settings
- Uses QTabWidget.setTabVisible() to toggle without destroying widgets
2026-05-31 16:35:13 +07:00
Maksim Totmin
885a401ad0 Rebrand project to neo-pod-desktop with updated description and improvements
- Rename project from 'youtube-to-ipod-nano' to 'neo-pod-desktop' across all files
- Update description: 'Desktop application for downloading, converting,
  managing and transferring music to iPod Nano devices'
- Update setup.py: name, description, url, entry_points, author
- Update run.py: docstring and argparse description
- Update src/__init__.py: module docstring
- Update src/main.py: docstring, window title, about label
- Update src/cli.py: docstring, class docstring, argparse description
- Update README.md: title and project description
- Improve duplicate track detection in ipod_nano7_db.py:
  case-insensitive matching, bulk removal with file cleanup
2026-05-31 16:19:15 +07:00
Maksim Totmin
a1881df910 Add iTunes-style playback bar and move Output Directory to Settings
- Add QMediaPlayer + QAudioOutput for playback within the app
- Playback bar at top of Library tab with:
  - Transport controls: Prev, Play/Pause, Next
  - Seekable progress slider with current/total time labels
  - Volume slider
  - Now playing label showing Artist - Title
- Double-click table row to start playback
- Playback auto-advances to next track on end
- Move Output Directory setting from Library tab to Settings tab
- Output Directory now shown in a dedicated 'Library' group in Settings
- Add _setup_player(), _play_track_from_index(), _format_time_ms()
- Add all playback handlers for position, duration, status changes
2026-05-31 15:32:57 +07:00
Maksim Totmin
7477cfba66 Replace Ready to Transfer list with sortable table (QTableWidget)
- Replace QListWidget with QTableWidget in Library tab
- 6 columns: #, Artist, Title, Duration, Genre, Size
- Track numbers displayed without leading zeros (1, 2, 3...)
- Dash shown when track number is unknown
- Sort by track number within album by default
- Clickable column headers for sorting by any field
- Alternating row colors for readability
- Row selection (SelectRows behavior)
- Artist and Title columns stretch to fill space
- Add genre field to TrackInfo dataclass
- Include genre in metadata extract_tags() return value
- Extract genre and track_number during library scan
2026-05-31 15:26:03 +07:00
Maksim Totmin
11e4d49e2b Auto-hide empty library sections in Library tab
- Hide 'Ready to Transfer' header and list when no tracks are ready
- Hide 'Source Files — Need Conversion' header and list when no source files exist
- Sections appear/disappear automatically on scan, add, convert, delete
2026-05-31 15:18:08 +07:00
Maksim Totmin
a2d92b75e0 Fix Add Files flow: manual source files now persist across scans
- Add self.library_source_files list to store manually added file paths
- _on_library_add_files now adds to library_source_files instead of
  calling _scan_library() (which would clear the list)
- _refresh_source_ui merges scanned sources + library_source_files
  with dedup by path. All items get proper UserRole data.
- _on_library_remove_selected now removes from library_source_files too
- Previously added files would be lost on every scan because
  _scan_library() called .clear() on the source list
2026-05-31 15:15:07 +07:00
Maksim Totmin
ea5f9d038b Fix library remove: delete files from disk, not just from UI
- _on_library_remove_selected now removes files from disk with confirmation
- Shows count, file names, sizes, and total size in dialog
- Cleans up empty parent directories after deletion
- Re-scans library after deletion to refresh the UI
2026-05-31 15:04:20 +07:00
Maksim Totmin
c68bc3a09a Add GTK theme integration for Linux desktop environments
- Add _setup_linux_theming() called before QApplication creation
- Auto-detect libqgtk3.so plugin from common Qt6 plugin paths
- Sets QT_QPA_PLATFORMTHEME=gtk3 so Qt follows system GTK theme
- Falls back to qt6ct if gtk3 plugin not found
- Falls back to Fusion style if no platform theme available
- Respects user-set QT_QPA_PLATFORMTHEME (never overrides)
2026-05-31 15:01:17 +07:00
Maksim Totmin
56a88cf420 Fix QThread lifecycle crash: 'Destroyed while thread is still running'
- Add _cleanup_worker() helper: calls wait() then deleteLater() before
  dropping the Python reference. This ensures the C++ thread is fully
  cleaned up before the QObject is destroyed.
- Replace all 'self.worker_thread = None' with _cleanup_worker()
- Add running thread guards to all handlers: prevent starting a new
  WorkerThread while one is already running
- Add timeout to wait() calls (3000ms) to avoid hanging on close
- WorkerThread.stop() now calls self.wait() to ensure clean shutdown
2026-05-31 14:58:13 +07:00
Maksim Totmin
4c41cba428 Rewrite Library tab as persistent mediатека, split iPod tab for device management
- Rename Convert → Library, Transfer → iPod
- Library tab scans Output Directory on startup and shows all m4a/mp3
  files with metadata (artist, title, duration, size)
- Library tab has two sections: 'Ready to Transfer' and 'Source Files'
  (FLAC/WAV/OGG waiting for conversion)
- Move 'Transfer to iPod' button from Transfer tab to Library tab
- iPod tab is now device-only: mount/eject, view tracks, remove, scan orphans
- No more RAM-only converted_tracks list — library is always from disk
- Auto-scan on startup, after conversion, after download, on directory change
2026-05-31 14:52:55 +07:00
Maksim Totmin
33c8534eb4 Add Transfer tab: Mount/Eject UI, track management, orphaned file scanning
- Add Mount/Eject buttons with device status display
- Auto-mount device on refresh
- Load and display tracks from iPod SQLite database
- Delete selected tracks from iPod with confirmation
- Scan for orphaned files (audio files without DB entries)
- Bulk delete orphaned files to reclaim space
- Show track count and free/total space
2026-05-31 14:39:18 +07:00
Maksim Totmin
762e9dffe8 Rewrite device handling: udisksctl mount/unmount, Nano 7 database integration
- Replace libimobiledevice dependency with udisksctl (works without root)
- Detect block devices (/dev/sdX) for iPod partitions
- Add mount_device() using udisksctl mount -b
- Add unmount_device() using udisksctl unmount + power-off
- Update transfer_file() to use Nano7Database.add_track()
- Handle duplicate skips (add_track returns None)
- Fall back to simple file copy if Nano 7 DB unavailable
2026-05-31 14:39:11 +07:00
Maksim Totmin
11c40c8a99 Fix Nano 7 database: duration samples, HASHAB cbk, duplicate detection, Locations.itdb
- Fix avformat_info duration: store in SAMPLES not ms (firmware uses this to
  determine playback length; wrong units caused tracks to stop at ~3-11 seconds)
- Add Locations.itdb insert/delete for each track (ipod_path mapping)
- Add sync_locations_cbk() with HASHAB signing via WASM module
- Detect FirewireGuid from SysInfo for cbk header signature
- Add duplicate detection in add_track (title+artist match, skip if exists)
- Add get_orphaned_files() and delete_orphaned_files() for cleanup
- Sync cbk after every add/delete operation
2026-05-31 14:39:04 +07:00
Maksim Totmin
4ee62764ca Add HASHAB signing support for iPod Nano 6G/7G
- Add hashab.py module using WASM calcHashAB (from dstaley/hashab)
- Bundle calcHashAB.wasm binary
- Implements 57-byte HASHAB signature for Locations.itdb.cbk
- Required by Nano 6G/7G firmware to accept SQLite databases
2026-05-31 14:38:55 +07:00
Maksim Totmin
381bf106ed Fix audio conversion: replace ffmpeg-python with subprocess, add AAC-LC profile and faststart
- Replace ffmpeg-python with subprocess.run + timeout (prevents hangs)
- Add -ar 44100 -ac 2 for iPod Nano 7 compatibility
- Add -profile:a aac_low and -movflags +faststart (moov atom at start)
- Add -map 0:a to skip embedded cover art streams in FLAC files
- Validate output file size, reject empty/corrupt conversions
2026-05-31 14:38:48 +07:00
Maksim Totmin
47bfdf0011 Add track management: view and delete tracks on iPod from Transfer tab
- Add get_all_tracks() to load all tracks with file paths via tag matching
- Add delete_track() to remove tracks from SQLite DB and delete physical files
- Add _cleanup_orphaned_entries() to remove orphaned artist/album records
- Add track count label and 'Remove Selected' button to Transfer tab
- Load existing tracks on device detection
- Confirmation dialog before deleting tracks
- Reload track list after successful transfer
2026-05-31 12:37:13 +07:00
Maksim Totmin
1b4c092a04 Add metadata extraction from local audio files for proper tag preservation
- Add extract_tags() to metadata_handler.py: reads tags from FLAC, MP3, OGG, M4A
- Support ID3v2 (MP3), Vorbis comments (FLAC/OGG), MP4 tags (M4A)
- Extract cover art from METADATA_BLOCK_PICTURE (FLAC), APIC (MP3), covr (M4A)
- Update _run_convert to use extract_tags instead of guessing from filename
- Fix tag reading in ipod_nano7_db.get_audio_info() using EasyID3 for MP3
2026-05-31 12:26:53 +07:00
Maksim Totmin
761f896ea8 Add iPod Nano 7 SQLite database support for proper track transfer
- Create ipod_nano7_db.py module for Nano 7 SQLite DB management (Library.itdb)
- Fix case-insensitive iPod label detection in device detection
- Add /run/media to mount point search paths for Arch Linux
- Support already-mounted devices without requiring ifuse
- Add local file selection in Convert tab (FLAC, WAV, OGG, etc.)
- Transfer now properly registers tracks in iPod database so they appear in UI
2026-05-31 12:07:17 +07:00
Antonio Lorusso
436898987b
update gitignore 2025-03-12 01:18:07 +01:00
Antonio Lorusso
9dcb1228ca initial app 2025-03-12 01:01:43 +01:00