Commit Graph
871 Commits
Author SHA1 Message Date
vicrodh 343bfff357 perf: add 200ms time throttle to download progress events
Add a minimum 200ms interval between progress emissions per track,
on top of the existing 2% change filter. Always emits at 100%.
Limits events to max 5/sec/track, reducing IPC pressure during
concurrent downloads.
2026-02-17 10:55:09 -06:00
vicrodh bc8300ea62 fix: add WAL mode to api_cache and favorites_preferences SQLite connections
These two databases were missing PRAGMA journal_mode=WAL and
PRAGMA synchronous=NORMAL, which could cause UI lag from lock
contention during concurrent reads/writes.
2026-02-17 10:22:33 -06:00
vicrodh d4bc1fe677 fix(immersive): improve visualizer panels per feedback
Energy Bands + Oscilloscope:
- Constrain drawing area to 85% of screen height, vertically centered

Oscilloscope:
- Change from bottom-left info to centered artwork layout (like Bars)

Transient Pulse:
- Lower backend threshold 0.15 -> 0.04, cooldown 6 -> 3 frames
- Use raw (un-smoothed) bass-weighted RMS for sharper detection
- Add frontend-side supplementary beat detection from energy data

Album Reactive:
- Fix glow layer centering (was anchored to top-left, now inset: 0)
- Double scale effect (0.04 -> 0.08) and glow spread (40 -> 80)
- Fast attack / medium decay smoothing for visible reactivity
2026-02-17 08:22:56 -06:00
vicrodh 6c4eaef9a5 feat(immersive): add 4 new visualizer tabs
Backend:
- Emit viz:energy with 5-band RMS (sub-bass, bass, mids, presence, air)
- Emit viz:transient with attack detection (threshold + cooldown)

Frontend panels:
- EnergyBandsPanel: concentric glowing rings around centered artwork
- LissajousPanel: stereo X/Y phase plot with trail (watermark layout)
- TransientPulsePanel: expanding rings from center on beat detection
- AlbumReactivePanel: album art with breathing scale/glow from energy

All panels extract colors from album art, throttle at 30fps, and follow
the existing visualizer lifecycle (enable/disable backend on mount).

Focus tabs now: Coverflow, Static, Bars, Scope, Energy, X/Y, Pulse,
Reactive, Lyrics, Queue (keys 1-0).
2026-02-17 07:53:49 -06:00
vicrodh 3b94acd95e feat(visualizer): emit stereo waveform data for oscilloscope
Add viz:waveform event emission alongside existing viz:data FFT output.
De-interleaves L/R channels from the raw sample buffer and downsamples
to 256 points per channel (512 floats = 2048 bytes). Pre-allocates the
waveform buffer outside the hot loop to avoid per-frame allocations.
2026-02-17 03:40:13 -06:00
vicrodh f583092a76 chore(packaging): add qobuzapp scheme to desktop files
All 6 .desktop files now declare x-scheme-handler/qobuzapp in their
MimeType line, enabling OS-level link capture for qobuzapp:// URLs.
2026-02-17 00:25:09 -06:00
vicrodh d286aec9ef feat(core): forward scheme links from single-instance and launch args
Single-instance plugin now inspects args for qobuzapp:// or
play.qobuz.com URLs and emits link:resolved event. Launch args
are also checked on first startup with a 1.5s delay for frontend
readiness.
2026-02-17 00:24:49 -06:00
vicrodh 261d420540 feat(v2): add qobuzapp handler registration commands
v2_check_qobuzapp_handler, v2_register_qobuzapp_handler,
v2_deregister_qobuzapp_handler — use xdg-mime for scheme handler
registration and mimeapps.list editing for deregistration.
2026-02-17 00:24:02 -06:00
vicrodh 9006e64fa2 feat(v2): add v2_resolve_qobuz_link command
Thin Tauri command that calls qbz_qobuz::resolve_link(). Pure parsing,
no State params, no auth required. Registered in invoke_handler.
2026-02-17 00:23:16 -06:00
vicrodh 0c66a14249 fix(player): stabilize seek interaction and remove misleading secondary bar refs #75
cx
2026-02-16 22:48:39 -06:00
vicrodh 39bbbdc230 fix(playback): reduce mpris desync and stale playback event lag refs #85
cx
2026-02-16 21:36:07 -06:00
vicrodh c3696f02d4 fix(playback): harden auto-advance for long-track edge cases
cx
2026-02-16 20:08:34 -06:00
vicrodh 99877fa740 fix(v2): align immersive track info/radio and i18n history keys
cx
2026-02-16 19:27:47 -06:00
vicrodh 37db48ea3d fix(v2): complete command migration sweep and musician/blacklist flows
- migrate remaining frontend invokes to V2 names
- add missing V2 command registrations and implementations
- enforce commands_v2 backend purity (no legacy delegation)
- restore blacklist/relationships/musician flows in V2
- align playlist/local-library/settings invoke paths with V2

