From 0460bb6bc1e2a56eb65b4c84ec75c45d584be720 Mon Sep 17 00:00:00 2001 From: Chun-Min Chang Date: Fri, 15 Feb 2019 16:10:23 -0800 Subject: [PATCH] Implement audiounit_get_current_channel_layout --- README.md | 6 +++--- src/backend/auto_release.rs | 4 ++++ src/backend/mod.rs | 33 +++++++++++++++++++++++++++++++ src/backend/test.rs | 39 +++++++++++++++++++++++++++++++++++++ src/backend/utils.rs | 21 ++++++++++++++++++++ 5 files changed, 100 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 716ca6c..d6f8fd1 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,9 @@ By applying the [patch][integrate-with-cubeb] to integrate within [Cubeb][cubeb] ### Interanl APIs -- 🥚 : 8/75 (10.6%) +- 🥚 : 7/75 (9.3%) - 🐣 : 7/75 (9.3%) -- 🐥 : 60/75 (80%) +- 🐥 : 61/75 (81.3%) | Interanl AudioUnit APIs | status | | ------------------------------------------- | ------ | @@ -96,7 +96,7 @@ By applying the [patch][integrate-with-cubeb] to integrate within [Cubeb][cubeb] | audiounit_get_default_device_id | 🐥 | | audiounit_convert_channel_layout | 🐥 | | audiounit_get_preferred_channel_layout | 🥚 | -| audiounit_get_current_channel_layout | 🥚 | +| audiounit_get_current_channel_layout | 🐥 | | audiounit_destroy | 🥚 | | audio_stream_desc_init | 🐥 | | audiounit_init_mixer | 🥚 | diff --git a/src/backend/auto_release.rs b/src/backend/auto_release.rs index 74d97f9..6de3443 100644 --- a/src/backend/auto_release.rs +++ b/src/backend/auto_release.rs @@ -21,6 +21,10 @@ impl AutoRelease { self.ptr = ptr; } + pub fn as_ref(&self) -> &T { + unsafe { &*self.ptr } + } + pub fn as_mut_ptr(&self) -> *mut T { self.ptr } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 9b35e71..c64a634 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1049,6 +1049,39 @@ fn audiounit_convert_channel_layout(layout: &AudioChannelLayout) -> ChannelLayou return cl; } +fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> ChannelLayout +{ + let mut rv = NO_ERR; + let mut size: usize = 0; + + rv = audio_unit_get_property_info(output_unit, + kAudioUnitProperty_AudioChannelLayout, + kAudioUnitScope_Output, + AU_OUT_BUS, + &mut size, + ptr::null_mut()); + if rv != NO_ERR { + cubeb_log!("AudioUnitGetPropertyInfo/kAudioUnitProperty_AudioChannelLayout rv={}", rv); + // TODO: This property isn't known before macOS 10.12, attempt another method. + return ChannelLayout::UNDEFINED; + } + assert!(size > 0); + + let layout = make_sized_audio_channel_layout(size); + rv = audio_unit_get_property(output_unit, + kAudioUnitProperty_AudioChannelLayout, + kAudioUnitScope_Output, + AU_OUT_BUS, + layout.as_mut_ptr(), + &mut size); + if rv != NO_ERR { + cubeb_log!("AudioUnitGetProperty/kAudioUnitProperty_AudioChannelLayout rv={}", rv); + return ChannelLayout::UNDEFINED; + } + + audiounit_convert_channel_layout(layout.as_ref()) +} + fn audio_stream_desc_init(ss: &mut AudioStreamBasicDescription, stream_params: &StreamParams) -> Result<()> { diff --git a/src/backend/test.rs b/src/backend/test.rs index 37a2b3a..b7af37c 100644 --- a/src/backend/test.rs +++ b/src/backend/test.rs @@ -2213,6 +2213,45 @@ fn test_convert_channel_layout() { } } +// get_current_channel_layout +// ------------------------------------ +// TODO: Should it be prevented ? The AudioUnitElement is for output only. +// It should be called for the input side. +// #[test] +// fn test_get_current_channel_layout_input() { +// // Initialize the unit to the default input device. +// let default_input_id = audiounit_get_default_device_id(DeviceType::INPUT); +// if !valid_id(default_input_id) { +// return; +// } +// let mut unit: AudioUnit = ptr::null_mut(); +// let device = device_info { +// id: default_input_id, +// flags: device_flags::DEV_INPUT | device_flags::DEV_SYSTEM_DEFAULT +// }; + +// assert!(audiounit_create_unit(&mut unit, &device).is_ok()); +// assert!(!unit.is_null()); +// assert_eq!(audiounit_get_current_channel_layout(unit), ChannelLayout::UNDEFINED); +// } + +#[test] +fn test_get_current_channel_layout_output() { + // Initialize the unit to default output device. + let default_output_id = audiounit_get_default_device_id(DeviceType::OUTPUT); + if !valid_id(default_output_id) { + return; + } + let mut unit: AudioUnit = ptr::null_mut(); + let device = device_info { + id: default_output_id, + flags: device_flags::DEV_OUTPUT | device_flags::DEV_SYSTEM_DEFAULT + }; + assert!(audiounit_create_unit(&mut unit, &device).is_ok()); + assert!(!unit.is_null()); + assert_ne!(audiounit_get_current_channel_layout(unit), ChannelLayout::UNDEFINED); +} + // audio_stream_desc_init // ------------------------------------ #[test] diff --git a/src/backend/utils.rs b/src/backend/utils.rs index 441ab32..e031eab 100644 --- a/src/backend/utils.rs +++ b/src/backend/utils.rs @@ -189,6 +189,27 @@ pub fn audio_object_remove_property_listener( } } +pub fn audio_unit_get_property_info( + unit: sys::AudioUnit, + property: sys::AudioUnitPropertyID, + scope: sys::AudioUnitScope, + element: sys::AudioUnitElement, + size: *mut usize, + writable: *mut sys::Boolean +) -> sys::OSStatus { + assert!(!unit.is_null()); + unsafe { + sys::AudioUnitGetPropertyInfo( + unit, + property, + scope, + element, + size as *mut sys::UInt32, + writable + ) + } +} + pub fn audio_unit_get_property( unit: sys::AudioUnit, property: sys::AudioUnitPropertyID,