Skip to content

Commit 8374eff

Browse files
feature(coreaudio): implement channel names
simplify unsafe structure
1 parent 828e896 commit 8374eff

1 file changed

Lines changed: 66 additions & 2 deletions

File tree

src/host/coreaudio/macos/device.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use objc2_core_audio::{
3131
kAudioDevicePropertyLatency, kAudioDevicePropertyNominalSampleRate,
3232
kAudioDevicePropertySafetyOffset, kAudioDevicePropertyStreamConfiguration,
3333
kAudioDevicePropertyStreamFormat, kAudioObjectPropertyClass, kAudioObjectPropertyElementMain,
34-
kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyScopeInput,
35-
kAudioObjectPropertyScopeOutput,
34+
kAudioObjectPropertyElementName, kAudioObjectPropertyScopeGlobal,
35+
kAudioObjectPropertyScopeInput, kAudioObjectPropertyScopeOutput,
3636
};
3737
use objc2_core_audio_types::{
3838
AudioBuffer, AudioBufferList, AudioStreamBasicDescription, AudioValueRange,
@@ -357,6 +357,10 @@ impl DeviceTrait for Device {
357357
timeout,
358358
)
359359
}
360+
361+
fn get_channel_name(&self, channel_index: u16, input: bool) -> Result<String, Error> {
362+
Device::get_channel_name(self, channel_index, input)
363+
}
360364
}
361365

362366
#[derive(Clone)]
@@ -690,6 +694,24 @@ impl Device {
690694
.map(|mut configs| configs.next().is_some())
691695
.unwrap_or(false)
692696
}
697+
698+
fn get_channel_name(&self, channel_index: u16, input: bool) -> Result<String, Error> {
699+
if input && !self.supports_input() {
700+
return Err(Error::with_message(
701+
ErrorKind::InvalidInput,
702+
"Device does not support input",
703+
));
704+
}
705+
706+
if !input && !self.supports_output() {
707+
return Err(Error::with_message(
708+
ErrorKind::InvalidInput,
709+
"Device does not support output",
710+
));
711+
}
712+
713+
get_channel_name_for_device(self.audio_device_id, channel_index, input)
714+
}
693715
}
694716

695717
impl Device {
@@ -1116,3 +1138,45 @@ pub(crate) fn get_device_buffer_frame_size(
11161138
)?;
11171139
Ok(frames as usize)
11181140
}
1141+
1142+
fn get_channel_name_for_device(
1143+
device_id: AudioDeviceID,
1144+
channel_index: u16,
1145+
input: bool,
1146+
) -> Result<String, Error> {
1147+
let mut channel_name: *mut CFString = std::ptr::null_mut();
1148+
let mut data_size = size_of::<*mut CFString>() as u32;
1149+
1150+
let property_address = AudioObjectPropertyAddress {
1151+
mSelector: kAudioObjectPropertyElementName,
1152+
mScope: if input {
1153+
kAudioObjectPropertyScopeInput
1154+
} else {
1155+
kAudioObjectPropertyScopeOutput
1156+
},
1157+
// Channels numbers start on 1 here
1158+
mElement: channel_index as u32 + 1,
1159+
};
1160+
1161+
let status = unsafe {
1162+
AudioObjectGetPropertyData(
1163+
device_id,
1164+
NonNull::from(&property_address),
1165+
0,
1166+
null(),
1167+
NonNull::from(&mut data_size),
1168+
NonNull::from(&mut channel_name).cast(),
1169+
)
1170+
};
1171+
check_os_status(status)?;
1172+
1173+
if !channel_name.is_null() {
1174+
let raw_name = unsafe { CFRetained::from_raw(NonNull::new(channel_name).unwrap()) };
1175+
Ok(raw_name.to_string())
1176+
} else {
1177+
Err(Error::with_message(
1178+
ErrorKind::Other,
1179+
"channel name is null",
1180+
))
1181+
}
1182+
}

0 commit comments

Comments
 (0)