//#![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>|{ 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::>()) .collect::>()?; 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(()) })) }