voicemeeter\interface/
device.rs1use std::{ffi::CStr, os::raw::c_char};
10
11use crate::{bindings::VBVMR_DEVTYPE, types::ZIndex};
12
13use super::VoicemeeterRemote;
14
15impl VoicemeeterRemote {
16 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 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 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 match res {
79 0 => Ok(()),
80 s => Err(GetDeviceError(s)),
81 }
82 }
83
84 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 match res {
128 0 => Ok(()),
129 s => Err(GetDeviceError(s)),
130 }
131 }
132}
133
134#[derive(Debug)]
136pub struct InputDevice {
137 pub r#type: DeviceType,
139 pub name: String,
141 pub hardware_id: String,
143}
144
145#[repr(i32)]
147#[derive(Debug)]
148pub enum DeviceType {
149 Mme = VBVMR_DEVTYPE::MME.0,
151 Wdm = VBVMR_DEVTYPE::WDM.0,
153 Ks = VBVMR_DEVTYPE::KS.0,
155 Asio = VBVMR_DEVTYPE::ASIO.0,
157 Other(VBVMR_DEVTYPE),
159}
160
161impl From<i32> for DeviceType {
162 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#[derive(Debug)]
176pub struct OutputDevice {
177 pub r#type: DeviceType,
179 pub name: String,
181 pub hardware_id: String,
183}
184
185#[derive(Debug, thiserror::Error, Clone)]
187#[error("unexpected device: error code {0}")]
188pub struct GetDeviceError(pub i32);
189
190#[derive(Debug, thiserror::Error, Clone)]
192#[error("could not get total device number: error code {0}")]
193pub struct GetTotalDeviceError(pub i32);