1use std::mem::MaybeUninit;
2use std::os::raw::{c_int, c_void};
3use std::ptr::null_mut;
4use std::slice;
5use std::sync::Arc;
6
7use parking_lot::Mutex;
8
9use crate::platform::platform;
10use crate::sdl2_sys::*;
11
12pub trait AudioCallback {
13 fn update(&mut self, out: &mut [i16]);
14}
15
16extern "C" fn c_audio_callback(userdata: *mut c_void, stream: *mut u8, len: c_int) {
17 let audio_callback = unsafe { &*userdata.cast::<Arc<Mutex<dyn AudioCallback>>>() };
18 let stream: &mut [i16] =
19 unsafe { slice::from_raw_parts_mut(stream.cast::<i16>(), len as usize / 2) };
20 audio_callback.lock().update(stream);
21}
22
23pub fn start_audio(
24 sample_rate: u32,
25 num_channels: u8,
26 num_samples: u16,
27 audio_callback: Arc<Mutex<dyn AudioCallback>>,
28) {
29 let userdata = Box::into_raw(Box::new(audio_callback)).cast();
30
31 let desired = SDL_AudioSpec {
32 freq: sample_rate as i32,
33 format: AUDIO_S16 as u16,
34 channels: num_channels,
35 silence: 0,
36 samples: num_samples,
37 padding: 0,
38 size: 0,
39 callback: Some(c_audio_callback),
40 userdata,
41 };
42
43 let mut obtained = MaybeUninit::uninit();
44 platform().audio_device_id =
45 unsafe { SDL_OpenAudioDevice(null_mut(), 0, &desired, obtained.as_mut_ptr(), 0) };
46
47 if platform().audio_device_id == 0 {
48 println!("Failed to initialize audio device");
49 }
50
51 set_audio_enabled(true);
52}
53
54pub fn set_audio_enabled(enabled: bool) {
55 let pause_on = i32::from(!enabled);
56 let audio_device_id = platform().audio_device_id;
57
58 if audio_device_id != 0 {
59 unsafe {
60 SDL_PauseAudioDevice(audio_device_id, pause_on);
61 }
62 }
63}