pub struct VoicemeeterRemote {
    pub program: VoicemeeterApplication,
    /* private fields */
}
Available on crate feature interface only.
Expand description

Interface for voicemeeter.

Fields§

§program: VoicemeeterApplication

The type of the running Voicemeeter instance.

Implementations§

source§

impl VoicemeeterRemote

source

pub fn audio_callback_register<'a, 'cb, 'g, F>( &'a self, mode: VBVMR_AUDIOCALLBACK, application_name: impl AsRef<str>, callback: F ) -> Result<CallbackGuard<'g, F>, AudioCallbackRegisterError>
where F: FnMut(CallbackCommand<'cb>, i32) -> c_long + 'g,

Register a callback for audio.

The callback is a function that will be called when the audio stream is started, changed or stopped and when data is sent to it.

The callback takes two arguments, the command sent from voicemeeter and a currently unused i32 parameter for additional data.

The mode determines what buffers are returned.

§Examples
use voicemeeter::{AudioCallbackMode, CallbackCommand, VoicemeeterRemote};

pub fn main() -> Result<(), Box<dyn std::error::Error>> {
   // Get the client.
   let remote = VoicemeeterRemote::new()?;

   let guard = remote.audio_callback_register(
       // The mode can be multiple modes
       AudioCallbackMode::MAIN | AudioCallbackMode::OUTPUT,
       "my_app",
       |command: CallbackCommand, _: i32| -> i32 {
           match command {
               // Receive all I/O to record or process it and replace or mix to BUS outputs.rocess audio outputs before master section.
               voicemeeter::CallbackCommand::BufferMain(data) => {
                   // do something with the data, this just simply relays it without any processing
                   let (read, mut write) = data.buffer.get_buffers();
                   write.copy_device_from(&read, remote.program.devices());
               }
               // Process audio outputs before master section.
               voicemeeter::CallbackCommand::BufferOut(data) => {
                   // do something with the data, this just simply relays it without any processing
                   let (read, mut write) = data.buffer.get_buffers();
                   write.copy_device_from(&read, remote.program.devices());
               }
               _ => {}
           }
           0
       },
   )?;

   // It is good practice to wait a bit here before starting the callback,
   // otherwise you may experience some crackling. Another reason
   // for crackle is not quick enough execution, try running in release mode for optimizations.
   std::thread::sleep(std::time::Duration::from_millis(500));
   println!("starting callback");
   remote.audio_callback_start()?;

   std::thread::sleep(std::time::Duration::from_millis(10000));

   println!("stopping callback");
   remote.audio_callback_unregister(guard)?;
   Ok(())
}
§Complete example
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<dyn std::error::Error>> {
   // 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,
   )?;
   // It is good practice to wait a bit here before starting the callback,
   // otherwise you may experience some crackling. Another reason
   // for crackle is not quick enough execution, try running in release mode for optimizations.
   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(())
}
source

pub fn audio_callback_unregister<F>( &self, guard: CallbackGuard<'_, F> ) -> Result<(), AudioCallbackUnregisterError>

Unregister a callback. This implicitly calls VoicemeeterRemote::audio_callback_stop.

source

pub fn audio_callback_unregister_leak<F>( &self ) -> Result<(), AudioCallbackUnregisterError>

Unregister a callback without dropping the callback, thus leaking data. This implicitly calls VoicemeeterRemote::audio_callback_stop.

source§

impl VoicemeeterRemote

source

pub fn audio_callback_start(&self) -> Result<(), AudioCallbackStartError>

Audio callback start.

source

pub fn audio_callback_stop(&self) -> Result<(), AudioCallbackStopError>

Audio callback stop.

source§

impl VoicemeeterRemote

source

pub fn initial_status() -> VoicemeeterStatus

Get the status of the running Voicemeeter instance when we first logged in

source

pub fn logout(self) -> Result<(), LogoutError>

Logout from the voicemeeter instance. This should only be called when you never need another VoiceMeeter remote again.

§Notes

VoicemeeterRemote::new will automatically login if needed.

source

pub fn run_voicemeeter( &self, type: VoicemeeterApplication ) -> Result<(), RunVoicemeeterError>

Invoke Voicemeeter to open and be visible on previous location.

source§

impl VoicemeeterRemote

source

pub fn get_total_input_device(&self) -> Result<i32, GetTotalDeviceError>

Get the number of Audio Input Devices available on the system.

source

pub fn get_total_output_device(&self) -> Result<i32, GetTotalDeviceError>

Get the number of Audio Output Devices available on the system.

source

pub fn get_input_device( &self, index: impl Into<ZIndex> ) -> Result<InputDevice, GetDeviceError>

Get the description of a specific Audio Input Device.

source

pub fn get_output_device( &self, index: impl Into<ZIndex> ) -> Result<OutputDevice, GetDeviceError>

Get the description of a specific Audio Output Device.

source§

impl VoicemeeterRemote

source

pub fn get_voicemeeter_type( &self ) -> Result<VoicemeeterApplication, GetVoicemeeterInformationError>

Get the application type of the running Voicemeeter instance.

source

pub fn get_voicemeeter_version( &self ) -> Result<VoicemeeterVersion, GetVoicemeeterInformationError>

Get the version of the running Voicemeeter instance.

source§

impl VoicemeeterRemote

source

pub fn get_level( &self, level_type: LevelType, device: Device, channel: usize ) -> Result<Option<f32>, GetLevelError>

Get the level of a channel on a device

source

pub fn get_midi_message(&self) -> Result<Vec<u8>, GetMidiMessageError>

Get a midi message.

source

pub fn get_midi_message_buff( &self, buffer: &mut [u8] ) -> Result<usize, GetMidiMessageError>

Get a midi message with a set buffer.

source§

impl VoicemeeterRemote

source

pub fn is_macrobutton_dirty(&self) -> Result<bool, IsMacroButtonDirtyError>

Check if macro buttons have changed

Call this function periodically to check if the macro buttons have changed, typically every 10ms.

§Security

This method must only be called from one thread.

source

pub fn get_macrobutton_state( &self, button: impl Into<LogicalButton> ) -> Result<MacroButtonStatus, GetMacroButtonStatusError>

Get a specific macro buttons status.

source

pub fn set_macrobutton_state( &self, button: impl Into<LogicalButton>, state: bool, displayed_state_only: bool ) -> Result<(), SetMacroButtonStatusError>

Set a macro buttons state.

use displayed_state_only to only set the displayed state of the macro button, but not trigger it’s associated requests.

source

pub fn get_macrobutton_trigger_state( &self, button: impl Into<LogicalButton> ) -> Result<MacroButtonStatus, GetMacroButtonStatusError>

Get the trigger state of the macrobutton.

source

pub fn set_macrobutton_trigger_state( &self, button: impl Into<LogicalButton>, state: bool ) -> Result<(), SetMacroButtonStatusError>

Set the trigger state of the macrobutton.

source§

impl VoicemeeterRemote

source

pub fn is_parameters_dirty(&self) -> Result<bool, IsParametersDirtyError>

Check if parameters have changed

Call this function periodically to check if parameters have changed, typically every 10ms. This function will also make sure voicemeeter processes any new pushed values for a parameter.

§Security

This method must only be called from one thread.

source

pub fn get_parameter_float( &self, param: &ParameterNameRef ) -> Result<f32, GetParameterError>

Get the float value of a parameter. See also VoicemeeterRemote::parameters() to do this with functions.

source

pub fn get_parameter_string( &self, param: &ParameterNameRef ) -> Result<String, GetParameterError>

Get the string value of a parameter. See also VoicemeeterRemote::parameters() to do this with functions.

source§

impl VoicemeeterRemote

source

pub fn set_parameter_float( &self, param: &ParameterNameRef, value: f32 ) -> Result<(), SetParameterError>

Set the float value of a parameter. See also VoicemeeterRemote::parameters() to do this with functions.

source

pub fn set_parameter_string( &self, param: &ParameterNameRef, value: &str ) -> Result<(), SetParameterError>

Set the string value of a parameter. See also VoicemeeterRemote::parameters() to do this with functions.

source

pub fn set_parameters(&self, script: &str) -> Result<(), SetParametersError>

Set parameters using a script. Similar to macro button scripts.

source§

impl VoicemeeterRemote

source

pub fn parameters(&self) -> Parameters<'_>

Get access to parameters of the application.

§Examples
use voicemeeter::VoicemeeterRemote;

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)?;
source§

impl VoicemeeterRemote

source

pub fn new() -> Result<Self, InitializationError>

Creates a new VoicemeeterRemote instance that is logged in with the client.

§Notes

If you create VoicemeeterRemote instances, when the last instance remaining is dropped, you will automatically be logged out of the API, meaning you cannot login again.

This is done to prevent leaving the API logged in when your program is closed, causing a visual bug in the voicemeeter application.

source

pub fn update_program(&mut self) -> Result<(), GetVoicemeeterInformationError>

Update the current program type.

Trait Implementations§

source§

impl Clone for VoicemeeterRemote

source§

fn clone(&self) -> VoicemeeterRemote

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for VoicemeeterRemote

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Drop for VoicemeeterRemote

source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more