1use crate::enums::{IntoResult, OtcBool, OtcResult};
16
17use lazy_static::lazy_static;
18use log::warn;
19use std::os::raw::c_void;
20use std::sync::atomic::{AtomicBool, Ordering};
21use std::sync::{Arc, Mutex};
22use thiserror::Error;
23
24lazy_static! {
25 static ref SINGLETON: Arc<Mutex<AudioDevice>> = Arc::new(Mutex::new(AudioDevice::new()));
26}
27
28#[derive(Error, Debug)]
29pub enum AudioDeviceError {
30 #[error("Audio device singleton not configured")]
31 MissingAudioDevice,
32 #[error("Audio device already initialized")]
33 InitializationFailure,
34}
35
36ffi_callback_with_return_singleton!(start_capturer, *const ffi::otc_audio_device, ffi::otc_bool);
37ffi_callback_with_return_singleton!(stop_capturer, *const ffi::otc_audio_device, ffi::otc_bool);
38ffi_callback_with_return_singleton!(start_renderer, *const ffi::otc_audio_device, ffi::otc_bool);
39ffi_callback_with_return_singleton!(stop_renderer, *const ffi::otc_audio_device, ffi::otc_bool);
40
41unsafe extern "C" fn get_capture_settings(
42 _: *const ffi::otc_audio_device,
43 _: *mut c_void,
44 settings: *mut ffi::otc_audio_device_settings,
45) -> ffi::otc_bool {
46 if settings.is_null() {
47 return false.into();
48 }
49 if let Ok(singleton) = SINGLETON.try_lock() {
50 let capture_settings = singleton.capture_settings();
51 (*settings).sampling_rate = capture_settings.sampling_rate;
52 (*settings).number_of_channels = capture_settings.number_of_channels;
53 true
54 } else {
55 false
56 }
57 .into()
58}
59
60unsafe extern "C" fn get_render_settings(
61 _: *const ffi::otc_audio_device,
62 _: *mut c_void,
63 settings: *mut ffi::otc_audio_device_settings,
64) -> ffi::otc_bool {
65 if settings.is_null() {
66 return false.into();
67 }
68 if let Ok(singleton) = SINGLETON.try_lock() {
69 let render_settings = singleton.render_settings();
70 (*settings).sampling_rate = render_settings.sampling_rate;
71 (*settings).number_of_channels = render_settings.number_of_channels;
72 true
73 } else {
74 false
75 }
76 .into()
77}
78
79pub struct AudioSampleData(pub Vec<i16>);
81
82pub struct AudioSample {
86 pub data: AudioSampleData,
87 pub sampling_rate: i32,
88 pub number_of_channels: i32,
89}
90
91#[derive(Clone, Debug, Copy)]
93pub struct AudioDeviceSettings {
94 pub sampling_rate: i32,
95 pub number_of_channels: i32,
96}
97
98impl Default for AudioDeviceSettings {
99 fn default() -> AudioDeviceSettings {
100 AudioDeviceSettings {
101 sampling_rate: 44100,
102 number_of_channels: 1,
103 }
104 }
105}
106
107type OnAudioSampleCallback = Box<dyn Fn(AudioSample) + Send + Sync + 'static>;
108
109#[derive(Clone)]
110pub struct AudioDevice {
111 ffi_callbacks: Arc<Mutex<ffi::otc_audio_device_callbacks>>,
112 capturer_ready: Arc<AtomicBool>,
113 capture_settings: Arc<Mutex<AudioDeviceSettings>>,
114 render_thread_running: Arc<AtomicBool>,
115 render_settings: Arc<Mutex<AudioDeviceSettings>>,
116 on_audio_sample_callbacks: Arc<Mutex<Vec<OnAudioSampleCallback>>>,
117}
118
119unsafe impl Send for AudioDevice {}
120unsafe impl Sync for AudioDevice {}
121
122impl AudioDevice {
123 fn new() -> Self {
124 let device = Self {
125 capturer_ready: Default::default(),
126 capture_settings: Default::default(),
127 render_thread_running: Default::default(),
128 render_settings: Default::default(),
129 on_audio_sample_callbacks: Default::default(),
130 ffi_callbacks: Arc::new(Mutex::new(ffi::otc_audio_device_callbacks {
131 init: None,
132 destroy: None,
133 init_capturer: None,
134 destroy_capturer: None,
135 start_capturer: Some(start_capturer),
136 stop_capturer: Some(stop_capturer),
137 is_capturer_initialized: None,
138 is_capturer_started: None,
139 get_estimated_capture_delay: None,
140 get_capture_settings: Some(get_capture_settings),
141 init_renderer: None,
142 destroy_renderer: None,
143 start_renderer: Some(start_renderer),
144 stop_renderer: Some(stop_renderer),
145 is_renderer_initialized: None,
146 is_renderer_started: None,
147 get_estimated_render_delay: None,
148 get_render_settings: Some(get_render_settings),
149 user_data: std::ptr::null_mut(),
150 reserved: std::ptr::null_mut(),
151 })),
152 };
153
154 unsafe {
155 if let Err(e) =
156 ffi::otc_set_audio_device(&*device.ffi_callbacks.lock().unwrap()
157 as *const ffi::otc_audio_device_callbacks)
158 .into_result()
159 {
160 warn!("Could not set audio device callbacks. {}", e);
161 }
162 }
163
164 device
165 }
166
167 pub fn get_instance() -> Arc<Mutex<AudioDevice>> {
168 SINGLETON.clone()
169 }
170
171 pub fn stop() {
172 let _ = SINGLETON.lock().unwrap().stop_renderer();
173 }
174
175 pub fn override_capture_settings(&self, settings: AudioDeviceSettings) {
176 *self.capture_settings.lock().unwrap() = settings;
177 }
178
179 pub fn override_render_settings(&self, settings: AudioDeviceSettings) {
180 *self.render_settings.lock().unwrap() = settings;
181 }
182
183 fn capture_settings(&self) -> AudioDeviceSettings {
184 *self.capture_settings.lock().unwrap()
185 }
186
187 fn render_settings(&self) -> AudioDeviceSettings {
188 *self.render_settings.lock().unwrap()
189 }
190
191 pub fn set_on_audio_sample_callback(&self, callback: OnAudioSampleCallback) {
192 self.on_audio_sample_callbacks
193 .lock()
194 .unwrap()
195 .push(callback);
196 }
197
198 pub fn push_audio_sample(&self, data: AudioSampleData) {
199 if !self.capturer_ready.load(Ordering::Relaxed) {
200 warn!("Audio capturer is not ready yet. Dropping audio sample");
201 return;
202 }
203 let size = data.0.len();
204 unsafe { ffi::otc_audio_device_write_capture_data(data.0.as_ptr(), size as u64) };
205 }
206
207 fn start_capturer(&self) -> OtcResult {
208 self.capturer_ready.store(true, Ordering::Relaxed);
209 Ok(())
210 }
211
212 fn stop_capturer(&self) -> OtcResult {
213 self.capturer_ready.store(false, Ordering::Relaxed);
214 Ok(())
215 }
216
217 fn start_renderer(&self) -> OtcResult {
218 self.render_thread_running.store(true, Ordering::Relaxed);
219 let render_thread_running = self.render_thread_running.clone();
220 let sampling_rate = self.render_settings.lock().unwrap().sampling_rate;
221 let number_of_channels = self.render_settings.lock().unwrap().number_of_channels;
222 let size = (sampling_rate / 100) * number_of_channels;
223 let on_audio_sample_callbacks = self.on_audio_sample_callbacks.clone();
224 std::thread::spawn(move || loop {
225 if !render_thread_running.load(Ordering::Relaxed) {
226 break;
227 }
228 let data = unsafe {
229 let mut data = Vec::with_capacity(size as usize);
230 let size = ffi::otc_audio_device_read_render_data(data.as_mut_ptr(), size as u64);
231 data.set_len(size as usize);
232 data
233 };
234 if data.is_empty() {
235 continue;
236 }
237 if let Ok(callbacks) = on_audio_sample_callbacks.try_lock() {
238 for ref callback in callbacks.iter() {
239 callback(AudioSample {
240 data: AudioSampleData(data.clone()),
241 sampling_rate,
242 number_of_channels,
243 });
244 }
245 }
246 std::thread::sleep(std::time::Duration::from_micros(10000));
247 });
248 Ok(())
249 }
250
251 fn stop_renderer(&self) -> OtcResult {
252 self.render_thread_running.store(false, Ordering::Relaxed);
253 Ok(())
254 }
255}