Commit Graph
7031 Commits
Author SHA1 Message Date
vicrodh 9eedb278f6 test: gate the loudness cache, scan, amplify, analyser and start-gain suites in the CI mirror
cc
2026-09-13 11:37:11 -06:00
vicrodh 7c71c6bf52 feat(qt): the player bar keeps the content pane's gutter on every mode, wider on macOS
Every now-playing bar (New / Classic / Large / Small) is inset by the same
8 px the content pane keeps to its frame — left, right and bottom — behind
a frame-tier backdrop, so the bar's ends line up with the pane's, nothing
in it touches the window edge, and the gutter reads as one continuous
frame with the sidebar rather than a band of raw background. The Large
cover dock lifts with the bar. On macOS the gutter is 16 px: Tahoe's
Liquid Glass windows round their corners far more than before (larger
still around a toolbar) and clip whatever sits inside the curve — the
cover at the bar's left end lost its corner — and Qt has no LayoutRegion
to nest content into the curve, so the margin is the fix.

cc
2026-09-13 11:37:11 -06:00
vicrodh 228a6f12f3 chore(i18n): drop the retired Purchases placement strings from the seven translated catalogs
cc
2026-09-13 11:31:29 -06:00
vicrodh ae644dc163 feat(qt): header tab labels grow to the sidebar's 13 px when the room allows
The full text tabs kept an 11 px label at every width. The size now comes
from measuring the labels: 11 px stays the floor (the tabs beside the search
box at the 1140 px breakpoint), 12 or 13 px when every label plus its chrome
fits in the room left of the centred search box — 13 px being what the
sidebar rows and the flyout entries use, so with space the two hosts read
the same. Measured rather than a width breakpoint because the labels are
translated and their count changes (offline hides the Qobuz sections,
Purchases is opt-in).

cc
2026-09-13 11:31:28 -06:00
vicrodh db7ddc5edd feat(qt): Purchases follows the section navigation, sidebar or header
The separate "Purchases in title bar" placement toggle is gone: with Show
Purchases on, the entry sits wherever the other sections are — in the
sidebar while the navigation lives there, in the header beside the full
tabs or the compact buttons otherwise — so it is never the one entry left
behind. The nav_tb_purchases pref and its bridge key are retired; the
Show Purchases description says where the entry goes.

cc
2026-09-13 11:28:44 -06:00
vicrodh d22907b0e0 feat(qt): Settings > Audio > Loudness — normalization toggle, target loudness presets, clipping guard
The bars' audio flyout keeps its switch; Settings > Audio gains the same
key with its two companions: a Target loudness select (-11 / -14 default /
-16 / -18 / -23 LUFS, a value set elsewhere shows as a display-only
"Custom (N LUFS)" entry instead of being re-mapped) and the Prevent
clipping toggle. Eight catalogs updated.

cc
2026-09-13 11:25:22 -06:00
vicrodh ec7311ce54 feat(player): normalization gain known before the first sample
Start gain resolves from the loudness cache, then from ReplayGain tags in
the bytes; the catalog's own ReplayGain is fetched once per track alongside
the CMAF setup (and the cached replays, the disk replay and the gapless
download), and a prefetched track the catalog cannot describe is
pre-analysed in full (EBU R128 + true peak) off the audio thread, reading
the bytes back from the playback cache since the prefetch streams them
straight in. DynamicAmplify now starts AT that gain instead of ramping from
unity, the published normalization gain is the real one, and the four
seeding sites share one resolver (normalization::plan_start_gain).

cc
2026-09-13 11:09:16 -06:00
vicrodh 8c4b140ef8 fix(audio): the clipping guard only limits a boost, never attenuates
A track that needs no boost keeps unity (or its own attenuation) even when
its peaks already sit above the -1 dBTP headroom: that is the master's
doing, not ours. Without this, every hot modern master exactly at the
target lost ~0.5-1 dB the moment the guard saw its peak.

cc
2026-09-13 11:09:15 -06:00
vicrodh 8fef2466cc feat(settings): normalization clipping guard (audio.normalization_prevent_clipping)
A new audio setting, on by default: the normalization boost is capped so the
track's known peak stays 1 dB under full scale. Store column + migration,
portable in the settings bundle, shown in diagnostics, and settable from
qbzd (settings get/set audio.normalization_prevent_clipping).

cc
2026-09-13 11:05:15 -06:00
vicrodh 32a78f4a27 feat(audio): loudness cache stores absolute LUFS with peak and source; analyser applies the live gain once and glides
The cache kept a target-relative gain (a target change invalidated every
row) and was rewritten every 5 s, so a skip left a 5-second window behind.
Rows now hold integrated LUFS + true/sample peak + a ranked source that a
weaker measurement cannot overwrite; the last window of a track is stored
as the full-track figure, and nothing shorter than 30 s is stored at all.
The analyser no longer re-levels a track that started with a known gain,
moves the live gain at most once (a seek keeps it), measures true peak, and
DynamicAmplify glides over 400 ms instead of 50 while polling the shared
atomic every 1024 samples instead of every sample. loudness_scan is the
pure full-track measurement the player's pre-analysis will feed.

cc
2026-09-13 11:02:02 -06:00
vicrodh c817331ece merge: integrate player QoL round 3 into pre-release
cc
2026-09-13 10:55:31 -06:00
vicrodh 2cfbf9b66f merge: integrate static-review hardening into pre-release
cc
2026-09-13 10:55:31 -06:00
vicrodh e8351e57ba feat(qt): Settings sub-nav regrouped under an Advanced fold, with new glyphs
Audio, Playback, Appearance, Navigation, Local Library, Offline,
Integrations and Updates stay in the column; Blacklist, Storage,
Import / Export, Developer (and Orbit while enabled) move under an ADVANCED
disclosure row with a chevron. The fold is not persisted: it opens itself
whenever the current section lives inside it, and reads as active while
closed over the selected page. Appearance takes lucide's
paintbrush-vertical, Integrations unplug and Storage database — baked into
every tint and registered as masters. The kiosk selector follows the same
order, flattened. "Share logs" stays pinned at the bottom.

cc
2026-09-13 10:26:34 -06:00
vicrodh 198fbfc6fe feat(qt): the offline cache is purged from the manager only, with a tooltip and an explicit modal
Settings > Offline loses its "Clear cache" row: it ran the same
QbzOffline.clearAll() as the trash glyph in the Offline Cache Manager's
stats bar, so the whole cache had two entry points and one misleading text
("your downloaded albums are kept" — what is kept are the purchased
downloads in the music folder). The glyph now carries a hover tooltip (the
manager mounts the shared QbzTooltip overlay; the limit and folder glyphs
get one too) and its confirmation says exactly what goes — the live track
count and size — and what stays. The Tauri-era string leaves the eight
catalogs; the new ones enter them.

cc
2026-09-13 10:26:33 -06:00
vicrodh 9b93e58367 refactor(qt): Offline cache and Playback cache return to their own sections
Settings > Storage keeps only the caches that have no section of their own:
the artwork cache, the lyrics cache and the Plex mirror. The offline
downloads group goes back to Offline and the playback cache (memory profile,
usage, storage folder) back to Playback, since both configure the feature
they sit next to rather than disk in general. Rows and bridge verbs are
unchanged; the playback cache QML test instantiates PlaybackSettings again
(16/16) and the .po location comments follow the artwork rows to Storage.

cc
2026-09-13 10:09:59 -06:00
vicrodh 71eee01e4c feat(qt): featured artists on track rows are on by default
The preference stays (opt-out); an absent key reads as on so rows never
flash without the names before the first settings snapshot.

cc
2026-09-13 09:20:21 -06:00
vicrodh 29710342a2 feat(qt): Settings > Storage — every on-disk cache in one section
Offline downloads, the artwork cache, the lyrics cache, the Plex mirror and
the playback cache (memory profile + storage folder) move to a new Storage
section, each row keeping the bridge verb it had. Offline keeps the mode
rows, Playback keeps the behaviour rows, Plex keeps Disconnect.

cc
2026-09-13 09:09:30 -06:00
vicrodh 903952cacb fix(artwork): bound the image cache during use, make the budget a setting, sweep orphans
The boot trim alone let a long session grow the folder past the budget
again (an early release reached 1 GB). A trim now also runs on the
blocking pool every 16 MB of new originals, the budget comes from
ui_prefs image_cache_max_mb (100/200/500/1000 MB, 200 default), .img files
with no row older than an hour are swept at boot, and the settings
document carries the stats, the size options and a clear action.

cc
2026-09-13 09:09:29 -06:00
vicrodh 903dfbefc6 feat(qt): every name on the artist line is its own link
With featured performers shown, the line is one elided StyledText whose
names are separate links: the main artist opens its page as before; a
featured name opens its page when the album credits carry its id and the
search for that name otherwise. Rows send the names with ids resolved.

cc
2026-09-13 09:09:29 -06:00
vicrodh 04e5c50045 feat(qt): featured performers as a comma-separated list after the main artist
cc
2026-09-13 08:20:44 -06:00
vicrodh 9174b33b1b feat(qt): A-B loop from the player bar's + menu
Mark A, mark B, loop between them until cleared; local playback only,
never persisted, cleared on track change or a seek outside the section.
A 100 ms watcher reads the millisecond position and reissues the local
seek; the seekbar shows the section and its two marks.

