fix(qt): platform capability flags, and hide the audio rows nothing can honour
Adds isWindows, traySupported, systemNotificationsSupported and rendererSelectable to the settings document, so Settings QML keeps reading ONE document the way it already does for isMacos. The two any(...) lists flip to include Windows when plan A-2 T3/T5 land; they point at that line. Then the Audio tab, measured on the box with the tab open: HiFi Wizard was live on Windows. qbz-dac-wizard-core generates a PipeWire/WirePlumber config and knows no other stack, so the wizard cannot finish anywhere but Linux. Hidden, not disabled - a disabled row invites a bug report. This is not the reference's backend-is-pipewire gate returning: inside Linux every backend still sees it, per the 2026-08-11 ruling in that file's own comment. Reserve DAC is D-Bus org.freedesktop.ReserveDevice1, Linux only. On Windows exclusive mode IS the reservation; on macOS it is Hog Mode. Exclusive mode was visible with no backend able to honour it. It now follows the backend: Linux unchanged (always visible, enabled only on ALSA), hidden on macOS, and on Windows it appears when Phase B publishes backendIsWasapi. QML reads an absent doc property as undefined and undefined === true is false, so this is correct today and correct again the day the field lands. The DSD row follows the same pair. Main.qml no longer boots the wizard off Linux, where its row is hidden and the audio-stack probe would reach nothing. Linux sees no change: every gate is isLinux-true or an added || on a field that is undefined there. Five QML audits pass. cc
This commit is contained in:
3 files changed
+48
-3
No files matched your search
@@ -355,6 +355,9 @@ ApplicationWindow {
|
||||
// all stay at their defaults, and nothing would be logged on either
|
||||
// side. The wizard is the loudest case after QbzBlacklist, because its
|
||||
// first step ends on "Checking your audio stack…" forever.
|
||||
// Linux only: the wizard's row is hidden elsewhere (AudioSettings.qml),
|
||||
// so booting it would spin up an audio-stack probe nothing can reach.
|
||||
if (QbzShell.isLinux)
|
||||
QbzDacWizard.boot()
|
||||
// Offline Cache Manager. Nothing to seed — the view is unmounted until
|
||||
// the Settings row opens it — but without this line the manager's very
|
||||
|
||||
@@ -150,7 +150,7 @@ Column {
|
||||
}
|
||||
}
|
||||
SettingRow {
|
||||
visible: root.doc.backendIsAlsa === true
|
||||
visible: root.doc.backendIsAlsa === true || root.doc.backendIsWasapi === true
|
||||
label: QbzSession.tr("DSD playback", QbzSession.trRev)
|
||||
description: QbzSession.tr("How DSD tracks reach the DAC. WARNING: choose DoP or Native only if your DAC supports it — on any other DAC they play as loud noise. Volume is fixed and seeking is disabled in DoP/Native mode. Native additionally needs kernel support for the DAC.", QbzSession.trRev)
|
||||
QbzSelect {
|
||||
@@ -174,6 +174,12 @@ Column {
|
||||
// Opening it resets the wizard and kicks the audio-stack probe off the UI
|
||||
// thread, so there is nothing to arm here.
|
||||
SettingRow {
|
||||
// The generated config is PipeWire/WirePlumber and qbz-dac-wizard-core
|
||||
// knows no other stack, so off Linux the wizard cannot finish. Hidden,
|
||||
// not disabled: a disabled row invites a bug report. This is NOT the
|
||||
// reference's `backend-is-pipewire` gate coming back - within Linux
|
||||
// every backend still sees it, which is the owner ruling above.
|
||||
visible: QbzShell.isLinux
|
||||
label: QbzSession.tr("HiFi Wizard", QbzSession.trRev)
|
||||
description: QbzSession.tr("Auto-detect your DACs and set up bit-perfect playback, step by step.", QbzSession.trRev)
|
||||
SettingsButton {
|
||||
@@ -190,16 +196,29 @@ Column {
|
||||
// =========================== BIT-PERFECT =============================
|
||||
GroupHeader { text: QbzSession.tr("BIT-PERFECT", QbzSession.trRev) }
|
||||
SettingRow {
|
||||
// Hidden where no backend can honour it: on Windows until WASAPI
|
||||
// exclusive lands (Phase B publishes backendIsWasapi), and on macOS,
|
||||
// whose only backend is System default. Linux is unchanged - visible
|
||||
// always, enabled only on ALSA.
|
||||
//
|
||||
// `backendIsWasapi` does not exist yet; QML reads an absent doc
|
||||
// property as `undefined`, and `undefined === true` is false, so this
|
||||
// is correct today and becomes correct again the day the field lands.
|
||||
visible: QbzShell.isLinux || root.doc.backendIsWasapi === true
|
||||
label: QbzSession.tr("Exclusive mode", QbzSession.trRev)
|
||||
description: QbzSession.tr("Lock the device so no other app can resample it.", QbzSession.trRev)
|
||||
rowEnabled: root.doc.backendIsAlsa === true
|
||||
rowEnabled: root.doc.backendIsAlsa === true || root.doc.backendIsWasapi === true
|
||||
QbzToggle {
|
||||
checked: root.doc.exclusiveMode === true
|
||||
enabled: root.doc.backendIsAlsa === true
|
||||
enabled: root.doc.backendIsAlsa === true || root.doc.backendIsWasapi === true
|
||||
onToggled: function (v) { QbzBridge.settingsBool("exclusive-mode", v) }
|
||||
}
|
||||
}
|
||||
SettingRow {
|
||||
// D-Bus org.freedesktop.ReserveDevice1, which is Linux only. On
|
||||
// Windows exclusive mode IS the reservation (Phase B); on macOS it is
|
||||
// Hog Mode.
|
||||
visible: QbzShell.isLinux
|
||||
label: QbzSession.tr("Reserve DAC while running", QbzSession.trRev)
|
||||
description: QbzSession.tr("Hold the device reserved so other apps can't grab it.", QbzSession.trRev)
|
||||
QbzToggle {
|
||||
|
||||
@@ -1812,6 +1812,20 @@ pub struct SettingsDoc {
|
||||
/// `AppearanceState.is-macos`.
|
||||
#[serde(rename = "isMacos")]
|
||||
pub is_macos: bool,
|
||||
#[serde(rename = "isWindows")]
|
||||
pub is_windows: bool,
|
||||
/// A tray backend exists on this platform (`tray_qt::init` would create
|
||||
/// one). Phase A: Linux + macOS. Plan A-2 Task 5 adds Windows.
|
||||
#[serde(rename = "traySupported")]
|
||||
pub tray_supported: bool,
|
||||
/// `notify.rs` has a real arm here. Phase A: Linux + macOS. Plan A-2
|
||||
/// Task 3 adds Windows.
|
||||
#[serde(rename = "systemNotificationsSupported")]
|
||||
pub system_notifications_supported: bool,
|
||||
/// The RENDERER group offers a real choice: Linux (Vulkan/GL/software)
|
||||
/// and Windows (D3D11/D3D12/GL/software). macOS is always Metal.
|
||||
#[serde(rename = "rendererSelectable")]
|
||||
pub renderer_selectable: bool,
|
||||
#[serde(rename = "trayIconThemes")]
|
||||
pub tray_icon_themes: Vec<String>,
|
||||
#[serde(rename = "trayIconThemeIndex")]
|
||||
@@ -2256,6 +2270,15 @@ pub async fn publish_snapshot() {
|
||||
.map(|t| t.mac_hide_dock)
|
||||
.unwrap_or(false),
|
||||
is_macos: cfg!(target_os = "macos"),
|
||||
is_windows: cfg!(target_os = "windows"),
|
||||
// When plan A-2 T3/T5 land, add target_os = "windows" to these
|
||||
// two lists; those plans point at this line.
|
||||
tray_supported: cfg!(any(target_os = "linux", target_os = "macos")),
|
||||
system_notifications_supported: cfg!(any(
|
||||
target_os = "linux",
|
||||
target_os = "macos"
|
||||
)),
|
||||
renderer_selectable: cfg!(any(target_os = "linux", target_os = "windows")),
|
||||
tray_icon_themes: TRAY_ICON_LABELS.iter().map(|l| qbz_i18n::t(l)).collect(),
|
||||
tray_icon_theme_index: tray()
|
||||
.get_settings()
|
||||
|
||||
Reference in new issue
Block a user