use super::{AudioDeviceCore};
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
pub struct FlufflAudioContext {
pub audio_ss: sdl2::AudioSubsystem,
}
pub struct FlufflAudioDeviceContext<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + std::marker::Copy + Send + 'static,
State: Send + 'static,
{
fluffl_audio_device: Arc<Mutex<RefCell<FlufflAudioDevice<Callback, State>>>>,
sdl2_device: Arc<sdl2::audio::AudioDevice<FlufflCallback<Callback, State>>>,
}
impl<Callback, State> Clone for FlufflAudioDeviceContext<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + std::marker::Copy + Send,
State: Send,
{
fn clone(&self) -> Self {
Self {
fluffl_audio_device: self.fluffl_audio_device.clone(),
sdl2_device: self.sdl2_device.clone(),
}
}
}
impl<Callback, State> FlufflAudioDeviceContext<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + Copy + Send,
State: Send,
{
pub fn new(
core: AudioDeviceCore<Callback, State>,
audio_context: Arc<RefCell<FlufflAudioContext>>,
) -> FlufflAudioDeviceContext<Callback, State> {
println!("new music context");
let desired_spec = sdl2::audio::AudioSpecDesired {
freq: core.desired_specs.sample_rate.clone().map(|a| {
println!("freq = {}", a);
a as i32
}),
channels: core.desired_specs.channels.clone().map(|a| {
println!("channels = {}", a);
a as u8
}),
samples: core.desired_specs.buffer_size.clone().map(|a| {
println!("buffer_size = {}", a);
a as u16
}),
};
let audio_device = Arc::new(Mutex::new(RefCell::new(FlufflAudioDevice { core })));
let glue_callback = FlufflCallback {
audio_device: audio_device.clone(),
};
let sdl2_device = audio_context
.borrow()
.audio_ss
.open_playback(None, &desired_spec, |_spec| {
glue_callback
})
.unwrap();
Self {
fluffl_audio_device: audio_device,
sdl2_device: Arc::new(sdl2_device),
}
}
pub fn modify_state<ModifyCallback>(&self, mut cb: ModifyCallback)
where
ModifyCallback: FnMut(Option<&mut State>),
{
let lck = self.fluffl_audio_device.lock().unwrap();
let device = &mut *lck.borrow_mut();
let s = device.core.state.as_mut();
cb(s)
}
pub fn resume(&self) {
self.sdl2_device.resume();
}
pub fn pause(&self) {
self.sdl2_device.pause();
}
}
pub struct FlufflAudioDevice<F, S>
where
F: FnMut(&mut S, &mut [f32]) + std::marker::Copy + Send + 'static,
S: Send,
{
core: AudioDeviceCore<F, S>,
}
impl<F, S> FlufflAudioDevice<F, S>
where
F: FnMut(&mut S, &mut [f32]) + std::marker::Copy + Send + 'static,
S: Send + 'static,
{
pub fn callback(&self) -> F {
self.core.callback()
}
pub fn state(&mut self) -> Option<&mut S> {
self.core.state.as_mut()
}
}
pub struct FlufflCallback<F, S>
where
F: FnMut(&mut S, &mut [f32]) + Copy + Send + 'static,
S: Send,
{
audio_device: Arc<Mutex<RefCell<FlufflAudioDevice<F, S>>>>,
}
impl<Callback, State> sdl2::audio::AudioCallback for FlufflCallback<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + Send + Copy,
State: Send + 'static,
{
type Channel = f32;
fn callback(&mut self, out: &mut [f32]) {
let mut glue_cb = self.audio_device.lock().unwrap().borrow().callback();
let device_lock = self.audio_device.lock().unwrap();
let device = &mut *device_lock.borrow_mut();
device.state().map(|state| {
glue_cb(state, out);
});
}
}