mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-01-31 08:36:40 +01:00
feat: show project status
This commit is contained in:
parent
a8f0fbb897
commit
ac7fbdb779
1 changed files with 184 additions and 138 deletions
196
app/tek.rs
196
app/tek.rs
|
|
@ -883,16 +883,32 @@ pub mod glue {
|
||||||
///
|
///
|
||||||
/// TODO: Replace these with scripted configurations.
|
/// TODO: Replace these with scripted configurations.
|
||||||
#[command(subcommand)] action: Action,
|
#[command(subcommand)] action: Action,
|
||||||
|
}
|
||||||
|
/// Application modes
|
||||||
|
#[derive(Debug, Clone, Subcommand, Default)]
|
||||||
|
enum Action {
|
||||||
|
/// Continue where you left off
|
||||||
|
#[default] Resume,
|
||||||
|
/// Run headlessly in current session.
|
||||||
|
Headless,
|
||||||
|
/// Show status of current session.
|
||||||
|
Status,
|
||||||
|
/// List known sessions.
|
||||||
|
List,
|
||||||
|
/// Continue work in a copy of the current session.
|
||||||
|
Fork,
|
||||||
|
/// Create a new empty session.
|
||||||
|
New {
|
||||||
/// 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
|
||||||
#[arg(short='S', long, default_value_t = false)] sync_lead: bool,
|
#[arg(short='Y', long, default_value_t = false)] sync_lead: bool,
|
||||||
/// Whether to sync to external transport master
|
/// Whether to sync to external transport master
|
||||||
#[arg(short='s', long, default_value_t = true)] sync_follow: bool,
|
#[arg(short='y', long, default_value_t = true)] sync_follow: bool,
|
||||||
/// Initial tempo in beats per minute
|
/// Initial tempo in beats per minute
|
||||||
#[arg(short='b', long, default_value = None)] bpm: Option<f64>,
|
#[arg(short='b', long, default_value = None)] bpm: Option<f64>,
|
||||||
/// Whether to include a transport toolbar (default: true)
|
/// Whether to include a transport toolbar (default: true)
|
||||||
#[arg(short='t', long, default_value_t = true)] show_clock: bool,
|
#[arg(short='c', long, default_value_t = true)] show_clock: bool,
|
||||||
/// MIDI outs to connect to (multiple instances accepted)
|
/// MIDI outs to connect to (multiple instances accepted)
|
||||||
#[arg(short='I', long)] midi_from: Vec<String>,
|
#[arg(short='I', long)] midi_from: Vec<String>,
|
||||||
/// MIDI outs to connect to (multiple instances accepted)
|
/// MIDI outs to connect to (multiple instances accepted)
|
||||||
|
|
@ -909,39 +925,88 @@ pub mod glue {
|
||||||
#[arg(short='L', long)] left_to: Vec<String>,
|
#[arg(short='L', long)] left_to: Vec<String>,
|
||||||
/// Audio ins to connect from right output
|
/// Audio ins to connect from right output
|
||||||
#[arg(short='R', long)] right_to: Vec<String>,
|
#[arg(short='R', long)] right_to: Vec<String>,
|
||||||
}
|
/// Tracks to create
|
||||||
/// Application modes
|
#[arg(short='t', long)] tracks: Option<usize>,
|
||||||
#[derive(Debug, Clone, Subcommand, Default)]
|
/// Scenes to create
|
||||||
enum Action {
|
#[arg(short='s', long)] scenes: Option<usize>,
|
||||||
/// Continue where you left off
|
},
|
||||||
#[default] Resume,
|
/// Import media as new session.
|
||||||
/// Show version.
|
Import,
|
||||||
Version,
|
|
||||||
/// Show configuration.
|
/// Show configuration.
|
||||||
Config,
|
Config,
|
||||||
/// Show status of current session.
|
/// Show version.
|
||||||
Status,
|
Version,
|
||||||
/// Run headlessly in current session.
|
|
||||||
Headless,
|
|
||||||
/// Create a new session instead of loading the previous one.
|
|
||||||
New,
|
|
||||||
/// Create new session from importable file.
|
|
||||||
Import,
|
|
||||||
}
|
}
|
||||||
impl Cli {
|
impl Cli {
|
||||||
fn midi_froms (&self) -> Vec<Connect> {
|
|
||||||
Connect::collect(&self.midi_from, &[] as &[&str], &self.midi_from_re)
|
|
||||||
}
|
|
||||||
fn midi_tos (&self) -> Vec<Connect> {
|
|
||||||
Connect::collect(&self.midi_to, &[] as &[&str], &self.midi_to_re)
|
|
||||||
}
|
|
||||||
pub fn run (&self) -> Usually<()> {
|
pub fn run (&self) -> Usually<()> {
|
||||||
if matches!(self.action, Action::Version) {
|
if let Action::Version = self.action {
|
||||||
println!("todo version");
|
return Ok(self.show_version())
|
||||||
} else {
|
}
|
||||||
let mut config = Config::new(None);
|
let mut config = Config::new(None);
|
||||||
config.init()?;
|
config.init()?;
|
||||||
if matches!(self.action, Action::Config) {
|
if let Action::Config = self.action {
|
||||||
|
self.show_config(&config);
|
||||||
|
} else if let Action::List = self.action {
|
||||||
|
todo!("list sessions")
|
||||||
|
} else if let Action::Resume = self.action {
|
||||||
|
todo!("resume session")
|
||||||
|
} else if let Action::New {
|
||||||
|
name, bpm, tracks, scenes, sync_lead, sync_follow,
|
||||||
|
midi_from, midi_from_re, midi_to, midi_to_re,
|
||||||
|
left_from, right_from, left_to, right_to, ..
|
||||||
|
} = &self.action {
|
||||||
|
let name = name.as_ref().map_or("tek", |x|x.as_str());
|
||||||
|
let jack = Jack::new(&name)?;
|
||||||
|
let empty = &[] as &[&str];
|
||||||
|
let left_froms = Connect::collect(&left_from, empty, empty);
|
||||||
|
let left_tos = Connect::collect(&left_to, empty, empty);
|
||||||
|
let right_froms = Connect::collect(&right_from, empty, empty);
|
||||||
|
let right_tos = Connect::collect(&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_outs = vec![];
|
||||||
|
for (index, connect) in Connect::collect(&midi_from, &[] as &[&str], &midi_from_re).iter().enumerate() {
|
||||||
|
midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?);
|
||||||
|
}
|
||||||
|
for (index, connect) in Connect::collect(&midi_to, &[] as &[&str], &midi_to_re).iter().enumerate() {
|
||||||
|
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
||||||
|
};
|
||||||
|
let clock = Clock::new(
|
||||||
|
&jack, *bpm
|
||||||
|
)?;
|
||||||
|
let mut project = Arrangement::new(
|
||||||
|
&jack, None, clock, vec![], vec![], midi_ins, midi_outs
|
||||||
|
);
|
||||||
|
project.tracks_add(tracks.unwrap_or(0), None, &[], &[])?;
|
||||||
|
project.scenes_add(scenes.unwrap_or(0))?;
|
||||||
|
if matches!(self.action, Action::Status) {
|
||||||
|
self.show_status(&project);
|
||||||
|
} else {
|
||||||
|
let app = App::new(&jack, project, config, ":menu");
|
||||||
|
let client = jack.run(move|jack|{
|
||||||
|
jack.sync_lead(*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(*sync_follow)?;
|
||||||
|
Ok(app)
|
||||||
|
})?;
|
||||||
|
if matches!(self.action, Action::Headless) {
|
||||||
|
println!("todo headless");
|
||||||
|
} else {
|
||||||
|
return Tui::new()?.run(&client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn show_version (&self) {
|
||||||
|
println!("todo version");
|
||||||
|
}
|
||||||
|
fn show_config (&self, config: &Config) {
|
||||||
use ::ansi_term::Color::*;
|
use ::ansi_term::Color::*;
|
||||||
println!("{:?}", config.dirs);
|
println!("{:?}", config.dirs);
|
||||||
for (k, v) in config.views.read().unwrap().iter() {
|
for (k, v) in config.views.read().unwrap().iter() {
|
||||||
|
|
@ -991,54 +1056,35 @@ pub mod glue {
|
||||||
v.keys);
|
v.keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let name = self.name.as_ref().map_or("tek", |x|x.as_str());
|
|
||||||
let jack = Jack::new(&name)?;
|
|
||||||
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 midi_ins = vec![];
|
|
||||||
let mut midi_outs = vec![];
|
|
||||||
for (index, connect) in self.midi_froms().iter().enumerate() {
|
|
||||||
midi_ins.push(jack.midi_in(&format!("M/{index}"), &[connect.clone()])?);
|
|
||||||
}
|
}
|
||||||
for (index, connect) in self.midi_tos().iter().enumerate() {
|
fn show_status (&self, project: &Arrangement) {
|
||||||
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
println!("Name: {:?}", &project.name);
|
||||||
};
|
println!("JACK: {:?}", &project.jack);
|
||||||
let clock = Clock::new(&jack, self.bpm)?;
|
println!("Buffer: {:?}", &project.clock.chunk);
|
||||||
let project = Arrangement::new(
|
println!("Sample rate: {:?}", &project.clock.timebase.sr);
|
||||||
&jack, None, clock, tracks, scenes, midi_ins, midi_outs
|
println!("MIDI PPQ: {:?}", &project.clock.timebase.ppq);
|
||||||
);
|
println!("Tempo: {:?}", &project.clock.timebase.bpm);
|
||||||
if matches!(self.action, Action::Status) {
|
println!("Quantize: {:?}", &project.clock.quant);
|
||||||
println!("{project:?}");
|
println!("Launch: {:?}", &project.clock.sync);
|
||||||
|
println!("Playhead: {:?}us", &project.clock.playhead.usec);
|
||||||
|
println!("Playhead: {:?}s", &project.clock.playhead.sample);
|
||||||
|
println!("Playhead: {:?}p", &project.clock.playhead.pulse);
|
||||||
|
println!("Started: {:?}", &project.clock.started);
|
||||||
|
println!("Tracks:");
|
||||||
|
for (i, t) in project.tracks.iter().enumerate() {
|
||||||
|
println!(" Track {i}: {} {} {:?} {:?}", t.name, t.width,
|
||||||
|
&t.sequencer.play_clip, &t.sequencer.next_clip);
|
||||||
|
}
|
||||||
|
println!("Scenes:");
|
||||||
|
for (i, t) in project.scenes.iter().enumerate() {
|
||||||
|
println!(" Scene {i}: {} {:?}", &t.name, &t.clips);
|
||||||
|
}
|
||||||
|
println!("MIDI Ins: {:?}", &project.midi_ins);
|
||||||
|
println!("MIDI Outs: {:?}", &project.midi_outs);
|
||||||
|
println!("Audio Ins: {:?}", &project.audio_ins);
|
||||||
|
println!("Audio Outs: {:?}", &project.audio_outs);
|
||||||
// TODO git integration
|
// TODO git integration
|
||||||
} else {
|
// TODO dawvert integration
|
||||||
let app = App::new(&jack, project, config, ":menu");
|
|
||||||
let client = jack.run(move|jack|{
|
|
||||||
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)
|
|
||||||
})?;
|
|
||||||
if matches!(self.action, Action::Headless) {
|
|
||||||
println!("todo headless");
|
|
||||||
} else {
|
|
||||||
return Tui::new()?.run(&client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue