Commit Graph
41 Commits
Author SHA1 Message Date
vicrodh b8cfcfb34a Add audio visualizer backend infrastructure
- Add spectrum-analyzer crate for FFT processing
- Create visualizer module with:
  - RingBuffer: lockless SPSC buffer for audio samples
  - FFT processor: dedicated thread for spectrum analysis
  - TappedSource: rodio Source wrapper for sample capture
  - VisualizerTap: shared state for audio thread integration
- Add Tauri commands: set_visualizer_enabled, is_visualizer_enabled
- Register visualizer in AppState and lib.rs

Backend compiles. Next: integrate with audio thread to capture samples.
2026-02-01 15:07:21 -06:00
vicrodh 1d2e28c1a8 feat(vectors): add sparse vector foundation for playlist suggestions
Phase 1 of playlist-suggestions feature:
- SparseVector: memory-efficient vector with math operations
  - set/get with sorted indices for O(log n) access
  - add, sub, scale, dot product, magnitude
  - normalize, cosine_similarity, top_k_similar
- ArtistVectorStore: SQLite persistence
  - artist_index table: MBID to integer index mapping
  - vector_entries table: sparse representation (one row per non-zero)
  - vector_metadata table: track freshness with TTL
  - find_nearest: cosine similarity search with exclusion
- 17 unit tests all passing
2026-01-27 11:19:55 -06:00
vicrodh b3117cc7c2 Bump version to 1.1.7 2026-01-27 04:58:28 -06:00
vicrodh fbc1938838 feat: compare studio albums only when matching artists
When comparing "X" vs "The X" variants, now fetches actual albums
and counts only studio albums (main discography) instead of total
album count. This filters out:
- Tributes (albums by other artists)
- Compilations (greatest hits, best of)
- Unofficial releases (bootlegs, broadcasts)
- Live albums
- EPs and singles

Uses the same categorization logic as the frontend (qobuzAdapters.ts).
This provides cleaner matching, e.g., "The Beatles" with 200+ studio
albums vs "Beatles" tribute compilation with 2 albums.
2026-01-25 23:08:46 -06:00
vicrodh e5779ce6cf feat(backend): Add playlist folders Phase 1 - database and Tauri commands
- Add uuid crate dependency for folder ID generation
- Add PlaylistFolder struct and database schema
- Add folder_id field to PlaylistSettings
- Add database migration for existing installations
- Add CRUD methods for playlist folders:
  - create_playlist_folder
  - get_all_playlist_folders
  - get_playlist_folder
  - update_playlist_folder
  - delete_playlist_folder
  - reorder_playlist_folders
  - move_playlist_to_folder
  - get_playlists_in_folder
- Register Tauri commands for frontend integration
2026-01-24 23:15:48 -06:00
vicrodh fc03bee9b1 feat(thumbnails): add backend thumbnail generation system 2026-01-23 01:07:16 -06:00
vicrodh 2a8b7c6d55 feat: Qobuz™ compliance, subscription gating, and settings cleanup
cx
2026-01-22 10:33:45 -06:00
vicrodh 6260b2f66c chore: Bump version to 1.1.6 for release 2026-01-20 22:00:40 -06:00
vicrodh 4748cef7df chore: Bump version to 1.1.6-rc and add ARM64 workflow
- Update version to 1.1.6-rc for release candidate testing
- Add Linux ARM64/aarch64 build workflow
- Uses ubuntu-24.04-arm GitHub runner (free for public repos)
- Builds .deb, .rpm, .AppImage, and AUR tarball for ARM64
- Workflow isolated with continue-on-error to not block x86_64 builds
2026-01-20 16:04:35 -06:00
vicrodh c749b7d932 chore: Update tauri-plugin-dialog to 2.6.0
Fixes version mismatch warning between Rust crate (2.5.0) and
NPM package (@tauri-apps/plugin-dialog 2.6.0)
2026-01-20 14:34:18 -06:00
vicrodh 0bbf6435b4 fix(queue): implement proper Fisher-Yates shuffle algorithm
Previous implementation had a critical bug in the shuffle algorithm
that used the same seed value for all iterations, resulting in
weak/predictable shuffling.

Changes:
- Add rand crate dependency for proper PRNG
- Fix Fisher-Yates to use unique random value per iteration
- Use StdRng with timestamp-based seed for reproducible randomness
- Each shuffle iteration now gets a new random number from the RNG

This fixes shuffle working inconsistently across different contexts
(albums, playlists, continuous play).

cc
2026-01-19 18:17:04 -06:00
vicrodh 9c76792741 Add alsa crate for direct ALSA hardware access
- Add alsa 0.9 as Linux-only dependency
- Will replace CPAL-based ALSA backend with direct alsa-rs implementation
- Required to properly access hw:X,Y devices for bit-perfect playback
2026-01-18 14:02:43 -06:00
vicrodh c810663c6f feat: implement 3-state DAC badge and hardware sample rate detection
Backend changes:
- Add audio_diagnostics module to read actual hardware sample rate from /proc/asound
- New command get_hardware_audio_status() parses hw_params for real-time monitoring
- Add glob dependency for file pattern matching

Frontend (AudioOutputBadges):
- Implement 3-state DAC badge system:
  - Green: DAC passthrough working correctly (rates match)
  - Yellow: DAC passthrough ON but resampling detected (warning)
  - Gray: DAC passthrough OFF (intentionally disabled)
- Dynamic tooltips showing actual hardware sample rate
- Compare file sample rate vs hardware sample rate
- Increase tooltip z-index to 9999 to prevent occlusion issues
- Add pointer-events: none to tooltip to prevent interaction issues

Frontend (SettingsView):
- Replace hardcoded "192 kHz" with dynamic hardware sample rate
- Load and display actual hardware audio status
- Show format details (e.g., S32_LE) when available
- Display "No active playback" when no audio is playing
- Add muted styling for inactive state

Frontend (QualityBadge):
- Add native tooltip showing tier and format
- Add cursor: help to indicate interactivity

i18n:
- Add "noActivePlayback" translations (EN/ES)

This allows users to verify bit-perfect playback is working and detect
resampling issues that would compromise audio quality.
2026-01-16 21:14:22 -06:00
vicrodh 73d022ae20 Add two-level audio cache system (L1: memory, L2: disk)
L1 (Memory): 300MB for ~3-4 Hi-Res tracks, instant access
L2 (Disk): 500MB playback cache at ~/.cache/qbz/playback/

Flow:
- When track evicted from memory, saved to disk cache
- When loading: check memory → disk → download cache → network
- Tracks promoted back to memory when accessed from disk

This reduces re-downloads when navigating back to recently played
tracks in mixed playlists.
2026-01-16 08:49:56 -06:00
vicrodh 2568862aa6 chore: bump version to 1.1.5 2026-01-14 08:29:42 -06:00
vicrodh 3a7b05b859 feat(settings): add notifications toggle
Users can now disable toast notifications (buffering, track changes, etc.)
from Settings > Appearance. Error notifications are always shown.

cc
2026-01-14 04:41:13 -06:00
vicrodh 827c033e6c chore: bump version to 1.1.3 2026-01-14 03:14:01 -06:00
vicrodh e6e86c29f7 chore(release): bump version to 1.1.2 2026-01-13 18:05:15 -06:00
vicrodh a86dc5bcba fix: restore playback buffering and mpris controls 2026-01-13 15:06:49 -06:00
vicrodh 3e3cc4746d chore(release): bump version to 1.1.0 2026-01-13 12:06:11 -06:00
vicrodh 1e6a8b1aee perf(rodio): reduce control polling during playback 2026-01-13 00:27:03 -06:00
vicrodh 486cc191f9 perf(alsa): reduce playback wakeups via cpal buffer tuning 2026-01-13 00:17:28 -06:00
vicrodh d2b219ea1d fix: CI workflow failures
Linux workflow:
- Remove xdg-portal feature from tauri-plugin-dialog to fix ashpd/zbus version incompatibility
- The ashpd 0.11.0 crate has breaking changes with zbus 5.x

