From c6510a7174c7ace2d32e74c76295a5b77dad35ac Mon Sep 17 00:00:00 2001 From: Roderick van Domburg Date: Sun, 20 Sep 2026 21:21:59 +0200 Subject: [PATCH] refactor(audioworklet,pulseaudio): use common wait_for_drain helper --- src/host/audioworklet/mod.rs | 9 ++------- src/host/mod.rs | 25 +++++++++++++++++++++++-- src/host/pulseaudio/stream.rs | 13 +++++-------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/host/audioworklet/mod.rs b/src/host/audioworklet/mod.rs index b25503580..5acfd39fe 100644 --- a/src/host/audioworklet/mod.rs +++ b/src/host/audioworklet/mod.rs @@ -24,7 +24,7 @@ use crate::{ DeviceDirection, DeviceId, DuplexCallbackInfo, DuplexStreamConfig, Error, ErrorKind, FrameCount, Sample, SampleFormat, SampleRate, StreamConfig, StreamInstant, StreamTimestamp, SupportedBufferSize, SupportedStreamConfig, SupportedStreamConfigRange, - host::frames_to_duration, + host::{frames_to_duration, secs_to_nanos}, traits::{DeviceTrait, HostTrait, StreamTrait}, }; @@ -1369,10 +1369,5 @@ fn total_latency_nanos(ctx: &web_sys::AudioContext) -> u64 { .unwrap_or(0.0) }; // `baseLatency` is fixed for the context lifetime; `outputLatency` can change. - let secs = read("baseLatency") + read("outputLatency"); - if secs.is_finite() && secs > 0.0 { - (secs * 1_000_000_000.0).round() as u64 - } else { - 0 - } + secs_to_nanos(read("baseLatency") + read("outputLatency")) } diff --git a/src/host/mod.rs b/src/host/mod.rs index 3d4446d86..801d94cff 100644 --- a/src/host/mod.rs +++ b/src/host/mod.rs @@ -277,7 +277,16 @@ pub(crate) const fn frames_to_duration( /// Converts a duration in seconds, as reported by the platform's audio session, to nanoseconds. /// /// Returns 0 for a value that is not finite and positive. -#[cfg(all(target_vendor = "apple", not(target_os = "macos")))] +#[cfg(any( + all(target_vendor = "apple", not(target_os = "macos")), + all( + target_arch = "wasm32", + target_os = "unknown", + feature = "wasm-bindgen", + feature = "audioworklet", + target_feature = "atomics" + ), +))] #[inline] pub(crate) fn secs_to_nanos(secs: f64) -> u64 { if secs.is_finite() && secs > 0.0 { @@ -294,7 +303,19 @@ pub(crate) fn secs_to_nanos(secs: f64) -> u64 { /// `Some(Duration::ZERO)` returns immediately. /// /// [`StreamTrait::stop`]: crate::traits::StreamTrait::stop -#[cfg(any(all(windows, feature = "asio"), target_vendor = "apple"))] +#[cfg(any( + all(windows, feature = "asio"), + target_vendor = "apple", + all( + any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + ), + any(feature = "jack", feature = "pulseaudio"), + ), +))] pub(crate) fn wait_for_drain(window: std::time::Duration, timeout: Option) { let wait = timeout.map_or(window, |t| window.min(t)); if !wait.is_zero() { diff --git a/src/host/pulseaudio/stream.rs b/src/host/pulseaudio/stream.rs index 56e9c82e1..bb51465fd 100644 --- a/src/host/pulseaudio/stream.rs +++ b/src/host/pulseaudio/stream.rs @@ -17,7 +17,7 @@ use pulseaudio::{AsPlaybackSource, protocol}; use crate::{ CallbackInfo, Data, Error, ErrorKind, FrameCount, SampleFormat, StreamInstant, StreamTimestamp, - host::{ErrorCallbackArc, emit_error, latch::Latch}, + host::{ErrorCallbackArc, emit_error, latch::Latch, wait_for_drain}, traits::StreamTrait, }; @@ -152,13 +152,10 @@ impl StreamTrait for Stream { } => { // TODO: use PulseAudio's drain() when https://github.com/colinmarc/pulseaudio-rs/pull/9 is merged. draining.store(true, Ordering::Relaxed); - if timeout != Some(Duration::ZERO) { - let buffered = Duration::from_micros(fill_usec.load(Ordering::Relaxed)); - let wait = timeout.map_or(buffered, |t| buffered.min(t)); - if !wait.is_zero() { - std::thread::sleep(wait); - } - } + wait_for_drain( + Duration::from_micros(fill_usec.load(Ordering::Relaxed)), + timeout, + ); block_on(stream.cork()).map_err(Error::from)?; block_on(stream.flush()).map_err(Error::from)?; handle.notify();