use crate::{types::VoicemeeterApplication, LoadError};
use self::{
communication_login_logout::LoginError, general_information::GetVoicemeeterInformationError,
};
pub mod callback;
pub mod communication_login_logout;
pub mod device;
pub mod general_information;
pub mod get_levels;
pub mod macro_buttons;
pub mod parameters;
#[derive(Clone)]
#[cfg(feature = "interface")] pub struct VoicemeeterRemote {
raw: &'static crate::bindings::VoicemeeterRemoteRaw,
logout_handle: Option<std::sync::Arc<bool>>,
pub program: VoicemeeterApplication,
}
pub(crate) static LOGOUT_HANDLE: std::sync::OnceLock<
std::sync::Mutex<Option<std::sync::Arc<bool>>>,
> = std::sync::OnceLock::new();
impl std::fmt::Debug for VoicemeeterRemote {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.program {
VoicemeeterApplication::None => write!(f, "[no voicemeeter program running]"),
p => write!(f, "[{}]", p),
}
}
}
impl VoicemeeterRemote {
#[tracing::instrument]
pub fn new() -> Result<Self, InitializationError> {
let raw = crate::get_voicemeeter_raw()?;
let mut s = VoicemeeterRemote::from_raw(raw);
if s.logout_handle.is_none() {
return Err(InitializationError::AlreadyLoggedOut);
}
match s.login() {
Ok(_) => {}
Err(LoginError::AlreadyLoggedIn(_)) => {}
e => {
e?;
}
};
s.update_program()?;
Ok(s)
}
fn from_raw(raw: &'static crate::VoicemeeterRemoteRaw) -> VoicemeeterRemote {
Self {
raw,
program: VoicemeeterApplication::Other,
logout_handle: LOGOUT_HANDLE
.get_or_init(|| std::sync::Mutex::new(Some(std::sync::Arc::new(false))))
.lock()
.unwrap()
.clone(),
}
}
pub fn update_program(&mut self) -> Result<(), GetVoicemeeterInformationError> {
match self.get_voicemeeter_type() {
Ok(t) => self.program = t,
Err(GetVoicemeeterInformationError::NoServer) => {
self.program = VoicemeeterApplication::None
}
Err(e) => return Err(e),
}
Ok(())
}
}
impl Drop for VoicemeeterRemote {
fn drop(&mut self) {
let _ = self._logout();
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum InitializationError {
#[error("could not load the client")]
LoadError(#[from] LoadError),
#[error("could not login")]
LoginError(#[from] LoginError),
#[error("application has already logged out, so cannot login again")]
AlreadyLoggedOut,
#[error("could not get voicemeeter type")]
InformationError(#[from] GetVoicemeeterInformationError),
}