cx
2026-02-16 18:40:07 -06:00
vicrodh 45b98c40d4 fix(v2): harden session restore and favorites query params
cx
2026-02-16 17:16:41 -06:00
vicrodh 6f7b8e0aff Revert "fix(v2): harden session restore and favorites query params"
This reverts commit c20bb034ae.
2026-02-16 17:16:29 -06:00
vicrodh c20bb034ae fix(v2): harden session restore and favorites query params
cx
2026-02-16 17:15:58 -06:00
vicrodh 1037b59cfa refactor(v2): hard-delete unused legacy command files
cx
2026-02-16 17:11:24 -06:00
vicrodh ffd5c992b0 refactor(v2): shrink legacy command module to internal minimum
cx
2026-02-16 17:09:29 -06:00
vicrodh 43ebf19ae1 chore(v2): hard-cut legacy invoke handler surface
cx
2026-02-16 17:04:08 -06:00
vicrodh a58116212c fix(v2): stabilize plex playback control and shuffle reorder semantics
cx
2026-02-16 15:23:46 -06:00
vicrodh e51f367b31 fix(v2): restore Plex command surface for LocalLibrary
cx
2026-02-16 12:53:20 -06:00
vicrodh 8ac5ba92fd refactor(v2): enforce backend purity and stabilize playback runtime
cx
2026-02-16 07:45:43 -06:00
vicrodh d64e0f38d7 chore(v2): apply phase-2 legacy cut-off for auth playback queue and context surface
cx
2026-02-16 04:14:13 -06:00
vicrodh 9e126a0c59 chore(v2): apply legacy invoke cut-off markers in handler with rollback notes
cx
2026-02-16 04:08:22 -06:00
vicrodh ee5998533d refactor(v2): route library flows through shared impls and remove command-to-command calls
cx
2026-02-16 04:05:16 -06:00
vicrodh d2a13ba95e refactor(v2): internalize notification offline playlist reset and reco training flows
cx
2026-02-16 04:02:52 -06:00
vicrodh 0aecda77e5 refactor(v2): migrate remaining unknown frontend invokes to v2 commands
cx
2026-02-16 03:53:24 -06:00
vicrodh d02b8a9628 refactor(v2): eliminate legacy frontend invokes and close remaining v2 command gaps
cx
2026-02-16 03:51:01 -06:00
vicrodh 54af46fea8 refactor(v2): close missing command surface for cast, library, offline and radio
cx
2026-02-16 03:35:52 -06:00
vicrodh 432dd828c1 refactor(v2): add native settings/cache/plex command surface
cx
2026-02-16 03:28:47 -06:00
vicrodh fafa98c46a refactor(v2): remove post-cutoff backend wrapper wave and restore pure v2 surface
cx
2026-02-16 03:10:21 -06:00
vicrodh 8d3627b743 feat(v2): add Library and Offline V2 command wrappers
Add V2 wrappers for frequently used commands:
- Library: play_track, get_albums, get_tracks_by_ids, check_folder_accessible,
  set_album_hidden, get_scan_progress, clear_artwork_cache,
  clear_thumbnails_cache, remove_folder, set_album_artwork
- Offline: get_pending_playlists, playlist_get_all_local_track_counts
2026-02-16 02:49:31 -06:00
vicrodh 12246ea2ad feat(v2): add more playlist V2 command wrappers
Add V2 wrappers for playlist commands:
- get_settings, get_all_settings
- get_stats, get_all_stats, increment_play_count
- get_favorites, get_local_tracks, get_local_tracks_with_position
- get_custom_order, has_custom_order, get_tracks_with_local_copies
- import_preview, import_execute
2026-02-16 02:28:33 -06:00
vicrodh 5dbd383bab feat(v2): add Plex V2 command wrappers
Wrap all 18 Plex commands with V2 RuntimeError handling:
- Network: ping, get_music_sections, get_section_tracks, get_track_metadata
- Auth: auth_pin_start, auth_pin_check, open_auth_url
- Cache: get_sections, save_sections, get_tracks, get_albums,
  get_album_tracks, search_tracks, save_tracks, update_track_quality,
  get_tracks_needing_hydration, clear
- Playback: play_track

Completes the Plex category of V2 migration.
2026-02-16 01:03:45 -06:00
vicrodh e565b964a5 feat(v2): add Other V2 commands
Add V2 commands for miscellaneous categories:

Audio Backends (7):
- v2_get_available_backends, v2_get_devices_for_backend
- v2_get_alsa_plugins, v2_check_alsa_utils_installed
- v2_get_default_device_name, v2_get_linux_distro
- v2_query_dac_capabilities

Audio Diagnostics (3):
- v2_get_hardware_audio_status
- v2_start_bitdepth_capture, v2_stop_bitdepth_capture

Radio (5):
- v2_create_artist_radio, v2_create_track_radio
- v2_refill_radio_queue, v2_get_queue_remaining
- v2_create_infinite_radio

Share (3):
- v2_get_qobuz_track_url/album_url/artist_url

Additional (7):
- v2_is_visualizer_enabled
- v2_get_current_queue_track, v2_peek_next_track
- v2_get_shuffle, v2_get_repeat
- v2_get_current_user_id
- v2_has_saved_credentials, v2_save_credentials

Total 25 new V2 commands.
2026-02-16 01:00:18 -06:00
vicrodh d39fe148ed feat(v2): add Cast/DLNA/AirPlay V2 commands
Add 39 V2 commands for casting:

Chromecast (14):
- v2_cast_start_discovery, v2_cast_stop_discovery
- v2_cast_get_devices, v2_cast_connect, v2_cast_disconnect
- v2_cast_get_status, v2_cast_get_position
- v2_cast_play_track, v2_cast_play_local_track
- v2_cast_play, v2_cast_pause, v2_cast_stop
- v2_cast_seek, v2_cast_set_volume

DLNA (14):
- v2_dlna_start_discovery, v2_dlna_stop_discovery
- v2_dlna_get_devices, v2_dlna_connect, v2_dlna_disconnect
- v2_dlna_get_status, v2_dlna_get_position
- v2_dlna_play_track, v2_dlna_load_media
- v2_dlna_play, v2_dlna_pause, v2_dlna_stop
- v2_dlna_seek, v2_dlna_set_volume

AirPlay (11):
- v2_airplay_start_discovery, v2_airplay_stop_discovery
- v2_airplay_get_devices, v2_airplay_connect
- v2_airplay_disconnect, v2_airplay_get_status
- v2_airplay_load_media
- v2_airplay_play, v2_airplay_pause, v2_airplay_stop
- v2_airplay_set_volume

All commands wrap existing implementations with RuntimeError.
2026-02-16 00:52:57 -06:00
vicrodh d269acc709 feat(v2): add playlist custom V2 commands
Add 10 V2 commands for playlist customization:
- v2_playlist_set_sort
- v2_playlist_set_artwork
- v2_playlist_add_local_track
- v2_playlist_remove_local_track
- v2_playlist_set_hidden
- v2_playlist_set_favorite
- v2_playlist_reorder (reorder playlists in sidebar)
- v2_playlist_init_custom_order
- v2_playlist_set_custom_order
- v2_playlist_move_track

All commands wrap existing library implementations with
proper type signatures and RuntimeError handling.
2026-02-16 00:50:57 -06:00
vicrodh a405954846 feat(v2): add V2 commands for cache management (clear cache, artist cache, vector store, offline cache, credentials) 2026-02-16 00:11:21 -06:00
vicrodh 477b032abe feat(v2): add V2 commands for settings (tray, graphics, window, developer, playback, favorites prefs, visualizer, blacklist, locale) 2026-02-16 00:07:12 -06:00
vicrodh 68aec71fdf fix(v2): migrate favorites cache, session, and context stores to V2 commands
- Add v2_save_session_state and v2_load_session_state commands
- Update favoritesStore to use V2 cache commands
- Update albumFavoritesStore to use V2 cache commands
- Update artistFavoritesStore to use V2 cache commands
- Update sessionService to use V2 session commands
- Update playbackContextStore to use V2 context commands
2026-02-15 21:55:15 -06:00
vicrodh 35758d07df feat(v2): add V2 commands for playback context, session, and favorites cache
- Add ContextType::Search variant
- Add V2 playback context commands (get, set, clear, has)
- Add V2 session persistence commands (save position/volume/mode, clear)
- Add V2 favorites cache commands (get/sync/add/remove for tracks/albums/artists)
- Register all new commands in lib.rs
2026-02-15 21:41:43 -06:00
vicrodh 7337b7e026 fix(v2): match V2QueueTrack field names to frontend interface
Remove serde rename attributes that caused mismatch:
- Frontend sends 'duration_secs', backend expected 'duration'
- Frontend sends 'artwork_url', backend expected 'artwork'

Now V2QueueTrack field names match BackendQueueTrack exactly.
2026-02-15 20:36:47 -06:00
vicrodh 045cf24a61 fix(v2): unify queue architecture - all commands use CoreBridge
Previously, V2 queue commands had a dual-queue bug:
- Writes (v2_set_queue, v2_add_to_queue, etc.) went to AppState.queue (legacy)
- Reads (v2_get_queue_state) came from CoreBridge/QbzCore queue
- Result: frontend sets queue, syncs, gets empty/stale data