cc
2026-09-13 03:50:29 -06:00
vicrodh 4824c672fa feat(qt): opt-in ±10 s skip buttons beside Previous and Next
Settings > Appearance > Player & Visuals, mirrored on QbzPlayer.showSkipTen;
hidden on hosts too narrow for the cluster.

cc
2026-09-13 03:50:28 -06:00
vicrodh 3ddb7cd083 feat(qt): QbzPlayer.seekBy with the seekbar's buffered-edge clamp
The keyboard seek never clamped to npSeekableMax; the shared helper now
does, so keys and the coming ±10 s buttons behave like a click on the bar.

cc
2026-09-13 03:50:28 -06:00
vicrodh 42d6087c6c feat(qt): bake the skip-back-10 and skip-forward-10 glyphs
cc
2026-09-13 03:50:10 -06:00
vicrodh c2c8d7de57 feat(qt): opt-in "feat." featured artists on the track-row artist line
Settings > Appearance > Player & Visuals. Qobuz rows only; the artist line
stays a single text so the artist link keeps its hit area.

cc
2026-09-13 03:50:10 -06:00
vicrodh 5e21fd12db ci(test-crates): gate the 2026-09 static-review regression suites
cc
2026-09-13 03:48:02 -06:00
vicrodh 30c2208a03 feat(qt): carry the featured artists on Qobuz track rows
cc
2026-09-13 03:48:02 -06:00
vicrodh 083e6ea172 fix(qt): format the blacklist Added date and the What's New release date in the user's locale
Both were rendered from a hardcoded English month table in Rust, invisible
to i18n. Rust now hands QML the raw timestamp / civil date and QML formats
it with Qt.formatDate(..., Locale.LongFormat) like the purchase views
already do.

cc
2026-09-13 03:48:02 -06:00
vicrodh a29eb624ce feat(qobuz): derive a track's featured artists from its performers credits
cc
2026-09-13 03:48:02 -06:00
vicrodh 196887534a chore: log the three failures that were silently discarded
Volume restore (desktop session and qbzd driver), a playback-thread panic
at stop, and a credentials decrypt failure (now naming the file and the
likely cause, without the inert legacy retry).

cc
2026-09-13 03:36:51 -06:00
vicrodh aff24e598b chore(offline-cache): drop the never-called LRU evictor and correct the comment that described it
get_tracks_for_eviction had no caller; the resolve-path comment claimed
check_cache_limit evicts by last_accessed_at, but it only refuses new
downloads — downloaded albums are kept by design.

cc
2026-09-13 03:36:51 -06:00
vicrodh 048fd37054 docs(qbzd): document the LAN-first bind and the token in the standalone README; posture line stops nagging gated setups
The public README never mentioned that the control API binds 0.0.0.0 by
default nor how to restrict it; the boot line also told users who had set
[server] token that anyone could control playback.

cc
2026-09-13 03:36:51 -06:00
vicrodh 08226a4ffd fix(cast): read timeout on the media-server proxy client
A stalled source server parked one media-server request thread forever;
a 30 s per-read timeout turns that into an io::Error the renderer sees.

cc
2026-09-13 03:36:51 -06:00
vicrodh acfded5a7e fix(account-migration): reuse an orphan "(migrated)" copy instead of creating a second one
plan() matched same-name twins but never looked for the copy name, so a
run interrupted between create_playlist and the ledger save produced a
duplicate copy on the next run.

cc
2026-09-13 03:36:50 -06:00
vicrodh 1006bc3ca1 fix(player): reject a zero sample rate or empty channel mask from codec params
The streaming sources unwrap NonZero::new on these values on the audio
thread; the decoded path already guarded both, the codec-params path did
not.

cc
2026-09-13 03:36:50 -06:00
vicrodh daf449baec fix(music-link): give the Tidal/proxy fast path a timeout and a shared client
Both requests built bare reqwest clients with no timeout; a stalled
connection parked the fast path forever and the Odesli fallback, which only
runs afterwards, never got its turn. One OnceLock client with the same
10 s / 5 s budget as odesli.rs.

cc
2026-09-13 03:36:50 -06:00
vicrodh 87410667ea fix(qobuz): keep signed CDN URLs out of CMAF fetch errors and redact CDN signature params
classify_reqwest formatted the raw reqwest error, whose Display embeds the
request URL with its hmac= token; the string is logged on every retry and
in the player's CMAF-failed warning. It now uses the URL-free helper the
legacy stream path already had, moved to qbz-qobuz::net_diag so both paths
share it. The log redaction layer additionally scrubs hmac=, Signature=,
Policy= and Key-Pair-Id= values.

