launch clips

This commit is contained in:
🪞👃🪞 2024-06-30 21:20:57 +03:00
parent 8a2693c297
commit a4061535b5
7 changed files with 117 additions and 28 deletions

View file

@ -134,6 +134,18 @@ pub trait Render {
fn render (&self, _b: &mut Buffer, _a: Rect) -> Usually<Rect> {
Ok(Rect { x: 0, y: 0, width: 0, height: 0 })
}
fn min_width (&self) -> u16 {
0
}
fn max_width (&self) -> u16 {
u16::MAX
}
fn min_height (&self) -> u16 {
0
}
fn max_height (&self) -> u16 {
u16::MAX
}
}
impl Render for Box<dyn Device> {

View file

@ -21,7 +21,7 @@ enum PluginKind {
LV2 {
world: ::livi::World,
features: Arc<::livi::Features>,
portList: Vec<::livi::Port>,
port_list: Vec<::livi::Port>,
instance: ::livi::Instance,
},
VST2 {
@ -105,7 +105,7 @@ impl Plugin {
inputs.push(atom);
}
let mut outputs = vec![];
for port in self.midi_outs.iter() {
for _ in self.midi_outs.iter() {
outputs.push(::livi::event::LV2AtomSequence::new(
&features,
scope.n_frames() as usize
@ -171,12 +171,12 @@ pub fn render (state: &Plugin, buf: &mut Buffer, area: Rect)
let Rect { x, y, height, .. } = area;
let mut width = 40u16;
match &state.plugin {
Some(PluginKind::LV2 { portList, instance, .. }) => {
Some(PluginKind::LV2 { port_list, instance, .. }) => {
let start = state.selected.saturating_sub((height as usize / 2).saturating_sub(1));
let end = start + height as usize - 2;
//draw_box(buf, Rect { x, y, width, height });
for i in start..end {
if let Some(port) = portList.get(i) {
if let Some(port) = port_list.get(i) {
let value = if let Some(value) = instance.control_input(port.index) {
value
} else {
@ -218,7 +218,7 @@ pub fn handle (s: &mut Plugin, event: &AppEvent) -> Usually<bool> {
s.selected = s.selected - 1
} else {
s.selected = match &s.plugin {
Some(PluginKind::LV2 { portList, .. }) => portList.len() - 1,
Some(PluginKind::LV2 { port_list, .. }) => port_list.len() - 1,
_ => 0
}
}
@ -229,8 +229,8 @@ pub fn handle (s: &mut Plugin, event: &AppEvent) -> Usually<bool> {
|s: &mut Plugin|{
s.selected = s.selected + 1;
match &s.plugin {
Some(PluginKind::LV2 { portList, .. }) => {
if s.selected >= portList.len() {
Some(PluginKind::LV2 { port_list, .. }) => {
if s.selected >= port_list.len() {
s.selected = 0;
}
},
@ -242,8 +242,8 @@ pub fn handle (s: &mut Plugin, event: &AppEvent) -> Usually<bool> {
[Char(','), NONE, "decrement", "decrement value",
|s: &mut Plugin|{
match s.plugin.as_mut() {
Some(PluginKind::LV2 { portList, ref mut instance, .. }) => {
let index = portList[s.selected].index;
Some(PluginKind::LV2 { port_list, ref mut instance, .. }) => {
let index = port_list[s.selected].index;
if let Some(value) = instance.control_input(index) {
instance.set_control_input(index, value - 0.01);
}
@ -256,8 +256,8 @@ pub fn handle (s: &mut Plugin, event: &AppEvent) -> Usually<bool> {
[Char('.'), NONE, "increment", "increment value",
|s: &mut Plugin|{
match s.plugin.as_mut() {
Some(PluginKind::LV2 { portList, ref mut instance, .. }) => {
let index = portList[s.selected].index;
Some(PluginKind::LV2 { port_list, ref mut instance, .. }) => {
let index = port_list[s.selected].index;
if let Some(value) = instance.control_input(index) {
instance.set_control_input(index, value + 0.01);
}

View file

@ -13,15 +13,15 @@ pub fn plug (uri: &str) -> Usually<PluginKind> {
break
}
let plugin = plugin.unwrap();
let mut portList = vec![];
let mut port_list = vec![];
for port in plugin.ports() {
portList.push(port);
port_list.push(port);
}
Ok(PluginKind::LV2 {
instance: unsafe {
plugin.instantiate(features.clone(), 48000.0).expect("boop")
},
portList,
port_list,
features,
world,
})

View file

@ -12,4 +12,3 @@ fn set_vst_plugin (host: &Arc<Mutex<Plugin>>, path: &str) -> Usually<PluginKind>
instance: loader.instance()?
})
}
//"file:///nix/store/ij3sz7nqg5l7v2dygdvzy3w6cj62bd6r-helm-0.9.0/lib/lxvst/helm.so"

View file

@ -152,9 +152,10 @@ impl PortList for Sampler {
pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rect)
-> Usually<Rect>
{
let width = 40;
let style = Style::default().gray();
format!(" {} ({})", state.name, state.voices.len()).blit(buf, x+1, y, Some(style.white().bold().not_dim()));
let title = format!(" {} ({})", state.name, state.voices.len());
title.blit(buf, x+1, y, Some(style.white().bold().not_dim()));
let mut width = title.len() + 2;
for (i, (note, sample)) in state.samples.iter().enumerate() {
let style = if i == state.cursor.0 {
Style::default().green()
@ -169,12 +170,14 @@ pub fn render (state: &Sampler, buf: &mut Buffer, Rect { x, y, height, .. }: Rec
if i as usize == state.cursor.0 {
"".blit(buf, x+1, y1, Some(style.bold()));
}
let label1 = format!("{note:3} {:10}", sample.name);
let label2 = format!("{:>7} {:>7}", sample.start, sample.end);
let label1 = format!("{note:3} {:8}", sample.name);
let label2 = format!("{:>6} {:>6}", sample.start, sample.end);
label1.blit(buf, x+2, y1, Some(style.bold()));
label2.blit(buf, x+3+label1.len()as u16, y1, Some(style));
width = width.max(label1.len() + label2.len() + 4);
}
Ok(Rect { x, y, width, height })
let height = ((1 + state.samples.len()) as u16).min(height);
Ok(Rect { x, y, width: width as u16, height })
}
//fn render_table (
@ -225,9 +228,10 @@ pub fn handle (state: &mut Sampler, event: &AppEvent) -> Usually<bool> {
Ok(handle_keymap(state, event, KEYMAP)?)
}
pub const KEYMAP: &'static [KeyBinding<Sampler>] = keymap!(Sampler {
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Enter, NONE, "select", "select item under cursor", select],
[Up, NONE, "cursor_up", "move cursor up", cursor_up],
[Down, NONE, "cursor_down", "move cursor down", cursor_down],
[Char('t'), NONE, "trigger", "play current sample", trigger],
[Enter, NONE, "select", "select item under cursor", select],
});
fn cursor_up (state: &mut Sampler) -> Usually<bool> {
state.cursor.0 = if state.cursor.0 == 0 {
@ -241,7 +245,7 @@ fn cursor_down (state: &mut Sampler) -> Usually<bool> {
state.cursor.0 = (state.cursor.0 + 1) % state.samples.len();
Ok(true)
}
fn select (state: &mut Sampler) -> Usually<bool> {
fn trigger (state: &mut Sampler) -> Usually<bool> {
for (i, sample) in state.samples.values().enumerate() {
if i == state.cursor.0 {
state.voices.push(sample.play(0))
@ -249,3 +253,11 @@ fn select (state: &mut Sampler) -> Usually<bool> {
}
Ok(true)
}
fn select (state: &mut Sampler) -> Usually<bool> {
for (i, sample) in state.samples.values().enumerate() {
if i == state.cursor.0 {
//state.voices.push(sample.play(0))
}
}
Ok(true)
}

View file

@ -43,12 +43,31 @@ pub const KEYMAP_TRACKS: &'static [KeyBinding<Launcher>] = keymap!(Launcher {
[Char(','), NONE, "clip_prev", "set clip to last phrase", clip_prev],
[Delete, CONTROL, "delete_track", "delete track", delete_track],
[Char('d'), CONTROL, "duplicate", "duplicate scene or track", duplicate],
[Enter, NONE, "clip_enter", "play or record clip or stop and advance", clip_enter],
[Enter, NONE, "activate", "activate item at cursor", activate],
});
fn duplicate (_: &mut Launcher) -> Usually<bool> {
Ok(true)
}
fn clip_enter (_: &mut Launcher) -> Usually<bool> {
fn activate (state: &mut Launcher) -> Usually<bool> {
if let (
Some((scene_id, scene)),
Some((track_id, track)),
) = (state.scene(), state.track()) {
// Launch clip
if let Some(Some(phrase_id)) = scene.clips.get(track_id) {
track.sequencer.state().sequence = *phrase_id;
}
} else if let Some((scene_id, scene)) = state.scene() {
// Launch scene
for (track_id, track) in state.tracks.iter().enumerate() {
if let Some(Some(phrase_id)) = scene.clips.get(track_id) {
track.sequencer.state().sequence = *phrase_id;
}
}
} else if let Some((track_id, track)) = state.track() {
// Rename track?
}
//let track = state.active_track().unwrap();
//let scene = state.active_scene();
//if state.cursor.1 >= 2 {

View file

@ -69,6 +69,9 @@ fn main () -> Result<(), Box<dyn Error>> {
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
] ),
play!(1 => [
MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
]),
play!(2 => [
MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
]),
@ -146,6 +149,50 @@ fn main () -> Result<(), Box<dyn Error>> {
MidiMessage::NoteOff { key: 41.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 42.into(), vel: 100.into() },
]),
]))),
Phrase::new("E E G Bb", ppq * 4, Some(BTreeMap::from([
play!(2 => [
MidiMessage::NoteOff { key: 42.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
play!(6 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
play!(10 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 39.into(), vel: 100.into() },
]),
play!(14 => [
MidiMessage::NoteOff { key: 39.into(), vel: 100.into() },
MidiMessage::NoteOn { key: 42.into(), vel: 100.into() },
]),
]))),
Phrase::new("E E E E", ppq * 4, Some(BTreeMap::from([
play!(0 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
]),
play!(2 => [
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
play!(4 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
]),
play!(6 => [
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
play!(8 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
]),
play!(10 => [
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
play!(12 => [
MidiMessage::NoteOff { key: 36.into(), vel: 100.into() },
]),
play!(14 => [
MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
]),
])))
]))?,
@ -156,8 +203,8 @@ fn main () -> Result<(), Box<dyn Error>> {
Some(vec![
Scene::new(&"Scene 1", &[Some(0), None, None, None]),
Scene::new(&"Scene 2", &[Some(0), Some(0), None, None]),
Scene::new(&"Scene 3", &[Some(1), Some(0), None, None]),
Scene::new(&"Scene 4", &[Some(2), Some(0), None, None]),
Scene::new(&"Scene 3", &[Some(1), Some(1), None, None]),
Scene::new(&"Scene 4", &[Some(2), Some(2), None, None]),
//Scene::new(&"Scene#03", &[None, Some(0), None, None]),
//Scene::new(&"Scene#04", &[None, None, None, None]),
//Scene::new(&"Scene#05", &[None, None, None, None]),