move project contents to main

This commit is contained in:
🪞👃🪞 2024-06-29 05:27:41 +03:00
parent 8a8d7b8704
commit 1b7892d11f
4 changed files with 102 additions and 104 deletions

View file

@ -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;

View file

@ -42,65 +42,14 @@ impl Scene {
}
}
impl Launcher {
pub fn new_with_controller (
name: &str,
midi_in: &str,
audio_outs: &[&str],
)
-> Result<DynamicDevice<Self>, Box<dyn Error>>
{
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<Vec<String>> = 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<Chain> = &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<DynamicDevice<Self>, Box<dyn Error>> {
pub fn new (
name: &str,
timebase: &Arc<Timebase>,
tracks: Option<Vec<Track>>,
scenes: Option<Vec<Scene>>
) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
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<Launcher> {
pub fn connect (self, midi_in: &str, audio_outs: &[&str]) -> Usually<Self> {
{
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<Vec<String>> = 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<Chain> = &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();

View file

@ -20,12 +20,55 @@ fn main () -> Result<(), Box<dyn Error>> {
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)?)
}

View file

@ -57,6 +57,7 @@ pub use jack::{
MidiOut,
NotificationHandler,
Port,
PortFlags,
PortId,
ProcessHandler,
ProcessScope,