mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 12:46:42 +01:00
chore: tidy
This commit is contained in:
parent
1b7892d11f
commit
f48f17e9a4
8 changed files with 66 additions and 73 deletions
234
src/device/chain/plugin.rs
Normal file
234
src/device/chain/plugin.rs
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
mod lv2;
|
||||
mod vst2;
|
||||
mod vst3;
|
||||
|
||||
pub struct Plugin {
|
||||
name: String,
|
||||
path: Option<String>,
|
||||
plugin: Option<PluginKind>,
|
||||
offset: usize,
|
||||
selected: usize,
|
||||
mapping: bool,
|
||||
midi_ins: Vec<Port<MidiIn>>,
|
||||
midi_outs: Vec<Port<MidiOut>>,
|
||||
audio_ins: Vec<Port<AudioIn>>,
|
||||
audio_outs: Vec<Port<AudioOut>>,
|
||||
}
|
||||
|
||||
enum PluginKind {
|
||||
LV2 {
|
||||
world: ::livi::World,
|
||||
features: Arc<::livi::Features>,
|
||||
portList: Vec<::livi::Port>,
|
||||
instance: ::livi::Instance,
|
||||
},
|
||||
VST2 {
|
||||
instance: ::vst::host::PluginInstance
|
||||
},
|
||||
VST3,
|
||||
}
|
||||
|
||||
const HELM: &'static str = "file:///nix/store/ij3sz7nqg5l7v2dygdvzy3w6cj62bd6r-helm-0.9.0/lib/lv2/helm.lv2";
|
||||
|
||||
impl Plugin {
|
||||
/// Load a LV2 plugin.
|
||||
pub fn lv2 (name: &str, path: &str, ports: &[usize;4]) -> Usually<DynamicDevice<Self>> {
|
||||
let plugin = Self::new(name, ports)?;
|
||||
let mut state = plugin.state();
|
||||
state.plugin = Some(self::lv2::plug(path)?);
|
||||
state.path = Some(String::from(path));
|
||||
std::mem::drop(state);
|
||||
Ok(plugin)
|
||||
}
|
||||
pub fn new (name: &str, ports: &[usize;4]) -> Usually<DynamicDevice<Self>> {
|
||||
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||
let [midi_ins, midi_outs, audio_ins, audio_outs] = ports;
|
||||
DynamicDevice::new(render, handle, Self::process, Self {
|
||||
name: name.into(),
|
||||
path: None,
|
||||
plugin: None,
|
||||
offset: 0,
|
||||
selected: 0,
|
||||
mapping: false,
|
||||
midi_ins: {
|
||||
let mut ports = vec![];
|
||||
for i in 0..*midi_ins {
|
||||
ports.push(client.register_port(&format!("midi-in-{i}"), MidiIn::default())?)
|
||||
}
|
||||
ports
|
||||
},
|
||||
midi_outs: {
|
||||
let mut ports = vec![];
|
||||
for i in 0..*midi_outs {
|
||||
ports.push(client.register_port(&format!("midi-out-{i}"), MidiOut::default())?)
|
||||
}
|
||||
ports
|
||||
},
|
||||
audio_ins: {
|
||||
let mut ports = vec![];
|
||||
for i in 0..*audio_ins {
|
||||
ports.push(client.register_port(&format!("audio-in-{i}"), AudioIn::default())?)
|
||||
}
|
||||
ports
|
||||
},
|
||||
audio_outs: {
|
||||
let mut ports = vec![];
|
||||
for i in 0..*audio_outs {
|
||||
ports.push(client.register_port(&format!("audio-out-{i}"), AudioOut::default())?)
|
||||
}
|
||||
ports
|
||||
},
|
||||
}).activate(client)
|
||||
}
|
||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
match self.plugin.as_mut() {
|
||||
Some(PluginKind::LV2 { features, ref mut instance, .. }) => {
|
||||
let urid = features.midi_urid();
|
||||
let mut inputs = vec![];
|
||||
for port in self.midi_ins.iter() {
|
||||
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(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
inputs.push(atom);
|
||||
}
|
||||
let mut outputs = vec![];
|
||||
for port in self.midi_outs.iter() {
|
||||
outputs.push(::livi::event::LV2AtomSequence::new(
|
||||
&features,
|
||||
scope.n_frames() as usize
|
||||
));
|
||||
}
|
||||
let ports = ::livi::EmptyPortConnections::new()
|
||||
.with_atom_sequence_inputs(
|
||||
inputs.iter()
|
||||
)
|
||||
.with_atom_sequence_outputs(
|
||||
outputs.iter_mut()
|
||||
)
|
||||
.with_audio_inputs(
|
||||
self.audio_ins.iter().map(|o|o.as_slice(scope))
|
||||
)
|
||||
.with_audio_outputs(
|
||||
self.audio_outs.iter_mut().map(|o|o.as_mut_slice(scope))
|
||||
);
|
||||
unsafe {
|
||||
instance.run(scope.n_frames() as usize, ports).unwrap()
|
||||
};
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
||||
impl PortList for Plugin {
|
||||
fn audio_ins (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.audio_ins.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
fn audio_outs (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.audio_outs.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
fn midi_ins (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.midi_ins.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
fn midi_outs (&self) -> Usually<Vec<String>> {
|
||||
let mut ports = vec![];
|
||||
for port in self.midi_outs.iter() {
|
||||
ports.push(port.name()?);
|
||||
}
|
||||
Ok(ports)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render (state: &Plugin, buf: &mut Buffer, area: Rect)
|
||||
-> Usually<Rect>
|
||||
{
|
||||
let Rect { x, y, width, height } = area;
|
||||
let height = height.saturating_sub(3);
|
||||
let style = Style::default().gray();
|
||||
let mut width = 40u16;
|
||||
match &state.plugin {
|
||||
Some(PluginKind::LV2 { portList, instance, .. }) => {
|
||||
for i in 0..height - 4 {
|
||||
if let Some(port) = portList.get(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);
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
};
|
||||
draw_header(state, buf, area.x, area.y, width);
|
||||
Ok(Rect { width, ..area })
|
||||
}
|
||||
|
||||
fn draw_header (state: &Plugin, buf: &mut Buffer, x: u16, y: u16, w: u16) -> Usually<Rect> {
|
||||
let style = Style::default().gray();
|
||||
buf.set_string(x + 1, y + 1,
|
||||
&format!(" {}", state.name), style.white().bold());
|
||||
buf.set_string(x + 13, y + 1,
|
||||
&format!("│ {}...", &HELM[..(w as usize - 20).min(HELM.len())]), style.not_dim());
|
||||
buf.set_string(x + 0, y + 2,
|
||||
&format!("├{}┤", "-".repeat(w as usize - 2)), style.dim());
|
||||
Ok(Rect { x, y, width: w, height: 3 })
|
||||
}
|
||||
|
||||
pub fn handle (s: &mut Plugin, event: &AppEvent) -> Usually<bool> {
|
||||
handle_keymap(s, event, keymap!(Plugin {
|
||||
[Up, NONE, "cursor_up", "move cursor up",
|
||||
|s: &mut Plugin|{
|
||||
s.selected = s.selected.saturating_sub(1);
|
||||
if s.selected < s.offset {
|
||||
s.offset = s.selected;
|
||||
}
|
||||
Ok(true)
|
||||
}],
|
||||
[Down, NONE, "cursor_down", "move cursor down",
|
||||
|s: &mut Plugin|{
|
||||
s.selected = s.selected + 1;
|
||||
if s.selected >= s.offset + 19 {
|
||||
s.offset = s.offset + 1;
|
||||
}
|
||||
Ok(true)
|
||||
}],
|
||||
[Char('m'), NONE, "toggle_midi_map", "toggle midi map mode",
|
||||
|s: &mut Plugin|{
|
||||
s.mapping = !s.mapping;
|
||||
Ok(true)
|
||||
}]
|
||||
}))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue