diff --git a/src/host/coreaudio/macos/mod.rs b/src/host/coreaudio/macos/mod.rs index 49ad5d144..8f0229828 100644 --- a/src/host/coreaudio/macos/mod.rs +++ b/src/host/coreaudio/macos/mod.rs @@ -43,6 +43,9 @@ pub use self::enumerate::{ SupportedOutputConfigs, }; +use coreaudio::sys::{ + kAudioDevicePropertyLatency, kAudioDevicePropertySafetyOffset, kAudioStreamPropertyLatency, +}; use property_listener::AudioObjectPropertyListener; pub mod enumerate; @@ -956,6 +959,55 @@ impl StreamTrait for Stream { stream.pause() } + + fn latency(&self) -> Option { + let stream = self.inner.lock().unwrap(); + let audio_unit = &stream.audio_unit; + + // device presentation latency + let device_latency: u32 = match audio_unit.get_property( + kAudioDevicePropertyLatency, + Scope::Global, + Element::Output, + ) { + Ok(device_latency) => device_latency, + Err(_) => return None, + }; + + // stream presentation latency + let stream_latency: u32 = match audio_unit.get_property( + kAudioStreamPropertyLatency, + Scope::Global, + Element::Output, + ) { + Ok(stream_latency) => stream_latency, + Err(_) => return None, + }; + + // device safety offset + let safety_offset: u32 = match audio_unit.get_property( + kAudioDevicePropertySafetyOffset, + Scope::Global, + Element::Output, + ) { + Ok(safety_offset) => safety_offset, + Err(_) => return None, + }; + + // IO buffer frame size + let buffer_size: u32 = match audio_unit.get_property( + kAudioDevicePropertyBufferFrameSize, + Scope::Global, + Element::Output, + ) { + Ok(buffer_size) => buffer_size, + Err(_) => return None, + }; + + let latency = device_latency + stream_latency + safety_offset + buffer_size; + + Some(latency) + } } fn get_io_buffer_frame_size_range( diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 6fc35f6f4..c0958f94a 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -499,6 +499,17 @@ macro_rules! impl_platform_host { )* } } + + fn latency(&self) -> Option { + match self.0 { + $( + $(#[cfg($feat)])? + StreamInner::$HostVariant(ref s) => { + s.latency() + } + )* + } + } } impl From for Device { diff --git a/src/traits.rs b/src/traits.rs index 2f1bd3469..405cfbd58 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -220,4 +220,12 @@ pub trait StreamTrait { /// Note: Not all devices support suspending the stream at the hardware level. This method may /// fail in these cases. fn pause(&self) -> Result<(), PauseStreamError>; + + /// The current latency of the stream in samples (if available). + /// + /// Note: This is not implemented on all platforms and not all backends return reliable + /// information. + fn latency(&self) -> Option { + None + } }