mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
156 lines
4.8 KiB
Rust
156 lines
4.8 KiB
Rust
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<String>,
|
|
/// Pulses per quarter note (arruencer resolution; default: 96)
|
|
#[arg(short, long)]
|
|
ppq: Option<usize>,
|
|
/// 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<E: Engine> {
|
|
/// Controls the JACK transport.
|
|
transport: Option<TransportToolbar<E>>,
|
|
/// Contains all the sequencers.
|
|
arranger: Arranger<E>,
|
|
/// This allows the sequencer view to be moved or hidden.
|
|
show_sequencer: Option<tek_core::Direction>,
|
|
///
|
|
focus: usize,
|
|
}
|
|
|
|
impl Content for ArrangerStandalone<Tui> {
|
|
type Engine = Tui;
|
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
|
let show = self.arranger.modal.is_some();
|
|
let modal = self.arranger.modal.as_ref().map(|x|x as &dyn Content<Engine = Tui>);
|
|
ModalHost(show, modal, Split::down(move|add|{
|
|
add(&(&self.transport as &dyn Widget<Engine = Tui>).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<Engine = Tui>)
|
|
.shrink_y(30)
|
|
.debug())?;
|
|
add(&(sequencer as &dyn Widget<Engine = Tui>)
|
|
.min_y(20)
|
|
.debug())?;
|
|
Ok(())
|
|
}))
|
|
} else {
|
|
add(&self.arranger)
|
|
}
|
|
}))
|
|
}
|
|
}
|
|
|
|
impl Handle<Tui> for ArrangerStandalone<Tui> {
|
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
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<Tui> {
|
|
fn focus (&self) -> usize {
|
|
self.focus
|
|
}
|
|
fn focus_mut (&mut self) -> &mut usize {
|
|
&mut self.focus
|
|
}
|
|
fn focusable (&self) -> [&dyn Focusable<Tui>;2] {
|
|
[
|
|
&self.transport as &dyn Focusable<Tui>,
|
|
&self.arranger as &dyn Focusable<Tui>,
|
|
]
|
|
}
|
|
fn focusable_mut (&mut self) -> [&mut dyn Focusable<Tui>;2] {
|
|
[
|
|
&mut self.transport as &mut dyn Focusable<Tui>,
|
|
&mut self.arranger as &mut dyn Focusable<Tui>,
|
|
]
|
|
}
|
|
}
|