cc
2026-09-13 03:36:50 -06:00
vicrodh d58fdf45b0 fix(log): never rotate a log file another live process is writing; qbzd logs to qbzd.log
open_log_file_at renamed the live file to .prev on every open, so a second
qbz launch (the #749 two-line qbz.log) or a qbzd in the same directory took
the running process's log away. Writers now hold a shared advisory lock on
<name>.lock; an opener that cannot take it exclusively appends instead of
rotating. The daemon gets its own qbzd.log.

cc
2026-09-13 03:36:50 -06:00
vicrodh e9b02cdedb fix(player): never panic the audio thread when the loudness cache cannot open
LoudnessCache::new failing (full disk, read-only profile, corrupt
loudness_cache.db) used to panic inside the audio thread, which is created
once in Player:🆕 playback was dead until restart while the log promised
the opposite. The cache now degrades to an in-memory session cache, then to
a disabled cache, and normalization keeps running.

cc
2026-09-13 03:36:50 -06:00
vicrodh c25ae457c1 fix(artwork): restore the shared image cache eviction lost with the Slint frontend
ImageCacheService::evict had no caller since 69ed61207 retired the Slint
app's spawn_evict, so ~/.cache/qbz/images grew without bound in 2.1.0 and
2.1.1. housekeeping() now trims it to the same 200 MB budget once per run,
in 64-row batches so the GUI thread is never parked behind the cache
mutex. evict is batched and covered by unit tests.

cc
2026-09-13 03:27:56 -06:00
vicrodh 5e739f658e merge: integrate 2.1.2 playback and library stabilization
cx
2026-09-13 02:57:34 -06:00
vicrodh e291eb3af4 fix: stabilize playback memory, local library sync and Qt settings
Add shared playback memory profiles, bounded disk-backed playback and storage
selection for desktop and daemon. Preserve gapless during streaming-only playback
and provide explicit cache eviction with playback confirmation.

Stop watcher read events and unchanged scans from rebuilding the local catalog.
Restore playlist/sidebar updates, folder availability feedback and player layout.
Add appearance presets and a radio-based cache settings panel with translated
trade-offs, plus consistent clipboard menus across visible Qt text editors.

Validate with Rust regressions, QML interaction tests, isolated release startup
and idle-library checks; extend the shared local and CI gates.

cx
2026-09-13 02:57:21 -06:00
vicrodh 3cf1f32177 merge: integrate updater recovery and installer into pre-release
cx
2026-09-12 16:25:14 -06:00
vicrodh 7a22fd6867 feat(updater): add native update channels and one-line installation
Support Flatpak portal updates and signed Windows MSI upgrades. Add the Linux/macOS installer for 2.1.2, release signing, translations and regression coverage.

cx
2026-09-12 16:25:08 -06:00
vicrodh 64ec3e2bc8 fix(updater): restore Qt release checks and signed installation
cx
2026-09-12 15:20:23 -06:00
vicrodh 6a02dcdd67 merge: integrate Orbit foundations into pre-release
cx
2026-09-12 13:02:38 -06:00
vicrodh 74e1610433 feat(orbit): add shared library foundations and gated host tools
Extract the HTTP host and catalog layer into qbz-control, preserve the
existing daemon API, and keep private session credentials out of SSE.

Scope library stores and scan workers to their host. Share bounded source
search and show Local results alongside Qobuz in the Qt search page.

Add the launch-gated Qt Orbit laboratory and persistent remote-context
banner. Let qbzd run --orbit own and administer its file library through
instance-scoped API and CLI operations. Full remote UI control remains
pending.

Validate library/control/daemon suites, Qt search and QML regressions,
two isolated daemon processes, Qt release build and final cargo check.

cx
2026-09-12 13:02:29 -06:00
vicrodh 6394ef176c chore: bump flake to 2.1.1
qbzVersion 2.1.1 and both tarball hashes from the published v2.1.1 assets
(nix-prefetch-url / sha256 at their final URLs).

cc
2026-09-11 17:19:05 -06:00
vicrodh 3a8c31339e Merge pre-release into main for 2.1.1
flake.nix: take pre-release's prebuilt-tarball flake (#744); main's
source-build variant with the 2.1.0 srcHash is superseded.

cc
2026-09-11 15:34:47 -06:00
vicrodh 456e12e114 docs(release-2.1.1): add the 2026-09-11 batch to the notes and metainfo
Resizable panels (#771), collapsible My QBZ sidebar, artist identity
matching (#768), album-card editions, queue ordering (#442), custom artwork
on cards, GNOME clipboard (#684) and dock icon, MPRIS after restore (#683),
and the prebuilt-tarball flake (#744). Release date moved to 2026-09-11.

cc
2026-09-11 15:34:08 -06:00