Flatpak workflow:
- Use build-options.append-path instead of shell export to properly set PATH for SDK extensions
- This ensures npm/rust binaries are available in all build commands
2026-01-12 11:55:04 -06:00
vicrodh 6d41741f76 feat: Redesign MiniPlayer to replace main window temporarily
- MiniPlayer now resizes the main window instead of creating a separate floating window
- Cider-inspired UI with large album art, track info, full playback controls
- Progress bar with current/remaining time display
- Shuffle, repeat, volume controls integrated
- Pin/restore buttons to control always-on-top and return to main view
- Fixed tray icon to use transparent PNG from static/icons
2026-01-12 07:28:14 -06:00
vicrodh 06fa565d84 feat: add system tray icon with playback controls
- Add tray-icon feature to Tauri dependencies
- Create tray.rs module with full tray implementation
- Tray menu: Play/Pause, Next, Previous, Show/Hide, Quit
- Left-click toggles window visibility
- Double-click always shows and focuses window
- Right-click shows context menu
- Frontend listens for tray:play_pause, tray:next, tray:previous events
- Tray icon uses app default icon with "QBZ - Music Player" tooltip
2026-01-12 02:07:51 -06:00
vicrodh 8257e8866b feat: platform-specific dialog plugin (xdg-portal on Linux only) 2026-01-12 01:22:44 -06:00
vicrodh bc7e13d756 Improve track notifications with artwork and quality info 2026-01-11 12:38:21 -06:00
vicrodh fbfa067b94 feat(cast): add multi-protocol support for Chromecast, DLNA, and AirPlay
- Update CastPicker to show protocol tabs with device counts
- Register DLNA and AirPlay state and commands in lib.rs
- Add Deserialize derive to DlnaMetadata and AirPlayMetadata
- Fix capabilities file (remove unavailable fs permissions)
- Remove unused IpAddr import in media_server.rs
2026-01-10 03:41:11 -06:00
vicrodh 3864fa8e4b feat: add download cache for offline listening
- SQLite-based index for tracking cached tracks
- Disk-based storage for audio files (~/.cache/qbz-nix/audio/)
- Download progress events via Tauri events
- LRU eviction with configurable cache size limit
- Integration with play_track for automatic local playback
- Open cache folder command for system file manager
2026-01-09 19:18:06 -06:00
vicrodh 8b10a47a03 Enable Chromecast casting with thread-safe architecture
- Add ChromecastHandle with dedicated thread for rust_cast operations
- Fix thread safety issue (rust_cast uses Rc, not Arc) using channels
- Enable rupnp full_device_spec feature for DLNA discovery
- Fix media_server response type consistency
- Register all cast commands in lib.rs
- Add Deserialize to MediaMetadata for Tauri command args
2026-01-09 18:24:55 -06:00
vicrodh 145186a06a feat: add casting module scaffolding (disabled)
Import Chromecast, AirPlay, and DLNA casting scaffolding from separate
branches. The module is currently disabled due to:

- Thread safety issues: rust_cast uses Rc internally (not Send)
- API compatibility: rupnp methods have changed

The scaffolding includes:
- Chromecast: mDNS discovery, device connection, media server
- AirPlay: Discovery scaffolding (RAOP playback pending)
- DLNA/UPnP: SSDP discovery scaffolding (playback pending)

