mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-08-28 12:56:57 +02:00
lv2 plugin plays!
This commit is contained in:
parent
403d0f2dfe
commit
a4a2f645b1
4 changed files with 125 additions and 88 deletions
|
|
@ -6,6 +6,8 @@ mod vst3;
|
|||
|
||||
pub struct Plugin {
|
||||
name: String,
|
||||
input: ::jack::Port<::jack::MidiIn>,
|
||||
outputs: [::jack::Port<::jack::AudioOut>;2],
|
||||
path: String,
|
||||
plugin: Option<PluginKind>,
|
||||
offset: usize,
|
||||
|
|
@ -14,34 +16,81 @@ pub struct Plugin {
|
|||
}
|
||||
|
||||
enum PluginKind {
|
||||
VST2(::vst::host::PluginInstance),
|
||||
LV2 {
|
||||
world: ::livi::World,
|
||||
features: Arc<::livi::Features>,
|
||||
input: ::livi::event::LV2AtomSequence,
|
||||
portList: Vec<::livi::Port>,
|
||||
instance: ::livi::Instance,
|
||||
outputs: [Vec<f32>;2],
|
||||
},
|
||||
VST2 {
|
||||
instance: ::vst::host::PluginInstance
|
||||
},
|
||||
VST3,
|
||||
LV2(Vec<::livi::Port>, ::livi::Instance),
|
||||
}
|
||||
|
||||
const HELM: &'static str = "file:///nix/store/ij3sz7nqg5l7v2dygdvzy3w6cj62bd6r-helm-0.9.0/lib/lv2/helm.lv2";
|
||||
|
||||
impl Plugin {
|
||||
pub fn new (name: &str) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
|
||||
let device = DynamicDevice::new(render, handle, process, Self {
|
||||
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||
DynamicDevice::new(render, handle, Self::process, Self {
|
||||
name: name.into(),
|
||||
input: client.register_port("in", MidiIn::default())?,
|
||||
outputs: [
|
||||
client.register_port("outL", AudioOut::default())?,
|
||||
client.register_port("outR", AudioOut::default())?,
|
||||
],
|
||||
path: HELM.into(),
|
||||
plugin: None,
|
||||
plugin: Some(self::lv2::plug_in(HELM)?),
|
||||
offset: 0,
|
||||
selected: 0,
|
||||
midi_map_enable: false
|
||||
});
|
||||
device.state.lock().unwrap().plugin = Some(self::lv2::plug_in(HELM)?);
|
||||
Ok(device)
|
||||
}).activate(client)
|
||||
}
|
||||
|
||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
match self.plugin.as_mut() {
|
||||
Some(PluginKind::LV2 {
|
||||
features, input, ref mut instance, ..
|
||||
}) => {
|
||||
let mut input = ::livi::event::LV2AtomSequence::new(
|
||||
&features, scope.n_frames() as usize
|
||||
);
|
||||
let urid = features.midi_urid();
|
||||
for event in self.input.iter(scope) {
|
||||
match event.bytes.len() {
|
||||
3 => input.push_midi_event::<3>(
|
||||
event.time as i64,
|
||||
urid,
|
||||
&event.bytes[0..3]
|
||||
).unwrap(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let ports = ::livi::EmptyPortConnections::new()
|
||||
.with_atom_sequence_inputs(
|
||||
std::iter::once(&input)
|
||||
)
|
||||
.with_audio_outputs(
|
||||
self.outputs.iter_mut().map(|o|o.as_mut_slice(scope)),
|
||||
);
|
||||
unsafe {
|
||||
instance.run(
|
||||
scope.n_frames() as usize,
|
||||
ports
|
||||
).unwrap()
|
||||
};
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
||||
impl ::vst::host::Host for Plugin {}
|
||||
|
||||
pub fn process (_: &mut Plugin, _: &Client, _: &ProcessScope) -> Control {
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
pub fn render (state: &Plugin, buf: &mut Buffer, area: Rect)
|
||||
-> Usually<Rect>
|
||||
{
|
||||
|
|
@ -50,43 +99,20 @@ pub fn render (state: &Plugin, buf: &mut Buffer, area: Rect)
|
|||
let style = Style::default().gray();
|
||||
let mut width = 40u16;
|
||||
match &state.plugin {
|
||||
Some(PluginKind::LV2(ports, instance)) => {
|
||||
Some(PluginKind::LV2 { portList, instance, .. }) => {
|
||||
for i in 0..height - 4 {
|
||||
let port = &ports[i as usize];
|
||||
let port = &portList[i as usize];
|
||||
let label = &format!("C·· M·· {:25} = {:03}", port.name, port.default_value);
|
||||
width = width.max(label.len() as u16);
|
||||
label.blit(buf, x + 2, y + 3 + i as u16, None);
|
||||
}
|
||||
draw_box(buf, Rect { x, y, width, height });
|
||||
|
||||
//let mut height = 3;
|
||||
//for (i, port) in ports
|
||||
//.iter()
|
||||
//.filter(|port|port.port_type == ::livi::PortType::ControlInput)
|
||||
//.skip(state.offset)
|
||||
//.enumerate()
|
||||
//{
|
||||
//if i >= 20 {
|
||||
//break
|
||||
//}
|
||||
//buf.set_string(x + 2, y + 3 + i as u16, &format!("C·· M·· {:25} = {:03}",
|
||||
//port.name,
|
||||
//port.default_value
|
||||
//), if i + state.offset == state.selected {
|
||||
//Style::default().white().bold()
|
||||
//} else {
|
||||
//Style::default().not_dim()
|
||||
//});
|
||||
//height = height + 1;
|
||||
//}
|
||||
//Ok(draw_box(buf, rect { x, y, width, height }))
|
||||
},
|
||||
_ => {
|
||||
buf.set_string(x + 1, y + 3, &format!(" Parameter 1 0.0"), style);
|
||||
buf.set_string(x + 1, y + 4, &format!(" Parameter 2 0.0"), style);
|
||||
buf.set_string(x + 1, y + 5, &format!(" Parameter 3 0.0"), style);
|
||||
buf.set_string(x + 1, y + 6, &format!(" Parameter 4 0.0"), style);
|
||||
//Ok(draw_box(buf, Rect { x, y, width: 40, height: 7 }))
|
||||
}
|
||||
};
|
||||
draw_header(state, buf, area.x, area.y, width);
|
||||
|
|
@ -135,6 +161,6 @@ impl DevicePorts for Plugin {
|
|||
Ok(vec!["in".into()])
|
||||
}
|
||||
fn audio_outs (&self) -> Usually<Vec<String>> {
|
||||
Ok(vec!["out L".into(), "out R".into()])
|
||||
Ok(vec!["outL".into(), "outR".into()])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue