use super::AudioDeviceCore;
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct FlufflAudioContext {
pub audio_ss: Arc<RefCell<be_sdl2::AudioSubsystem>>,
}
pub struct FlufflAudioDeviceContext<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + Copy + Send + 'static,
State: Send + 'static,
{
fluffl_audio_device: Arc<Mutex<FlufflAudioDevice<Callback, State>>>,
sdl2_device: Arc<be_sdl2::audio::AudioDevice<FlufflCallback<Callback, State>>>,
}
impl<Callback, State> Clone for FlufflAudioDeviceContext<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + 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: FlufflAudioContext,
) -> FlufflAudioDeviceContext<Callback, State> {
let desired_spec = be_sdl2::audio::AudioSpecDesired {
freq: core.desired_specs.sample_rate.map(|a| {
a as i32
}),
channels: core.desired_specs.channels.map(|a| {
a as u8
}),
samples: core.desired_specs.buffer_size.map(|a| {
a as u16
}),
};
let audio_device = Arc::new(Mutex::new(FlufflAudioDevice { core }));
let glue_callback = FlufflCallback {
audio_device: audio_device.clone(),
};
let sdl2_device = audio_context
.audio_ss
.borrow_mut()
.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>) -> Option<()>,
{
let mut lck = self.fluffl_audio_device.lock().unwrap();
let device = &mut *lck;
let s = device.core.state.as_mut();
let _ = 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<Callback, State>
where
Callback: FnMut(&mut State, &mut [f32]) + Copy + Send + 'static,
State: Send,
{
audio_device: Arc<Mutex<FlufflAudioDevice<Callback, State>>>,
}
impl<Callback, State> be_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 callback = self.audio_device.lock().unwrap().callback();
let mut device_lock = self.audio_device.lock().unwrap();
let device = &mut *device_lock;
if let Some(state) = device.state() {
callback(state, out);
}
}
}