To enable casting in the future:
1. Fix rust_cast thread safety (or use spawn_blocking)
2. Update rupnp API calls for current version
3. Add Deserialize derive to metadata types
4. Uncomment cast module in lib.rs
5. Wire up commands in invoke_handler
2026-01-09 17:40:26 -06:00
vicrodh e908d334c1 fix: use Tauri clipboard plugin for reliable share links
- Add tauri-plugin-clipboard-manager for reliable clipboard access
- Replace browser clipboard API with Tauri plugin
- Improve error messages in share functions to be more specific
- Add loading indicator for Song.link fetch
2026-01-09 17:35:18 -06:00
vicrodh 6eed045404 feat(auth): add secure credential persistence using system keyring
- Add keyring crate for secure credential storage (KWallet/GNOME Keyring)
- Create credentials module with save/load/clear functions
- Add auto_login command that uses saved credentials
- Add "Remember me" checkbox to login form (default: checked)
- Auto-login on app startup if credentials are saved
- Clear credentials from keyring on logout
- Show dynamic status during initialization (connecting, checking, logging in)
2026-01-09 14:37:49 -06:00
vicrodh 541f46e430 feat(integrations): add Discogs artwork fetch and fix Last.fm env loading
- Add Discogs API client for fetching missing album artwork
- Add UI button in Local Library settings to fetch missing artwork
- Load .env file at runtime using dotenvy for development
- Fix Last.fm to check runtime env vars as fallback to compile-time
- Use XDG Portal for dialog plugin (cross-desktop compatibility)
- Update README and .env.example with Discogs configuration
2026-01-09 14:30:35 -06:00
vicrodh b0a64b9caa feat: add tauri-plugin-dialog for file picker 2026-01-09 13:56:10 -06:00
vicrodh 1895812830 feat(library): integrate local library module from Codex
Full local library implementation with:
- Filesystem scanner for FLAC, WAV, AIFF, APE, ALAC files
- Metadata extraction using lofty crate
- CUE sheet parsing for single-file albums
- SQLite persistence with WAL mode
- 13 Tauri commands for library management

Commands:
- library_add_folder, library_remove_folder, library_get_folders
- library_scan, library_get_scan_progress
- library_get_albums, library_get_album_tracks, library_get_artists
- library_search, library_get_stats, library_clear
- library_get_track, library_play_track (with CUE seek support)

Based on implementation by Codex in local-library worktree.
2026-01-09 13:23:32 -06:00
vicrodh 19bad7200b feat(lastfm): improve auth flow with embedded credentials support
- Add support for build-time credentials via LASTFM_API_KEY/LASTFM_API_SECRET env vars
- Add lastfm_has_embedded_credentials command to check for embedded keys
- Add lastfm_open_auth_url command to open browser via native opener
- Simplify UI flow: if embedded credentials exist, just click Connect
- Add cancel button during authorization flow
- Clean up UI when waiting for user to authorize in browser
2026-01-09 13:02:05 -06:00
vicrodh ef8feebc45 Add system notifications for track changes
- Add notify-rust dependency for desktop notifications
- Create notification.rs commands module with show_track_notification and show_notification
- Register notification commands in lib.rs
- Wire up notifications in frontend for all playback scenarios:
  - Search results playback
  - Album track playback
  - Playlist track playback
  - Queue navigation and auto-advance
2026-01-09 11:04:03 -06:00
vicrodh 62e59f599a feat: add MPRIS media controls integration
Backend (Rust):
- Add souvlaki crate for MPRIS support on Linux
- Create media_controls module with MediaControlsManager
- Track metadata (title, artist, album, duration, cover)
- Playback state (playing/paused/stopped)
- Wire pause/resume/stop commands to update MPRIS
- Add set_media_metadata Tauri command

Frontend (Svelte):
- Call set_media_metadata when track starts playing
- Send track info to MPRIS for system integration

Now shows track info in system media controls and
supports media key events (logged for now).
2026-01-09 09:30:26 -06:00
vicrodh 3a0e3f26d5 fix: add missing CSS import and fix UI issues
- Add app.css import to +layout.svelte (fixes broken/light UI)
- Add logging for audio debugging
- Add image fallbacks for album and track artwork
- Fix sidebar/main-content layout (flex-shrink, min-width)
- Remove placeholder data from HomeView
- Add LoginView and SearchView components
- Update window title and branding to QBZ
2026-01-09 08:47:53 -06:00
vicrodh 8a094ef467 Initial project setup
- Tauri 2.0 + Svelte + TypeScript scaffolding
- Qobuz API client implementation (Rust)
  - Bundle token extraction
  - User authentication
  - Request signing (MD5 signatures)
  - Search/browse endpoints
  - Stream URL retrieval with quality fallback
- Tauri commands for frontend IPC
- Module stubs for player, queue, config
2026-01-08 22:35:34 -06:00