From 1b7892d11f31d6804450f9664a9bb79a64c20892 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 29 Jun 2024 05:27:41 +0300 Subject: [PATCH] move project contents to main --- src/device.rs | 9 +-- src/device/launcher.rs | 137 ++++++++++++++--------------------------- src/main.rs | 59 +++++++++++++++--- src/prelude.rs | 1 + 4 files changed, 102 insertions(+), 104 deletions(-) diff --git a/src/device.rs b/src/device.rs index a584699a..2bed067c 100644 --- a/src/device.rs +++ b/src/device.rs @@ -10,14 +10,15 @@ mod sequencer; mod track; mod transport; +pub use self::track::Track; +pub use self::launcher::{Launcher, Scene}; +pub use self::sequencer::{Sequencer, Phrase}; pub use self::chain::Chain; -pub use self::launcher::Launcher; +pub use self::plugin::Plugin; + pub use self::looper::Looper; pub use self::mixer::Mixer; -pub use self::plugin::Plugin; pub use self::sampler::Sampler; -pub use self::sequencer::{Sequencer, Phrase}; -pub use self::track::Track; pub use self::transport::Transport; use crossterm::event; diff --git a/src/device/launcher.rs b/src/device/launcher.rs index 89fe2998..0490315c 100644 --- a/src/device/launcher.rs +++ b/src/device/launcher.rs @@ -42,65 +42,14 @@ impl Scene { } } impl Launcher { - pub fn new_with_controller ( - name: &str, - midi_in: &str, - audio_outs: &[&str], - ) - -> Result, Box> - { - let launcher = Self::new(name)?; - { - let state = &launcher.state(); - let (client, _status) = Client::new( - &format!("{name}-init"), - ClientOptions::NO_START_SERVER - )?; - let midi_ins = client.ports( - Some(midi_in), - None, - ::jack::PortFlags::IS_OUTPUT - ); - let audio_outs: Vec> = audio_outs - .iter() - .map(|pattern|client.ports( - Some(pattern), - None, - ::jack::PortFlags::IS_INPUT - )) - .collect(); - for (i, sequencer) in state.tracks.iter().enumerate() { - for sequencer_midi_in in sequencer.midi_ins()?.iter() { - for midi_in in midi_ins.iter() { - client.connect_ports_by_name( - &midi_in, - &sequencer_midi_in - )?; - } - } - let chain: &DynamicDevice = &state.tracks[i].chain; - for midi_out in sequencer.midi_outs()?.iter() { - for midi_in in chain.midi_ins()?.iter() { - client.connect_ports_by_name(&midi_out, &midi_in)?; - } - } - for (j, port) in chain.audio_outs()?.iter().enumerate() { - for audio_out in audio_outs[j % audio_outs.len()].iter() { - client.connect_ports_by_name(&port, &audio_out)?; - } - } - } - } - Ok(launcher) - } - pub fn new (name: &str,) -> Result, Box> { + pub fn new ( + name: &str, + timebase: &Arc, + tracks: Option>, + scenes: Option> + ) -> Result, Box> { let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?; let transport = client.transport(); - let timebase = Arc::new(Timebase { - rate: AtomicUsize::new(client.sample_rate()), - tempo: AtomicUsize::new(113000), - ppq: AtomicUsize::new(96), - }); let ppq = timebase.ppq() as u32; DynamicDevice::new(render, handle, process, Self { name: name.into(), @@ -112,47 +61,18 @@ impl Launcher { transport, cursor: (1, 1), position: 0, - scenes: vec![ - Scene::new(&"Scene#01", &[Some(0), None, None, None]), - Scene::new(&"Scene#02", &[Some(0), Some(0), 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]), - ], - tracks: vec![ - - Track::new("Kick", &timebase, Some(vec![ - //Sampler::new("Sampler")?.boxed(), - Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(), - ]), Some(vec![ - Phrase::new("HelloKick", ppq * 4, Some(BTreeMap::from([ + scenes: scenes.unwrap_or_else(||vec![Scene::new(&"Scene 1", &[None])]), + tracks: if let Some(tracks) = tracks { tracks } else { vec![ + Track::new("Track 1", &timebase, None, Some(vec![ + Phrase::new("MIDI Clip 1", ppq * 4, Some(BTreeMap::from([ ( ppq * 0, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), ( ppq * 1, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), ( ppq * 2, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), ( ppq * 3, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), ]))) ]))?, - - Track::new("Helm", &timebase, Some(vec![ - Plugin::lv2("Helm", "file:///home/user/.lv2/Helm.lv2", &[1, 0, 0, 2])?.boxed(), - ]), Some(vec![ - Phrase::new("HelloBass", ppq * 4, Some(BTreeMap::from([ - ( ppq / 2 + ppq * 0, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 1 / 2, vec![MidiMessage::NoteOff { key: 36.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 1, vec![MidiMessage::NoteOn { key: 39.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 3 / 2, vec![MidiMessage::NoteOff { key: 39.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 2, vec![MidiMessage::NoteOn { key: 41.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 5 / 2, vec![MidiMessage::NoteOff { key: 41.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 3, vec![MidiMessage::NoteOn { key: 42.into(), vel: 100.into() }] ), - ( ppq / 2 + ppq * 7 / 2 - 1, vec![MidiMessage::NoteOff { key: 42.into(), vel: 100.into() }] ), - ]))) - ]))?, - - //Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(), - //Plugin::lv2("Bass/Helm", "file:///home/user/.lv2/Helm.lv2", &[1, 0, 0, 2])?.boxed(), - //Plugin::lv2("Pads/Odin2", "file:///home/user/.lv2/Odin2.lv2", &[1, 0, 0, 2])?.boxed(), - ], - timebase, + ] }, + timebase: timebase.clone(), show_help: true }).activate(client) } @@ -211,6 +131,39 @@ impl Launcher { self.active_track().map(|t|t.chain.state()) } } +impl DynamicDevice { + pub fn connect (self, midi_in: &str, audio_outs: &[&str]) -> Usually { + { + let state = &self.state(); + let (client, _status) = Client::new( + &format!("{}-init", &state.name), ClientOptions::NO_START_SERVER + )?; + let midi_ins = client.ports(Some(midi_in), None, PortFlags::IS_OUTPUT); + let audio_outs: Vec> = audio_outs.iter() + .map(|pattern|client.ports(Some(pattern), None, PortFlags::IS_INPUT)) + .collect(); + for (i, sequencer) in state.tracks.iter().enumerate() { + for sequencer_midi_in in sequencer.midi_ins()?.iter() { + for midi_in in midi_ins.iter() { + client.connect_ports_by_name(&midi_in, &sequencer_midi_in)?; + } + } + let chain: &DynamicDevice = &state.tracks[i].chain; + for port in sequencer.midi_outs()?.iter() { + for midi_in in chain.midi_ins()?.iter() { + client.connect_ports_by_name(&port, &midi_in)?; + } + } + for (j, port) in chain.audio_outs()?.iter().enumerate() { + for audio_out in audio_outs[j % audio_outs.len()].iter() { + client.connect_ports_by_name(&port, &audio_out)?; + } + } + } + } + Ok(self) + } +} impl PortList for Launcher {} pub fn process (state: &mut Launcher, _: &Client, _: &ProcessScope) -> Control { let transport = state.transport.query().unwrap(); diff --git a/src/main.rs b/src/main.rs index 9c106899..430077a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,12 +20,55 @@ fn main () -> Result<(), Box> { let xdg = microxdg::XdgApp::new("tek")?; crate::config::create_dirs(&xdg)?; //run(Sampler::new("Sampler#000")?) - run(Launcher::new_with_controller( - "Launcher#0", - ".*nanoKEY.*", - &[ - "Komplete.*:playback_FL", - "Komplete.*:playback_FR", - ] - )?) + let input = ".*nanoKEY.*"; + let output = ["Komplete.*:playback_FL", "Komplete.*:playback_FR"]; + let (client, _) = Client::new("init", ClientOptions::NO_START_SERVER)?; + let timebase = Arc::new(Timebase { + rate: AtomicUsize::new(client.sample_rate()), + tempo: AtomicUsize::new(113000), + ppq: AtomicUsize::new(96), + }); + let ppq = timebase.ppq() as u32; + run(Launcher::new("Launcher#0", &timebase, + Some(vec![ + Track::new("Kick", &timebase, Some(vec![ + //Sampler::new("Sampler")?.boxed(), + Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(), + ]), Some(vec![ + Phrase::new("HelloKick", ppq * 4, Some(BTreeMap::from([ + ( ppq * 0, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), + ( ppq * 1, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), + ( ppq * 2, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), + ( ppq * 3, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), + ]))) + ]))?, + + Track::new("Helm", &timebase, Some(vec![ + Plugin::lv2("Helm", "file:///home/user/.lv2/Helm.lv2", &[1, 0, 0, 2])?.boxed(), + ]), Some(vec![ + Phrase::new("HelloBass", ppq * 4, Some(BTreeMap::from([ + ( ppq / 2 + ppq * 0, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 1 / 2, vec![MidiMessage::NoteOff { key: 36.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 1, vec![MidiMessage::NoteOn { key: 39.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 3 / 2, vec![MidiMessage::NoteOff { key: 39.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 2, vec![MidiMessage::NoteOn { key: 41.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 5 / 2, vec![MidiMessage::NoteOff { key: 41.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 3, vec![MidiMessage::NoteOn { key: 42.into(), vel: 100.into() }] ), + ( ppq / 2 + ppq * 7 / 2 - 1, vec![MidiMessage::NoteOff { key: 42.into(), vel: 100.into() }] ), + ]))) + ]))?, + + //Plugin::lv2("Kick/ChowKick", "file:///home/user/.lv2/ChowKick.lv2", &[1, 1, 0, 2])?.boxed(), + //Plugin::lv2("Bass/Helm", "file:///home/user/.lv2/Helm.lv2", &[1, 0, 0, 2])?.boxed(), + //Plugin::lv2("Pads/Odin2", "file:///home/user/.lv2/Odin2.lv2", &[1, 0, 0, 2])?.boxed(), + ]), + Some(vec![ + Scene::new(&"Scene#01", &[Some(0), None, None, None]), + Scene::new(&"Scene#02", &[Some(0), Some(0), 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]), + ]) + + )?.connect(input, &output)?) } diff --git a/src/prelude.rs b/src/prelude.rs index 8ad56a61..0a06d565 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -57,6 +57,7 @@ pub use jack::{ MidiOut, NotificationHandler, Port, + PortFlags, PortId, ProcessHandler, ProcessScope,