include!("lib.rs"); use tek_core::clap::{self, Parser}; pub fn main () -> Usually<()> { Tui::run(Arc::new(RwLock::new(crate::ArrangerStandalone::from_args()?)))?; Ok(()) } struct ArrangerStandalone { /// Contains all the sequencers. arranger: Arranger, /// Controls the JACK transport. transport: Option>, /// This allows the sequencer view to be moved or hidden. show_sequencer: Option, /// focus: usize, } #[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)] transport: Option, /// 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 ArrangerStandalone { pub fn from_args () -> Usually { let args = ArrangerCli::parse(); let mut arranger = Arranger::new(""); let mut transport = match args.transport { Some(true) => Some(TransportToolbar::new(None)), _ => None }; if let Some(name) = args.name { *arranger.name.write().unwrap() = name.clone(); } for _ in 0..args.tracks { let track = arranger.track_add(None)?; for _ in 0..args.scenes { track.phrases.push( Arc::new(RwLock::new(Phrase::new("", 96 * 4, None))) ); } } for _ in 0..args.scenes { let _scene = arranger.scene_add(None)?; //for i in 0..args.tracks { //scene.clips[i] = Some(i); //} } transport.set_focused(true); Ok(ArrangerStandalone { transport, show_sequencer: Some(tek_core::Direction::Down), arranger, focus: 0 }) } } impl Content for ArrangerStandalone { type Engine = Tui; fn content (&self) -> impl Widget { Split::down(|add|{ add(&self.transport)?; add(&self.arranger)?; if let Some(sequencer) = self.arranger.sequencer() { add(sequencer)?; } Ok(()) }) //if let Some(ref modal) = self.arranger.modal { //to.fill_bg(area, Nord::bg_lo(false, false)); //to.fill_fg(area, Nord::bg_hi(false, false)); //modal.render(to)?; //} } } 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, ] } }