@@ -17,16 +17,19 @@ use sys::pid_t;
1717use sys:: {
1818 kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceIsAlive,
1919 kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyHogMode,
20- kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioHardwareNoError,
20+ kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput,
21+ kAudioDevicePropertyStreamConfiguration, kAudioHardwareNoError,
2122 kAudioHardwarePropertyDefaultInputDevice, kAudioHardwarePropertyDefaultOutputDevice,
2223 kAudioHardwarePropertyDevices, kAudioObjectPropertyElementMaster,
23- kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject,
24+ kAudioObjectPropertyElementWildcard, kAudioObjectPropertyScopeGlobal,
25+ kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput, kAudioObjectSystemObject,
2426 kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO,
2527 kAudioStreamPropertyAvailablePhysicalFormats, kAudioStreamPropertyPhysicalFormat,
2628 kCFStringEncodingUTF8, AudioDeviceID , AudioObjectAddPropertyListener ,
2729 AudioObjectGetPropertyData , AudioObjectGetPropertyDataSize , AudioObjectID ,
28- AudioObjectPropertyAddress , AudioObjectRemovePropertyListener , AudioObjectSetPropertyData ,
29- AudioStreamBasicDescription , AudioStreamRangedDescription , AudioValueRange , OSStatus ,
30+ AudioObjectPropertyAddress , AudioObjectPropertyScope , AudioObjectRemovePropertyListener ,
31+ AudioObjectSetPropertyData , AudioStreamBasicDescription , AudioStreamRangedDescription ,
32+ AudioValueRange , OSStatus ,
3033} ;
3134
3235use crate :: audio_unit:: audio_format:: { AudioFormat , LinearPcmFlags } ;
@@ -115,10 +118,15 @@ pub fn audio_unit_from_device_id(
115118}
116119
117120/// List all audio device ids on the system.
118- pub fn get_audio_device_ids ( ) -> Result < Vec < AudioDeviceID > , Error > {
121+ pub fn get_audio_device_ids_for_scope ( scope : Scope ) -> Result < Vec < AudioDeviceID > , Error > {
122+ let dev_scope = match scope {
123+ Scope :: Input => kAudioObjectPropertyScopeInput,
124+ Scope :: Output => kAudioObjectPropertyScopeOutput,
125+ _ => kAudioObjectPropertyScopeGlobal,
126+ } ;
119127 let property_address = AudioObjectPropertyAddress {
120128 mSelector : kAudioHardwarePropertyDevices,
121- mScope : kAudioObjectPropertyScopeGlobal ,
129+ mScope : dev_scope ,
122130 mElement : kAudioObjectPropertyElementMaster,
123131 } ;
124132
@@ -161,6 +169,68 @@ pub fn get_audio_device_ids() -> Result<Vec<AudioDeviceID>, Error> {
161169 Ok ( audio_devices)
162170}
163171
172+ pub fn get_audio_device_ids ( ) -> Result < Vec < AudioDeviceID > , Error > {
173+ get_audio_device_ids_for_scope ( Scope :: Global )
174+ }
175+
176+ /// does this device support input / ouptut?
177+ pub fn get_audio_device_supports_scope ( devid : AudioDeviceID , scope : Scope ) -> Result < bool , Error > {
178+ let dev_scope: AudioObjectPropertyScope = match scope {
179+ Scope :: Input => kAudioObjectPropertyScopeInput,
180+ Scope :: Output => kAudioObjectPropertyScopeOutput,
181+ _ => kAudioObjectPropertyScopeGlobal,
182+ } ;
183+ let property_address = AudioObjectPropertyAddress {
184+ mSelector : kAudioDevicePropertyStreamConfiguration,
185+ mScope : dev_scope,
186+ mElement : kAudioObjectPropertyElementWildcard,
187+ } ;
188+
189+ macro_rules! try_status_or_return {
190+ ( $status: expr) => {
191+ if $status != kAudioHardwareNoError as i32 {
192+ return Err ( Error :: Unknown ( $status) ) ;
193+ }
194+ } ;
195+ }
196+
197+ let data_size = 0u32 ;
198+ let status = unsafe {
199+ AudioObjectGetPropertyDataSize (
200+ devid,
201+ & property_address as * const _ ,
202+ 0 ,
203+ null ( ) ,
204+ & data_size as * const _ as * mut _ ,
205+ )
206+ } ;
207+ try_status_or_return ! ( status) ;
208+
209+ let mut bfrs: Vec < u8 > = Vec :: with_capacity ( data_size as usize ) ;
210+ let buffers = bfrs. as_mut_ptr ( ) as * mut sys:: AudioBufferList ;
211+ unsafe {
212+ let status = AudioObjectGetPropertyData (
213+ devid,
214+ & property_address as * const _ ,
215+ 0 ,
216+ null ( ) ,
217+ & data_size as * const _ as * mut _ ,
218+ buffers as * mut _ ,
219+ ) ;
220+ if status != kAudioHardwareNoError as i32 {
221+ return Err ( Error :: Unknown ( status) ) ;
222+ }
223+
224+ for i in 0 ..( * buffers) . mNumberBuffers {
225+ let buf = ( * buffers) . mBuffers [ i as usize ] ;
226+ if buf. mNumberChannels > 0 {
227+ return Ok ( true ) ;
228+ }
229+ }
230+ }
231+ Ok ( false )
232+ }
233+
164234/// Get the device name for a device id.
165235pub fn get_device_name ( device_id : AudioDeviceID ) -> Result < String , Error > {
166236 let property_address = AudioObjectPropertyAddress {
0 commit comments