This commit fixes the architecture:
- All V2 queue commands now use CoreBridge methods
- Added queue methods to QbzCore: add_track, add_tracks, add_track_next,
  set_queue, remove_track, remove_upcoming_track, move_track, play_index,
  next_track, previous_track, peek_upcoming
- Added corresponding methods to CoreBridge
- Fixed v2_set_shuffle to use CoreBridge (was using legacy AppState)
- Fixed runtime requirements: v2_toggle_shuffle and v2_clear_queue now
  use RequiresUserSession like other queue commands (consistency)
- Prefetch now gets upcoming tracks from CoreBridge, not legacy queue
- Updated tests to match V2 behavior (v2_toggle_shuffle, available field)
2026-02-15 20:07:01 -06:00
vicrodh 81e9279add fix(v2): proper teardown for V2 integration state
ListenBrainzV2State::clear_credentials() now resets internal client to
fresh state, not just wrapper fields.

LastFmV2State:
- Added clear_session() method that clears session_key AND pending_token
- init_with_session(None) now calls clear_session() instead of no-op

Ensures no credentials leak across sessions on logout/deactivate.

Closes Must-Fix #2 from MUST_FIX_BEFORE_RELEASE_RUNTIME_V2.md
2026-02-15 16:06:43 -06:00
vicrodh af910c4617 fix(v2): add transactional auth rollback on login failures
Added rollback_auth_state() helper that clears legacy_auth, corebridge_auth,
and emits AuthChanged event on partial login failures.

Applied to all error paths in v2_auto_login, v2_manual_login, and v2_login:
- CoreBridge auth failure now rolls back
- Session activation failure now rolls back

Ensures runtime_get_status never reports half-authenticated state.

Closes Must-Fix #1 from MUST_FIX_BEFORE_RELEASE_RUNTIME_V2.md
2026-02-15 16:06:37 -06:00
vicrodh 130c95dbdf feat(v2): add MusicBrainz metadata support to ListenBrainz commands
V2 ListenBrainz now_playing and scrobble commands now accept optional
MusicBrainz identifiers (recording_mbid, release_mbid, artist_mbids),
ISRC, and duration_ms parameters for richer scrobbles.

The AdditionalInfo struct is populated when any metadata is provided,
automatically including QBZ media player identification.
2026-02-15 15:37:10 -06:00
vicrodh 53927b5c6f Add missing V2 commands and deprecate legacy integration commands
New V2 commands:
- v2_lastfm_set_session: Set session key for restored sessions
- v2_listenbrainz_queue_listen: Queue listen for offline (uses legacy cache)

Deprecated legacy commands (with #[deprecated] markers):
- ListenBrainz: get_status, is_enabled, set_enabled, connect, disconnect,
  now_playing, scrobble, queue_listen
- Last.fm: is_authenticated, get_auth_url, authenticate, set_session,
  disconnect, scrobble, now_playing
- MusicBrainz: is_enabled, set_enabled
- Audio: reinit_audio_device

All deprecated commands point to their V2 replacements in the note.
Frontend migration to V2 commands is next.
2026-02-15 15:29:59 -06:00
vicrodh 943f886637 Add V2 integration states to session lifecycle
Integrates ListenBrainzV2State, MusicBrainzV2State, and LastFmV2State
from qbz-integrations crate into the session activation/deactivation
lifecycle.

In activate_session:
- After legacy integrations init (which loads from SQLite), sync
  credentials to V2 states
- ListenBrainz V2: gets token, user_name, enabled from legacy client
- MusicBrainz V2: gets enabled state (use_proxy defaults to true)
- LastFm V2: initialized to clean state (no legacy equivalent)

In deactivate_session:
- Clear V2 state credentials to prevent cross-user leaks
- Reset states to defaults

This ensures V2 commands (using qbz-integrations crate) have access
to the same credentials as legacy commands, enabling a smooth
migration path.
2026-02-15 15:06:59 -06:00
vicrodh 856ceb796d Enforce ToS gate in backend for all login entrypoints
Add centralized require_tos_accepted() helper function that checks
ToS acceptance before any authentication attempt. This prevents
non-UI clients (TUI/CLI/tests) from bypassing the ToS gate.

Affected commands:
- v2_auto_login: Returns tos_not_accepted error code
- v2_manual_login: Returns tos_not_accepted error code
- v2_login: Returns RuntimeError::Internal

The ToS check was already in runtime_bootstrap, but these commands
could be called directly. Now the gate is enforced at the backend
level regardless of entry point.

Also updates obsolete comment about frontend handling ToS.
2026-02-15 15:02:15 -06:00