Skip to content

Commit c9bbe6e

Browse files
authored
Merge pull request #96 from aLagoG/rkilgore-features
Add support for scope related queries
2 parents 14fab50 + 53566ef commit c9bbe6e

File tree

4 files changed

+89
-9
lines changed

4 files changed

+89
-9
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ core_midi = ["coreaudio-sys/core_midi"]
2424
[dependencies]
2525
bitflags = "1.0"
2626
coreaudio-sys = { version = "0.2", default-features = false }
27-
core-foundation-sys = "0.6.2"
27+
core-foundation-sys = "0.8.3"
2828

2929
[package.metadata.docs.rs]
3030
all-features = true

examples/sine_advanced.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ extern crate coreaudio;
55

66
use coreaudio::audio_unit::audio_format::LinearPcmFlags;
77
use coreaudio::audio_unit::macos_helpers::{
8-
audio_unit_from_device_id, find_matching_physical_format, get_default_device_id, get_hogging_pid,
9-
get_supported_physical_stream_formats, set_device_physical_stream_format,
8+
audio_unit_from_device_id, find_matching_physical_format, get_default_device_id,
9+
get_hogging_pid, get_supported_physical_stream_formats, set_device_physical_stream_format,
1010
set_device_sample_rate, toggle_hog_mode, AliveListener, RateListener,
1111
};
1212
use coreaudio::audio_unit::render_callback::{self, data};

src/audio_unit/macos_helpers.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@ use sys::pid_t;
1717
use 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

3235
use 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.
165235
pub fn get_device_name(device_id: AudioDeviceID) -> Result<String, Error> {
166236
let property_address = AudioObjectPropertyAddress {

src/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ pub mod audio {
4141
}
4242
}
4343

44+
impl std::error::Error for Error {}
45+
4446
impl ::std::fmt::Display for Error {
4547
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
4648
let description = match *self {
@@ -93,6 +95,8 @@ pub mod audio_codec {
9395
}
9496
}
9597

98+
impl std::error::Error for Error {}
99+
96100
impl ::std::fmt::Display for Error {
97101
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
98102
let description = match *self {
@@ -139,6 +143,8 @@ pub mod audio_format {
139143
}
140144
}
141145

146+
impl std::error::Error for Error {}
147+
142148
impl ::std::fmt::Display for Error {
143149
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
144150
let description = match *self {
@@ -209,6 +215,8 @@ pub mod audio_unit {
209215
}
210216
}
211217

218+
impl std::error::Error for Error {}
219+
212220
impl ::std::fmt::Display for Error {
213221
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
214222
let description = match *self {
@@ -302,6 +310,8 @@ impl Error {
302310
}
303311
}
304312

313+
impl std::error::Error for Error {}
314+
305315
impl ::std::fmt::Display for Error {
306316
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
307317
match *self {

0 commit comments

Comments
 (0)