Skip to content

Commit

Permalink
Merge pull request #96 from aLagoG/rkilgore-features
Browse files Browse the repository at this point in the history
Add support for scope related queries
  • Loading branch information
simlay authored Oct 13, 2023
2 parents 14fab50 + 53566ef commit c9bbe6e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ core_midi = ["coreaudio-sys/core_midi"]
[dependencies]
bitflags = "1.0"
coreaudio-sys = { version = "0.2", default-features = false }
core-foundation-sys = "0.6.2"
core-foundation-sys = "0.8.3"

[package.metadata.docs.rs]
all-features = true
Expand Down
4 changes: 2 additions & 2 deletions examples/sine_advanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ extern crate coreaudio;

use coreaudio::audio_unit::audio_format::LinearPcmFlags;
use coreaudio::audio_unit::macos_helpers::{
audio_unit_from_device_id, find_matching_physical_format, get_default_device_id, get_hogging_pid,
get_supported_physical_stream_formats, set_device_physical_stream_format,
audio_unit_from_device_id, find_matching_physical_format, get_default_device_id,
get_hogging_pid, get_supported_physical_stream_formats, set_device_physical_stream_format,
set_device_sample_rate, toggle_hog_mode, AliveListener, RateListener,
};
use coreaudio::audio_unit::render_callback::{self, data};
Expand Down
82 changes: 76 additions & 6 deletions src/audio_unit/macos_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ use sys::pid_t;
use sys::{
kAudioDevicePropertyAvailableNominalSampleRates, kAudioDevicePropertyDeviceIsAlive,
kAudioDevicePropertyDeviceNameCFString, kAudioDevicePropertyHogMode,
kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput, kAudioHardwareNoError,
kAudioDevicePropertyNominalSampleRate, kAudioDevicePropertyScopeOutput,
kAudioDevicePropertyStreamConfiguration, kAudioHardwareNoError,
kAudioHardwarePropertyDefaultInputDevice, kAudioHardwarePropertyDefaultOutputDevice,
kAudioHardwarePropertyDevices, kAudioObjectPropertyElementMaster,
kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject,
kAudioObjectPropertyElementWildcard, kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput, kAudioObjectSystemObject,
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_EnableIO,
kAudioStreamPropertyAvailablePhysicalFormats, kAudioStreamPropertyPhysicalFormat,
kCFStringEncodingUTF8, AudioDeviceID, AudioObjectAddPropertyListener,
AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize, AudioObjectID,
AudioObjectPropertyAddress, AudioObjectRemovePropertyListener, AudioObjectSetPropertyData,
AudioStreamBasicDescription, AudioStreamRangedDescription, AudioValueRange, OSStatus,
AudioObjectPropertyAddress, AudioObjectPropertyScope, AudioObjectRemovePropertyListener,
AudioObjectSetPropertyData, AudioStreamBasicDescription, AudioStreamRangedDescription,
AudioValueRange, OSStatus,
};

use crate::audio_unit::audio_format::{AudioFormat, LinearPcmFlags};
Expand Down Expand Up @@ -115,10 +118,15 @@ pub fn audio_unit_from_device_id(
}

/// List all audio device ids on the system.
pub fn get_audio_device_ids() -> Result<Vec<AudioDeviceID>, Error> {
pub fn get_audio_device_ids_for_scope(scope: Scope) -> Result<Vec<AudioDeviceID>, Error> {
let dev_scope = match scope {
Scope::Input => kAudioObjectPropertyScopeInput,
Scope::Output => kAudioObjectPropertyScopeOutput,
_ => kAudioObjectPropertyScopeGlobal,
};
let property_address = AudioObjectPropertyAddress {
mSelector: kAudioHardwarePropertyDevices,
mScope: kAudioObjectPropertyScopeGlobal,
mScope: dev_scope,
mElement: kAudioObjectPropertyElementMaster,
};

Expand Down Expand Up @@ -161,6 +169,68 @@ pub fn get_audio_device_ids() -> Result<Vec<AudioDeviceID>, Error> {
Ok(audio_devices)
}

pub fn get_audio_device_ids() -> Result<Vec<AudioDeviceID>, Error> {
get_audio_device_ids_for_scope(Scope::Global)
}

/// does this device support input / ouptut?
pub fn get_audio_device_supports_scope(devid: AudioDeviceID, scope: Scope) -> Result<bool, Error> {
let dev_scope: AudioObjectPropertyScope = match scope {
Scope::Input => kAudioObjectPropertyScopeInput,
Scope::Output => kAudioObjectPropertyScopeOutput,
_ => kAudioObjectPropertyScopeGlobal,
};
let property_address = AudioObjectPropertyAddress {
mSelector: kAudioDevicePropertyStreamConfiguration,
mScope: dev_scope,
mElement: kAudioObjectPropertyElementWildcard,
};

macro_rules! try_status_or_return {
($status:expr) => {
if $status != kAudioHardwareNoError as i32 {
return Err(Error::Unknown($status));
}
};
}

let data_size = 0u32;
let status = unsafe {
AudioObjectGetPropertyDataSize(
devid,
&property_address as *const _,
0,
null(),
&data_size as *const _ as *mut _,
)
};
try_status_or_return!(status);

let mut bfrs: Vec<u8> = Vec::with_capacity(data_size as usize);
let buffers = bfrs.as_mut_ptr() as *mut sys::AudioBufferList;
unsafe {
let status = AudioObjectGetPropertyData(
devid,
&property_address as *const _,
0,
null(),
&data_size as *const _ as *mut _,
buffers as *mut _,
);
if status != kAudioHardwareNoError as i32 {
return Err(Error::Unknown(status));
}

for i in 0..(*buffers).mNumberBuffers {
let buf = (*buffers).mBuffers[i as usize];
if buf.mNumberChannels > 0 {
return Ok(true);
}
}
}
Ok(false)
}

/// Get the device name for a device id.
pub fn get_device_name(device_id: AudioDeviceID) -> Result<String, Error> {
let property_address = AudioObjectPropertyAddress {
Expand Down
10 changes: 10 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub mod audio {
}
}

impl std::error::Error for Error {}

impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
let description = match *self {
Expand Down Expand Up @@ -93,6 +95,8 @@ pub mod audio_codec {
}
}

impl std::error::Error for Error {}

impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
let description = match *self {
Expand Down Expand Up @@ -139,6 +143,8 @@ pub mod audio_format {
}
}

impl std::error::Error for Error {}

impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
let description = match *self {
Expand Down Expand Up @@ -209,6 +215,8 @@ pub mod audio_unit {
}
}

impl std::error::Error for Error {}

impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
let description = match *self {
Expand Down Expand Up @@ -302,6 +310,8 @@ impl Error {
}
}

impl std::error::Error for Error {}

impl ::std::fmt::Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
match *self {
Expand Down

0 comments on commit c9bbe6e

Please sign in to comment.