voicemeeter\interface\callback/
commands.rs

1//! Callback command types.
2//!
3//! These are returned to the callback function.
4use crate::{bindings::VBVMR_CBCOMMAND, types::VoicemeeterApplication};
5
6use super::data::{
7    AudioBuffer, AudioInfo, BufferInData, BufferMainData, BufferOutData, RawCallbackData,
8};
9
10macro_rules! implement {
11    (@audio_info $($name:ident),* $(,)?) => {
12        $(
13            impl HasAudioInfo for $name<'_> {
14                fn get(&self) -> &AudioInfo {
15                    self.info
16                }
17            }
18        )*
19    };
20    (@audio_buffer $($name:ident),* $(,)?) => {
21        // $(
22        //     impl HasAudioBuffer for $name<'_> {
23        //         fn get(&self) -> &AudioBuffer {
24        //             &self.buffer
25        //         }
26        //         fn get_mut(&mut self) -> &mut AudioBuffer {
27        //             &mut self.buffer
28        //         }
29        //     }
30        // )*
31    };
32}
33
34implement! { @audio_info
35    Starting,
36    Ending,
37    Change,
38}
39
40implement! { @audio_buffer
41    BufferIn,
42    BufferOut,
43    BufferMain,
44}
45
46/// Callback command with audio info. Used to abstract away the command type in client code
47pub trait HasAudioInfo {
48    /// Get the audio info.
49    fn get(&self) -> &AudioInfo;
50}
51
52/// Callback command with audio buffer. Used to abstract away the command type in client code
53pub trait HasAudioBuffer {
54    /// Get the audio buffer.
55    fn get(&self) -> &AudioBuffer;
56}
57
58// FIXME: add .mds for these docs
59
60/// Starting command.
61#[derive(Debug)]
62pub struct Starting<'a> {
63    /// Audio info
64    pub info: &'a AudioInfo,
65}
66
67impl<'a> Starting<'a> {
68    /// Create a new `Starting` command.
69    //#[tracing::instrument(skip_all, name = "Starting::new")]
70    pub(crate) fn new(info: &'a AudioInfo) -> Self {
71        Self { info }
72    }
73}
74
75/// Ending command.
76#[derive(Debug)]
77pub struct Ending<'a> {
78    /// Audio info
79    pub info: &'a AudioInfo,
80}
81
82impl<'a> Ending<'a> {
83    /// Create a new `Ending` command.
84    //#[tracing::instrument(skip_all, name = "Ending::new")]
85    pub(crate) fn new(info: &'a AudioInfo) -> Self {
86        Self { info }
87    }
88}
89
90/// Change command.
91#[derive(Debug)]
92pub struct Change<'a> {
93    /// Audio info
94    pub info: &'a AudioInfo,
95}
96
97impl<'a> Change<'a> {
98    /// Create a new `Change` command.
99    //#[tracing::instrument(skip_all, name = "Change::new")]
100    pub(crate) fn new(info: &'a AudioInfo) -> Self {
101        Self { info }
102    }
103}
104
105/// Data for input mode.
106pub struct BufferIn<'a> {
107    /// Buffer data for input mode
108    pub buffer: BufferInData<'a>,
109    /// Sample rate
110    pub sr: usize,
111    /// Number of samples per frame
112    pub nbs: usize,
113    /// Total number of inputs in buffer.
114    pub nbi: usize,
115    /// Total number of outputs in buffer.
116    pub nbo: usize,
117}
118
119impl<'a> BufferIn<'a> {
120    //#[tracing::instrument(skip_all, name = "BufferIn::new")]
121    pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
122        Self {
123            sr: buffer.audiobuffer_sr as usize,
124            nbs: buffer.audiobuffer_nbs as usize,
125            nbi: buffer.audiobuffer_nbi as usize,
126            nbo: buffer.audiobuffer_nbo as usize,
127            buffer: BufferInData::new(program, buffer, buffer.audiobuffer_nbs as usize),
128        }
129    }
130}
131
132/// Data for output mode.
133pub struct BufferOut<'a> {
134    /// Sample rate
135    pub sr: usize,
136    /// Buffer data for output mode
137    pub buffer: BufferOutData<'a>,
138    /// Number of samples per frame
139    pub nbs: usize,
140    /// Total number of inputs in buffer.
141    pub nbi: usize,
142    /// Total number of outputs in buffer.
143    pub nbo: usize,
144}
145
146impl<'a> BufferOut<'a> {
147    //#[tracing::instrument(skip_all, name = "BufferOut::new")]
148    pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
149        Self {
150            sr: buffer.audiobuffer_sr as usize,
151            nbs: buffer.audiobuffer_nbs as usize,
152            nbi: buffer.audiobuffer_nbi as usize,
153            nbo: buffer.audiobuffer_nbo as usize,
154            buffer: BufferOutData::new(program, buffer, buffer.audiobuffer_nbs as usize),
155        }
156    }
157}
158
159/// Data for main mode.
160pub struct BufferMain<'a> {
161    /// Buffer data for main mode
162    pub buffer: BufferMainData<'a>,
163    /// Sample rate
164    pub sr: usize,
165    /// Number of samples per frame
166    pub nbs: usize,
167    /// Total number of inputs in buffer.
168    pub nbi: usize,
169    /// Total number of outputs in buffer.
170    pub nbo: usize,
171}
172
173impl<'a> BufferMain<'a> {
174    //#[tracing::instrument(skip_all, name = "BufferMain::new")]
175    pub(crate) fn new(program: VoicemeeterApplication, buffer: &'a mut AudioBuffer) -> Self {
176        Self {
177            sr: buffer.audiobuffer_sr as usize,
178            nbs: buffer.audiobuffer_nbs as usize,
179            nbi: buffer.audiobuffer_nbi as usize,
180            nbo: buffer.audiobuffer_nbo as usize,
181            buffer: BufferMainData::new(program, buffer, buffer.audiobuffer_nbs as usize),
182        }
183    }
184}
185
186/// Callback command passed to the [audio callback](crate::VoicemeeterRemote::audio_callback_register).
187#[repr(i32)]
188#[cfg(feature = "interface")] // for doc_cfg
189#[allow(clippy::large_enum_variant)]
190pub enum CallbackCommand<'a> {
191    /// Starting command
192    ///
193    /// this is the first call of your Callback, made to let you initialize your
194    /// possible different DSP processing objects, allocate memory, precompute date...
195    Starting(Starting<'a>),
196    /// Ending command
197    ///
198    /// this is the last call of your Callback, to release all your structure
199    /// previously allocated in the first call.
200    Ending(Ending<'a>),
201    /// Change command
202    ///
203    /// this command is called if the samplerate or buffer size have changed
204    Change(Change<'a>),
205    /// BufferIn command
206    ///
207    /// buffers for inputs
208    BufferIn(BufferIn<'a>),
209    /// BufferOut command
210    ///
211    /// buffers for outputs
212    BufferOut(BufferOut<'a>),
213    /// BufferMain command
214    ///
215    /// buffers for all i/o
216    BufferMain(BufferMain<'a>),
217    /// Other inknown command
218    Other(VBVMR_CBCOMMAND, RawCallbackData),
219}
220
221impl<'a> CallbackCommand<'a> {
222    /// Make a new callback command. This is not meant to be used in consumer code.
223    #[doc(hidden)]
224    pub unsafe fn new_unchecked(
225        program: VoicemeeterApplication,
226        command: VBVMR_CBCOMMAND,
227        ptr: RawCallbackData,
228    ) -> Self {
229        match command {
230            VBVMR_CBCOMMAND::STARTING => {
231                Self::Starting(Starting::new(unsafe { ptr.as_audio_info() }))
232            }
233            VBVMR_CBCOMMAND::ENDING => Self::Ending(Ending::new(unsafe { ptr.as_audio_info() })),
234            VBVMR_CBCOMMAND::CHANGE => Self::Change(Change::new(unsafe { ptr.as_audio_info() })),
235            VBVMR_CBCOMMAND::BUFFER_IN => {
236                Self::BufferIn(BufferIn::new(program, unsafe { ptr.as_audio_buffer() }))
237            }
238            VBVMR_CBCOMMAND::BUFFER_OUT => {
239                Self::BufferOut(BufferOut::new(program, unsafe { ptr.as_audio_buffer() }))
240            }
241            VBVMR_CBCOMMAND::BUFFER_MAIN => {
242                Self::BufferMain(BufferMain::new(program, unsafe { ptr.as_audio_buffer() }))
243            }
244            i => Self::Other(i, ptr),
245        }
246    }
247
248    /// Get the command "name"
249    pub fn name(&self) -> Option<&'static str> {
250        Some(match self {
251            Self::Starting(_) => "Starting",
252            Self::Ending(_) => "Ending",
253            Self::Change(_) => "Change",
254            Self::BufferIn(_) => "BufferIn",
255            Self::BufferOut(_) => "BufferOut",
256            Self::BufferMain(_) => "BufferMain",
257            Self::Other(_, _) => return None,
258        })
259    }
260}