use crate::{bindings::VBVMR_CBCOMMAND, types::VoicemeeterApplication};
use super::data::{
AudioBuffer, AudioInfo, BufferInData, BufferMainData, BufferOutData, RawCallbackData,
};
macro_rules! implement {
(@audio_info $($name:ident),* $(,)?) => {
$(
impl HasAudioInfo for $name<'_> {
fn get(&self) -> &AudioInfo {
self.info
}
}
)*
};
(@audio_buffer $($name:ident),* $(,)?) => {
};
}
implement! { @audio_info
Starting,
Ending,
Change,
}
implement! { @audio_buffer
BufferIn,
BufferOut,
BufferMain,
}
pub trait HasAudioInfo {
fn get(&self) -> &AudioInfo;
}
pub trait HasAudioBuffer {
fn get(&self) -> &AudioBuffer;
}
#[derive(Debug)]
pub struct Starting<'a> {
pub info: &'a AudioInfo,
}
impl<'a> Starting<'a> {
pub(crate) fn new(info: &'a AudioInfo) -> Self {
Self { info }
}
}
#[derive(Debug)]
pub struct Ending<'a> {
pub info: &'a AudioInfo,
}
impl<'a> Ending<'a> {
pub(crate) fn new(info: &'a AudioInfo) -> Self {
Self { info }
}
}
#[derive(Debug)]
pub struct Change<'a> {
pub info: &'a AudioInfo,
}
impl<'a> Change<'a> {
pub(crate) fn new(info: &'a AudioInfo) -> Self {
Self { info }
}
}
pub struct BufferIn<'a> {
pub buffer: BufferInData<'a>,
pub sr: usize,
pub nbs: usize,
pub nbi: usize,
pub nbo: usize,
}
impl<'a> BufferIn<'a> {
pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
Self {
sr: buffer.audiobuffer_sr as usize,
nbs: buffer.audiobuffer_nbs as usize,
nbi: buffer.audiobuffer_nbi as usize,
nbo: buffer.audiobuffer_nbo as usize,
buffer: BufferInData::new(program, buffer, buffer.audiobuffer_nbs as usize),
}
}
}
pub struct BufferOut<'a> {
pub sr: usize,
pub buffer: BufferOutData<'a>,
pub nbs: usize,
pub nbi: usize,
pub nbo: usize,
}
impl<'a> BufferOut<'a> {
pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
Self {
sr: buffer.audiobuffer_sr as usize,
nbs: buffer.audiobuffer_nbs as usize,
nbi: buffer.audiobuffer_nbi as usize,
nbo: buffer.audiobuffer_nbo as usize,
buffer: BufferOutData::new(program, buffer, buffer.audiobuffer_nbs as usize),
}
}
}
pub struct BufferMain<'a> {
pub buffer: BufferMainData<'a>,
pub sr: usize,
pub nbs: usize,
pub nbi: usize,
pub nbo: usize,
}
impl<'a> BufferMain<'a> {
pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
Self {
sr: buffer.audiobuffer_sr as usize,
nbs: buffer.audiobuffer_nbs as usize,
nbi: buffer.audiobuffer_nbi as usize,
nbo: buffer.audiobuffer_nbo as usize,
buffer: BufferMainData::new(program, buffer, buffer.audiobuffer_nbs as usize),
}
}
}
#[repr(i32)]
#[cfg(feature = "interface")] #[allow(clippy::large_enum_variant)]
pub enum CallbackCommand<'a> {
Starting(Starting<'a>),
Ending(Ending<'a>),
Change(Change<'a>),
BufferIn(BufferIn<'a>),
BufferOut(BufferOut<'a>),
BufferMain(BufferMain<'a>),
Other(VBVMR_CBCOMMAND, RawCallbackData),
}
impl<'a> CallbackCommand<'a> {
#[doc(hidden)]
pub unsafe fn new_unchecked(
program: VoicemeeterApplication,
command: VBVMR_CBCOMMAND,
ptr: RawCallbackData,
) -> Self {
match command {
VBVMR_CBCOMMAND::STARTING => {
Self::Starting(Starting::new(unsafe { ptr.as_audio_info() }))
}
VBVMR_CBCOMMAND::ENDING => Self::Ending(Ending::new(unsafe { ptr.as_audio_info() })),
VBVMR_CBCOMMAND::CHANGE => Self::Change(Change::new(unsafe { ptr.as_audio_info() })),
VBVMR_CBCOMMAND::BUFFER_IN => {
Self::BufferIn(BufferIn::new(program, unsafe { ptr.as_audio_buffer() }))
}
VBVMR_CBCOMMAND::BUFFER_OUT => {
Self::BufferOut(BufferOut::new(program, unsafe { ptr.as_audio_buffer() }))
}
VBVMR_CBCOMMAND::BUFFER_MAIN => {
Self::BufferMain(BufferMain::new(program, unsafe { ptr.as_audio_buffer() }))
}
i => Self::Other(i, ptr),
}
}
pub fn name(&self) -> Option<&'static str> {
Some(match self {
Self::Starting(_) => "Starting",
Self::Ending(_) => "Ending",
Self::Change(_) => "Change",
Self::BufferIn(_) => "BufferIn",
Self::BufferOut(_) => "BufferOut",
Self::BufferMain(_) => "BufferMain",
Self::Other(_, _) => return None,
})
}
}