mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
214 lines
9.6 KiB
Rust
214 lines
9.6 KiB
Rust
//#![feature(fn_traits)]
|
|
//#![feature(unboxed_closures)]
|
|
#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]
|
|
|
|
//#[global_allocator]
|
|
//static A: rlsf::SmallGlobalTlsf = rlsf::SmallGlobalTlsf::new();
|
|
|
|
extern crate clap;
|
|
extern crate jack as _jack;
|
|
extern crate crossterm;
|
|
|
|
pub mod cli;
|
|
pub mod config;
|
|
pub mod control;
|
|
pub mod core;
|
|
pub mod model;
|
|
pub mod view;
|
|
pub mod jack;
|
|
|
|
use crate::{core::*, model::*};
|
|
|
|
/// Application entrypoint.
|
|
pub fn main () -> Usually<()> {
|
|
let mut app = App::default();
|
|
|
|
// Load config
|
|
let xdg = Arc::new(microxdg::XdgApp::new("tek")?);
|
|
app.xdg = Some(xdg.clone());
|
|
if crate::config::AppPaths::new(&xdg)?.should_create() {
|
|
app.modal = Some(Box::new(crate::config::SetupModal(Some(xdg.clone()))));
|
|
}
|
|
let midi_from = ["nanoKEY Studio.*capture.*"];
|
|
let audio_into = ["Komplete.+:playback_FL", "Komplete.+:playback_FR"];
|
|
|
|
// Init
|
|
let ppq = app.timebase.ppq() as usize;
|
|
app.track_cursor = 1;
|
|
app.scene_cursor = 1;
|
|
app.note_start = 12;
|
|
app.time_zoom = 12;
|
|
app.quant = 24;
|
|
|
|
// Start main loop
|
|
app.run(Some(|app: Arc<RwLock<App>>|{
|
|
let mut state = app.write().unwrap();
|
|
|
|
// Start JACK and setup device graph
|
|
let jack = jack_run("tek", &app)?;
|
|
let client = jack.as_client();
|
|
state.transport = Some(client.transport());
|
|
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
|
|
|
|
let _ = midi_from
|
|
.iter()
|
|
.map(|name|client
|
|
.ports(Some(name), None, PortFlags::empty())
|
|
.iter()
|
|
.map(|name|{
|
|
if let Some(port) = client.port_by_name(name) {
|
|
client.connect_ports(&port, &state.midi_in.as_ref().unwrap())?;
|
|
}
|
|
Ok(())
|
|
})
|
|
.collect::<Usually<()>>())
|
|
.collect::<Usually<()>>()?;
|
|
|
|
let audio_outs: Vec<_> = audio_into
|
|
.iter()
|
|
.map(|name|client
|
|
.ports(Some(name), None, PortFlags::empty())
|
|
.get(0)
|
|
.map(|name|client.port_by_name(name)))
|
|
.flatten()
|
|
.collect();
|
|
|
|
state.jack = Some(jack);
|
|
|
|
state.add_track_with_cb(Some("Drums"), |_, track|{
|
|
|
|
track.add_device_with_cb(Sampler::new("Sampler", Some(BTreeMap::from([
|
|
sample!(34, "808", "/home/user/Lab/Music/pak/808.wav"),
|
|
sample!(35, "Kick1", "/home/user/Lab/Music/pak/kik.wav"),
|
|
sample!(36, "Kick2", "/home/user/Lab/Music/pak/kik2.wav"),
|
|
sample!(40, "Snare", "/home/user/Lab/Music/pak/sna.wav"),
|
|
sample!(44, "Hihat", "/home/user/Lab/Music/pak/chh.wav"),
|
|
])))?, |track, device|{
|
|
device.connect_midi_in(0, &track.midi_out.clone_unowned())?;
|
|
Ok(())
|
|
})?;
|
|
|
|
track.add_device_with_cb(Plugin::lv2(
|
|
"Panagement",
|
|
"file:///home/user/.lv2/Auburn Sounds Panagement 2.lv2"
|
|
)?, |track, device|{
|
|
device.connect_audio_in(0, &track.devices[0].audio_outs()?[0])?;
|
|
device.connect_audio_in(0, &track.devices[0].audio_outs()?[1])?;
|
|
if let Some(Some(left)) = audio_outs.get(0) {
|
|
device.connect_audio_out(0, left)?;
|
|
}
|
|
if let Some(Some(right)) = audio_outs.get(0) {
|
|
device.connect_audio_out(1, right)?;
|
|
}
|
|
Ok(())
|
|
})?;
|
|
|
|
track.sequence = Some(1); // FIXME
|
|
|
|
track.add_phrase("4 kicks", ppq * 4, Some(phrase! {
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
}));
|
|
track.add_phrase("5 kicks", ppq * 4, Some(phrase! {
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
14 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
}));
|
|
track.add_phrase("D-Beat", ppq * 4, Some(phrase! {
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
10 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
}));
|
|
track.add_phrase("Garage", ppq * 4, Some(phrase! {
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
01 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
02 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
03 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
06 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
07 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
09 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
10 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
14 * ppq/4 => MidiMessage::NoteOn { key: 44.into(), vel: 100.into() },
|
|
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
00 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() },
|
|
02 * ppq/4 => MidiMessage::NoteOn { key: 34.into(), vel: 100.into() },
|
|
07 * ppq/4 => MidiMessage::NoteOn { key: 34.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
11 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
|
|
11 * ppq/4 => MidiMessage::NoteOn { key: 35.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
}));
|
|
Ok(())
|
|
})?;
|
|
|
|
state.add_track_with_cb(Some("Bass"), |_, track|{
|
|
track.add_device_with_cb(Plugin::lv2(
|
|
"Odin2",
|
|
"file:///home/user/.lv2/Odin2.lv2"
|
|
)?, |track, device|{
|
|
device.connect_midi_in(0, &track.midi_out.clone_unowned())?;
|
|
if let Some(Some(left)) = audio_outs.get(0) {
|
|
device.connect_audio_out(0, left)?;
|
|
}
|
|
if let Some(Some(right)) = audio_outs.get(0) {
|
|
device.connect_audio_out(1, right)?;
|
|
}
|
|
Ok(())
|
|
})?;
|
|
track.sequence = Some(0); // FIXME
|
|
track.add_phrase("Custom", ppq * 4, None);
|
|
track.add_phrase("Offbeat", ppq * 4, Some(phrase! {
|
|
00 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
|
|
02 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
04 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
|
|
06 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
08 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
|
|
10 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
12 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
|
|
14 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
|
|
}));
|
|
Ok(())
|
|
})?;
|
|
|
|
state.add_track_with_cb(Some("Lead"), |_, track|{
|
|
//track.add_device_with_cb(Plugin::lv2(
|
|
//"Helm",
|
|
//"file:///home/user/.lv2/Helm.lv2"
|
|
//)?, |track, device|{
|
|
//device.connect_midi_in(0, &track.midi_out.clone_unowned())?;
|
|
//if let Some(Some(left)) = audio_outs.get(0) {
|
|
//device.connect_audio_out(0, left)?;
|
|
//}
|
|
//if let Some(Some(right)) = audio_outs.get(0) {
|
|
//device.connect_audio_out(1, right)?;
|
|
//}
|
|
//Ok(())
|
|
//})?;
|
|
track.sequence = Some(0); // FIXME
|
|
track.add_phrase("Custom", ppq * 4, None);
|
|
Ok(())
|
|
})?;
|
|
|
|
state.scenes = vec![
|
|
Scene::new("Intro", vec![None, Some(0), None, None]),
|
|
Scene::new("Hook", vec![Some(0), Some(1), None, None]),
|
|
Scene::new("Verse", vec![Some(2), Some(0), Some(0), None]),
|
|
Scene::new("Chorus", vec![Some(1), Some(1), None, None]),
|
|
Scene::new("Bridge", vec![Some(3), Some(0), Some(0), None]),
|
|
Scene::new("Outro", vec![None, Some(1), None, None]),
|
|
];
|
|
|
|
Ok(())
|
|
}))
|
|
|
|
}
|