murmur_core/audio/
activate.rs1pub fn prepare_default_input() {
24 #[cfg(target_os = "macos")]
25 macos::activate_default_input();
26}
27
28#[cfg(target_os = "macos")]
31mod macos {
32 use std::os::raw::c_void;
33
34 type AudioObjectID = u32;
36 type AudioDeviceID = u32;
37 type OSStatus = i32;
38
39 const K_AUDIO_OBJECT_SYSTEM_OBJECT: AudioObjectID = 1;
40
41 const K_AUDIO_HARDWARE_PROPERTY_DEFAULT_INPUT_DEVICE: u32 = u32::from_be_bytes(*b"dIn ");
43 const K_AUDIO_OBJECT_PROPERTY_SCOPE_GLOBAL: u32 = u32::from_be_bytes(*b"glob");
44 const K_AUDIO_OBJECT_PROPERTY_ELEMENT_MAIN: u32 = 0;
45
46 #[repr(C)]
47 struct AudioObjectPropertyAddress {
48 selector: u32,
49 scope: u32,
50 element: u32,
51 }
52
53 #[link(name = "CoreAudio", kind = "framework")]
54 extern "C" {
55 fn AudioObjectGetPropertyData(
56 object_id: AudioObjectID,
57 address: *const AudioObjectPropertyAddress,
58 qualifier_data_size: u32,
59 qualifier_data: *const c_void,
60 data_size: *mut u32,
61 data: *mut c_void,
62 ) -> OSStatus;
63
64 fn AudioObjectSetPropertyData(
65 object_id: AudioObjectID,
66 address: *const AudioObjectPropertyAddress,
67 qualifier_data_size: u32,
68 qualifier_data: *const c_void,
69 data_size: u32,
70 data: *const c_void,
71 ) -> OSStatus;
72 }
73
74 pub(super) fn activate_default_input() {
81 let addr = AudioObjectPropertyAddress {
82 selector: K_AUDIO_HARDWARE_PROPERTY_DEFAULT_INPUT_DEVICE,
83 scope: K_AUDIO_OBJECT_PROPERTY_SCOPE_GLOBAL,
84 element: K_AUDIO_OBJECT_PROPERTY_ELEMENT_MAIN,
85 };
86
87 let mut device_id: AudioDeviceID = 0;
88 let mut size = std::mem::size_of::<AudioDeviceID>() as u32;
89
90 let status = unsafe {
91 AudioObjectGetPropertyData(
92 K_AUDIO_OBJECT_SYSTEM_OBJECT,
93 &addr,
94 0,
95 std::ptr::null(),
96 &mut size,
97 &mut device_id as *mut _ as *mut c_void,
98 )
99 };
100
101 if status != 0 {
102 log::debug!("CoreAudio: failed to get default input device (status={status})");
103 return;
104 }
105
106 let status = unsafe {
107 AudioObjectSetPropertyData(
108 K_AUDIO_OBJECT_SYSTEM_OBJECT,
109 &addr,
110 0,
111 std::ptr::null(),
112 std::mem::size_of::<AudioDeviceID>() as u32,
113 &device_id as *const _ as *const c_void,
114 )
115 };
116
117 if status != 0 {
118 log::debug!("CoreAudio: failed to re-set default input device (status={status})");
119 } else {
120 log::info!("CoreAudio: activated default input device (id={device_id})");
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn prepare_default_input_does_not_panic() {
131 prepare_default_input();
133 }
134}