use std::{ffi::c_void, os::raw::c_int};
use super::Channel;
use crate::bind;
pub mod lib;
pub type Effect<'device> = Box<dyn FnMut(&mut [u8]) + 'device>;
pub trait EffectAttachExt {
fn attach(&self, effect: Effect);
fn detach_all(&self);
}
impl<'device> EffectAttachExt for Channel<'device> {
fn attach(&self, effect: Effect) {
let wrapped = Box::new(effect);
let raw = Box::into_raw(wrapped);
let _ = unsafe {
bind::Mix_RegisterEffect(
self.0,
Some(effect_attach_effect_handler),
Some(effect_attach_done_handler),
raw.cast(),
)
};
}
fn detach_all(&self) {
let _ = unsafe { bind::Mix_UnregisterAllEffects(self.0) };
}
}
pub(crate) extern "C" fn effect_attach_effect_handler(
_: c_int,
stream: *mut c_void,
len: c_int,
userdata: *mut c_void,
) {
let callback = unsafe { &mut *(userdata as *mut Effect) };
let stream = unsafe { std::slice::from_raw_parts_mut(stream.cast(), len as _) };
callback(stream);
}
pub(crate) extern "C" fn effect_attach_done_handler(_: c_int, userdata: *mut c_void) {
let _ = unsafe { Box::from_raw(userdata as *mut Effect) };
}