Merge branch 'pre-release' into feature/external/macos-qol
This commit is contained in:
10 files changed
+158
-11
No files matched your search
@@ -0,0 +1,117 @@
|
|||||||
|
# 1.2.11 — Exclusive Hardening
|
||||||
|
|
||||||
|
This release tightens bit-perfect playback on both fronts. macOS finally gets a real **CoreAudio Exclusive Mode** thanks to **@Vudgekek**'s first-class contribution (PR #391), and on Linux the player now actively **reserves the DAC** via the standard `org.freedesktop.ReserveDevice1` D-Bus protocol for the lifetime of an ALSA Direct stream. Both halves landed in the same cycle by happy coincidence — hence the codename.
|
||||||
|
|
||||||
|
Beyond audio, this is the largest **Local Library** release since the local engine landed: a new folder-tree mode, ephemeral playback that never writes to your library DB, and a metadata-grouped Albums tab that finally treats Plex as a first-class peer.
|
||||||
|
|
||||||
|
A new **Offline Cache Manager** view replaces the old Settings shortcut, with a configurable cache cap (5 GB default), live progress rings, and per-album expand. **Discord Rich Presence** lands as opt-in and works inside the Flathub sandbox via a small symlink bridge. macOS gets a proper title bar integration thanks to **@afonsojramos**, who continues to keep the macOS build healthy alongside this round of fixes.
|
||||||
|
|
||||||
|
Welcome to **@Vudgekek** and **@DoubleGate** as new contributors — thanks for the first PRs, and for taking the time to engage with the review process.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exclusive Audio
|
||||||
|
|
||||||
|
- **macOS CoreAudio Exclusive Mode** (PR #391, @Vudgekek) — bit-perfect playback on Apple hardware via `kAudioDevicePropertyHogMode`; exclusive stream recreation on track changes; CoreAudio device-rate checked against the requested track rate before claiming the device
|
||||||
|
- **macOS hardware volume alignment** — the exclusive device's hardware volume tracks qbz's volume slider when in exclusive mode (@Vudgekek)
|
||||||
|
- **macOS exclusive stream hardening** — defensive cleanup on stream errors and shutdown so a failed claim never strands the device (@afonsojramos)
|
||||||
|
- **Linux DAC reservation** — per-process zbus client acquires `org.freedesktop.ReserveDevice1` (the standard cross-app coordination protocol used by JACK, PipeWire, and PulseAudio) for the lifetime of an `AlsaDirectStream`; other apps see qbz as the sole DAC owner instead of getting silent, misleading "device busy" errors
|
||||||
|
- **Reserve-DAC toggle** — Settings → Audio adds an opt-out for the reservation, persisted in `audio_settings.db` alongside the existing backend choice
|
||||||
|
- **ALSA card resolution by id** — ALSA card matching now uses the stable card id (`hw:0`) instead of the long descriptive name; any plugin prefix is accepted and parse failures degrade gracefully
|
||||||
|
- **`audio_settings` defaults** — `backend_type` now defaults to a per-OS choice and migrates rows where the column was NULL on older installs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Local Library
|
||||||
|
|
||||||
|
- **Folder Tree mode** — new two-column layout with the folder tree on the left and a folder detail pane on the right; drag-resizable sidebar (default ×1.8), recursive multi-select, search with path-parents preserved, and a network-folder filter for shares that take a while to walk
|
||||||
|
- **Ephemeral folder playback** — pick a folder outside your watched library and play it without writing anything to the library DB, including CUE support, a format whitelist, ephemeral-aware gapless prefetch, and a session-restore filter so transient picks don't pin themselves
|
||||||
|
- **Albums tab — metadata-grouped** — the existing folder-grouped Albums view is now joined by a metadata-grouped variant that merges entries across folders (and Plex), with the full action bar (group/filter/sort/view/select)
|
||||||
|
- **Per-user Library tab order** — new modal to reorder, show, or hide tabs; persists per user; the active tab loader now triggers after preferences settle on mount, so the loader never hits the wrong tab
|
||||||
|
- **Plex per-track artwork** preserved during library scan; the same fix is applied to both scan loops, with a folder-lookup cache to avoid the second-loop regression
|
||||||
|
- **Compact album view** for the tree right pane, with selection + bulk actions, circular play, and a per-view track search
|
||||||
|
- **Multi-select coverage in Album Detail** (#381) — bulk action bar now reaches the album-detail tracklist as well
|
||||||
|
- **Local Library performance** — viewport-driven Plex hydration with a quality override map; batched track-quality with per-call timeout; sort pushed into SQL instead of `localeCompare` on the client
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Discord Rich Presence (#336)
|
||||||
|
|
||||||
|
- **Opt-in track display** with album, artist, and elapsed time
|
||||||
|
- **Native Discord** (deb / rpm / AUR builds) writes the IPC socket directly under `$XDG_RUNTIME_DIR` and works without setup
|
||||||
|
- **Discord-via-Flathub** — qbz reads the Discord-Flatpak app dir (with `:create` permission) and lays down its own `discord-ipc-{0..9}` symlinks pointing at it; the symlinks bridge the two sandboxes for the `discord-rich-presence` crate, which only knows the static path
|
||||||
|
- **Lazy bridge** — symlinks are only laid down after you enable the toggle in Settings, so users who never opt in never touch that filesystem path
|
||||||
|
- **Translations** — keys for all five locales (en/es/de/fr/pt)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Offline Cache Manager
|
||||||
|
|
||||||
|
- **Dedicated view** replaces the old "Open folder" shortcut in Settings; navigate via the new sidebar entry or the Manage offline cache button
|
||||||
|
- **Album rows** with expand-by-default, per-track actions, album cover artwork, and live progress rings on both album and track rows
|
||||||
|
- **Alpha-index artist rail** — jump to artists alphabetically; empty-state CTA when nothing is cached yet
|
||||||
|
- **Cache size limit** — modal to set a configurable cap (default bumped from 2 GB to 5 GB), persisted across restarts; new track downloads enforce the limit
|
||||||
|
- **Re-download flow** — copy renamed from "Re-download album" to "Re-download all tracks" to match what actually happens
|
||||||
|
- **Excluded from `last_view` persistence** — opening the manager doesn't pin it on next launch
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sleep Timer (#402)
|
||||||
|
|
||||||
|
- **Hard-stop pause** — at expiry the player pauses cleanly (no fadeouts that overrun the deadline)
|
||||||
|
- **Smart-positioned popover** with refined typography; custom durations from 1 minute upward
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Title bar
|
||||||
|
|
||||||
|
- **macOS integration** (@afonsojramos) — qbz custom titlebar now mounts on macOS with traffic-light reservation, drag band aligned to sidebar top padding; new nav and search titlebar toggles plus a hide-title-bar toggle in Settings; legacy macOS overlay drag region retired
|
||||||
|
- **Mode selector** — Settings → Appearance → Title bar replaces the hide/system toggles with a `system / plasma / stripped` dropdown; legacy preferences are migrated, sandbox/Wayland caveats are surfaced as inline hints
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## QConnect
|
||||||
|
|
||||||
|
- **Startup persistence** — new `startup_mode` (Auto / Always-on / Disabled) and `last_known_state` write-through on connect/disconnect, both persisted; settings dropdown surfaces the choice with a local-library hint
|
||||||
|
- **CLI override** — `--enable-qconnect` and `--disable-qconnect` flags applied during app setup
|
||||||
|
- **Honor peer-controller seeks** when qbz is the active renderer — peer-driven seeks no longer get clobbered by the local cursor-align
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Album & Artist detail polish
|
||||||
|
|
||||||
|
- **Header gradient backdrop** — palette-derived gradient and blurred artwork on Album/Artist detail
|
||||||
|
- **Album metadata enrichment** — featured artist line, parental warning badge, click-to-expand description, tracklist toolbar, label/awards sidebar shrunk by ~20%
|
||||||
|
- **Tracklist columns aligned** with smooth select-mode toggle
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Immersive background
|
||||||
|
|
||||||
|
- **Kawarp WebGL renderer** replaces the legacy WebGL2 path in `Full` mode; attribution added to the About modal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bug fixes
|
||||||
|
|
||||||
|
- **Mixtape detail** — virtualized list scroll-up behavior stabilized
|
||||||
|
- **Library** — Albums tab visible in Edit Library Tabs modal; Plex albums included in metadata-grouped Albums view
|
||||||
|
- **Audio (Linux)** — host stream drop deferred on Stop so the device can be reused across track changes (@afonsojramos)
|
||||||
|
- **Audio (macOS)** — output device picker populated; the 50 ms post-stop sleep is now gated to `cfg(target_os = "linux")` (@afonsojramos)
|
||||||
|
- **Playback** — uniform 250 ms state polling cadence eliminates seekbar cold-start latency
|
||||||
|
- **Playlist** — track-selection key includes the row index for duplicate tracks (#386); multi-select is now aligned with the TrackRow checkbox pattern; the checkbox input is pointer-transparent so the row click handler always fires
|
||||||
|
- **Sidebar** — `isOffline` `$effect` skips its initial subscription so a stale value doesn't flip the offline indicator on mount (@DoubleGate, PR #384)
|
||||||
|
- **Home** — sticky tab header pop-in animation unified across the macOS and Linux paths (@afonsojramos, PR #407)
|
||||||
|
- **Theme** — WCAG-aware `btn-primary-text` token across all themes (the previous fixed value failed contrast on a couple of light themes)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Internal & packaging
|
||||||
|
|
||||||
|
- **Node 20 → 24** across CI workflows and the Flatpak manifest
|
||||||
|
- **Dependency bumps** — Tauri 2.10.3 → 2.11.1, openssl 0.10.79, tokio 1.52.1, axum 0.8.9, sha2 0.11.0, mdns-sd 0.19.1, plus the usual minor/patch swarm
|
||||||
|
- **Flatpak permissions** — the manifest now declares `--filesystem=xdg-run/discord-ipc-0` and `--filesystem=xdg-run/app/com.discordapp.Discord:create` for the lazy Discord IPC bridge
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Full changelog: https://github.com/vicrodh/qbz/compare/v1.2.10...v1.2.11
|
||||||
@@ -15,10 +15,10 @@
|
|||||||
# VERSION BUMP: update version, rev, and hashes
|
# VERSION BUMP: update version, rev, and hashes
|
||||||
# when tagging a new release.
|
# when tagging a new release.
|
||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
qbzVersion = "1.2.10";
|
qbzVersion = "1.2.11";
|
||||||
qbzRev = "v${qbzVersion}";
|
qbzRev = "v${qbzVersion}";
|
||||||
srcHash = "sha256-cPe7J0KtcTQFfjhNL9giRPLx2VwHsUYRDV/ZM/2dFas=";
|
srcHash = "sha256-6KAm9dZBNwjEcmaKTWSq4r91Cu1f6Fqr3G9Z//FaOCU=";
|
||||||
npmHash = "sha256-MYBxnLGSz4MyrpdNKUIBtnA6HFimPwrcEOYOGSbS5AY=";
|
npmHash = "sha256-Iz5QzSsMhP/82kANYOhZftX7n1wrLeTUI5Hda/JM0pE=";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages.default = pkgs.rustPlatform.buildRustPackage rec {
|
packages.default = pkgs.rustPlatform.buildRustPackage rec {
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "qbz-nix",
|
"name": "qbz-nix",
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "qbz-nix",
|
"name": "qbz-nix",
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@icons-pack/svelte-simple-icons": "^7.2.0",
|
"@icons-pack/svelte-simple-icons": "^7.2.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "qbz-nix",
|
"name": "qbz-nix",
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"description": "Native high-fidelity client for Qobuz™ subscribers on Linux with Hi-Fi audio support (uses the Qobuz API; not certified by Qobuz)",
|
"description": "Native high-fidelity client for Qobuz™ subscribers on Linux with Hi-Fi audio support (uses the Qobuz API; not certified by Qobuz)",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -69,6 +69,26 @@
|
|||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="1.2.11" date="2026-05-09">
|
||||||
|
<description>
|
||||||
|
<p>Exclusive Hardening: bit-perfect playback gets reinforced on both ends — macOS gains a real CoreAudio Exclusive Mode (community PR by @Vudgekek) and Linux now reserves the DAC via the standard ReserveDevice1 D-Bus protocol while ALSA Direct is engaged.</p>
|
||||||
|
<ul>
|
||||||
|
<li>macOS Exclusive Mode: bit-perfect playback on Apple hardware (PR #391); CoreAudio device-rate check, exclusive stream recreation, and hardware volume alignment</li>
|
||||||
|
<li>Linux DAC reservation: per-process zbus client acquires org.freedesktop.ReserveDevice1 for the lifetime of an ALSA Direct stream, with a Settings toggle</li>
|
||||||
|
<li>Discord Rich Presence (#336): opt-in track display with a sandbox-aware Flatpak socket bridge — symlinks discord-ipc-{0..9} only after the user enables the toggle</li>
|
||||||
|
<li>Sleep Timer (#402): pause-on-end with a smart-positioned popover, custom values from 1 minute upward</li>
|
||||||
|
<li>Offline Cache Manager: dedicated view replacing the old Settings shortcut, with per-album expand, alpha-index artist rail, live progress rings, and a configurable cache cap (5 GB default)</li>
|
||||||
|
<li>Local Library: new folder-tree mode with two-column layout, recursive multi-select, drag-resizable sidebar, search with path-parents preserved, and network-folder filter</li>
|
||||||
|
<li>Local Library: ephemeral folder playback that doesn't write to the library DB, with CUE support, format whitelist, and gapless prefetch</li>
|
||||||
|
<li>Local Library: metadata-grouped Albums tab (with Plex inclusion) and per-user tab order modal</li>
|
||||||
|
<li>macOS title bar integration (@afonsojramos): qbz custom titlebar mounts on macOS with traffic-light reservation, plus nav/search/hide toggles in Settings</li>
|
||||||
|
<li>Title bar mode selector replaces the hide/system toggles with a system/plasma/stripped dropdown</li>
|
||||||
|
<li>QConnect startup persistence: startup_mode and last_known_state on disk, plus --enable-qconnect / --disable-qconnect CLI flags</li>
|
||||||
|
<li>Album and artist detail polish: palette-derived gradient backdrops, featured artist line, parental warning, click-to-expand description, tracklist toolbar</li>
|
||||||
|
<li>Bug fixes: Plex per-track artwork preserved during scan; macOS output device picker populated; uniform 250ms playback poll cadence; QConnect honors peer-controller seeks; playlist multi-select aligned with TrackRow</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="1.2.10" date="2026-04-29">
|
<release version="1.2.10" date="2026-04-29">
|
||||||
<description>
|
<description>
|
||||||
<p>Fix an issue with gapless play introduced by a new feature in 1.2.9.</p>
|
<p>Fix an issue with gapless play introduced by a new feature in 1.2.9.</p>
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
name: qbz-player
|
name: qbz-player
|
||||||
title: "QBZ — Native Qobuz Client for Linux"
|
title: "QBZ — Native Qobuz Client for Linux"
|
||||||
version: '1.2.10'
|
version: '1.2.11'
|
||||||
summary: Native Qobuz player for Linux with bit-perfect audio and DAC control
|
summary: Native Qobuz player for Linux with bit-perfect audio and DAC control
|
||||||
description: |
|
description: |
|
||||||
QBZ is a native Linux desktop client for Qobuz™, designed for high-fidelity playback.
|
QBZ is a native Linux desktop client for Qobuz™, designed for high-fidelity playback.
|
||||||
|
|||||||
Generated
+1
-1
@@ -5148,7 +5148,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "qbz-nix"
|
name = "qbz-nix"
|
||||||
version = "1.2.10"
|
version = "1.2.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "qbz-nix"
|
name = "qbz-nix"
|
||||||
version = "1.2.10"
|
version = "1.2.11"
|
||||||
description = "Native high-fidelity client for Qobuz™ subscribers on Linux with Hi-Fi audio support (uses the Qobuz API; not certified by Qobuz)"
|
description = "Native high-fidelity client for Qobuz™ subscribers on Linux with Hi-Fi audio support (uses the Qobuz API; not certified by Qobuz)"
|
||||||
authors = ["blitzkriegfc"]
|
authors = ["blitzkriegfc"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "QBZ",
|
"productName": "QBZ",
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"identifier": "com.blitzfc.qbz",
|
"identifier": "com.blitzfc.qbz",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
<span class="label">{$t('about.buildInfo.version')}</span>
|
<span class="label">{$t('about.buildInfo.version')}</span>
|
||||||
<span class="value">{appVersion}</span>
|
<span class="value">{appVersion}</span>
|
||||||
<span class="label">{$t('about.buildInfo.codename')}</span>
|
<span class="label">{$t('about.buildInfo.codename')}</span>
|
||||||
<span class="value codename">Quiet Polish</span>
|
<span class="value codename">Exclusive Hardening</span>
|
||||||
<span class="label">{$t('about.buildInfo.license')}</span>
|
<span class="label">{$t('about.buildInfo.license')}</span>
|
||||||
<span class="value">MIT</span>
|
<span class="value">MIT</span>
|
||||||
<span class="label">{$t('about.buildInfo.platform')}</span>
|
<span class="label">{$t('about.buildInfo.platform')}</span>
|
||||||
@@ -190,6 +190,16 @@
|
|||||||
AdamArstall
|
AdamArstall
|
||||||
<ExternalLink size={10} />
|
<ExternalLink size={10} />
|
||||||
</button>
|
</button>
|
||||||
|
<button class="contributor-link" onclick={() => handleOpenUrl('https://github.com/Vudgekek')}>
|
||||||
|
<img src="https://github.com/Vudgekek.png?size=28" alt="Vudgekek" class="contributor-avatar" />
|
||||||
|
Vudgekek
|
||||||
|
<ExternalLink size={10} />
|
||||||
|
</button>
|
||||||
|
<button class="contributor-link" onclick={() => handleOpenUrl('https://github.com/DoubleGate')}>
|
||||||
|
<img src="https://github.com/DoubleGate.png?size=28" alt="DoubleGate" class="contributor-avatar" />
|
||||||
|
DoubleGate
|
||||||
|
<ExternalLink size={10} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user