mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
move project contents to main
This commit is contained in:
parent
8a8d7b8704
commit
1b7892d11f
4 changed files with 102 additions and 104 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
59
src/main.rs
59
src/main.rs
|
|
@ -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)?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ pub use jack::{
|
|||
MidiOut,
|
||||
NotificationHandler,
|
||||
Port,
|
||||
PortFlags,
|
||||
PortId,
|
||||
ProcessHandler,
|
||||
ProcessScope,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue