Commit Graph
100 Commits
Author SHA1 Message Date
vicrodh f778874fdd fix(audio): #508 ALSA-exclusive + streaming regression; flatpak ReserveDevice1 own-name
Store the CMAF duration at command-accept so the seek bar and progress can't
freeze at 0:00, backfill it on the Resume rebuild, and clear + surface the
zombie stream-create-failure path. Degrade every non-priority device-reservation
contention error (only a higher-priority holder stays fatal) so a sandboxed
D-Bus RequestName denial can't block bit-perfect playback. Honor the
stream_buffer_seconds floor in the dynamic CMAF path and wire the network
throttle (record_segment_bandwidth / record_underrun / prefetch cap) to tame the
#591 underrun loop. Grant --own-name=org.freedesktop.ReserveDevice1.* in the
repo flatpak manifest so WirePlumber releases the card cleanly.

cc
2026-07-16 16:29:58 -06:00
vicrodh 5ae5d8e651 docs(readme): add Headless Daemon (qbzd) feature section linking the wiki manual
cc
2026-07-15 15:51:40 -06:00
vicrodh b4bff581ae feat(qbzd): wide sidebar, wrapped descriptions and fixed control column in setup TUI
cc
2026-07-15 12:15:32 -06:00
vicrodh e6cb5114a9 fix(qbzd): posture voice on the TUI network screen and pinned boot note
cc
2026-07-15 11:41:29 -06:00
vicrodh e6cc082669 feat(qbzd): default control-plane and login binds to 0.0.0.0 for LAN-first posture
cc
2026-07-15 11:32:44 -06:00
vicrodh 2e9e6a35ac fix(qbzd): honest OSC 52 copy semantics, copy-all file artifact and wizard polish
cc
2026-07-15 11:09:17 -06:00
vicrodh 90412328be feat(qbzd): hifi wizard section with copyable config blocks in setup TUI
cc
2026-07-15 10:49:38 -06:00
vicrodh ff1dbf7425 feat(qbzd): frames layout for setup TUI — sidebar nav, content frame, header and breadcrumb
cc
2026-07-15 10:10:09 -06:00
vicrodh 927b5aa762 fix(qbzd): footer state mapping test, layout parity and help-tint precision in themed TUI
cc
2026-07-15 08:47:15 -06:00
vicrodh 74dcc60b18 feat(qbzd): themed setup TUI with section borders and accent palette
cc
2026-07-15 08:37:56 -06:00
vicrodh 6b444f9748 fix(qbzd): family-aware bind fallback, URL-first output and IP-validated callback host
cc
2026-07-15 08:17:39 -06:00
vicrodh 7799017c69 feat(qbzd): auto-detect LAN callback host from SSH sessions for login
cc
2026-07-15 08:08:49 -06:00
vicrodh 42b9e39992 feat(qbz): wire settings export modal to the bundle engine (04 §4.2)
SettingsExportActions.confirm() -> settings::export_settings: read the
include-auth gate, close the modal, then off the event loop build the bundle
via qbz_app::settings::bundle::export(ExportSource::Desktop, ..) (no new
export logic), open a native rfd save dialog seeded with
qbz-settings-YYYYMMDD.qbzb, write it 0600 via write_bundle_file, and toast
the "qbzd settings import <file>" step. Errors surface a toast; cancel is a
no-op.

cc
2026-07-15 07:50:27 -06:00
vicrodh 897ba7128c feat(qbz-ui): settings export modal + Developer row (04 §4.2)
Add the desktop "Export settings…" surface for the qbzd daemon epic (T18):
a Developer-settings row that opens a modal with the single default-off
"Include Qobuz login and integration tokens" gate, its warning line, and a
Cancel/Export footer. Confirm() is a Rust callback (wired next). New
SettingsExportState/SettingsExportActions globals, exported from app.slint
so the Rust layer binds them, and the modal mounted in AppShell. New strings
translated across all 8 locales (en es de fr pt ru ja nl).

cc
2026-07-15 07:50:27 -06:00
vicrodh d658a501ad fix(qbzd): store I/O failures in settings set exit 1 not 2
cc
2026-07-14 22:04:11 -06:00
vicrodh 722a0207ec fix(qbzd): latch network.online from real network-class outcomes
cc
2026-07-14 21:59:50 -06:00
vicrodh 47081b7666 fix(qbzd): drop qconnect control handle before device release in shutdown
cc
2026-07-14 21:54:55 -06:00
vicrodh ece9b1ebc6 fix(qbzd): confirmed-kill escalation in acceptance script stop path
cc
2026-07-14 21:41:41 -06:00
vicrodh f48fc6ceb8 test(qbzd): P0 acceptance script for exit codes, status contract and roundtrip
cc
2026-07-14 21:31:19 -06:00
vicrodh 601188a2c0 ci: build qbzd on ubuntu-22.04 with slint-free and glibc-floor gates
cc
2026-07-14 21:12:21 -06:00
vicrodh 39eb12fc45 feat(packaging): ship qbzd binary and user unit in deb/rpm and tarball
cc
2026-07-14 21:02:34 -06:00
vicrodh 80a20f4322 fix(qbzd): land setup on menu when credentials exist, use multiplication sign in size warning
cc
2026-07-14 20:56:22 -06:00
vicrodh a1fbbafc79 feat(qbzd): ratatui setup TUI, six screens with explicit-save semantics
Implements owner requirement 2 (03-setup-tui.md): `qbzd setup`, a six-screen
raspi-config-grade configurator over the daemon's real stores — zero new
persistence. ratatui 0.30 (IV5: unifies on the lock's unicode-width 0.2.2;
0.29 forbidden). A synchronous event loop on a blocking thread; disk/HTTP only
at screen entry, `r`, save and the immediate actions, on workers with a spinner
(no I/O on keystrokes). Non-tty exits 2 with the verbatim copy; alt-screen +
panic-hook restore.

Screens: Account (T5 login engine; inline masked token paste, suspend-and-run
browser login, logout confirm), Audio (the §3.2.3 constraint matrix + 7
cascades verified 1:1 vs the desktop code, device picker re-deriving the
§3.2.2 grouping/BP-badge rules, DSD guard), Playback (ask->fallback rule,
infinite-radio read-only), QConnect (startup/name/volume_mode, live preview),
Network (whole-file qbzd.toml rewrite preserving every key), Import/Export
(pure renderer of the T12 bundle plan; interactive device re-pick; default-off
auth gate). Saves reuse T11 write_one + reload/status classification (§4.3);
dirty marker + Save/Discard/Stay. All user-facing strings centralized.

cc
2026-07-14 20:42:42 -06:00
vicrodh 8021393925 fix(qbzd): mask secret values in import summary and distinguish reload refusal
cc
2026-07-14 19:58:31 -06:00
vicrodh 0b7cd6c5e3 feat(qbz-app): settings bundle engine with importer-side classification
Export/import CLI on qbzd; requirements 4 and 5 complete with zero desktop builds.

cc
2026-07-14 19:44:01 -06:00
vicrodh a864aa8d55 feat(qbzd): settings reload endpoint and settings/qconnect/config CLI verbs
Route table complete: 17 P0 routes, CI-counted.

cc
2026-07-14 19:02:10 -06:00
vicrodh 6fa0428127 fix(qbzd): pin player volume to 100 percent at connect in locked volume mode
cc
2026-07-14 18:27:43 -06:00
vicrodh adccb98e76 feat(qbzd): report tick, daemon device identity, volume modes and queue persistence
cc
2026-07-14 18:14:52 -06:00
vicrodh 196f167873 feat(qbzd): copy QConnect glue with TODO(converge) markers and daemon trait impls
Real-volume join report and reconnect credential re-resolution are daemon-copy
fixes; desktop call sites untouched (OD2).

