voicemeeter\interface/
get_levels.rs

1//! Level and midi related functions
2//!
3//! # Functions
4//!
5//! * [`get_level`](VoicemeeterRemote::get_level)
6//! * [`get_midi_message`](VoicemeeterRemote::get_midi_message)
7//! * [`get_midi_message_buff`](VoicemeeterRemote::get_midi_message_buff)
8use std::ptr;
9
10pub use crate::types::{Device, LevelType};
11
12use super::VoicemeeterRemote;
13
14impl VoicemeeterRemote {
15    // TODO: one thread only
16    /// Get the level of a channel on a device
17    pub fn get_level(
18        &self,
19        level_type: LevelType,
20        device: Device,
21        channel: usize,
22    ) -> Result<Option<f32>, GetLevelError> {
23        let mut f = f32::NAN;
24        let dev_num =
25            if let Some(dev_num) = device.as_level_device_num(&self.program, level_type, channel) {
26                dev_num as i32
27            } else {
28                return Ok(None);
29            };
30        let res = unsafe { self.raw.VBVMR_GetLevel(level_type as i32, dev_num, &mut f) };
31        match res {
32            0 => Ok(Some(f)),
33            -1 => Err(GetLevelError::CannotGetClient),
34            -2 => Err(GetLevelError::NoServer),
35            -3 => Err(GetLevelError::NoLevel),
36            -4 => Err(GetLevelError::OutOfRange),
37            s => Err(GetLevelError::Other(s)),
38        }
39    }
40
41    // TODO: one thread only
42    /// Get a midi message.
43    pub fn get_midi_message(&self) -> Result<Vec<u8>, GetMidiMessageError> {
44        let mut v = vec![0; 1024];
45        let len = self.get_midi_message_buff(&mut v)?;
46        v.truncate(len);
47        Ok(v)
48    }
49
50    // TODO: one thread only
51    /// Get a midi message with a set buffer.
52    #[inline]
53    pub fn get_midi_message_buff(&self, buffer: &mut [u8]) -> Result<usize, GetMidiMessageError> {
54        let res = unsafe {
55            self.raw
56                .VBVMR_GetMidiMessage(ptr::addr_of_mut!(buffer[0]), buffer.len() as _)
57        };
58        match res {
59            res if res >= 0 => Ok(res as usize),
60            -1 => Err(GetMidiMessageError::CannotGetClient),
61            -2 => Err(GetMidiMessageError::NoServer),
62            v @ -5 | v @ -6 => Err(GetMidiMessageError::NoMidiData(v)),
63            s => Err(GetMidiMessageError::Other(s)),
64        }
65    }
66}
67
68/// Errors that can happen when querying levels from Voicemeeter.
69#[derive(Debug, thiserror::Error, Clone)]
70#[non_exhaustive]
71pub enum GetLevelError {
72    /// Cannot get client.
73    #[error("cannot get client (unexpected)")]
74    CannotGetClient,
75    /// No server found.
76    #[error("no server")]
77    NoServer,
78    /// No level found.
79    #[error("no level available")]
80    NoLevel,
81    /// Level is out of range.
82    #[error("out of range")]
83    OutOfRange,
84    /// An unexpected error code occured.
85    #[error("unexpected error occurred: error code {0}")]
86    Other(i32),
87}
88
89/// Errors that can happen when querying midi messages from Voicemeeter.
90#[derive(Debug, thiserror::Error, Clone)]
91#[non_exhaustive]
92pub enum GetMidiMessageError {
93    /// Cannot get client.
94    #[error("cannot get client (unexpected)")]
95    CannotGetClient,
96    /// No server found.
97    #[error("no server")]
98    NoServer,
99    /// No midi data found.
100    #[error("no level available")]
101    NoMidiData(i32),
102    /// An unexpected error code occured.
103    #[error("unexpected error occurred: error code {0}")]
104    Other(i32),
105}