use super::*;
pub struct Strip<'a> {
remote: &'a VoicemeeterRemote,
strip_index: ZIndex,
}
impl<'a> Strip<'a> {
#[doc(hidden)]
pub fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
Strip {
remote,
strip_index,
}
}
pub fn param(&self, dot: impl Display) -> Cow<'static, ParameterNameRef> {
Cow::Owned(format!("{STRIP}[{}].{}", self.strip_index, dot).into())
}
#[rustfmt::skip]
pub fn is_physical(&self) -> bool {
matches!((self.remote.program, self.strip_index.0),
| (VoicemeeterApplication::Voicemeeter, 0..=1)
| (VoicemeeterApplication::VoicemeeterBanana, 0..=2)
| (VoicemeeterApplication::VoicemeeterPotato, 0..=4)
| (VoicemeeterApplication::PotatoX64Bits, 0..=4)
)
}
pub fn is_virtual(&self) -> bool {
!(self.is_physical() || matches!(self.remote.program, VoicemeeterApplication::Other))
}
pub fn mono(&self) -> BoolParameter {
BoolParameter::new(self.param("Mono"), self.remote)
}
pub fn mute(&self) -> BoolParameter {
BoolParameter::new(self.param("Mute"), self.remote)
}
pub fn solo(&self) -> BoolParameter {
BoolParameter::new(self.param("Solo"), self.remote)
}
pub fn mute_center(&self) -> BoolParameter {
BoolParameter::new(self.param("MC"), self.remote)
}
pub fn gain(&self) -> FloatParameter {
FloatParameter::new(self.param("Gain"), self.remote, -60.0..=12.0)
}
pub fn gain_layer(&self, layer: impl Into<ZIndex>) -> FloatParameter {
let layer = layer.into();
let name = self.param(format!("GainLayer[{layer}]"));
FloatParameter::new(name, self.remote, -60.0..=12.0)
}
pub fn pan_x(&self) -> FloatParameter {
FloatParameter::new(self.param("Pan_x"), self.remote, -0.5..=0.5)
}
pub fn pan_y(&self) -> FloatParameter {
FloatParameter::new_unranged(self.param("Pan_y"), self.remote)
}
pub fn color_x(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_virtual() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "Color_x".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("Color_x"),
self.remote,
-0.5..=0.5,
))
}
}
pub fn color_y(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_virtual() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "Color_y".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("Color_y"),
self.remote,
0.0..=1.0,
))
}
}
pub fn fx_x(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_virtual() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "fx_x".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("fx_x"),
self.remote,
-0.5..=0.5,
))
}
}
pub fn fx_y(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_virtual() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "fx_y".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("fx_y"),
self.remote,
0.0..=1.0,
))
}
}
pub fn audability(&self) -> FloatParameter {
FloatParameter::new(self.param("Audability"), self.remote, 0.0..=10.0)
}
pub fn comp(&self) -> FloatParameter {
FloatParameter::new(self.param("Comp"), self.remote, 0.0..=10.0)
}
pub fn comp_detailed(&self) -> Result<StripCompressor, ParameterError> {
const VALID: &[VoicemeeterApplication] = &[
VoicemeeterApplication::VoicemeeterPotato,
VoicemeeterApplication::PotatoX64Bits,
];
if VALID.contains(&self.remote.program) {
if self.is_physical() {
Ok(StripCompressor::new(self.remote, self.strip_index))
} else {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "Comp".to_string(),
}
.into())
}
} else {
Err(InvalidVoicemeeterVersion {
expected: VALID,
found: self.remote.program,
parameter: self.param("Comp").to_string(),
}
.into())
}
}
pub fn gate(&self) -> FloatParameter {
FloatParameter::new(self.param("Gate"), self.remote, 0.0..=10.0)
}
pub fn gate_detailed(&self) -> Result<StripGate, ParameterError> {
const VALID: &[VoicemeeterApplication] = &[
VoicemeeterApplication::VoicemeeterPotato,
VoicemeeterApplication::PotatoX64Bits,
];
if VALID.contains(&self.remote.program) {
if self.is_physical() {
Ok(StripGate::new(self.remote, self.strip_index))
} else {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "Gate".to_string(),
}
.into())
}
} else {
Err(InvalidVoicemeeterVersion {
expected: VALID,
found: self.remote.program,
parameter: self.param("Gate").to_string(),
}
.into())
}
}
pub fn denoiser(&self) -> Result<FloatParameter, ParameterError> {
const VALID: &[VoicemeeterApplication] = &[
VoicemeeterApplication::VoicemeeterPotato,
VoicemeeterApplication::PotatoX64Bits,
];
if VALID.contains(&self.remote.program) {
if self.is_physical() {
Ok(FloatParameter::new(
self.param("Denoiser"),
self.remote,
0.0..10.0,
))
} else {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "Gate".to_string(),
}
.into())
}
} else {
Err(InvalidVoicemeeterVersion {
expected: VALID,
found: self.remote.program,
parameter: self.param("Gate").to_string(),
}
.into())
}
}
pub fn karaoke(&self) -> IntParameter {
IntParameter::new(self.param("Karaoke"), self.remote, 0..=4)
}
pub fn limit(&self) -> IntParameter {
IntParameter::new(self.param("Limit"), self.remote, -40..=12)
}
pub fn eq_gain1(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_physical() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "EQGain1".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("EQGain1"),
self.remote,
-12.0..=12.0,
))
}
}
pub fn eq_gain2(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_physical() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "EQGain2".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("EQGain2"),
self.remote,
-12.0..=12.0,
))
}
}
pub fn eq_gain3(&self) -> Result<FloatParameter, InvalidTypeError> {
if self.is_physical() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "EQGain3".to_string(),
})
} else {
Ok(FloatParameter::new(
self.param("EQGain3"),
self.remote,
-12.0..=12.0,
))
}
}
pub fn label(&self) -> StringParameter {
StringParameter::new(self.param("Label"), self.remote)
}
pub fn a1(&self) -> BoolParameter {
BoolParameter::new(self.param("A1"), self.remote)
}
pub fn a2(&self) -> BoolParameter {
BoolParameter::new(self.param("A2"), self.remote)
}
pub fn a3(&self) -> BoolParameter {
BoolParameter::new(self.param("A3"), self.remote)
}
pub fn a4(&self) -> BoolParameter {
BoolParameter::new(self.param("A4"), self.remote)
}
pub fn a5(&self) -> BoolParameter {
BoolParameter::new(self.param("A5"), self.remote)
}
pub fn b1(&self) -> BoolParameter {
BoolParameter::new(self.param("B1"), self.remote)
}
pub fn b2(&self) -> BoolParameter {
BoolParameter::new(self.param("B2"), self.remote)
}
pub fn b3(&self) -> BoolParameter {
BoolParameter::new(self.param("B3"), self.remote)
}
pub fn eq_on(&self) -> BoolParameter {
BoolParameter::new(self.param("EQ.on"), self.remote)
}
pub fn eq_ab(&self) -> BoolParameter {
BoolParameter::new(self.param("EQ.AB"), self.remote)
}
pub fn eq(&self, channel: usize) -> Result<EqChannelParameter, ParameterError> {
const VALID: &[VoicemeeterApplication] = &[
VoicemeeterApplication::VoicemeeterPotato,
VoicemeeterApplication::PotatoX64Bits,
];
let eq = EqChannelParameter::new_strip(self.remote, self.strip_index, channel);
if VALID.contains(&self.remote.program) {
if self.is_physical() {
Ok(eq)
} else {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: eq.name().to_string(),
}
.into())
}
} else {
Err(InvalidVoicemeeterVersion {
expected: VALID,
found: self.remote.program,
parameter: eq.name().to_string(),
}
.into())
}
}
pub fn fade_to(&self) -> TupleParameter<'_, i32, usize> {
TupleParameter::new(self.param("FadeTo"), self.remote)
}
pub fn fade_by(&self) -> TupleParameter<'_, i32, usize> {
TupleParameter::new(self.param("FadeBy"), self.remote)
}
pub fn reverb(&self) -> FloatParameter {
FloatParameter::new(self.param("Reverb"), self.remote, 0.0..=10.0)
}
pub fn delay(&self) -> FloatParameter {
FloatParameter::new(self.param("Delay"), self.remote, 0.0..=10.0)
}
pub fn fx1(&self) -> FloatParameter {
FloatParameter::new(self.param("Fx1"), self.remote, 0.0..=10.0)
}
pub fn fx2(&self) -> FloatParameter {
FloatParameter::new(self.param("Fx2"), self.remote, 0.0..=10.0)
}
pub fn post_reverb(&self) -> BoolParameter {
BoolParameter::new(self.param("PostReverb"), self.remote)
}
pub fn post_delay(&self) -> BoolParameter {
BoolParameter::new(self.param("PostDelay"), self.remote)
}
pub fn post_fx1(&self) -> BoolParameter {
BoolParameter::new(self.param("PostFx1"), self.remote)
}
pub fn post_fx2(&self) -> BoolParameter {
BoolParameter::new(self.param("PostFx2"), self.remote)
}
pub fn app_gain_indexed(&self, application_index: ZIndex) -> FloatParameter<'_, true, false> {
FloatParameter::new(
self.param(format!("App[{application_index}].Gain")),
self.remote,
0.0..=1.0,
)
}
pub fn app_mute_indexed(&self, application_index: ZIndex) -> BoolParameter<'_, true, false> {
BoolParameter::new(
self.param(format!("App[{application_index}].Mute")),
self.remote,
)
}
pub fn app_gain(&self) -> TupleParameter<'_, String, f32, true, false> {
TupleParameter::new(self.param("AppGain"), self.remote)
}
pub fn app_mute(&self) -> TupleParameter<'_, String, bool, true, false> {
TupleParameter::new(self.param("AppMute"), self.remote)
}
pub fn device(&self) -> Result<StripDevice<'a>, InvalidTypeError> {
if self.is_virtual() {
Err(InvalidTypeError::ExpectedPhysical {
name: STRIP,
strip_index: self.strip_index,
parameter: "device".to_string(),
})
} else {
Ok(StripDevice::new(self.remote, self.strip_index))
}
}
}
pub struct StripDevice<'a> {
remote: &'a VoicemeeterRemote,
strip_index: ZIndex,
}
impl<'a> StripDevice<'a> {
fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
Self {
remote,
strip_index,
}
}
pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
Cow::Owned(format!("{STRIP}[{}].device.{}", self.strip_index, dot.to_string()).into())
}
pub fn name(&self) -> StringParameter<'a, false, true> {
StringParameter::new(self.param("name"), self.remote)
}
pub fn sr(&self) -> IntParameter<'a, false, true> {
IntParameter::new_unranged(self.param("sr"), self.remote)
}
pub fn wdm(&self) -> StringParameter<'a, true, false> {
StringParameter::new(self.param("wdm"), self.remote)
}
pub fn ks(&self) -> StringParameter<'a, true, false> {
StringParameter::new(self.param("ks"), self.remote)
}
pub fn mme(&self) -> StringParameter<'a, true, false> {
StringParameter::new(self.param("mme"), self.remote)
}
pub fn asio(&self) -> StringParameter<'a, true, false> {
StringParameter::new(self.param("asio"), self.remote)
}
}
pub struct StripCompressor<'a> {
remote: &'a VoicemeeterRemote,
strip_index: ZIndex,
}
impl<'a> StripCompressor<'a> {
fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
Self {
remote,
strip_index,
}
}
pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
Cow::Owned(format!("{STRIP}[{}].comp.{}", self.strip_index, dot.to_string()).into())
}
pub fn gain_in(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("GainIn"), self.remote, -24.0..24.0)
}
pub fn ratio(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Ratio"), self.remote, 1.0..8.0)
}
pub fn threshold(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Threshold"), self.remote, -40.0..-3.0)
}
pub fn attack(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Attack"), self.remote, 0.0..200.0)
}
pub fn release(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Release"), self.remote, 0.0..5000.0)
}
pub fn knee(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Knee"), self.remote, 0.0..1.0)
}
pub fn gain_out(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("GainOut"), self.remote, -24.0..24.0)
}
pub fn make_up(&self) -> BoolParameter<'a, true, true> {
BoolParameter::new(self.param("MakeUp"), self.remote)
}
}
pub struct StripGate<'a> {
remote: &'a VoicemeeterRemote,
strip_index: ZIndex,
}
impl<'a> StripGate<'a> {
fn new(remote: &'a VoicemeeterRemote, strip_index: ZIndex) -> Self {
Self {
remote,
strip_index,
}
}
pub fn param(&self, dot: impl ToString) -> Cow<'static, ParameterNameRef> {
Cow::Owned(format!("{STRIP}[{}].Gate.{}", self.strip_index, dot.to_string()).into())
}
pub fn threshold(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Threshold"), self.remote, -60.0..-10.0)
}
pub fn damping(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Damping"), self.remote, -60.0..-10.0)
}
pub fn bp_sidechain(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("BPSidechain"), self.remote, 100.0..=4000.0)
}
pub fn attack(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Attack"), self.remote, 0.0..=1000.0)
}
pub fn hold(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Hold"), self.remote, 0.0..=5000.0)
}
pub fn release(&self) -> FloatParameter<'a, true, true> {
FloatParameter::new(self.param("Release"), self.remote, 0.0..=5000.0)
}
}