feat(audio): JACK backend foundation (#263 Tier 3 — player wiring pending)

Backend-side foundation for a native JACK output. The hard, RT-sensitive part
is done and compiles: jack_backend.rs holds a JackStream that opens a JACK client
'qbz' with stable ports qbz:out_FL/FR, a lock-free SPSC ring buffer, and an
allocation-free process callback (de-interleaves stereo f32 to the ports). The
feeder pushes interleaved f32 via write_f32().

Also: jack 0.13 dep (linux), AudioBackendType::Jack + its factory arm + the
qbz-slint label/bit-perfect match arms. NOT yet offered in the selector
(available_backends push commented) because the player wiring is still pending:
StreamType::Jack + the dispatch branch (backend==Jack -> JackStream) + a
PlaybackEngine::Jack feeder thread that resamples each track to the JACK graph
rate. JACK mode will be opt-in and NOT bit-perfect (one fixed graph rate); the
ALSA-exclusive / DAC-passthrough bit-perfect paths are untouched.

TODO(distribution): feature-gate jack for Flatpak/distro builds without libjack.

cc
This commit is contained in:
vicrodh committed 2026-05-31 12:36:37 -06:00
1 parent d2c4aaf99c
commit fbc03f41b7
6 files changed
+279 -6

No files matched your search

+3 -1
View File
@@ -235,7 +235,8 @@ fn device_is_bit_perfect(backend: AudioBackendType, device: &qbz_audio::AudioDev
alsa_section(&device.id, device.is_default, label) == AlsaSection::BitPerfect
}
AudioBackendType::PipeWire => device.is_hardware,
AudioBackendType::Pulse | AudioBackendType::SystemDefault => false,
// JACK never bit-perfect (resampled to the graph rate); no per-device concept.
AudioBackendType::Pulse | AudioBackendType::SystemDefault | AudioBackendType::Jack => false,
}
}
@@ -245,6 +246,7 @@ fn backend_label(t: AudioBackendType) -> String {
AudioBackendType::Alsa => "ALSA",
AudioBackendType::Pulse => "PulseAudio",
AudioBackendType::SystemDefault => "System default",
AudioBackendType::Jack => "JACK",
}
.to_string()
}