use super::SeedlingContext;
use firewheel::{FirewheelConfig, FirewheelCtx, backend::AudioBackend};
use std::sync::mpsc;
#[derive(Debug)]
pub struct InnerContext(mpsc::Sender<ThreadLocalCall>);
type ThreadLocalCall = Box<dyn FnOnce(&mut SeedlingContext) + Send + 'static>;
impl InnerContext {
#[inline(always)]
pub fn new<B>(settings: FirewheelConfig) -> Self
where
B: AudioBackend + 'static,
B::StreamError: Send + Sync + 'static,
{
let (bev_to_audio_tx, bev_to_audio_rx) = mpsc::channel::<ThreadLocalCall>();
std::thread::spawn(move || {
let context = FirewheelCtx::<B>::new(settings);
let mut context = SeedlingContext::new(context);
while let Ok(func) = bev_to_audio_rx.recv() {
(func)(&mut context);
}
});
InnerContext(bev_to_audio_tx)
}
#[inline(always)]
pub fn with<F, O>(&mut self, f: F) -> O
where
F: FnOnce(&mut SeedlingContext) -> O + Send,
O: Send + 'static,
{
let (send, receive) = mpsc::sync_channel(1);
let func: Box<dyn FnOnce(&mut SeedlingContext) + Send> = Box::new(move |ctx| {
let result = f(ctx);
send.send(result).unwrap();
});
let func = unsafe {
core::mem::transmute::<
Box<dyn FnOnce(&mut SeedlingContext) + Send>,
Box<dyn FnOnce(&mut SeedlingContext) + Send + 'static>,
>(func)
};
self.0.send(func).unwrap();
receive.recv().unwrap()
}
}