use crate::core::*; pub mod lv2; pub mod vst2; pub mod vst3; use self::lv2::*; pub struct Plugin { pub name: String, pub path: Option, pub plugin: Option, pub selected: usize, pub mapping: bool, pub ports: JackPorts, } render!(Plugin = crate::view::plugin::render); handle!(Plugin = crate::control::plugin::handle); process!(Plugin = Plugin::process); pub enum PluginKind { LV2(LV2Plugin), VST2 { instance: ::vst::host::PluginInstance }, VST3, } impl Plugin { /// Create a plugin host device. pub fn new (name: &str) -> Usually { Ok(Self { name: name.into(), path: None, plugin: None, selected: 0, mapping: false, ports: JackPorts::default() }) } pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { match self.plugin.as_mut() { Some(PluginKind::LV2(LV2Plugin { features, ref mut instance, ref mut input_buffer, .. })) => { let urid = features.midi_urid(); input_buffer.clear(); for port in self.ports.midi_ins.values() { let mut atom = ::livi::event::LV2AtomSequence::new( &features, scope.n_frames() as usize ); for event in port.iter(scope) { match event.bytes.len() { 3 => atom.push_midi_event::<3>( event.time as i64, urid, &event.bytes[0..3] ).unwrap(), _ => {} } } input_buffer.push(atom); } let mut outputs = vec![]; for _ in self.ports.midi_outs.iter() { outputs.push(::livi::event::LV2AtomSequence::new( &features, scope.n_frames() as usize )); } let ports = ::livi::EmptyPortConnections::new() .with_atom_sequence_inputs( input_buffer.iter() ) .with_atom_sequence_outputs( outputs.iter_mut() ) .with_audio_inputs( self.ports.audio_ins.values().map(|o|o.as_slice(scope)) ) .with_audio_outputs( self.ports.audio_outs.values_mut().map(|o|o.as_mut_slice(scope)) ); unsafe { instance.run(scope.n_frames() as usize, ports).unwrap() }; }, _ => {} } Control::Continue } }