voicemeeter\interface/
device.rs

1//! Device related interfaces.
2//!
3//! # Functions
4//!
5//! * [`get_total_input_device`](VoicemeeterRemote::get_total_input_device)
6//! * [`get_total_output_device`](VoicemeeterRemote::get_total_output_device)
7//! * [`get_input_device`](VoicemeeterRemote::get_input_device)
8//! * [`get_output_device`](VoicemeeterRemote::get_output_device)
9use std::{ffi::CStr, os::raw::c_char};
10
11use crate::{bindings::VBVMR_DEVTYPE, types::ZIndex};
12
13use super::VoicemeeterRemote;
14
15impl VoicemeeterRemote {
16    /// Get the number of Audio Input Devices available on the system.
17    pub fn get_total_input_device(&self) -> Result<i32, GetTotalDeviceError> {
18        let res = unsafe { self.raw.VBVMR_Input_GetDeviceNumber() };
19        if res < 0 {
20            Err(GetTotalDeviceError(res))
21        } else {
22            Ok(res)
23        }
24    }
25    /// Get the number of Audio Output Devices available on the system.
26    pub fn get_total_output_device(&self) -> Result<i32, GetTotalDeviceError> {
27        let res = unsafe { self.raw.VBVMR_Output_GetDeviceNumber() };
28        if res < 0 {
29            Err(GetTotalDeviceError(res))
30        } else {
31            Ok(res)
32        }
33    }
34    /// Get the description of a specific Audio Input Device.
35    pub fn get_input_device(
36        &self,
37        index: impl Into<ZIndex>,
38    ) -> Result<InputDevice, GetDeviceError> {
39        let mut r#type = -1;
40        let index = index.into().0;
41        let mut name = [0 as c_char; 256];
42        let mut hardware_id = [0 as c_char; 256];
43        unsafe {
44            self._get_input_device(
45                index,
46                Some(&mut r#type),
47                Some(&mut name),
48                Some(&mut hardware_id),
49            )?;
50        }
51        Ok(InputDevice {
52            r#type: DeviceType::from(r#type),
53            name: unsafe { CStr::from_ptr(name.as_ptr()) }
54                .to_string_lossy()
55                .into_owned(),
56            hardware_id: unsafe { CStr::from_ptr(hardware_id.as_ptr()) }
57                .to_string_lossy()
58                .into_owned(),
59        })
60    }
61
62    pub(crate) unsafe fn _get_input_device(
63        &self,
64        index: i32,
65        r#type: Option<&mut i32>,
66        name: Option<&mut [c_char; 256]>,
67        hardware_id: Option<&mut [c_char; 256]>,
68    ) -> Result<(), GetDeviceError> {
69        let type_p = crate::opt_or_null(r#type);
70        let name_p = crate::opt_or_null(name.map(|a| &mut a[0]));
71        let hardware_id_p = crate::opt_or_null(hardware_id.map(|a| &mut a[0]));
72
73        let res = unsafe {
74            self.raw
75                .VBVMR_Input_GetDeviceDescA(index, type_p, name_p, hardware_id_p)
76        };
77        //cleanup
78        match res {
79            0 => Ok(()),
80            s => Err(GetDeviceError(s)),
81        }
82    }
83
84    /// Get the description of a specific Audio Output Device.
85    pub fn get_output_device(
86        &self,
87        index: impl Into<ZIndex>,
88    ) -> Result<OutputDevice, GetDeviceError> {
89        let mut r#type = 0;
90        let index = index.into().0;
91        let mut name = [0 as c_char; 256];
92        let mut hardware_id = [0 as c_char; 256];
93        unsafe {
94            self._get_output_device(
95                index,
96                Some(&mut r#type),
97                Some(&mut name),
98                Some(&mut hardware_id),
99            )?;
100        }
101        Ok(OutputDevice {
102            r#type: DeviceType::from(r#type),
103            name: unsafe { CStr::from_ptr(name.as_ptr()) }
104                .to_string_lossy()
105                .into_owned(),
106            hardware_id: unsafe { CStr::from_ptr(hardware_id.as_ptr()) }
107                .to_string_lossy()
108                .into_owned(),
109        })
110    }
111
112    pub(crate) unsafe fn _get_output_device(
113        &self,
114        index: i32,
115        r#type: Option<&mut i32>,
116        name: Option<&mut [c_char; 256]>,
117        hardware_id: Option<&mut [c_char; 256]>,
118    ) -> Result<(), GetDeviceError> {
119        let type_p = crate::opt_or_null(r#type);
120        let name_p = crate::opt_or_null(name.map(|a| &mut a[0]));
121        let hardware_id_p = crate::opt_or_null(hardware_id.map(|a| &mut a[0]));
122        let res = unsafe {
123            self.raw
124                .VBVMR_Output_GetDeviceDescA(index, type_p, name_p, hardware_id_p)
125        };
126        //cleanup
127        match res {
128            0 => Ok(()),
129            s => Err(GetDeviceError(s)),
130        }
131    }
132}
133
134/// A Audio Input Device.
135#[derive(Debug)]
136pub struct InputDevice {
137    /// The type of the device.
138    pub r#type: DeviceType,
139    /// Device name
140    pub name: String,
141    /// Hardware ID
142    pub hardware_id: String,
143}
144
145/// Represents the type of an audio device.
146#[repr(i32)]
147#[derive(Debug)]
148pub enum DeviceType {
149    /// MME (Multimedia Extension) audio driver.
150    Mme = VBVMR_DEVTYPE::MME.0,
151    /// WDM (Windows Driver Model) audio driver.
152    Wdm = VBVMR_DEVTYPE::WDM.0,
153    /// KS (Kernel Streaming) audio driver.
154    Ks = VBVMR_DEVTYPE::KS.0,
155    /// ASIO (Audio Stream Input/Output) audio driver.
156    Asio = VBVMR_DEVTYPE::ASIO.0,
157    /// Other audio device types not explicitly defined.
158    Other(VBVMR_DEVTYPE),
159}
160
161impl From<i32> for DeviceType {
162    /// Converts an integer value to a DeviceType.
163    fn from(value: i32) -> Self {
164        match VBVMR_DEVTYPE(value) {
165            VBVMR_DEVTYPE::MME => DeviceType::Mme,
166            VBVMR_DEVTYPE::WDM => DeviceType::Wdm,
167            VBVMR_DEVTYPE::KS => DeviceType::Ks,
168            VBVMR_DEVTYPE::ASIO => DeviceType::Asio,
169            o => DeviceType::Other(o),
170        }
171    }
172}
173
174/// A Audio Output Device.
175#[derive(Debug)]
176pub struct OutputDevice {
177    /// The type of the device.
178    pub r#type: DeviceType,
179    /// Device name
180    pub name: String,
181    /// Hardware ID
182    pub hardware_id: String,
183}
184
185/// Error when getting the device description.
186#[derive(Debug, thiserror::Error, Clone)]
187#[error("unexpected device: error code {0}")]
188pub struct GetDeviceError(pub i32);
189
190/// Error when getting the total devices.
191#[derive(Debug, thiserror::Error, Clone)]
192#[error("could not get total device number: error code {0}")]
193pub struct GetTotalDeviceError(pub i32);