chore(qbz-audio): polish AlsaDirectStream reservation wiring

- Skip the 50 ms PipeWire-vacate margin on the degraded D-Bus path;
  no reservation transition happened, so no settle delay is needed.
- Add TODO(Task 5) breadcrumb for the app_device_name placeholder
  so Task 5's UI surfacing wires it to the user-facing DAC name.
- Soften the timing-claim comment on the sleep; the specific "~2-4 ms"
  was spec-cited, not measured in this commit.
- Lift the 50 ms literal into a named PIPEWIRE_VACATE_MARGIN const.

No behaviour change for the active-reservation path.

cc
This commit is contained in:
vicrodh committed 2026-05-07 10:19:59 -06:00
1 parent 92633dcf12
commit 6b7ed75cc9
1 file changed
+21 -6
+21 -6
View File
@@ -46,6 +46,15 @@ pub struct AlsaDirectStream {
device_id: String,
}
/// Defensive settle delay between reservation acquisition and PCM open.
///
/// Only applied when the reservation actually transitioned ownership (i.e.
/// `DeviceReservation::is_active()` is `true`). Sized conservatively; do not
/// reduce without revisiting the Lifetime-A safety contract in
/// `qbz-nix-docs/specs/2026-05-07-alsa-exclusive-hardening-design.md`.
#[cfg(target_os = "linux")]
const PIPEWIRE_VACATE_MARGIN: std::time::Duration = std::time::Duration::from_millis(50);
#[cfg(target_os = "linux")]
impl AlsaDirectStream {
/// Create new ALSA direct stream
@@ -66,9 +75,8 @@ impl AlsaDirectStream {
// This is the canonical Lifetime-A consumer the `acquire` doc-comment's
// tight-coupling rule allows: a `DeviceReservation` is created
// immediately before a real `PCM::new()` and held for as long as that
// PCM is open. The 50 ms sleep below gives PipeWire a defensive margin
// to vacate the device after releasing the reservation; observed ~2-4 ms
// in practice on the dev box but kept conservative.
// PCM is open.
// TODO(Task 5): replace second arg with user-facing DAC name from settings.
let reservation =
crate::DeviceReservation::acquire(device_id, device_id).map_err(|e| {
format!(
@@ -77,9 +85,16 @@ impl AlsaDirectStream {
)
})?;
// Defensive margin between reservation acquisition and PCM open. Do not
// reduce or remove without an explicit instruction from the user.
std::thread::sleep(std::time::Duration::from_millis(50));
// Defensive margin only matters when the reservation actually displaced
// a holder (or could have). On the degraded D-Bus path the bus name is
// not held at all, so PipeWire's view of the device hasn't changed and
// no settle delay is needed. PIPEWIRE_VACATE_MARGIN is conservative;
// PipeWire-side release latency is typically much shorter, but this
// margin is part of the design spec's Lifetime-A safety contract — do
// not reduce without revisiting the spec.
if reservation.is_active() {
std::thread::sleep(PIPEWIRE_VACATE_MARGIN);
}
// Open PCM device
let pcm = PCM::new(device_id, Direction::Playback, false)