mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-01-31 08:36:40 +01:00
feat: cli
This commit is contained in:
parent
b1074bd831
commit
204e26a324
2 changed files with 99 additions and 54 deletions
134
app/tek.rs
134
app/tek.rs
|
|
@ -145,6 +145,22 @@ pub mod model {
|
||||||
pub mod core {
|
pub mod core {
|
||||||
use super::{*, model::*, gui::*};
|
use super::{*, model::*, gui::*};
|
||||||
impl App {
|
impl App {
|
||||||
|
pub fn new (
|
||||||
|
jack: &Jack<'static>,
|
||||||
|
project: Arrangement,
|
||||||
|
config: Config,
|
||||||
|
mode: impl AsRef<str>
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
color: ItemTheme::random(),
|
||||||
|
dialog: Dialog::welcome(),
|
||||||
|
jack: jack.clone(),
|
||||||
|
mode: config.modes.clone().read().unwrap().get(mode.as_ref()).cloned().unwrap(),
|
||||||
|
config,
|
||||||
|
project,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn update_clock (&self) {
|
pub fn update_clock (&self) {
|
||||||
ViewCache::update_clock(&self.project.clock.view_cache, self.clock(), self.size.w() > 80)
|
ViewCache::update_clock(&self.project.clock.view_cache, self.clock(), self.size.w() > 80)
|
||||||
}
|
}
|
||||||
|
|
@ -847,7 +863,7 @@ pub mod glue {
|
||||||
}
|
}
|
||||||
/// Command-line configuration.
|
/// Command-line configuration.
|
||||||
#[cfg(feature = "cli")] pub mod cli {
|
#[cfg(feature = "cli")] pub mod cli {
|
||||||
use super::{*, model::*, gui::*};
|
use super::{*, model::*};
|
||||||
use clap::{self, Parser, Subcommand};
|
use clap::{self, Parser, Subcommand};
|
||||||
/// CLI banner.
|
/// CLI banner.
|
||||||
const HEADER: &'static str = r#"
|
const HEADER: &'static str = r#"
|
||||||
|
|
@ -866,7 +882,7 @@ pub mod glue {
|
||||||
/// Pre-defined configuration modes.
|
/// Pre-defined configuration modes.
|
||||||
///
|
///
|
||||||
/// TODO: Replace these with scripted configurations.
|
/// TODO: Replace these with scripted configurations.
|
||||||
#[command(subcommand)] mode: Option<LaunchMode>,
|
#[command(subcommand)] action: Action,
|
||||||
/// Name of JACK client
|
/// Name of JACK client
|
||||||
#[arg(short='n', long)] name: Option<String>,
|
#[arg(short='n', long)] name: Option<String>,
|
||||||
/// Whether to attempt to become transport master
|
/// Whether to attempt to become transport master
|
||||||
|
|
@ -895,10 +911,22 @@ pub mod glue {
|
||||||
#[arg(short='R', long)] right_to: Vec<String>,
|
#[arg(short='R', long)] right_to: Vec<String>,
|
||||||
}
|
}
|
||||||
/// Application modes
|
/// Application modes
|
||||||
#[derive(Debug, Clone, Subcommand)]
|
#[derive(Debug, Clone, Subcommand, Default)]
|
||||||
enum LaunchMode {
|
enum Action {
|
||||||
|
/// Continue where you left off
|
||||||
|
#[default] Resume,
|
||||||
|
/// Show version.
|
||||||
|
Version,
|
||||||
|
/// Show configuration.
|
||||||
|
Config,
|
||||||
|
/// Show status of current session.
|
||||||
|
Status,
|
||||||
|
/// Run headlessly in current session.
|
||||||
|
Headless,
|
||||||
/// Create a new session instead of loading the previous one.
|
/// Create a new session instead of loading the previous one.
|
||||||
New,
|
New,
|
||||||
|
/// Create new session from importable file.
|
||||||
|
Import,
|
||||||
}
|
}
|
||||||
impl Cli {
|
impl Cli {
|
||||||
fn midi_froms (&self) -> Vec<Connect> {
|
fn midi_froms (&self) -> Vec<Connect> {
|
||||||
|
|
@ -908,63 +936,61 @@ pub mod glue {
|
||||||
Connect::collect(&self.midi_to, &[] as &[&str], &self.midi_to_re)
|
Connect::collect(&self.midi_to, &[] as &[&str], &self.midi_to_re)
|
||||||
}
|
}
|
||||||
pub fn run (&self) -> Usually<()> {
|
pub fn run (&self) -> Usually<()> {
|
||||||
let name = self.name.as_ref().map_or("tek", |x|x.as_str());
|
if matches!(self.action, Action::Version) {
|
||||||
let tracks = vec![];
|
println!("todo version");
|
||||||
let scenes = vec![];
|
} else {
|
||||||
let empty = &[] as &[&str];
|
let mut config = Config::new(None);
|
||||||
let left_froms = Connect::collect(&self.left_from, empty, empty);
|
config.init()?;
|
||||||
let left_tos = Connect::collect(&self.left_to, empty, empty);
|
if matches!(self.action, Action::Config) {
|
||||||
let right_froms = Connect::collect(&self.right_from, empty, empty);
|
println!("{config:#?}");
|
||||||
let right_tos = Connect::collect(&self.right_to, empty, empty);
|
} else {
|
||||||
let _audio_froms = &[left_froms.as_slice(), right_froms.as_slice()];
|
let name = self.name.as_ref().map_or("tek", |x|x.as_str());
|
||||||
let _audio_tos = &[left_tos.as_slice(), right_tos.as_slice()];
|
let jack = Jack::new(&name)?;
|
||||||
let mut config = Config::new(None);
|
let tracks = vec![];
|
||||||
config.init()?;
|
let scenes = vec![];
|
||||||
Tui::new()?.run(&Jack::new_run(&name, move|jack|{
|
let empty = &[] as &[&str];
|
||||||
let midi_ins = {
|
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 midi_ins = vec![];
|
let mut midi_ins = vec![];
|
||||||
|
let mut midi_outs = vec![];
|
||||||
for (index, connect) in self.midi_froms().iter().enumerate() {
|
for (index, connect) in self.midi_froms().iter().enumerate() {
|
||||||
midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?);
|
midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?);
|
||||||
}
|
}
|
||||||
midi_ins
|
|
||||||
};
|
|
||||||
let midi_outs = {
|
|
||||||
let mut midi_outs = vec![];
|
|
||||||
for (index, connect) in self.midi_tos().iter().enumerate() {
|
for (index, connect) in self.midi_tos().iter().enumerate() {
|
||||||
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
||||||
};
|
};
|
||||||
midi_outs
|
let clock = Clock::new(&jack, self.bpm)?;
|
||||||
};
|
let project = Arrangement::new(
|
||||||
let project = Arrangement {
|
&jack, None, clock, tracks, scenes, midi_ins, midi_outs
|
||||||
name: Default::default(),
|
);
|
||||||
color: ItemTheme::random(),
|
if matches!(self.action, Action::Status) {
|
||||||
jack: jack.clone(),
|
println!("{project:?}");
|
||||||
clock: Clock::new(&jack, self.bpm)?,
|
// TODO git integration
|
||||||
tracks,
|
} else {
|
||||||
scenes,
|
let app = App::new(&jack, project, config, ":menu");
|
||||||
selection: Selection::TrackClip { track: 0, scene: 0 },
|
let client = jack.run(move|jack|{
|
||||||
midi_ins,
|
jack.sync_lead(self.sync_lead, |mut state|{
|
||||||
midi_outs,
|
let clock = app.clock();
|
||||||
..Default::default()
|
clock.playhead.update_from_sample(state.position.frame() as f64);
|
||||||
};
|
state.position.bbt = Some(clock.bbt());
|
||||||
let app = App {
|
state.position
|
||||||
jack: jack.clone(),
|
})?;
|
||||||
color: ItemTheme::random(),
|
jack.sync_follow(self.sync_follow)?;
|
||||||
dialog: Dialog::welcome(),
|
Ok(app)
|
||||||
mode: config.modes.clone().read().unwrap().get(":menu").cloned().unwrap(),
|
})?;
|
||||||
config,
|
if matches!(self.action, Action::Headless) {
|
||||||
project,
|
println!("todo headless");
|
||||||
..Default::default()
|
} else {
|
||||||
};
|
return Tui::new()?.run(&client)
|
||||||
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
|
Ok(())
|
||||||
})?;
|
|
||||||
jack.sync_follow(self.sync_follow)?;
|
|
||||||
Ok(app)
|
|
||||||
})?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,25 @@ impl Arrangement {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arrangement {
|
impl Arrangement {
|
||||||
|
/// Create a new arrangement.
|
||||||
|
pub fn new (
|
||||||
|
jack: &Jack<'static>,
|
||||||
|
name: Option<Arc<str>>,
|
||||||
|
clock: Clock,
|
||||||
|
tracks: Vec<Track>,
|
||||||
|
scenes: Vec<Scene>,
|
||||||
|
midi_ins: Vec<MidiInput>,
|
||||||
|
midi_outs: Vec<MidiOutput>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
clock, tracks, scenes, midi_ins, midi_outs,
|
||||||
|
jack: jack.clone(),
|
||||||
|
name: name.unwrap_or_default(),
|
||||||
|
color: ItemTheme::random(),
|
||||||
|
selection: Selection::TrackClip { track: 0, scene: 0 },
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Width of display
|
/// Width of display
|
||||||
pub fn w (&self) -> u16 {
|
pub fn w (&self) -> u16 {
|
||||||
self.size.w() as u16
|
self.size.w() as u16
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue