craydate/sound/
headphone.rs1use alloc::boxed::Box;
2use core::ffi::c_void;
3
4use super::Sound;
5use crate::capi_state::CApiState;
6
7type ActiveMicrophoneInnerBox = Box<dyn Fn(&[i16]) -> MicrophoneCallbackOutput + Sync>;
8
9pub enum MicrophoneCallbackOutput {
10 StopRecording,
11 ContinueRecording,
12}
13
14pub struct ActiveMicrophoneCallback {
15 generation: usize,
16 _c_function_data: Box<ActiveMicrophoneInnerBox>,
19}
20impl ActiveMicrophoneCallback {
21 pub(crate) fn set_active_callback<F: Fn(&[i16]) -> MicrophoneCallbackOutput + Sync + 'static>(
22 closure: F,
23 force_device_microphone: bool,
24 ) -> Self {
25 let gen = CApiState::get().headphone_change_generation.get() + 1;
26 CApiState::get().headphone_change_generation.set(gen);
27
28 let inner: ActiveMicrophoneInnerBox = Box::new(closure);
30 let c_function_data: *mut ActiveMicrophoneInnerBox = Box::into_raw(Box::new(inner));
32 let boxed_c_function_data = unsafe { Box::from_raw(c_function_data) };
34
35 unsafe extern "C" fn c_func(c_data: *mut c_void, buf: *mut i16, len: i32) -> i32 {
36 let closure = c_data as *mut ActiveMicrophoneInnerBox;
37 let out = (*closure)(core::slice::from_raw_parts(buf, len as usize));
38 match out {
39 MicrophoneCallbackOutput::ContinueRecording => 1,
40 MicrophoneCallbackOutput::StopRecording => 0,
41 }
42 }
43 unsafe {
44 Sound::fns().setMicCallback.unwrap()(
45 Some(c_func),
46 c_function_data as *mut c_void,
47 force_device_microphone as i32,
48 )
49 };
50
51 ActiveMicrophoneCallback {
52 generation: gen,
53 _c_function_data: boxed_c_function_data,
54 }
55 }
56}
57
58impl Drop for ActiveMicrophoneCallback {
59 fn drop(&mut self) {
60 if self.generation == CApiState::get().headphone_change_generation.get() {
63 unsafe { Sound::fns().setMicCallback.unwrap()(None, core::ptr::null_mut(), false as i32) }
64 }
65 }
66}