### Start and Unregister Audio Callback Source: https://docs.rs/voicemeeter/latest/voicemeeter/struct.VoicemeeterRemote.html This example demonstrates how to start an audio callback and then unregister it. It includes a delay before starting the callback to prevent crackling and uses a spin loop to keep the main thread alive while the callback is active. Ensure you run in release mode for optimizations. ```rust std::thread::sleep(std::time::Duration::from_millis(500)); remote.audio_callback_start()?; while running.load(Ordering::SeqCst) { std::hint::spin_loop() } remote.audio_callback_unregister(guard)?; println!("total frames: {frame}"); Ok(()) ``` -------------------------------- ### Example: Get and Set Strip Parameters Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters/strip.rs.html Demonstrates how to retrieve the label of a strip and set its output routing. Includes a necessary delay for parameter changes to register. ```rust use voicemeeter::VoicemeeterRemote; // Get the client. let remote = VoicemeeterRemote::new()?; // Get the label of strip 1 (index 0) println!("{}", remote.parameters().strip(0)?.label().get()?); // Set strip 3 (index 2) to output to A1 remote.parameters().strip(2)?.a1().set(true)?; // Ensure the change is registered. remote.is_parameters_dirty()?; // We need to sleep here because otherwise the change won't be registered, // in a long running program this is not needed. std::thread::sleep(std::time::Duration::from_millis(50)); # Ok::<(), Box>(()) ``` -------------------------------- ### Complete Voicemeeter Remote Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/struct.VoicemeeterRemote.html This example demonstrates a complete setup for interacting with Voicemeeter, including setting up a Ctrl+C handler, initializing the remote client, defining a sine wave generator, and registering a custom audio callback. The callback handles various `CallbackCommand` types, including audio buffer output and main buffer processing, showcasing how to apply custom audio modifications and copy data between buffers and devices. ```rust use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use voicemeeter::types::Device; use voicemeeter::{AudioCallbackMode, CallbackCommand, DeviceBuffer, VoicemeeterRemote}; pub fn main() -> Result<(), Box> { // Setup a hook for catching ctrl+c to properly stop the program. let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); }) .expect("Error setting Ctrl-C handler"); // Get the client. let remote = VoicemeeterRemote::new()?; let mut frame = 0; let mut sample_rate = None; let mut sine_r_phase = 0.; // A simple sine generator let mut sine_r = |sr: f32| { sine_r_phase = (sine_r_phase + 440.0 * 1.0 / sr).fract(); std::f32::consts::TAU * sine_r_phase }; // This is the callback command that will be called by voicemeeter on every audio frame, // start, stop and change. // This callback can capture data from its scope let callback = |command: CallbackCommand, _nnn: i32| -> i32 { match command { CallbackCommand::Starting(info) => { sample_rate = Some(info.info.samplerate); println!("starting!\n{info:?}") } CallbackCommand::Ending(_) => println!("ending!"), CallbackCommand::Change(info) => println!("application change requested!\n{info:?}"), // Output mode modifies the voicemeeter::CallbackCommand::BufferOut(data) => { frame += 1; // The `get_buffers` method gives the read and write buffers in a tuple. let (read, mut write) = data.buffer.get_buffers(); // Apply a function on all channels of `OutputA1`. write.output_a1.apply_all_samples( &read.output_a1, |ch: usize, r: &f32, w: &mut f32| { // if right if ch == 0 { *w = sine_r(sample_rate.unwrap() as f32); // otherwise } else { *w = *r; } }, ); // Apply another function on all channels of `OutputA2`. write .output_a2 .apply(&read.output_a2, |_ch: usize, r: &[f32], w: &mut [f32]| { w.copy_from_slice(r) }); // the buffer write type has a convenience method to // copy data for specified devices. write.copy_device_from( &read, &[ //Device::OutputA1, //Device::OutputA2, Device::OutputA3, Device::OutputA4, Device::OutputA5, Device::VirtualOutputB1, Device::VirtualOutputB2, Device::VirtualOutputB3, ], ); } // The MAIN command acts like a main i/o hub for all audio. voicemeeter::CallbackCommand::BufferMain(mut data) => { // The data returned by voicemeeter is a slice of frames per "channel" // containing another slice with `data.nbs` samples. // Each device has a number of channels // (e.g left, right, center, etc. typically 8 channels) for device in remote.program.devices() { let (buffer_in, buffer_out): (&[&[f32]], &mut [&mut [f32]]) = match ( data.buffer.read.device(device), data.buffer.write.device_mut(device), ) { (DeviceBuffer::Buffer(r), DeviceBuffer::Buffer(w)) => (r, w), _ => continue, }; // If the input is as large as the output // (which should always be true because of `DeviceBuffer`) if buffer_out.len() == buffer_in.len() { for (read, write) in buffer_in.iter().zip(buffer_out.iter_mut()) { // Write the input to the output write.copy_from_slice(read); } } } // Instead of the above, the equivalent with convenience functions would be let (read, mut write) = data.buffer.get_buffers(); write.copy_device_from(&read, remote.program.devices()); } _ => (), } 0 }; // Register the callback let guard = remote.audio_callback_register( // The mode can be multiple modes AudioCallbackMode::MAIN | AudioCallbackMode::OUTPUT, "my_app", callback, )?; // Keep the program running until Ctrl+C is pressed. while running.load(Ordering::SeqCst) { std::thread::sleep(std::time::Duration::from_millis(500)); } Ok(()) } ``` -------------------------------- ### Create Voicemeeter Instance and Get Version Source: https://docs.rs/voicemeeter Instantiate the Voicemeeter Remote SDK and print the Voicemeeter version. This requires the SDK to be installed and accessible. ```rust use voicemeeter::{types::Device, VoicemeeterRemote}; let remote = VoicemeeterRemote::new()?; println!("{}", remote.get_voicemeeter_version()?); println!( "Strip 1: {}", remote.parameters().strip(Device::Strip1)?.label().get()? ); ``` -------------------------------- ### Run Voicemeeter Application Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/bindings.rs.html Launches the Voicemeeter application. It determines the installation directory and starts the executable. Accepts a parameter for the Voicemeeter type (e.g., 1 for Standard, 2 for Banana, 3 for Potato). Returns 0 on success, -1 if not installed, and -2 for unknown type. ```rust pub unsafe fn VBVMR_RunVoicemeeter( &self, vType: ::std::os::raw::c_long, ) -> ::std::os::raw::c_long { // Function body omitted for brevity, but would call the underlying C function } ``` -------------------------------- ### Starting Command Struct and Implementation Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/commands.rs.html Represents the 'Starting' callback command, containing audio information. Used to signify the beginning of an audio processing event. ```rust /// Starting command. #[derive(Debug)] pub struct Starting<'a> { /// Audio info pub info: &'a AudioInfo, } impl<'a> Starting<'a> { /// Create a new `Starting` command. //#[tracing::instrument(skip_all, name = "Starting::new")] pub(crate) fn new(info: &'a AudioInfo) -> Self { Self { info } } } ``` -------------------------------- ### Voicemeeter Remote Audio Callback Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/struct.VoicemeeterRemote.html Demonstrates setting up a Voicemeeter remote client and registering an audio callback. This includes handling Ctrl+C for graceful shutdown, initializing the remote connection, and defining a callback function that processes audio buffers for different modes (MAIN and OUTPUT). The callback handles starting, ending, and buffer changes, including applying custom audio processing like a sine wave generator to specific output devices. ```rust use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use voicemeeter::types::Device; use voicemeeter::{AudioCallbackMode, CallbackCommand, DeviceBuffer, VoicemeeterRemote}; pub fn main() -> Result<(), Box> { // Setup a hook for catching ctrl+c to properly stop the program. let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); }) .expect("Error setting Ctrl-C handler"); // Get the client. let remote = VoicemeeterRemote::new()?; let mut frame = 0; let mut sample_rate = None; let mut sine_r_phase = 0.; // A simple sine generator let mut sine_r = |sr: f32| { sine_r_phase = (sine_r_phase + 440.0 * 1.0 / sr).fract(); std::f32::consts::TAU * sine_r_phase }; // This is the callback command that will be called by voicemeeter on every audio frame, // start, stop and change. // This callback can capture data from its scope let callback = |command: CallbackCommand, _nnn: i32| -> i32 { match command { CallbackCommand::Starting(info) => { sample_rate = Some(info.info.samplerate); println!("starting!\n{info:?}") } CallbackCommand::Ending(_) => println!("ending!"), CallbackCommand::Change(info) => println!("application change requested!\n{info:?}"), // Output mode modifies the voicemeeter::CallbackCommand::BufferOut(data) => { frame += 1; // The `get_buffers` method gives the read and write buffers in a tuple. let (read, mut write) = data.buffer.get_buffers(); // Apply a function on all channels of `OutputA1`. write.output_a1.apply_all_samples( &read.output_a1, |ch: usize, r: &f32, w: &mut f32| { // if right if ch == 0 { *w = sine_r(sample_rate.unwrap() as f32); // otherwise } else { *w = *r; } }, ); // Apply another function on all channels of `OutputA2`. write .output_a2 .apply(&read.output_a2, |_ch: usize, r: &[f32], w: &mut [f32]| { w.copy_from_slice(r) }); // the buffer write type has a convenience method to // copy data for specified devices. write.copy_device_from( &read, &[ //Device::OutputA1, //Device::OutputA2, Device::OutputA3, Device::OutputA4, Device::OutputA5, Device::VirtualOutputB1, Device::VirtualOutputB2, Device::VirtualOutputB3, ], ); } // The MAIN command acts like a main i/o hub for all audio. voicemeeter::CallbackCommand::BufferMain(mut data) => { // The data returned by voicemeeter is a slice of frames per "channel" // containing another slice with `data.nbs` samples. // Each device has a number of channels // (e.g left, right, center, etc. typically 8 channels) for device in remote.program.devices() { let (buffer_in, buffer_out): (&[&[f32]], &mut [&mut [f32]]) = match ( data.buffer.read.device(device), data.buffer.write.device_mut(device), ) { (DeviceBuffer::Buffer(r), DeviceBuffer::Buffer(w)) => (r, w), _ => continue, }; // If the input is as large as the output // (which should always be true because of `DeviceBuffer`) if buffer_out.len() == buffer_in.len() { for (read, write) in buffer_in.iter().zip(buffer_out.iter_mut()) { // Write the input to the output write.copy_from_slice(read); } } } // Instead of the above, the equivalent with convenience functions would be let (read, mut write) = data.buffer.get_buffers(); write.copy_device_from(&read, remote.program.devices()); } _ => (), } 0 }; // Register the callback let guard = remote.audio_callback_register( // The mode can be multiple modes AudioCallbackMode::MAIN | AudioCallbackMode::OUTPUT, "my_app", callback, )?; } ``` -------------------------------- ### Starting Struct Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/callback/commands/struct.Starting.html The Starting struct is used to represent the Starting command. It is available only when the `interface` feature flag is enabled. ```APIDOC ## Struct Starting `pub struct Starting<'a>` Starting command. ### Fields * `info: &'a AudioInfo` - Audio info ``` -------------------------------- ### VBVMR_RunVoicemeeter Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/struct.VoicemeeterRemoteRaw.html Runs the Voicemeeter application. It gets the installation directory and then runs the application. ```APIDOC ## VBVMR_RunVoicemeeter ### Description Run Voicemeeter Application (get installation directory and run Voicemeeter Application). ### Parameters - `vType` (c_long) - Voicemeeter type (1 = Voicemeeter, 2= Voicemeeter Banana, 3= Voicemeeter Potato, 6 = Potato x64 bits). ### Returns - `0`: Ok. - `-1`: Not installed (UninstallString not found in registry). - `-2`: Unknown vType number. ``` -------------------------------- ### Starting Struct Definition Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/callback/commands/struct.Starting.html Defines the Starting struct, which holds a reference to AudioInfo. This struct is available when the 'interface' crate feature is enabled. ```rust pub struct Starting<'a> { pub info: &'a AudioInfo, } ``` -------------------------------- ### Audio Callback Start Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/start_stop.rs.html Starts the audio callback for Voicemeeter. This function should be called to enable receiving audio data. It returns Ok(()) on success or an error if the server is not available or no callback is registered. ```APIDOC ## audio_callback_start ### Description Starts the audio callback for Voicemeeter. ### Method `pub fn audio_callback_start(&self) -> Result<(), AudioCallbackStartError>` ### Parameters None ### Returns - `Ok(())`: If the audio callback started successfully. - `Err(AudioCallbackStartError)`: If an error occurred. - `AudioCallbackStartError::NoServer`: If the Voicemeeter server is not running. - `AudioCallbackStartError::NoCallbackRegistered`: If no audio callback has been registered. - `AudioCallbackStartError::Unexpected(i32)`: For any other unexpected error code. ### Example ```rust // Assuming `remote` is an instance of VoicemeeterRemote match remote.audio_callback_start() { Ok(_) => println!("Audio callback started successfully."), Err(e) => eprintln!("Failed to start audio callback: {}", e), } ``` ``` -------------------------------- ### Option::as_ref Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetLevel.html Demonstrates converting an Option to an Option<&T> without consuming the original Option. This is useful for borrowing the inner value to perform operations like getting its length. ```rust let text: Option = Some("Hello, world!".to_string()); // First, cast `Option` to `Option<&String>` with `as_ref`, // then consume *that* with `map`, leaving `text` on the stack. let text_length: Option = text.as_ref().map(|s| s.len()); println!("still can print text: {:?}", text); ``` -------------------------------- ### Get and Set Bus Parameters Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/parameters/bus/struct.Bus.html Demonstrates how to get the Voicemeeter client, access a specific bus by index, retrieve its label, and set its mute state. Includes a note about ensuring changes are registered and a necessary sleep for immediate effect in short-lived programs. ```rust use voicemeeter::VoicemeeterRemote; // Get the client. let remote = VoicemeeterRemote::new()?; // Get the label of bus A1 (index 0) println!("{}", remote.parameters().bus(0)?.label().get()?); // Mute bus A4 (index 5) remote.parameters().bus(2)?.mute().set(true)?; // Ensure the change is registered. remote.is_parameters_dirty()?; // We need to sleep here because otherwise changes won't be registered, // in a long running program this is not needed. std::thread::sleep(std::time::Duration::from_millis(50)); ``` -------------------------------- ### VBVMR_AudioCallbackStart Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/struct.VoicemeeterRemoteRaw.html Starts or stops the audio processing for registered callbacks. ```APIDOC ## VBVMR_AudioCallbackStart ### Description Start / Stop Audio processing. The Callback will be called. ### Returns - `c_long`: 0: OK (no error). -1: error. -2: no callback registered. ``` -------------------------------- ### VBVMR_AudioCallbackStart Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_INTERFACE.html Starts the audio callback stream. Returns 0 on success, otherwise an error code. ```APIDOC ## VBVMR_AudioCallbackStart ### Description Starts the audio callback stream. ### Returns - `i32`: 0 on success, otherwise an error code. ``` -------------------------------- ### Option::and Examples Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetLevel.html Demonstrates the behavior of the `and` method with different combinations of `Some` and `None` values. ```rust let x = Some(2); let y: Option<&str> = None; assert_eq!(x.and(y), None); ``` ```rust let x: Option = None; let y = Some("foo"); assert_eq!(x.and(y), None); ``` ```rust let x = Some(2); let y = Some("foo"); assert_eq!(x.and(y), Some("foo")); ``` ```rust let x: Option = None; let y: Option<&str> = None; assert_eq!(x.and(y), None); ``` -------------------------------- ### Access Voicemeeter Parameters Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Get access to the parameters interface for interacting with Voicemeeter settings. Examples show how to retrieve labels and device names, and how to set boolean states. ```rust use voicemeeter::VoicemeeterRemote; # let remote: VoicemeeterRemote = todo!(); println!("Strip 1: {}", remote.parameters().strip(0)?.label().get()?); println!( "Bus 0 (A1) Device: {}", remote.parameters().bus(0)?.device().name().get()? ); // Enable A1 on strip 1 remote.parameters().strip(0)?.a1().set(true)?; # Ok::<(), Box>(()) ``` -------------------------------- ### Option::as_slice Inverse Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_SetParameterStringA.html Illustrates the inverse relationship between Option::as_slice and slice::first. ```rust for i in [Some(1234_u16), None] { assert_eq!(i.as_ref(), i.as_slice().first()); } ``` -------------------------------- ### Option::is_none Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetLevel.html Demonstrates how to check if an Option is None. This is useful for verifying the absence of a value. ```rust let x: Option = Some(2); assert_eq!(x.is_none(), false); let x: Option = None; assert_eq!(x.is_none(), true); ``` -------------------------------- ### Option::as_slice Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_SetParameterStringA.html Shows how to get a slice of the contained value if the Option is Some, or an empty slice if it is None. ```rust assert_eq!( [Some(1234).as_slice(), None.as_slice()], [&[1234][..], &[][..]], ); ``` -------------------------------- ### Option::as_mut_slice Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_AudioCallbackStop.html Shows how to get a mutable slice from an Option's content, returning an empty mutable slice if None. ```rust let mut x = Some(1234); assert_eq!(x.as_mut_slice(), &mut [1234]); let mut y: Option = None; assert_eq!(y.as_mut_slice(), &mut []); ``` -------------------------------- ### Example: Copying Specific Output Devices Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data/buffer_abstraction.rs.html Demonstrates how to copy data from read buffers to write buffers for OutputA1 and OutputA2 devices. Asserts that the data has been successfully copied. ```rust buffer .write .copy_device_from(&buffer.read, &[Device::OutputA1, Device::OutputA2]); assert!( buffer.read.output_a1.to_slice() == buffer.write.output_a1.to_mut_slice(), "strip1 was copied" ); assert!( buffer.read.output_a2.to_slice() == buffer.write.output_a2.to_mut_slice(), "strip2 was copied" ); ``` -------------------------------- ### Option::xor Examples Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetLevel.html Shows the exclusive OR behavior of `xor`. Returns `Some` if exactly one of the two options is `Some`. ```rust let x = Some(2); let y: Option = None; assert_eq!(x.xor(y), Some(2)); ``` ```rust let x: Option = None; let y = Some(2); assert_eq!(x.xor(y), Some(2)); ``` ```rust let x = Some(2); let y = Some(2); assert_eq!(x.xor(y), None); ``` ```rust let x: Option = None; let y: Option = None; assert_eq!(x.xor(y), None); ``` -------------------------------- ### Accessing Strip Name Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Example of how to get the name of a specific strip using the Voicemeeter remote interface. This requires establishing a connection to Voicemeeter first. ```rust # use voicemeeter::VoicemeeterRemote; # let remote: VoicemeeterRemote = todo!(); println!( "Strip 1: {}", remote.parameters().strip(0)?.device()?.name().get()? ); # Ok::<(), Box>(()) ``` -------------------------------- ### Example Usage of copy_device_from Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data/buffer_abstraction.rs.html Demonstrates copying audio data from Strip1 and Strip2 from the read buffer to the write buffer and asserts that the data has been copied correctly. ```rust buffer .write .copy_device_from(&buffer.read, &[Device::Strip1, Device::Strip2]); assert!( buffer.read.strip1.to_slice() == buffer.write.strip1.to_mut_slice(), "strip1 was copied" ); assert!( buffer.read.strip2.to_slice() == buffer.write.strip2.to_mut_slice(), "strip2 was copied" ); ``` -------------------------------- ### Start Audio Callback in Voicemeeter Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/start_stop.rs.html Initiates the audio callback for Voicemeeter. Returns Ok(()) on success, or an error if the server is not found, no callback is registered, or an unexpected error occurs. ```rust pub fn audio_callback_start(&self) -> Result<(), AudioCallbackStartError> { let res = unsafe { self.raw.VBVMR_AudioCallbackStart() }; match res { 0 => Ok(()), -1 => Err(AudioCallbackStartError::NoServer), 1 => Err(AudioCallbackStartError::NoCallbackRegistered), s => Err(AudioCallbackStartError::Unexpected(s)), } } ``` -------------------------------- ### Copying Device Data Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/callback/data/main/struct.WriteDevices.html Demonstrates how to copy audio data from read buffers to write buffers for specified output devices using the `copy_device_from` method. This is useful for routing audio within VoiceMeeter. ```rust use voicemeeter::{interface::callback::BufferMainData, types::Device}; buffer .write .copy_device_from(&buffer.read, &[Device::OutputA1, Device::OutputA2]); assert!( buffer.read.output_a1.to_slice() == buffer.write.output_a1.to_mut_slice(), "strip1 was copied" ); assert!( buffer.read.output_a2.to_slice() == buffer.write.output_a2.to_mut_slice(), "strip2 was copied" ); ``` -------------------------------- ### Get IntParameter Value Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/parameters/struct.IntParameter.html Gets the integer value of this parameter. Requires the READ feature to be enabled. ```rust pub fn get(&self) -> Result ``` -------------------------------- ### Integer Parameter Get Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Gets an integer parameter. Requires the parameter to be readable. Converts f32 to i32. ```rust pub fn get(&self) -> Result { Ok(self.remote.get_parameter_float(&self.name)? as i32) } ``` -------------------------------- ### Option::or Examples Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetLevel.html Demonstrates the `or` method, which returns the first `Some` value encountered, or `None` if both are `None`. Arguments are eagerly evaluated. ```rust let x = Some(2); let y = None; assert_eq!(x.or(y), Some(2)); ``` ```rust let x = None; let y = Some(100); assert_eq!(x.or(y), Some(100)); ``` ```rust let x = Some(2); let y = Some(100); assert_eq!(x.or(y), Some(2)); ``` ```rust let x: Option = None; let y = None; assert_eq!(x.or(y), None); ``` -------------------------------- ### Get String Parameter Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Get the value of a string parameter. This function retrieves the current string value associated with the parameter name. ```rust pub fn get(&self) -> Result { self.remote.get_parameter_string(&self.name) } ``` -------------------------------- ### Get Float Parameter Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Get the value of a float parameter. This function retrieves the current float value associated with the parameter name. ```rust pub fn get(&self) -> Result { self.remote.get_parameter_float(&self.name) } ``` -------------------------------- ### Create VoicemeeterRemote Instance Source: https://docs.rs/voicemeeter Creates a new instance of the Voicemeeter SDK. The instance is automatically logged in upon creation. This example also demonstrates how to retrieve the Voicemeeter version and a specific strip's label. ```APIDOC ## Create VoicemeeterRemote Instance ### Description Creates a new instance of the Voicemeeter SDK. The instance is automatically logged in. ### Usage ```rust use voicemeeter::{types::Device, VoicemeeterRemote}; let remote = VoicemeeterRemote::new()?; println!("Voicemeeter version: {}", remote.get_voicemeeter_version()?); println!("Strip 1 label: {}", remote.parameters().strip(Device::Strip1)?.label().get()?); ``` ### Parameters None ### Returns - `Result`: A new instance of `VoicemeeterRemote` on success, or a `LoadError` on failure. ``` -------------------------------- ### Boolean Parameter Get Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters.rs.html Gets a boolean parameter. Requires the parameter to be readable. Converts float value to bool (1.0 is true, others are false). ```rust pub fn get(&self) -> Result { Ok(self.remote.get_parameter_float(&self.name)? == 1.0) } ``` -------------------------------- ### Start/Pause Recording Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/parameters/recorder/struct.VoicemeeterRecorder.html Provides methods to initiate and control the recording process. Use `record` to start recording and `pause` to temporarily halt it. ```rust pub fn record(&self) -> BoolParameter<'_> ``` ```rust pub fn pause(&self) -> BoolParameter<'_> ``` -------------------------------- ### Get Option as a Slice Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetParameterStringW.html Use `as_slice` to get a slice of the contained value if the Option is Some, or an empty slice if None. This is useful for iterating over Option contents uniformly. ```rust assert_eq!( [Some(1234).as_slice(), None.as_slice()], [&[1234][..], &[][..]], ); ``` ```rust for i in [Some(1234_u16), None] { assert_eq!(i.as_ref(), i.as_slice().first()); } ``` -------------------------------- ### Creating BufferMainData Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data.rs.html Constructor for BufferMainData, initializing the internal Main struct with audio buffer data and samples per frame, and setting up read and write devices. ```rust impl<'a> BufferMainData<'a> { pub(crate) fn new<'b: 'a>( program: VoicemeeterApplication, data: &'b AudioBuffer, samples_per_frame: usize, ) -> Self { let mut data = Main { data: data.read_write_buffer(), samples_per_frame, program, }; unsafe { Self { read: main::ReadDevices::new(&mut data), write: main::WriteDevices::new(&mut data), } } } /// Convenience function to get the read and write buffers /// /// ```rust,no_run /// # use voicemeeter::interface::callback::BufferMain; let data: BufferMain = unimplemented!(); /// let (read, mut write) = data.buffer.get_buffers(); /// ``` pub fn get_buffers(self) -> (main::ReadDevices<'a, 'a>, main::WriteDevices<'a, 'a>) { (self.read, self.write) } } ``` -------------------------------- ### Getting an Option's Content as a Slice Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_AudioCallbackStart.html Use as_slice() to get a slice of the contained value if the Option is Some, or an empty slice if it is None. This unifies iteration over Options and slices. ```rust assert_eq!( [Some(1234).as_slice(), None.as_slice()], [&[1234][..], &[][..]], ); for i in [Some(1234_u16), None] { assert_eq!(i.as_ref(), i.as_slice().first()); } ``` -------------------------------- ### Audio Callback Start Error Enum Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/start_stop.rs.html Defines the possible errors that can occur when starting the audio callback. Includes cases for no server, no callback registered, and unexpected error codes. ```rust pub enum AudioCallbackStartError { // TODO: is this correct? /// No server. #[error("no server")] NoServer, /// No callback registered. #[error("no callback registered")] NoCallbackRegistered, /// An unknown error code occured. #[error("an unexpected error occurred: error code {0}")] Unexpected(i32), } ``` -------------------------------- ### Create VoicemeeterOption Instance Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters/option.rs.html Constructor for VoicemeeterOption, requiring a reference to a VoicemeeterRemote. ```rust impl<'a> VoicemeeterOption<'a> { #[doc(hidden)] pub fn new(remote: &'a VoicemeeterRemote) -> Self { VoicemeeterOption { remote } } // ... other methods ``` -------------------------------- ### VoicemeeterRemote::new() Source: https://docs.rs/voicemeeter/latest/index.html Creates a new instance of the Voicemeeter SDK. The instance is automatically logged in. ```APIDOC ## Create Voicemeeter Instance ### Description Creates a new instance of the Voicemeeter SDK. The instance is automatically logged in. ### Method `new()` ### Endpoint N/A (SDK method) ### Parameters None ### Request Example ```rust use voicemeeter::VoicemeeterRemote; let remote = VoicemeeterRemote::new()?; ``` ### Response #### Success Response - `VoicemeeterRemote` instance #### Response Example ```rust // Successful creation returns a VoicemeeterRemote instance ``` ## Get Voicemeeter Version ### Description Retrieves the version of the Voicemeeter application. ### Method `get_voicemeeter_version()` ### Endpoint N/A (SDK method) ### Parameters None ### Request Example ```rust let version = remote.get_voicemeeter_version()?; println!("Voicemeeter version: {}", version); ``` ### Response #### Success Response - `String` representing the Voicemeeter version #### Response Example ```rust // Example output: "Voicemeeter version: 1.0.5" ``` ## Get Strip Label ### Description Retrieves the label of a specific strip in Voicemeeter. ### Method `parameters().strip(Device::Strip1)?.label().get()` ### Endpoint N/A (SDK method) ### Parameters - `Device::Strip1` (enum variant): Specifies the target strip (e.g., `Device::Strip1`, `Device::Strip2`, etc.). ### Request Example ```rust use voicemeeter::types::Device; let strip_label = remote.parameters().strip(Device::Strip1)?.label().get()?; println!("Strip 1 label: {}", strip_label); ``` ### Response #### Success Response - `String` representing the label of the specified strip #### Response Example ```rust // Example output: "Strip 1 label: Music" ``` ``` -------------------------------- ### Get FloatParameter Value Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/parameters/struct.FloatParameter.html Implementation for getting the float value of a FloatParameter. This method is available when the READ generic parameter is true. It returns a Result containing the f32 value or a GetParameterError. ```rust pub fn get(&self) -> Result ``` -------------------------------- ### Get Mutable Option as a Slice Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/type.T_VBVMR_GetParameterStringW.html Use `as_mut_slice` to get a mutable slice of the contained value if the Option is Some, or an empty slice if None. This allows mutable iteration over Option contents. ```rust pub const fn as_mut_slice(&mut self) -> &mut [T] ``` -------------------------------- ### VoicemeeterRemoteRaw::new Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/lib.rs.html Initializes the raw Voicemeeter remote interface by loading the necessary DLL from the specified path. ```APIDOC ## VoicemeeterRemoteRaw::new ### Description Initializes the raw Voicemeeter remote interface by loading the necessary DLL from the specified path. ### Method ```rust pub unsafe fn new(path: &OsStr) -> Result ``` ### Parameters - **path** (`&OsStr`): The path to the Voicemeeter remote DLL. ### Returns - `Result`: Ok containing a `VoicemeeterRemoteRaw` instance on success, or a `libloading::Error` on failure. ``` -------------------------------- ### Get Macro Button Status Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/macro_buttons.rs.html Retrieves the current status of a specific macro button. Handles potential errors like inability to get the client or server connection issues. ```rust pub fn get_macrobutton_state( &self, button: impl Into, ) -> Result { let mut f = 0.0f32; let button = button.into(); let res = unsafe { self.raw.VBVMR_MacroButton_GetStatus(button.0 .0, &mut f, 0) }; match res { 0 => Ok(MacroButtonStatus(f == 1.)), -1 => Err(GetMacroButtonStatusError::CannotGetClient), -2 => Err(GetMacroButtonStatusError::NoServer), -3 => Err(GetMacroButtonStatusError::UnknownParameter(button)), /* FIXME: Lossless always (assuming vmr doesn't modify :) ), unsafe? */ -5 => Err(GetMacroButtonStatusError::StructureMismatch(button, 1)), s => Err(GetMacroButtonStatusError::Other(s)), } } ``` -------------------------------- ### Create WriteDevices Buffer Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data/buffer_abstraction.rs.html Initializes a `WriteDevices` struct by preparing to write to the provided output buffer. This is an unsafe operation and requires careful handling. ```rust pub(crate) unsafe fn new(buffer: &'_ mut Output) -> Self { unsafe { Self { output_a1: buffer.device_write(&Device::OutputA1), output_a2: buffer.device_write(&Device::OutputA2), output_a3: buffer.device_write(&Device::OutputA3), ``` -------------------------------- ### VBVMR_Login Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/struct.VoicemeeterRemoteRaw.html Opens the communication pipe with Voicemeeter. This should typically be called on software startup. ```APIDOC ## VBVMR_Login ### Description Opens Communication Pipe With Voicemeeter (typically called on software startup). ### Returns - `0`: OK (no error). - `1`: OK but Voicemeeter Application not launched. - `-1`: Cannot get client (unexpected). - `-2`: Unexpected login (logout was expected before). ``` -------------------------------- ### Create Input Write Buffer Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data/buffer_abstraction.rs.html Initializes a `WriteDevices` struct by preparing write buffers for each available audio device from the input. ```rust pub(crate) unsafe fn new(buffer: &'_ mut Input) -> Self { unsafe { Self { strip1: buffer.device_write(&Device::Strip1), strip2: buffer.device_write(&Device::Strip2), strip3: buffer.device_write(&Device::Strip3), strip4: buffer.device_write(&Device::Strip4), strip5: buffer.device_write(&Device::Strip5), virtual_input: buffer.device_write(&Device::VirtualInput), virtual_input_aux: buffer.device_write(&Device::VirtualInputAux), virtual_input8: buffer.device_write(&Device::VirtualInput8), _pd: Default::default(), } } } ``` -------------------------------- ### Get Voicemeeter MIDI Message (Convenience) Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/get_levels.rs.html A convenience function to get a MIDI message from Voicemeeter. It internally allocates a buffer and truncates it to the actual message size. This simplifies MIDI message retrieval for common use cases. ```rust pub fn get_midi_message(&self) -> Result, GetMidiMessageError> { let mut v = vec![0; 1024]; let len = self.get_midi_message_buff(&mut v)?; v.truncate(len); Ok(v) } ``` -------------------------------- ### Initialize VoicemeeterRecorder Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/parameters/recorder.rs.html Creates a new instance of VoicemeeterRecorder. This is typically used internally by the VoicemeeterRemote. ```rust pub fn new(remote: &'a VoicemeeterRemote) -> Self { VoicemeeterRecorder { remote } } ``` -------------------------------- ### VBVMR_GetVoicemeeterVersion Source: https://docs.rs/voicemeeter/latest/voicemeeter/bindings/struct.VoicemeeterRemoteRaw.html Retrieves the version of Voicemeeter installed. ```APIDOC ## VBVMR_GetVoicemeeterVersion ### Description Get Voicemeeter Version. ### Parameters #### Path Parameters - **pVersion** (*c_long*) - Pointer to a 32-bit integer that will receive the version (v1.v2.v3.v4). - v1 = (version & 0xFF000000) >> 24 - v2 = (version & 0x00FF0000) >> 16 - v3 = (version & 0x0000FF00) >> 8 - v4 = version & 0x000000FF ### Return Value - **0**: OK (no error). - **-1**: Cannot get client (unexpected). - **-2**: No server. ### Source ```rust pub unsafe fn VBVMR_GetVoicemeeterVersion(&self, pVersion: *mut c_long) -> c_long ``` ``` -------------------------------- ### Initialize Voicemeeter Remote Bindings Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/bindings.rs.html Loads the Voicemeeter DLL and retrieves function pointers for all available API functions. This is typically done once when initializing the remote control interface. ```rust let VBVMR_GetLevel = __library.get(b"VBVMR_GetLevel\0").map(|sym| *sym)?; let VBVMR_GetMidiMessage = __library.get(b"VBVMR_GetMidiMessage\0").map(|sym| *sym)?; let VBVMR_SetParameterFloat = __library .get(b"VBVMR_SetParameterFloat\0") .map(|sym| *sym)?; let VBVMR_SetParameterStringA = __library .get(b"VBVMR_SetParameterStringA\0") .map(|sym| *sym)?; let VBVMR_SetParameterStringW = __library .get(b"VBVMR_SetParameterStringW\0") .map(|sym| *sym)?; let VBVMR_SetParameters = __library.get(b"VBVMR_SetParameters\0").map(|sym| *sym)?; let VBVMR_SetParametersW = __library.get(b"VBVMR_SetParametersW\0").map(|sym| *sym)?; let VBVMR_Output_GetDeviceNumber = __library .get(b"VBVMR_Output_GetDeviceNumber\0") .map(|sym| *sym)?; let VBVMR_Output_GetDeviceDescA = __library .get(b"VBVMR_Output_GetDeviceDescA\0") .map(|sym| *sym)?; let VBVMR_Output_GetDeviceDescW = __library .get(b"VBVMR_Output_GetDeviceDescW\0") .map(|sym| *sym)?; let VBVMR_Input_GetDeviceNumber = __library .get(b"VBVMR_Input_GetDeviceNumber\0") .map(|sym| *sym)?; let VBVMR_Input_GetDeviceDescA = __library .get(b"VBVMR_Input_GetDeviceDescA\0") .map(|sym| *sym)?; let VBVMR_Input_GetDeviceDescW = __library .get(b"VBVMR_Input_GetDeviceDescW\0") .map(|sym| *sym)?; let VBVMR_AudioCallbackRegister = __library .get(b"VBVMR_AudioCallbackRegister\0") .map(|sym| *sym)?; let VBVMR_AudioCallbackStart = __library .get(b"VBVMR_AudioCallbackStart\0") .map(|sym| *sym)?; let VBVMR_AudioCallbackStop = __library .get(b"VBVMR_AudioCallbackStop\0") .map(|sym| *sym)?; let VBVMR_AudioCallbackUnregister = __library .get(b"VBVMR_AudioCallbackUnregister\0") .map(|sym| *sym)?; let VBVMR_MacroButton_IsDirty = __library .get(b"VBVMR_MacroButton_IsDirty\0") .map(|sym| *sym)?; let VBVMR_MacroButton_GetStatus = __library .get(b"VBVMR_MacroButton_GetStatus\0") .map(|sym| *sym)?; let VBVMR_MacroButton_SetStatus = __library .get(b"VBVMR_MacroButton_SetStatus\0") .map(|sym| *sym)?; Ok(VoicemeeterRemoteRaw { __library, VBVMR_Login, VBVMR_Logout, VBVMR_RunVoicemeeter, VBVMR_GetVoicemeeterType, VBVMR_GetVoicemeeterVersion, VBVMR_IsParametersDirty, VBVMR_GetParameterFloat, VBVMR_GetParameterStringA, VBVMR_GetParameterStringW, VBVMR_GetLevel, VBVMR_GetMidiMessage, VBVMR_SetParameterFloat, VBVMR_SetParameterStringA, VBVMR_SetParameterStringW, VBVMR_SetParameters, VBVMR_SetParametersW, VBVMR_Output_GetDeviceNumber, VBVMR_Output_GetDeviceDescA, VBVMR_Output_GetDeviceDescW, VBVMR_Input_GetDeviceNumber, VBVMR_Input_GetDeviceDescA, VBVMR_Input_GetDeviceDescW, VBVMR_AudioCallbackRegister, VBVMR_AudioCallbackStart, VBVMR_AudioCallbackStop, VBVMR_AudioCallbackUnregister, VBVMR_MacroButton_IsDirty, VBVMR_MacroButton_GetStatus, VBVMR_MacroButton_SetStatus, }) } ``` -------------------------------- ### Copy Device Data Example Source: https://docs.rs/voicemeeter/latest/voicemeeter/interface/callback/data/input/struct.WriteDevices.html Copies data from an input read buffer to the input write buffer for specified devices. Asserts that the data has been correctly copied for strip1 and strip2. ```rust use voicemeeter::{interface::callback::BufferInData, types::Device}; buffer .write .copy_device_from(&buffer.read, &[Device::Strip1, Device::Strip2]); assert!( buffer.read.strip1.to_slice() == buffer.write.strip1.to_mut_slice(), "strip1 was copied" ); assert!( buffer.read.strip2.to_slice() == buffer.write.strip2.to_mut_slice(), "strip2 was copied" ); ``` -------------------------------- ### Create ReadDevices Buffer Source: https://docs.rs/voicemeeter/latest/src/voicemeeter/interface/callback/data/buffer_abstraction.rs.html Initializes a `ReadDevices` struct by reading from the provided output buffer. This is an unsafe operation and requires careful handling. ```rust pub(crate) unsafe fn new(buffer: &'_ mut Output) -> Self { unsafe { Self { output_a1: buffer.device_read(&Device::OutputA1), output_a2: buffer.device_read(&Device::OutputA2), output_a3: buffer.device_read(&Device::OutputA3), output_a4: buffer.device_read(&Device::OutputA4), output_a5: buffer.device_read(&Device::OutputA5), virtual_output_b1: buffer.device_read(&Device::VirtualOutputB1), virtual_output_b2: buffer.device_read(&Device::VirtualOutputB2), virtual_output_b3: buffer.device_read(&Device::VirtualOutputB3), _pd: Default::default(), } } } ```