cc
2026-07-14 17:47:33 -06:00
vicrodh 05e2216acc fix(qbzd): strict queue payload parsing, history in queue response, honest race comment
cc
2026-07-14 17:19:44 -06:00
vicrodh 92c49e648b feat(qbzd): queue routes and CLI verbs with server-side track materialization
cc
2026-07-14 17:05:15 -06:00
vicrodh 393a6e01a7 fix(qbzd): serialize volume canonically in JSON responses
cc
2026-07-14 16:49:20 -06:00
vicrodh e700084f0b feat(qbzd): playback routes and transport CLI verbs with full advance ritual
cc
2026-07-14 16:35:21 -06:00
vicrodh dd63b18ae9 fix(qbzd): treat empty [server] token as unset
cc
2026-07-14 16:10:34 -06:00
vicrodh 286cb51957 feat(qbzd): tiny_http control plane, Origin shield + opt-in token, ping/info/status and CLI diagnostics
cc
2026-07-14 15:59:17 -06:00
vicrodh 9597573a61 fix(qbzd): bind login nonce into the redirect path instead of relying on state echo
cc
2026-07-14 15:26:56 -06:00
vicrodh 66c9acfa86 feat(qbzd): login via one-shot nonce-bound listener, paste and token paths
Port the desktop system-browser OAuth (crates/qbz/src/auth.rs) into the daemon
CLI with three daemon-specific changes: the one-shot listener binds an ephemeral
port (never the control-API port, D6), a CSPRNG state nonce binds the callback,
and the command only validates + persists the token into the daemon root then
best-effort nudges a running daemon. Adds validate_token / login_browser /
login_paste / login_with_token_arg / nudge_reload plus logout; no email+password
surface anywhere. cli/copy.rs carries the verbatim 02 §2.2 timeout, success and
logout strings.

cc
2026-07-14 15:13:07 -06:00
vicrodh 8534a02f0d test(qbz-app): pin duration==0 end-detection edge in playback driver
cc
2026-07-14 14:22:02 -06:00
vicrodh 297bbad326 feat(qbz-app): headless playback driver with pure plan_tick and thin IO shell
cc
2026-07-14 14:09:22 -06:00
vicrodh 4d0f52138a feat(qbzd): headless runtime bring-up with daemon-root stores and credential restore
Adds additive _at credential fns (crypto/format untouched), DaemonAdapter
broadcast bus, numbered boot per 01 §8.1 incl. the #521 shutdown pair.

cc
2026-07-14 13:40:49 -06:00
vicrodh 18a10d14d9 fix(qbzd): warn on config-dir create/chmod failure instead of silent discard
cc
2026-07-14 13:18:30 -06:00
vicrodh d911f43856 feat(qbzd): qbzd.toml with unknown-key warning, flock instance lock, daemon_prefs store
cc
2026-07-14 13:10:08 -06:00
vicrodh 02c2dba68d feat(qbzd): scaffold slint-free qbzd crate with clap verb tree and CI gate
IV6 build peak: 795 MB max RSS (summed across the cargo-capped build's
process tree via /proc VmRSS polling; /usr/bin/time -v is not installed
on this box). aws-lc-rs in graph: 0 (single rustls provider: ring
v0.17.14 throughout).

cc
2026-07-14 12:53:09 -06:00
vicrodh 90d9d1c66a fix(themes): Catppuccin Latte is a light theme, not dark
PR #612 added the three Catppuccin flavors but grouped all of them under ThemeCategory::Dark. Latte is the LIGHT flavor (its palette already builds light via bg_is_light); move it to the Light category arm so the theme picker groups it correctly. Frappé/Macchiato stay Dark.

cc
2026-07-14 11:19:32 -06:00
Victor RH 771f1a29fb Merge pull request #612 from TerminalTilt/add-catppuccin-themes
feat(themes): add Catppuccin Latte, Frappé, and Macchiato
2026-07-14 11:18:42 -06:00
Victor RH 99a1f53fd4 Merge pull request #609 from afonsojramos/bugfix/lastfm-no-token-prefix-log
fix(log): stop logging Last.fm token prefixes and session bodies
2026-07-14 08:43:16 -06:00
vicrodh bf29892aa4 fix(dsd): DsdErrorReport holds SharedState, not Arc<SharedState>
The merged #599 typed DsdErrorReport.state as Arc<SharedState>, but the audio thread passes thread_state — a SharedState, which is itself a #[derive(Clone)] handle of Arc<Atomic..> fields (a clone already shares the state). The extra Arc broke the qbz-player build in the combined pre-release (E0308 at the four DoP / native-DSD wrap sites), failing the test-crates CI. Switches the field + new() to SharedState and drops the now-redundant Arc::new in the two DSD tests. Verified with scripts/cargo-test.sh (workspace, no UI): all crates green.

