pub(crate) use tek::*; pub(crate) use clap::{self, Parser, Subcommand}; /// Application entrypoint. pub fn main () -> Usually<()> { Cli::parse().run() } #[derive(Debug, Parser)] #[command(name = "tek", version, about = Some(HEADER), long_about = Some(HEADER))] pub struct Cli { /// Pre-defined configuration modes. /// /// TODO: Replace these with scripted configurations. #[command(subcommand)] mode: Option, /// Name of JACK client #[arg(short='n', long)] name: Option, /// Whether to attempt to become transport master #[arg(short='S', long, default_value_t = false)] sync_lead: bool, /// Whether to sync to external transport master #[arg(short='s', long, default_value_t = true)] sync_follow: bool, /// Initial tempo in beats per minute #[arg(short='b', long, default_value = None)] bpm: Option, /// Whether to include a transport toolbar (default: true) #[arg(short='t', long, default_value_t = true)] show_clock: bool, /// MIDI outs to connect to (multiple instances accepted) #[arg(short='I', long)] midi_from: Vec, /// MIDI outs to connect to (multiple instances accepted) #[arg(short='i', long)] midi_from_re: Vec, /// MIDI ins to connect to (multiple instances accepted) #[arg(short='O', long)] midi_to: Vec, /// MIDI ins to connect to (multiple instances accepted) #[arg(short='o', long)] midi_to_re: Vec, /// Audio outs to connect to left input #[arg(short='l', long)] left_from: Vec, /// Audio outs to connect to right input #[arg(short='r', long)] right_from: Vec, /// Audio ins to connect from left output #[arg(short='L', long)] left_to: Vec, /// Audio ins to connect from right output #[arg(short='R', long)] right_to: Vec, } /// Application modes #[derive(Debug, Clone, Subcommand)] pub enum LaunchMode { /// Create a new session instead of loading the previous one. New, } impl Cli { pub fn run (&self) -> Usually<()> { let name = self.name.as_ref().map_or("tek", |x|x.as_str()); let tracks = vec![]; let scenes = vec![]; let empty = &[] as &[&str]; let left_froms = Connect::collect(&self.left_from, empty, empty); let left_tos = Connect::collect(&self.left_to, empty, empty); let right_froms = Connect::collect(&self.right_from, empty, empty); let right_tos = Connect::collect(&self.right_to, empty, empty); let _audio_froms = &[left_froms.as_slice(), right_froms.as_slice()]; let _audio_tos = &[left_tos.as_slice(), right_tos.as_slice()]; let mut config = Config::new(None); config.init()?; Tui::new()?.run(&Jack::new_run(&name, move|jack|{ let app = App { jack: jack.clone(), color: ItemTheme::random(), dialog: Dialog::welcome(), mode: config.modes.clone().read().unwrap().get(":menu").cloned().unwrap(), config, project: Arrangement { name: Default::default(), color: ItemTheme::random(), jack: jack.clone(), clock: Clock::new(&jack, self.bpm)?, tracks, scenes, selection: Selection::TrackClip { track: 0, scene: 0 }, midi_ins: { let mut midi_ins = vec![]; for (index, connect) in self.midi_froms().iter().enumerate() { midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?); } midi_ins }, midi_outs: { let mut midi_outs = vec![]; for (index, connect) in self.midi_tos().iter().enumerate() { midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?); }; midi_outs }, ..Default::default() }, ..Default::default() }; jack.sync_lead(self.sync_lead, |mut state|{ let clock = app.clock(); clock.playhead.update_from_sample(state.position.frame() as f64); state.position.bbt = Some(clock.bbt()); state.position })?; jack.sync_follow(self.sync_follow)?; Ok(app) })?) } fn midi_froms (&self) -> Vec { Connect::collect(&self.midi_from, &[] as &[&str], &self.midi_from_re) } fn midi_tos (&self) -> Vec { Connect::collect(&self.midi_to, &[] as &[&str], &self.midi_to_re) } } /// CLI header const HEADER: &'static str = r#" ~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~ ~ ~ ~~ ~ ~ ~ ~~ ~ ~ ~ ~ ~~~~~~ ~ ~~~ ~~ ║ ~ ╟─╌ ~╟─< ~ v0.3.0, 2025 sum(m)er @ the nose of the cat. ~ ~~~ ╨ ~ ╙──╜ ╨ ╜ ~ ~~~ ~ ~ ~ ~ ~~~ ~~~ ~ ~~ ~~ ~~ ~ ~~ On first run, Tek will create configuration and state dirs: * [x] ~/.config/tek - config * [ ] ~/.local/share/tek - projects * [ ] ~/.local/lib/tek - plugins * [ ] ~/.cache/tek - cache ~"#; #[cfg(test)] #[test] fn test_cli () { use clap::CommandFactory; Cli::command().debug_assert(); //let jack = Jack::default(); }