Commit Graph
4626 Commits
Author SHA1 Message Date
vicrodh bf56eefd7a chore(deps): bump cpal 0.17.1 -> 0.17.3 and alsa 0.10 -> 0.11
cpal 0.17.3 requires alsa 0.11, which in turn pulls alsa-sys 0.4. The
`links = "alsa"` constraint permits only one alsa-sys in the dependency
graph, so qbz-audio's direct alsa stack is raised in lockstep:
alsa 0.10 -> 0.11 and alsa-sys 0.3 -> 0.4. Both workspace lockfiles
(crates/ and src-tauri/) are updated to cpal 0.17.3 / alsa 0.11.0 /
alsa-sys 0.4.0.

No source changes required: alsa_direct.rs uses only the stable
high-level alsa API (pcm, HwParams, Format, Direction, ValueOr, mixer),
and the snd_lib_error_set_handler FFI in alsa_error_handler.rs is
unchanged in alsa-sys 0.4. Both workspaces pass cargo check.

cc
2026-05-23 22:25:26 -06:00
vicrodh bec71d58d5 chore(deps-dev): bump vite from 8.0.13 to 8.0.14
cc
2026-05-23 18:08:06 -06:00
vicrodh e9b021e7e5 chore(deps-dev): bump vitest to 4.1.7
cc
2026-05-23 17:17:55 -06:00
vicrodh a4a281221a chore(deps): bump @kawarp/core to 1.2.0
cc
2026-05-23 17:17:44 -06:00
vicrodh 81d3751cb9 chore(deps-dev): bump vite to 8.0.13
cc
2026-05-23 17:17:40 -06:00
vicrodh cb8421accc chore(deps-dev): bump @tauri-apps/cli to 2.11.2
cc
2026-05-23 17:17:32 -06:00
vicrodh b1c946de6c chore(deps-dev): bump @sveltejs/kit from 2.59.1 to 2.60.1
cc
2026-05-23 17:17:21 -06:00
vicrodh 97dd405bcf chore(deps): bump open from 5.3.4 to 5.3.5
cc
2026-05-23 14:04:48 -06:00
vicrodh 9b2c6743e6 chore(deps): bump tauri-build from 2.6.1 to 2.6.2
cc
2026-05-23 14:03:10 -06:00
vicrodh d5f9d0b83c chore(deps): bump tokio from 1.52.2 to 1.52.3
cc
2026-05-23 14:01:17 -06:00
vicrodh d5d2e93744 chore(deps): bump ashpd from 0.13.10 to 0.13.11
cc
2026-05-23 13:59:34 -06:00
vicrodh 9e505a9fa4 chore(deps): bump tower-http from 0.6.8 to 0.6.11
cc
2026-05-23 13:58:00 -06:00
vicrodh a8ee939dab Merge bugfix/internal/post-1.2.13: post-1.2.13 bugfixes
Fixes #467 (long-session offline death), #468 (favorite on see-all), #466
(PipeWire backend hidden without pactl), #452 (remix version on initial play
from favorites), #449 (sample-rate sync regression on PipeWire), and #453
(macOS queue drag — pending Mac confirmation). Includes the recovered adaptive
prefetch throttle that #467's offline-liveness signal builds on.

cc
2026-05-23 12:05:05 -06:00
vicrodh e437e620a1 fix(queue): restore drag-and-drop reordering on macOS (#453)
c1c151ee added `-webkit-user-select: none` to <body>; on macOS WKWebView this
also blocks dragstart on the draggable .queue-track rows (WebKit couples
selectability with draggability), so queue reordering and its blue insertion
line silently broke. Marking the rows as `-webkit-user-drag: element` restores
drag initiation. WebKitGTK (Linux) is unaffected. Needs confirmation on a Mac.

cc
2026-05-23 12:04:29 -06:00
vicrodh ee4c889c55 fix(player): rebuild output stream on sample-rate change for all backends (#449)
The stream-recreate decision only forced a rebuild on a decoded-format change
for bit-perfect backends (DAC passthrough, ALSA Direct, CoreAudio exclusive).
The default/PipeWire path relied on Stop dropping the stream to get a fresh one
at the new rate; once that drop was deferred to avoid a track-change click
(e93fcaec), the PipeWire node stayed locked to the first track's rate for all
subsequent tracks — a regression vs 1.2.10. Make any decoded-format change
rebuild the stream on every backend; same-rate tracks still reuse it, so the
click fix is preserved.

Verified on hardware via pw-top: PipeWire without passthrough now switches rate
per track; PipeWire with passthrough and ALSA Direct unchanged (no regression).

cc
2026-05-23 08:35:38 -06:00
vicrodh d075902380 fix(favorites): carry remix/edition version on initial click-to-play from the favorites tracks view (#452)
The favorites queue builder forwarded the track version, so skipping/seeking to
a track showed its remix subtitle, but buildDisplayTrack (used for the initial
click-to-play via onTrackPlay) dropped it — so the now-playing bar, queue,
MPRIS and Last.fm lost the version on first play. Add version to the
DisplayTrack interface and buildDisplayTrack.

cc
2026-05-22 23:16:53 -06:00
vicrodh 3a09ce7fe7 fix(audio): detect PipeWire via runtime socket so the backend is not hidden without pactl (#466)
is_pipewire_available() shelled out to `pactl info`, which lives in
pulseaudio-utils and is absent on PipeWire-only systems — hiding the PipeWire
backend even though PipeWire was running. Detect via the
$XDG_RUNTIME_DIR/pipewire-0 socket first (no extra package required), with
pw-cli and pactl as fallbacks.

cc
2026-05-22 23:16:53 -06:00
vicrodh f5de06aeef fix(discovery): wire favorite button on browse/see-all pages (#468)
The heart overlay on AlbumCardLite always renders and calls onFavorite, but
VirtualizedFavoritesAlbumGrid never forwarded onFavorite/isFavorite, so the
button was dead on every discover see-all page. Thread both through the grid
and wire DiscoverBrowseView to the shared albumFavoritesStore (same pattern as
the collapsed DiscoveryView). Fixes favoriting across all six browse pages.

cc
2026-05-22 21:46:34 -06:00
vicrodh 50384d3d3c fix(player): never skip the gapless target offline + bound the skip cascade (#467)
The offline-skip recursion walked the entire remaining queue synchronously,
desyncing the logical queue from the still-playing engine. Fixes:

- The gapless-transition target is the track the engine is already playing;
  never run the availability-skip branch for it.
- isTrackAvailable now counts the in-memory/disk cache (new v2_is_track_cached
  command), not just downloaded copies.
- Cap consecutive offline skips and play-failure auto-skips at 5 in both
  +page.svelte and playbackService.ts.

cc
2026-05-22 21:46:34 -06:00
vicrodh bdaee1af1a fix(qobuz): retry transient fetch failures with backoff instead of skipping (#467)
A single transient 5xx / timeout / reset on the next track's file/url or a CMAF
segment used to be terminal and skipped the track. Add a retry wrapper (3
attempts, exponential backoff + jitter) around get_file_url, the init segment,
and per-segment fetches. Retry only transient errors (network/timeout, 5xx, 429
honoring Retry-After); a real 404 is classified as TrackUnavailable and
propagates immediately to the bounded skip path.

cc
2026-05-22 21:46:33 -06:00
vicrodh 133e90f752 fix(offline): hysteresis + cheap probe + streaming liveness override (#467)
Long sessions died when a single transient blip flipped the app to offline and
the queue then skipped every cached-but-not-downloaded track. Harden the
detector:

- Consecutive-failure hysteresis: declare offline only after 2 failed polls,
  not a single blip.
- Replace the HEAD https://1.1.1.1 probe with a concurrent race of cheap
  generate_204 endpoints, so a saturated link (long Hi-Res tracks) no longer
  times the probe out.
- Positive liveness override: if a segment downloaded within the last 45s we
  are online by definition, regardless of the probe.

cc
2026-05-22 21:46:33 -06:00
vicrodh e4fa90c1b2 feat(prefetch): adaptive throttle based on observed bandwidth + underrun signal
Recovered from 63ecc324 (authored on the native-port branch, never merged to
pre-release). Backend-only, no Slint. Scales the prefetch cap down on slow
links and during audio underruns, and exposes the per-segment download signal
the offline detector reuses as a positive liveness override (#467).

cc
2026-05-22 21:46:07 -06:00
vicrodh 4b66775688 Merge refactor/internal/shared-cache-credentials: share image cache and credentials via crates
cc
2026-05-18 14:11:14 -06:00
vicrodh 3477edfb76 refactor: share the image cache and credential store via crates
Extracts two self-contained, framework-agnostic modules out of
src-tauri so they can be reused by other clients without duplicating
logic:

- ImageCacheService / ImageCacheStats move into the qbz-cache crate
  (LRU disk cache, MD5-keyed, SQLite index).
- The credential store (keyring + AES-256-GCM encrypted file for Qobuz
  credentials and the OAuth token) moves into a new qbz-credentials
  crate.

src-tauri/image_cache.rs and src-tauri/credentials/mod.rs become thin
re-exports, keeping their Tauri managed-state wrappers. The Tauri app
is behavior-identical; both modules were already self-contained (no
Tauri and no crate:: references).

cc
2026-05-18 14:11:05 -06:00
vicrodh 196fa796f5 Merge refactor/qbz-app-session-activation: minimal session activation
cc
2026-05-18 09:35:55 -06:00
vicrodh 7ef6300a22 refactor(qbz-app): add minimal session activation to AppRuntime
Task 2 of the Slint POC readiness audit. AppRuntime now performs
framework-agnostic per-user session activation: activate, activate_at,
activate_offline, deactivate, plus is_session_active, active_user_id,
and a with_session_store accessor.

This is the minimal version per the 2026-05-18 audit correction. It
opens only the session store and does the portable scaffolding (user
paths, directories, last_user_id marker, runtime state machine). It
does not touch Tauri's session_lifecycle, does not initialize the
src-tauri-side per-user stores, and does not run the flat-to-user
migration. The shipping app keeps identical behavior; this is additive.

activate_at takes explicit directories and is the testable core;
activate resolves real per-user paths through UserDataPaths.

cc
2026-05-18 09:26:22 -06:00
vicrodh f979c52307 Merge refactor/qbz-app-shell-facade: shell facade skeleton
cc
2026-05-18 08:29:01 -06:00
vicrodh a213b37807 refactor(qbz-app): add AppRuntime shell facade skeleton
Adds a framework-agnostic composition root for non-Tauri UI shells
(Slint, TUI, headless) as Task 1 of the Slint POC readiness audit
(session-20-slint-poc-readiness-audit).

AppRuntime<A> owns an Arc<QbzCore<A>> plus the runtime state machine,
built with the same recipe as the Tauri CoreBridge but with no Tauri
dependency. Scope is composition and accessors only; per-user store
ownership and session activation are deferred to Task 2.

qbz-app now depends on qbz-core, qbz-player, qbz-audio, and qbz-models.
The Tauri app does not consume this module; it is purely additive.

cc
2026-05-18 07:28:19 -06:00
vicrodh d4ea8b01a7 Merge refactor/qbz-app-playback-context: playback context foundation 2026-05-17 20:14:54 -06:00
vicrodh 1052ff25b3 refactor(tauri): use qbz-app playback context
cx
2026-05-17 19:42:53 -06:00
vicrodh f79c550889 refactor(qbz-app): add playback context
cx
2026-05-17 19:39:14 -06:00
vicrodh 2ed2a30a2c Merge refactor/qbz-app-session-store: session store foundation 2026-05-17 19:30:34 -06:00
vicrodh 8b850999f9 refactor(tauri): use qbz-app session store
cx
2026-05-17 19:19:47 -06:00
vicrodh 4ba96fe59a refactor(qbz-app): add session store foundation
cx
2026-05-17 19:16:13 -06:00
vicrodh ba7cf05b6f chore: bump Nix flake hashes for v1.2.13
Update srcHash and npmHash to point at the v1.2.13 tag. qbzVersion was
already bumped during the release version bump.

cc
2026-05-17 16:38:27 -06:00
vicrodh d647268af8 fix: play individual tracks from expanded Mixtape items
Clicking a track inside an expanded Mixtape/Collection item now plays
it. Qobuz albums and playlists build the queue directly; Plex and
local-library albums delegate to the backend collection-item resolver,
then jump the queue cursor to the clicked track.

cc
2026-05-17 13:15:32 -06:00
vicrodh 3a22cbdbd5 fix: show playlist tracks and version in expanded Mixtape items
Expanded playlist items showed "No results found"; fetch their tracks
via v2_get_playlist. Also carry the remix/edition version field so
titles render consistently.

cc
2026-05-17 13:15:32 -06:00
vicrodh 6cb9284968 fix: pass remix/edition version metadata from playlists (#443)
Carry the track version field through PlaylistDetailView so remix and
edition subtitles reach the now-playing bar and queue views.

cc
2026-05-17 13:15:32 -06:00
vicrodh d9d6caae55 feat: include playback preferences in diagnostics snapshot
Add playback/audio/graphics settings to the diagnostics snapshot via
v2_get_playback_preferences. No sensitive data (no username or paths);
gated by the existing diagnostics opt-in toggle.

cc
2026-05-17 13:15:32 -06:00
vicrodh 74d75f3fbf fix: persist session durably to survive reboot (#440)
Switch the session store SQLite connection from synchronous=NORMAL to
synchronous=FULL. With WAL + NORMAL the last writes can sit unsynced in
the WAL and be lost on a hard reboot / power loss, dropping the restored
session.

cc
2026-05-17 13:15:32 -06:00
vicrodh 813892d605 Merge pre-release: 1.2.13 (400+ stars)
cc
2026-05-16 19:28:22 -06:00
vicrodh 3dac920187 fix(cast): suspend Qobuz Connect while casting (#439)
Qobuz Connect renderer mode and casting are mutually exclusive output modes. While qbz is registered as a QConnect renderer, the Qobuz cloud drives playback through the renderer-command path, which bypasses the cast path entirely — the cast device receives no LOAD and stays silent.

connectToDevice() now checks QConnect status and, if it is on, suspends it (v2_qconnect_disconnect) before connecting the cast device. When the cast ends, disconnect() restores QConnect only if it was on beforehand; a failed cast connection restores it too. Applies to Chromecast and DLNA alike.

Fixes #439.

cc
2026-05-16 18:59:34 -06:00
vicrodh 59990fdc35 docs(release): add 1.2.13 release notes and full changelog
TAG_DETAILS.md is the curated, user-facing release summary rendered by the website and the in-app About modal. CHANGELOG_FULL.md is the complete commit list for v1.2.12..v1.2.13, restoring the two-file release-docs layout last used at 1.2.5.

cc
2026-05-16 14:40:09 -06:00
vicrodh c747c72e9d chore(release): bump version to 1.2.13 "400+ stars"
Version bumped across Cargo.toml, tauri.conf.json, package.json, snapcraft.yaml (version + source-tag), flake.nix, and the lockfiles. metainfo.xml gains a 1.2.13 release entry, the About modal codename becomes "400+ stars", and the README contributors list adds @Vudgekek and @DoubleGate.

cc
2026-05-16 14:40:09 -06:00
vicrodh bfcd769055 fix(cast): heartbeat the Chromecast every 5s to keep the connection alive
Google Cast closes a control connection that goes roughly 10 seconds without a heartbeat PING. QBZ pinged every 25 seconds, so any cast connection left idle between connect and load — for example while the track downloads, or across a delayed second play attempt — was dropped by the receiver. The next LOAD then failed with EPIPE (broken pipe): the device chimed on connect but never played audio, and the heartbeat thread logged repeating broken-pipe warnings.

Pinging every 5s is the cadence the Cast protocol expects and keeps the connection alive through those idle gaps.

Fixes #439.

cc
2026-05-16 14:38:29 -06:00
vicrodh bf734546d1 Merge bugfix/pre-1.2.13: graphics recommendation cleanup, faster track resume
cc
2026-05-16 13:53:24 -06:00
vicrodh 3abb7f66cb fix(playback): gate within-track resume on cache, drop slow seek path
Session resume of a Qobuz track no longer forces the streaming start-position path, which buffered the CMAF stream sequentially from byte 0 up to the saved offset (up to ~30s wait, with no buffering indication).

v2_play_track is now always called without a start position. The track resumes at the saved offset only on a cache hit (format_id === null), where the audio is a full in-memory buffer and Seek lands like a local file. On a cache miss it starts from 0:00 instead of blocking on a sequential buffer fill.

No backend or audio-engine change; the start_position_secs streaming path is now unused.

cc
2026-05-16 13:53:17 -06:00
vicrodh 3d29cf1384 fix(graphics): make recommendation advisory-only, GPU-aware DMA-BUF help
The graphics recommendation banner no longer writes settings: the Apply button and the v2_apply_graphics_recommendation command are removed, so the banner only detects and explains. The user applies the change with the real toggles, matching the HiFi Wizard's advisory model. write_recommendation stays for the qbz --autoconfig-graphics CLI.

The Force DMA-BUF help text is now GPU-aware: the instability warning only shows on NVIDIA-only systems; non-NVIDIA and hybrid hosts are told it is safe to enable. On hybrid hosts the rendering GPU dropdown marks the integrated GPU as recommended.

cc
2026-05-16 12:22:41 -06:00
vicrodh 29b766ae24 fix(graphics): recommend CPU for NVIDIA-only, allow DMA-BUF on hybrid
NVIDIA-only systems no longer get a hardware-acceleration recommendation that visibly stutters under WebKitGTK. The three NVIDIA-only branches (Wayland+GNOME, Wayland, X11) collapse into one CPU-rendering profile, since XWayland does not rescue the stutter either.

NVIDIA + iGPU hybrid now allows DMA-BUF: WebKit composites on the stable iGPU stack, so the instability that affects NVIDIA-only systems does not apply. The recommendation also tells the user to pick the iGPU explicitly in the rendering GPU selector instead of Auto.

cc
2026-05-16 12:22:41 -06:00
vicrodh f02e19258b Merge branch 'pre-release' into bugfix/pre-1.2.13 2026-05-16 10:16:42 -06:00