cc
2026-07-13 21:15:22 -06:00
vicrodh 8c50c16faa fix(offline): clarify that Clear cache keeps downloaded albums
After #606 the offline Clear-cache purges only the transient cache dirs (tracks/tracks-cmaf/artwork), never the organized downloaded albums — those are removed per-item from the offline manager. The old copy ('Remove every downloaded track. This cannot be undone.') was misleading. Relabels the row 'Clear cache', rewrites the description to say downloads are kept and point to the manager, and softens the toasts to 'Cache cleared' / 'Couldn't clear the cache'. 8 locales.

cc
2026-07-13 21:01:48 -06:00
vicrodh af1ccce398 chore(scripts): add prune-incremental.sh for stale incremental caches
Keeps only the most-recently-modified incremental-compilation dir per crate under crates/target and prunes the rest (slint-run.sh's per-RAM-tier RUSTFLAGS spawn a new hash dir each time; Cargo never GCs them). Release builds do not use incremental, so unaffected.

cc
2026-07-13 21:01:48 -06:00
vicrodh ba7be747a7 fix(immersive): persist volume on drag-end
The immersive VolumeBar only called set-volume (live) and never persist-volume, so a volume set in the immersive view was lost on restart/track-change. Adds a released(float) callback emitted on pointer-up, wired to NowPlayingState.persist-volume — parity with the NPB sliders. Pure .slint; persist-volume already exists in Rust.

cc
2026-07-13 21:01:48 -06:00
vicrodh 41f8578b78 feat(home): sort control for the Library Albums rail
Adds a compact dropdown in the Library Albums (favoriteAlbums) row header, left of the page chevrons: Recently added (default), First added (reverse), Random (shuffle). Reorders the cached base list in Rust with no re-fetch and re-fires artwork by the new index. Also corrects the stale HomeView comment that claimed the recently-played refresh lives in the toolbar (it is a row-header button). 8 locales updated.

cc
2026-07-13 21:01:48 -06:00
vicrodh dfc74fb6d4 Merge branch 'pr/606' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:27:23 -06:00
vicrodh 12dcedbc0f Merge branch 'pr/611' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:14:09 -06:00
vicrodh 0a4a6b6367 Merge branch 'pr/610' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:13:57 -06:00
vicrodh 30c57c9f54 Merge branch 'pr/608' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:13:57 -06:00
vicrodh 97ab577778 Merge branch 'pr/598' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:13:57 -06:00
vicrodh 3f974752ae Merge branch 'pr/595' into integration/pr-review-smoke-2026-07-13
# Conflicts:
#	crates/qbz-player/src/player/mod.rs
2026-07-13 14:13:47 -06:00
vicrodh 83c47933cb Merge branch 'pr/594' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:12:49 -06:00
vicrodh 7b0b2ed7da Merge branch 'pr/599' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:12:39 -06:00
vicrodh c2e23dfa95 Merge branch 'pr/593' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:12:39 -06:00
vicrodh 116fe38476 Merge branch 'pr/607' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:08:28 -06:00
vicrodh d4522c3585 Merge branch 'pr/604' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:08:28 -06:00
vicrodh 62dc3f55aa Merge branch 'pr/601' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:08:28 -06:00
vicrodh a88a38c644 Merge branch 'pr/600' into integration/pr-review-smoke-2026-07-13 2026-07-13 14:08:28 -06:00
vicrodh 4051f76970 merge: 2.0.2 follow-ups (renderer #558, circle-actions, palette, home refresh, np source)
cc
2026-07-13 13:12:05 -06:00
vicrodh b3d12e6b2c fix(playback): give the now-playing "source" button a per-track context
The "playing from" button read a single global context set once at play time;
refresh_now_playing_meta never republished it, so it went stale across track
changes (previous track's album) and single-track plays fell back to the
current track's album instead of the playlist it came from. Add per-track
context_kind/context_id to QueueTrack (serde-default None, back-compat), stamp
the real container at every play path (album/artist/playlist/label), and
republish the context from the current track on EVERY track change (gapless
included) — never cached. open-context routes all stamped kinds.

cc
2026-07-13 13:11:43 -06:00
vicrodh a174e06119 feat(home): auto-refresh recently-played rails + a row refresh button
Home's recently-played albums/tracks only populated on a full home load, so
tracks played mid-session never appeared until restart. Re-read the LOCAL
store into the rails when a track is recorded while Home is visible, and on
Home re-mount if it went dirty — event-driven, no polling, cheap (small JSON
read + cached artwork). Also add a manual refresh button in each recently-
played row header next to the page chevrons (moved off the top toolbar, where
it crowded the discovery tab bar).

cc
2026-07-13 13:11:43 -06:00
vicrodh 8df8c18ab0 fix(theme): sync std-widgets Palette to the active QBZ theme
Native std-widgets (LineEdit/TextEdit) render from Slint's own Palette, which
we never synced to the QBZ theme, so on a light theme their text collided with
its own background (Settings input fields, effectively invisible). Add
Theme.is-dark (computed in Rust from the surface luminance, so it is correct
for static/auto/custom themes) and drive Palette.color-scheme from it in the
AppWindow: light/dark follow the theme, System stays `unknown` (follows the
OS). Reactive on theme change.

cc
2026-07-13 13:11:12 -06:00
vicrodh a9dff18d25 fix(ui): make CircleAction buttons visible on light themes
CircleAction defaults to hardcoded light-on-dark colors, so every instance
sitting on the normal page background (not over artwork) vanished on light
themes. Set on-surface: true on those clusters — Popular Tracks (artist +
label), the PlaylistView hero row, LocalAlbumView, AwardView,
PurchaseDetailView, MixtapeDetailView, FavoritesView, LocalLibraryView — so
they use theme-appropriate colors. Buttons over artwork/dark headers keep the
light-on-dark defaults.

cc
2026-07-13 13:11:12 -06:00
vicrodh 80088b6a0b fix(renderer): keep the app alive when the wgpu surface goes Outdated (#558)
At a non-default UI scale, SLINT_SCALE_FACTOR changes the physical surface
size and the first frames race the winit resize/scale-factor event that
reconfigures the swapchain, so get_current_texture() returns Outdated. The
vendored femtovg-wgpu backend reconfigured and retried once, then propagated a
second Outdated via `?`, which killed the event loop and left the app unable
to start at any interface size other than default. Treat a persistent Outdated
like the #540 timeout: skip the frame and back off briefly; the next
resize/redraw reconfigures cleanly. wgpu now survives the scale race without
depending on the degradation ladder falling back to GL.

cc
2026-07-13 13:11:12 -06:00
vicrodh 957ac6503a merge: 2.0.2 fixes into pre-release
Kiosk polish + volume fluidity + playlist drag-reorder + quality badge, and
issue fixes: #491/#519 album/artist header, #534 snap audio, #573 plex sync,
#578 gpu tier, #588 trackpad scroll, #588/#590 quality, #591/#592 pipewire.

cc
2026-07-13 09:40:53 -06:00
vicrodh fa161be525 fix(header): gradient height = header container (ends at divider), artist-page parity, action buttons readable with gradient off
The album header gradient was a fixed px that overshot the header/track-list divider on tall (description-bearing) headers; bind its height to the divider's y so it ends exactly at the header container's bottom at any size. Apply the same readable-text + gradient-to-boundary treatment to the artist page. And CircleAction gains an on-surface variant (theme-colored fill/border/icon) driven by the gradient toggle, so when the header gradient is off the action buttons are visible on light themes instead of white-on-white. Below-divider content untouched. Extends #491/#519.

cc
2026-07-13 07:50:46 -06:00
vicrodh d0a7ded531 fix(audio): superseded plays skip the 60s initial-buffer wait; non-streaming path falls back to legacy
Follow-ups to #591/#592. The streaming initial-buffer wait blocked the audio thread up to 60s even when the play had been superseded by a newer track, which fed the stop/restart-loop feel; play_generation moved onto SharedState and threaded through PlayStreaming so a superseded wait exits in ~50ms (the 60s timeout stays for genuine slow networks). And the non-streaming Play path gained the same legacy-CPAL fallback the streaming path got, instead of dead-ending on backend-init failure (macOS keeps surfacing the error). Control flow only; sample path untouched.

cc
2026-07-13 05:01:22 -06:00
vicrodh c3523722f4 feat(local-library): add a Plex sync button to refresh media without restarting
Fetching new Plex music required restarting QBZ. Add a sync button in the Local Library header (gated on plex-available, with a busy spinner) that triggers the existing Plex re-sync (new plex_auth::sync_now over the persisted selected libraries) and refreshes the view. Strings in all 8 locales. Resolves #573.

cc
2026-07-13 04:44:08 -06:00
vicrodh 99cf738a4c fix(scroll): boost Wayland trackpad scroll speed in the vendored Flickable
Trackpad PixelDelta events arrive divided by the HiDPI scale factor, making trackpad scrolling far slower than other apps on scaled Wayland desktops. In FlickableData::scroll_delta, distinguish line-based wheel deltas (always exact multiples of 60) from pixel-precise trackpad deltas and apply a 2.75x factor to the latter only; wheel and fling scrolling are unchanged. Resolves #588.

cc
2026-07-13 04:44:08 -06:00
vicrodh f8a256c62d fix(audio): don't require pactl for PipeWire, and fall back to legacy on streaming init failure
Two stacked defects broke playback under sandboxes (Snap/Flatpak/minimal .deb) in 2.0.1: PipeWireBackend::is_available() probed only `pactl info`, which those images don't ship, so PipeWire reported unavailable even though it was running (native pw-dump enumeration succeeded in the same log). And the streaming stream-init path had no legacy fallback (unlike init_device), so a failure dead-ended into a stuck spinner until the 45s watchdog. is_available() now checks the pipewire-0 socket + pw-dump (both time-bounded, fail-fast) with pactl kept as a last fallback; the StartStreaming path falls back to legacy CPAL on non-macOS. Sample path untouched (no gain/resample/rate change). Addresses #591/#592.

cc
2026-07-13 04:44:08 -06:00
vicrodh 0f88361427 fix(album): readable header text on light themes + gradient reaches the divider
The header sits on the always-dark art atmosphere, but its text used Theme.text-* which is dark on a light theme = unreadable. Route the header title/artist/meta/description through hdr-strong/hdr-body colors that go white over the gradient and fall back to the theme colors when the gradient is off; below-divider text is untouched. The atmosphere also faded out above the divider on description-bearing headers — raise its height to 440px and push the fade start to 74% so it reaches the header/track-list divider. Addresses #491/#519.

cc
2026-07-13 04:28:26 -06:00
vicrodh f5a8afc0f2 fix(playlist): reorder via the existing row drag gesture, not a bespoke grip
The prior reorder reused only the DragGhost but re-implemented the drag gesture with its own grip + absolute-position math, which placed the ghost several px off the cursor. Remove the grip entirely and drive reorder off the SAME row-body drag that already adds a track to a sidebar playlist: it captures the source index on start, the shared DragGhost (positioned by the Rust DragActions path) follows the cursor exactly, the drop slot is read from DragState.pointer-y against the ListView's absolute-position (no row double-count), and releasing WITHIN the list reorders while releasing on a sidebar playlist still adds. Reverted the sidebar drop suppression + removed DragState.reorder.

cc
2026-07-13 02:45:10 -06:00
vicrodh 85e11d284a feat(quality): downgrade arrow + true-quality tooltip on the Now Playing badge
Follow-up to #590: playback now downgrades to the streaming-quality setting but the badge still showed the catalog max with no indicator. The poll loop already received the delivered stream's sample-rate/bit-depth in PlaybackEvent but dropped them; publish them plus a quality-downgraded flag (effective < catalog max, DSD-exempt on depth) and the true effective detail string. AudioStamp shows an amber down-arrow glyph when downgraded and a Source/Output hover tooltip; mirrored to the miniplayer. Strings translated in all 8 locales.

cc
2026-07-13 01:49:18 -06:00
vicrodh 6e58682aa6 fix(playlist): reuse the shared drag ghost for custom-order reorder
The bespoke reorder ghost read a row's absolute-position inside a ListView, which double-counts the row's own offset, so it only sat at the cursor for row 0 and flew off for the rest. Drive the app-wide DragState directly from the reorder gesture so the shared DragGhost (positioned in AppShell at the proven window coords) renders the reorder ghost; a new DragState.reorder flag keeps the sidebar from claiming it as an add-to-playlist drop and keeps the Rust DragActions path out of it. Removed the buggy local ghost. Reorder logic + persistence unchanged. (state.slint also carries the quality-badge fields for the next commit.)

cc
2026-07-13 01:29:09 -06:00
vicrodh 4210ec088a fix(playback): honor the streaming-quality setting
The Settings streaming-quality dropdown persisted the pref but playback used a hardcoded UltraHiRes const, so the setting did nothing. Resolve the pref (via a new streaming_quality_for_key mapping to the Quality format ids) at playback time for the normal, prefetch and gapless paths. Resolves #590.

cc
2026-07-13 00:19:51 -06:00
vicrodh c85686c473 feat(media-controls): inhibit system sleep/idle while playing (Linux)
QBZ let the machine suspend mid-playback. Take an org.freedesktop.login1 Inhibit (sleep:idle, block) fd while the MPRIS status is Playing and drop it on pause/stop, hooked to the same play-state channel MPRIS already uses. Linux-only, all failures log-and-continue. Resolves #522.

cc
2026-07-13 00:19:51 -06:00
vicrodh b3f866d933 fix(audio): treat D-Bus device-reservation name failure as non-fatal
Under Snap's mediated session bus, requesting the org.freedesktop.ReserveDevice name is denied and the error aborted ALSA Direct stream creation, so there was no audio. Fall back to the existing Degraded state (proceed without the reservation) on acquire failure, reusing the same non-fatal path the card-index / no-bus cases already take. Audio sample path untouched. Resolves #534.

cc
2026-07-13 00:19:51 -06:00
vicrodh 3174488d8e fix(renderer): classify Intel UHD 600 (Gemini Lake) as weak -> GL tier
It flickers on the wgpu tier; the reporter confirmed QBZ_RENDERER=gl fixes it. Added the uhd-600 markers to WEAK_GPU_MARKERS so it auto-selects the stable GL renderer. Resolves #578.

cc
2026-07-13 00:19:51 -06:00
vicrodh 256b0d36a0 fix(volume): kill the slider rubberband on release
The live-drag thumb reverted to the round-tripped bound value on release; because that value echoes back asynchronously the thumb snapped to the stale position then to the fresh one (a rubberband bounce). The thumb now tracks drag-fraction, which stays put on release and re-syncs to the external value only when it changes on its own (MPRIS / keyboard) while not dragging.

cc
2026-07-13 00:19:51 -06:00
vicrodh a0cca35810 fix(volume): live drag state on the slider primitives so the thumb follows the pointer
The de-quantization (0.1% scale + f32-bits atomic) removed the stepping in the VALUE, but the thumb still derived from the round-tripped bound value, so it felt snappy/laggy during a drag. Give QbzSlider/QbzVerticalSlider a live drag fraction: while held, the thumb tracks the pointer position directly (continuous, no round-trip); on release it reverts to the bound value. The emitted value is still the nearest step to the pointer (round), now imperceptible at the 0.1% scale.

cc
2026-07-12 23:38:34 -06:00
vicrodh e369f4bb3a chore(issue-template): require a logs checklist on bug reports
Adds a prominent 'bug reports need logs' banner and a required pre-flight checklist (attach logs or explain why not, searched duplicates, included repro steps). Without logs most reports stall on needs-info.

cc
2026-07-12 20:17:12 -06:00
vicrodh 42105eaf46 fix(volume): make the volume control fully fluid (de-quantize)
Volume snapped between 1% steps from two integer quantizers. UI: the volume sliders now use a 0..1000 scale so the shared int slider's round() lands on 0.1% (imperceptible). Runtime: the player volume atomic widened from integer-percent AtomicU64 to f32-bits AtomicU32 (same idiom as normalization_gain) so a continuous value no longer re-snaps on track restart / device switch / gapless. Bit-perfect untouched: 1.0f32 round-trips its bits, no gain multiply or ramp added to the protected ALSA-direct / DoP / JACK paths.

cc
2026-07-12 20:17:12 -06:00
vicrodh 2103bbd3eb feat(playlist): drag-and-drop reorder for custom-order tracks
Adds a dedicated drag HANDLE (grip) in the reorder gutter with the queue's drag gesture (6px threshold, absolute-position - root.y correction, three end paths incl. the changed-pressed safety net), so the row-body drag-to-sidebar stays intact. PlaylistView keeps component-local reorder state (slot math folds in the ListView viewport-y), a drop indicator and a floating ghost; commit fires PlaylistActions.reorder-track(from,to). Rust reuses the arbitrary-index persist path (repo::reorder for local, persist_custom for Qobuz) the arrows already back. Edge auto-scroll during drag is a follow-up TODO. Resolves #589.

cc
2026-07-12 20:17:12 -06:00
Victor RH 02cf9ad011 Merge pull request #586 from afonsojramos/bugfix/internal/cast-csprng-tokens
fix(cast): use CSPRNG media path tokens and redact URIs in logs
2026-07-12 19:40:03 -06:00
Victor RH 22a69a1db8 Merge pull request #585 from afonsojramos/bugfix/internal/dop-write-errors
fix(player): stop DoP writer on ALSA write failure
2026-07-12 19:40:00 -06:00
Victor RH db2f21289c Merge pull request #584 from afonsojramos/bugfix/internal/seek-engine-restore
fix(player): clear playing state when seek rebuild fails
2026-07-12 19:39:57 -06:00
Victor RH 287c3e93b5 Merge pull request #583 from afonsojramos/bugfix/internal/cancel-superseded-play
fix(player): cancel superseded play_track completions
2026-07-12 19:39:54 -06:00
Victor RH b99598e122 Merge pull request #582 from afonsojramos/bugfix/internal/log-redaction-all-sinks
fix(log): redact secrets on stderr and stop Last.fm body dumps
2026-07-12 19:39:51 -06:00
Victor RH 7fcbe1255a Merge pull request #581 from afonsojramos/bugfix/internal/queue-clear-keep-current
fix(queue): keep current_index track on clear(true)
2026-07-12 19:39:47 -06:00
Victor RH 9352a498a7 Merge pull request #574 from afonsojramos/ci/test-crates
ci: add test-crates workflow for workspace unit tests
2026-07-12 19:39:44 -06:00
vicrodh f4a6858f6b merge: kiosk profile (2.0.2 frente #3) into pre-release
Lightweight kiosk shell — profile boot (windowed default, fullscreen opt-in),
immersive mount, Now Playing redesign, Search All dashboard, lyrics lite-fill,
plus the owned-playlists Library fix.

cc
2026-07-12 19:39:17 -06:00
vicrodh d61b59223e fix(favorites): show owned playlists in the Library playlists tab
load_favorites built the Playlists Library sub-tab only from locally-hearted ids and the Following list excludes owner.id == uid, so the user's own playlists appeared nowhere. Seed the Library list with owned playlists first, then hearted-but-not-owned (dedup). Fixes desktop and kiosk.

cc
2026-07-12 19:38:43 -06:00
vicrodh ec8c487564 feat(lyrics): lite-fill display pref — static active-line highlight to cut CPU
The per-word karaoke sweep animates a clip rect ~60x/s, driving continuous full-window repaints (~4% CPU). Lite fill highlights the active line whole (no per-frame animation) so the surface only repaints on line changes. New toggle in the lyrics controls flyout, persisted via lyrics_prefs; default off (smooth karaoke). Kiosk / weak-GPU tiers force it on via ShellState.reduce-motion.

cc
2026-07-12 19:38:43 -06:00
vicrodh 5fa4e8bdd5 feat(kiosk): redesign Now Playing panel — dominant contain cover, compact meta, floating quality stamp
The cover is image-fit:contain filling the flex art area (no fragile parent-geometry math), so it is large and scales with the window. Toggle and meta rows get vertical-stretch:0 so only the art area takes the slack (nested layouts stretch greedily) — kills the dead space and the ~55px cover. Title toned to 20px, quality stamp floats on the transport row instead of owning a line. Cover<->Lyrics toggle; lyrics fill the panel width.

cc
2026-07-12 19:38:43 -06:00