feat(qt): HiFi Wizard — guided DAC setup ported from Slint

Six-step modal (Welcome / Check / DACs / Configure / Test / Done) opened
from Settings > Audio. It probes the audio stack and renders per-distro
remediations, enumerates DACs with a manual node.name escape hatch,
generates the PipeWire / WirePlumber snippets to copy, and plays four
tracks spanning 16/44.1 to 24/192 with a live requested-vs-negotiated
read-back. Read-only: it never writes a system file or runs a command.

The logic was unreachable from Qt — every public function in
qbz-dac-wizard takes a &AppWindow and writes straight into Slint globals.
It is lifted into a new frontend-agnostic crate, qbz-dac-wizard-core,
which returns plain data. qbz-dac-wizard itself is left untouched.

Rust owns everything it computes plus `open`, so the reset and the probe
are one act; QML owns the step navigation and the four progress
checkboxes, which is how the reference splits them too.

Two deliberate divergences from the reference: the row sits at the end of
OUTPUT rather than BIT-PERFECT, and it is offered on every backend
instead of PipeWire only — someone on ALSA direct is exactly who needs
the walkthrough.

The green glyphs use the accent tint, not success: success has no qrc bake
directory, so a degraded tint set would render nothing at all. Every
success-toned text keeps theme.success (#3fae6a verbatim).

Verified by 309 tests, both QML audits and the offscreen smoke, plus a
forced-route probe that mounts Settings and walks the wizard's steps —
the standard smoke only mounts Home, so it is no evidence for a modal.
The modal was also driven and screenshotted over VNC.

cc
This commit is contained in:
vicrodh committed 2026-08-11 11:26:50 -06:00
1 parent 79e3cdc46b
commit 8ba9483462
28 files changed
+3983 -3

No files matched your search

+8
View File
@@ -273,6 +273,14 @@ ApplicationWindow {
// importer makes (the whole progress panel, the log, the summary) is
// dropped on the floor with nothing logged on either side.
QbzPlaylistImport.boot()
// HiFi Wizard. Nothing to seed — the modal is closed until the
// Settings > Audio row opens it — but without this line every publish
// the wizard makes is dropped on the floor: the health verdict, the
// enumerated DACs, the generated config and the live read-back would
// 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.
QbzDacWizard.boot()
// Miniplayer (2026-08-03 miniplayer/tray contract, block B1). Booted
// like every other domain singleton, after QbzSession: `boot()` is what
// registers the Qt-thread hop, and without it `mini_bridge::ui()` is a