include!("lib.rs"); use tek_core::clap::{self, Parser}; pub fn main () -> Usually<()> { ArrangerCli::parse().run() } #[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct ArrangerCli { /// Name of JACK client #[arg(short, long)] name: Option, /// Pulses per quarter note (arruencer resolution; default: 96) #[arg(short, long)] ppq: Option, /// Whether to include a transport toolbar (default: true) #[arg(short, long, default_value_t = true)] transport: bool, /// Number of tracks #[arg(short = 'x', long, default_value_t = 8)] tracks: usize, /// Number of scenes #[arg(short, long, default_value_t = 8)] scenes: usize, } impl ArrangerCli { fn run (&self) -> Usually<()> { let mut arranger = Arranger::new(""); let mut transport = self.transport.then_some(TransportToolbar::new(None)); if let Some(name) = self.name.as_ref() { *arranger.name.write().unwrap() = name.clone(); } for _ in 0..self.tracks { let track = arranger.track_add(None)?; for _ in 0..self.scenes { track.phrases.push( Arc::new(RwLock::new(Phrase::new("", 96 * 4, None))) ); } } for _ in 0..self.scenes { let _scene = arranger.scene_add(None)?; //for i in 0..self.tracks { //scene.clips[i] = Some(i); //} } transport.set_focused(true); Tui::run(Arc::new(RwLock::new(ArrangerStandalone { transport, show_sequencer: Some(tek_core::Direction::Down), arranger, focus: 0 })))?; Ok(()) } } struct ArrangerStandalone { /// Controls the JACK transport. transport: Option>, /// Contains all the sequencers. arranger: Arranger, /// This allows the sequencer view to be moved or hidden. show_sequencer: Option, /// focus: usize, } impl Content for ArrangerStandalone { type Engine = Tui; fn content (&self) -> impl Widget { let show = self.arranger.modal.is_some(); let modal = self.arranger.modal.as_ref().map(|x|x as &dyn Content); ModalHost(show, modal, Split::down(move|add|{ add(&(&self.transport as &dyn Widget).debug())?; if let (Some(direction), Some(sequencer)) = ( self.show_sequencer, self.arranger.sequencer(), ) { add(&Split::new(direction, move|add|{ add(&(&self.arranger as &dyn Widget) .shrink_y(30) .debug())?; add(&(sequencer as &dyn Widget) .min_y(20) .debug())?; Ok(()) })) } else { add(&self.arranger) } })) } } impl Handle for ArrangerStandalone { fn handle (&mut self, from: &TuiInput) -> Perhaps { match from.event() { key!(KeyCode::Char(' ')) => { if let Some(ref mut transport) = self.transport { transport.toggle_play()?; } else { return Ok(None) } }, key!(KeyCode::Tab) => { self.focus_next(); }, key!(KeyCode::BackTab) => { self.focus_prev(); }, key!(KeyCode::Down) => { if self.focus == 0 || ( self.focus == 1 && self.arranger.is_last_row() ) { self.focus_next(); } else { return self.focused_mut().handle(from) } }, key!(KeyCode::Up) => { if self.focus == 1 && self.arranger.is_first_row() { self.focus_prev(); } else { return self.focused_mut().handle(from) } }, _ => return self.focused_mut().handle(from) } Ok(Some(true)) } } impl Focus<2, Tui> for ArrangerStandalone { fn focus (&self) -> usize { self.focus } fn focus_mut (&mut self) -> &mut usize { &mut self.focus } fn focusable (&self) -> [&dyn Focusable;2] { [ &self.transport as &dyn Focusable, &self.arranger as &dyn Focusable, ] } fn focusable_mut (&mut self) -> [&mut dyn Focusable;2] { [ &mut self.transport as &mut dyn Focusable, &mut self.arranger as &mut dyn Focusable, ] } }