From 8a0c8b886186e442f244ad4589a3b44c71d4046b Mon Sep 17 00:00:00 2001 From: Yury Date: Thu, 16 Jan 2025 21:10:08 +0300 Subject: [PATCH] continue on core audio --- cidre/src/core_audio/hardware.rs | 72 ++++++++++++++++++--------- cidre/src/core_audio/hardware_base.rs | 8 +-- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/cidre/src/core_audio/hardware.rs b/cidre/src/core_audio/hardware.rs index 0c6377c2..21bb7648 100644 --- a/cidre/src/core_audio/hardware.rs +++ b/cidre/src/core_audio/hardware.rs @@ -502,6 +502,13 @@ impl std::ops::DerefMut for Device { } impl Device { + pub fn with_uid(uid: arc::R) -> os::Result { + System::OBJ.prop_with_qualifier( + &PropSelector::HARDWARE_TRANSLATE_UID_TO_DEVICE.global_addr(), + &uid, + ) + } + pub fn uid(&self) -> os::Result> { self.cf_prop(&PropSelector::DEVICE_UID.global_addr()) } @@ -516,17 +523,34 @@ impl Device { &val, ) } + /// + /// A f64 that indicates the current actual sample rate of the AudioDevice as measured by its time stamps. + #[doc(alias = "kAudioDevicePropertyActualSampleRate")] + pub fn actual_sample_rate(&self) -> os::Result { + self.prop(&PropSelector::DEVICE_ACTUAL_SAMPLE_RATE.global_addr()) + } + + pub fn asbd(&self, scope: PropScope) -> os::Result { + // NOTE: this is depricated property for device, but it is working well + self.prop(&PropSelector::STREAM_VIRTUAL_FORMAT.addr(scope, PropElement::MAIN)) + } + + #[inline] + pub fn input_asbd(&self) -> os::Result { + self.asbd(PropScope::INPUT) + } + + #[inline] + pub fn output_asbd(&self) -> os::Result { + self.asbd(PropScope::OUTPUT) + } pub fn available_nominal_sample_rates(&self) -> os::Result> { self.prop_vec(&PropSelector::DEVICE_AVAILABLE_NOMINAL_SAMPLE_RATES.global_addr()) } pub fn stream_cfg(&self, scope: PropScope) -> os::Result { - let addr = PropAddr { - selector: PropSelector::DEVICE_STREAM_CFG, - scope, - element: PropElement::WILDCARD, - }; + let addr = PropSelector::DEVICE_STREAM_CFG.addr(scope, PropElement::MAIN); let mut size = self.prop_size(&addr)?; let mut res = AudioBufListN::new(size as _); unsafe { @@ -559,13 +583,6 @@ impl Device { self.prop(&PropSelector::DEVICE_TRANSPORT_TYPE.global_addr()) } - /// A f64 that indicates the current actual sample rate of the AudioDevice - /// as measured by its time stamps. - #[doc(alias = "kAudioDevicePropertyActualSampleRate")] - pub fn actual_sample_rate(&self) -> os::Result { - self.prop(&PropSelector::DEVICE_ACTUAL_SAMPLE_RATE.global_addr()) - } - /// A cf::String that contains the UID for the AudioClockDevice that is currently /// serving as the main time base of the device. #[doc(alias = "kAudioDevicePropertyClockDevice")] @@ -578,13 +595,7 @@ impl Device { /// Note that this property does not apply to aggregate devices, just real, physical devices. #[doc(alias = "kAudioDevicePropertyProcessMute")] pub fn is_process_muted(&self, scope: PropScope) -> os::Result { - let addr = PropAddr { - selector: PropSelector::DEVICE_PROCESS_MUTE, - scope, - element: PropElement::WILDCARD, - }; - - self.bool_prop(&addr) + self.bool_prop(&PropSelector::DEVICE_PROCESS_MUTE.addr(scope, PropElement::WILDCARD)) } pub fn is_process_input_muted(&self) -> os::Result { @@ -1260,7 +1271,7 @@ impl Stream { /// the AudioStream. The virtual format refers to the data format in which all /// IOProcs for the owning AudioDevice will perform IO transactions. #[doc(alias = "kAudioStreamPropertyVirtualFormat")] - pub fn virtual_format(&self) -> os::Result { + pub fn virtual_format(&self) -> os::Result { self.prop(&PropSelector::STREAM_VIRTUAL_FORMAT.global_addr()) } @@ -1273,7 +1284,7 @@ impl Stream { /// the AudioStream. The physical format refers to the data format in which the /// hardware for the owning AudioDevice performs its IO transactions. #[doc(alias = "kAudioStreamPropertyPhysicalFormat")] - pub fn physical_format(&self) -> os::Result { + pub fn physical_format(&self) -> os::Result { self.prop(&PropSelector::STREAM_PHYSICAL_FORMAT.global_addr()) } @@ -1659,6 +1670,17 @@ mod tests { ns, os, }; + #[test] + fn device() { + let uid = cf::str!(c"BuiltInSpeakerDevice"); + let device = Device::with_uid(uid.retained()).unwrap(); + let uid_from_device = device.uid().unwrap(); + assert_eq!(uid, uid_from_device.as_ref()); + unsafe { assert_ne!(uid.as_type_ptr(), uid_from_device.as_type_ptr()) }; + let uid2 = uid.retained(); + unsafe { assert_eq!(uid.as_type_ptr(), uid2.as_type_ptr()) }; + } + #[test] fn list_devices() { let addr = PropSelector::HARDWARE_DEFAULT_INPUT_DEVICE.global_addr(); @@ -1684,8 +1706,9 @@ mod tests { #[test] fn aggregate_device() { - let output_device = System::default_output_device().unwrap(); - let output_uid = output_device.uid().unwrap(); + // let output_device = System::default_output_device().unwrap(); + let output_uid = cf::str!(c"BuiltInSpeakerDevice"); // output_device.uid().unwrap(); + println!("device_uid {output_uid:?}"); let uuid = cf::Uuid::new().to_cf_string(); let dict = cf::DictionaryOf::with_keys_values( &[ @@ -1761,6 +1784,9 @@ mod tests { let _proc_id = agg_device.create_io_proc_id(proc, None).unwrap(); + let input = agg_device.output_asbd().unwrap(); + println!("input {input:?}"); + let streams = agg_device.streams().unwrap(); println!("streams {streams:?}"); let asbd = streams[0].virtual_format().unwrap(); diff --git a/cidre/src/core_audio/hardware_base.rs b/cidre/src/core_audio/hardware_base.rs index 7a6e434b..353f2c2c 100644 --- a/cidre/src/core_audio/hardware_base.rs +++ b/cidre/src/core_audio/hardware_base.rs @@ -24,7 +24,7 @@ impl std::fmt::Debug for Class { } #[doc(alias = "AudioObjectPropertySelector")] -#[derive(Eq, PartialEq, Copy, Clone)] +#[derive(Eq, PartialEq, Copy, Clone, Hash)] #[repr(transparent)] pub struct PropSelector(pub u32); @@ -59,7 +59,7 @@ impl std::fmt::Debug for PropSelector { } #[doc(alias = "AudioObjectPropertyScope")] -#[derive(Eq, PartialEq, Copy, Clone)] +#[derive(Eq, PartialEq, Copy, Clone, Hash)] #[repr(transparent)] pub struct PropScope(pub u32); @@ -74,12 +74,12 @@ impl std::fmt::Debug for PropScope { } #[doc(alias = "AudioObjectPropertyElement")] -#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] #[repr(transparent)] pub struct PropElement(pub u32); #[doc(alias = "AudioObjectPropertyAddress")] -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Hash)] #[repr(C)] pub struct PropAddr { pub selector: PropSelector,