@@ -17,16 +17,19 @@ use sys::pid_t;
17
17
use sys:: {
18
18
kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceIsAlive,
19
19
kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyHogMode,
20
- kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioHardwareNoError,
20
+ kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput,
21
+ kAudioDevicePropertyStreamConfiguration, kAudioHardwareNoError,
21
22
kAudioHardwarePropertyDefaultInputDevice, kAudioHardwarePropertyDefaultOutputDevice,
22
23
kAudioHardwarePropertyDevices, kAudioObjectPropertyElementMaster,
23
- kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject,
24
+ kAudioObjectPropertyElementWildcard, kAudioObjectPropertyScopeGlobal,
25
+ kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput, kAudioObjectSystemObject,
24
26
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO,
25
27
kAudioStreamPropertyAvailablePhysicalFormats, kAudioStreamPropertyPhysicalFormat,
26
28
kCFStringEncodingUTF8, AudioDeviceID , AudioObjectAddPropertyListener ,
27
29
AudioObjectGetPropertyData , AudioObjectGetPropertyDataSize , AudioObjectID ,
28
- AudioObjectPropertyAddress , AudioObjectRemovePropertyListener , AudioObjectSetPropertyData ,
29
- AudioStreamBasicDescription , AudioStreamRangedDescription , AudioValueRange , OSStatus ,
30
+ AudioObjectPropertyAddress , AudioObjectPropertyScope , AudioObjectRemovePropertyListener ,
31
+ AudioObjectSetPropertyData , AudioStreamBasicDescription , AudioStreamRangedDescription ,
32
+ AudioValueRange , OSStatus ,
30
33
} ;
31
34
32
35
use crate :: audio_unit:: audio_format:: { AudioFormat , LinearPcmFlags } ;
@@ -115,10 +118,15 @@ pub fn audio_unit_from_device_id(
115
118
}
116
119
117
120
/// 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
+ } ;
119
127
let property_address = AudioObjectPropertyAddress {
120
128
mSelector : kAudioHardwarePropertyDevices,
121
- mScope : kAudioObjectPropertyScopeGlobal ,
129
+ mScope : dev_scope ,
122
130
mElement : kAudioObjectPropertyElementMaster,
123
131
} ;
124
132
@@ -161,6 +169,68 @@ pub fn get_audio_device_ids() -> Result<Vec<AudioDeviceID>, Error> {
161
169
Ok ( audio_devices)
162
170
}
163
171
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
+
164
234
/// Get the device name for a device id.
165
235
pub fn get_device_name ( device_id : AudioDeviceID ) -> Result < String , Error > {
166
236
let property_address = AudioObjectPropertyAddress {
0 commit comments