use lv2_core::feature::{FeatureCache, FeatureCollection, MissingFeatureError};
use lv2_core::feature::{HardRTCapable, IsLive};
use lv2_core::prelude::*;
use std::ops::Drop;
use std::os::raw::c_char;
use urid::*;
#[uri("http://lv2plug.in/plugins.rs/example_amp")]
struct Amp {
activated: bool,
}
#[derive(PortCollection)]
struct AmpPorts {
gain: InputPort<Control>,
input: InputPort<Audio>,
output: OutputPort<Audio>,
}
#[derive(FeatureCollection)]
struct Features {
_rt_capable: HardRTCapable,
is_live: Option<IsLive>,
}
impl Plugin for Amp {
type Ports = AmpPorts;
type InitFeatures = Features;
type AudioFeatures = ();
#[inline]
fn new(plugin_info: &PluginInfo, features: &mut Features) -> Option<Self> {
assert_eq!(
plugin_info.plugin_uri().to_str().unwrap(),
"http://lv2plug.in/plugins.rs/example_amp"
);
assert_eq!(
plugin_info.bundle_path().to_str().unwrap(),
"/home/lv2/amp.lv2/"
);
assert_eq!(plugin_info.sample_rate() as u32, 44100);
assert!(features.is_live.is_none());
Some(Amp { activated: false })
}
fn activate(&mut self, _: &mut Features) {
assert!(!self.activated);
self.activated = true;
}
#[inline]
fn run(&mut self, ports: &mut AmpPorts, _: &mut (), _: u32) {
assert!(self.activated);
let coef = *(ports.gain);
let input = ports.input.iter();
let output = ports.output.iter_mut();
for (input_sample, output_sample) in input.zip(output) {
*output_sample = (*input_sample) * coef;
}
}
fn deactivate(&mut self, _: &mut Features) {
assert!(self.activated);
self.activated = false;
}
}
impl Drop for Amp {
fn drop(&mut self) {
assert!(!self.activated);
}
}
lv2_descriptors! {
Amp
}
#[test]
fn test_discovery() {
use lv2_sys::*;
unsafe {
let descriptor: &LV2_Descriptor = lv2_descriptor(0).as_ref().unwrap();
assert_eq!(
Uri::from_ptr(descriptor.URI),
Uri::from_bytes_with_nul_unchecked(b"http://lv2plug.in/plugins.rs/example_amp\0")
);
assert_eq!(lv2_descriptor(1), std::ptr::null());
}
}
#[test]
fn test_plugin() {
use lv2_sys::*;
use urid::UriBound;
let mut gain: f32 = 2.0;
let mut input: Box<[f32; 128]> = Box::new([0.0; 128]);
for i in 0..128 {
input[i] = i as f32;
}
let mut output: Box<[f32; 128]> = Box::new([0.0; 128]);
let hard_rt_capable = LV2_Feature {
URI: HardRTCapable::URI.as_ptr() as *const c_char,
data: std::ptr::null_mut(),
};
let features: &[*const LV2_Feature] = &[&hard_rt_capable, std::ptr::null()];
unsafe {
let descriptor: &LV2_Descriptor = lv2_descriptor(0).as_ref().unwrap();
let plugin: LV2_Handle = (descriptor.instantiate.unwrap())(
descriptor,
44100.0,
"/home/lv2/amp.lv2/\0".as_ptr() as *const c_char,
features.as_ptr(),
);
assert_ne!(plugin, std::ptr::null_mut());
let connect_port = descriptor.connect_port.unwrap();
(connect_port)(plugin, 0, (&mut gain) as *mut f32 as *mut _);
(connect_port)(plugin, 1, input.as_mut_ptr() as *mut _);
(connect_port)(plugin, 2, output.as_mut_ptr() as *mut _);
(descriptor.activate.unwrap())(plugin);
(descriptor.run.unwrap())(plugin, 128);
(descriptor.deactivate.unwrap())(plugin);
(descriptor.cleanup.unwrap())(plugin)
}
for i in 0..128 {
assert!((input[i] * gain - output[i]).abs() < std::f32::EPSILON);
}
}