pub fn prepare_default_input() {
#[cfg(target_os = "macos")]
macos::activate_default_input();
}
#[cfg(target_os = "macos")]
mod macos {
use std::os::raw::c_void;
type AudioObjectID = u32;
type AudioDeviceID = u32;
type OSStatus = i32;
const K_AUDIO_OBJECT_SYSTEM_OBJECT: AudioObjectID = 1;
const K_AUDIO_HARDWARE_PROPERTY_DEFAULT_INPUT_DEVICE: u32 = u32::from_be_bytes(*b"dIn ");
const K_AUDIO_OBJECT_PROPERTY_SCOPE_GLOBAL: u32 = u32::from_be_bytes(*b"glob");
const K_AUDIO_OBJECT_PROPERTY_ELEMENT_MAIN: u32 = 0;
#[repr(C)]
struct AudioObjectPropertyAddress {
selector: u32,
scope: u32,
element: u32,
}
#[link(name = "CoreAudio", kind = "framework")]
extern "C" {
fn AudioObjectGetPropertyData(
object_id: AudioObjectID,
address: *const AudioObjectPropertyAddress,
qualifier_data_size: u32,
qualifier_data: *const c_void,
data_size: *mut u32,
data: *mut c_void,
) -> OSStatus;
fn AudioObjectSetPropertyData(
object_id: AudioObjectID,
address: *const AudioObjectPropertyAddress,
qualifier_data_size: u32,
qualifier_data: *const c_void,
data_size: u32,
data: *const c_void,
) -> OSStatus;
}
pub(super) fn activate_default_input() {
let addr = AudioObjectPropertyAddress {
selector: K_AUDIO_HARDWARE_PROPERTY_DEFAULT_INPUT_DEVICE,
scope: K_AUDIO_OBJECT_PROPERTY_SCOPE_GLOBAL,
element: K_AUDIO_OBJECT_PROPERTY_ELEMENT_MAIN,
};
let mut device_id: AudioDeviceID = 0;
let mut size = std::mem::size_of::<AudioDeviceID>() as u32;
let status = unsafe {
AudioObjectGetPropertyData(
K_AUDIO_OBJECT_SYSTEM_OBJECT,
&addr,
0,
std::ptr::null(),
&mut size,
&mut device_id as *mut _ as *mut c_void,
)
};
if status != 0 {
log::debug!("CoreAudio: failed to get default input device (status={status})");
return;
}
let status = unsafe {
AudioObjectSetPropertyData(
K_AUDIO_OBJECT_SYSTEM_OBJECT,
&addr,
0,
std::ptr::null(),
std::mem::size_of::<AudioDeviceID>() as u32,
&device_id as *const _ as *const c_void,
)
};
if status != 0 {
log::debug!("CoreAudio: failed to re-set default input device (status={status})");
} else {
log::info!("CoreAudio: activated default input device (id={device_id})");
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn prepare_default_input_does_not_panic() {
prepare_default_input();
}
}