mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-09-18 12:56:42 +02:00
This commit is contained in:
parent
68236a7210
commit
ae496987c8
7 changed files with 458 additions and 172 deletions
|
|
@ -1,6 +1,17 @@
|
|||
use crate::*;
|
||||
|
||||
def_command!(FileBrowserCommand: |sampler: Sampler|{
|
||||
impl App {
|
||||
/// Return reference to content browser if open.
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(tek::App::default().browser(), None);
|
||||
/// ```
|
||||
pub fn browser (&self) -> Option<&Browse> {
|
||||
if let Dialog::Browse(_, ref b) = self.dialog { Some(b) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
def_command!(FileBrowserCommand: |_browse: Browse|{
|
||||
//("begin" [] Some(Self::Begin))
|
||||
//("cancel" [] Some(Self::Cancel))
|
||||
//("confirm" [] Some(Self::Confirm))
|
||||
|
|
@ -539,3 +550,20 @@ def_command!(CropCommand: |pool: Pool| {
|
|||
Ok(None)
|
||||
}
|
||||
});
|
||||
|
||||
pub fn scan (dir: &PathBuf) -> Usually<(Vec<OsString>, Vec<OsString>)> {
|
||||
let (mut subdirs, mut files) = std::fs::read_dir(dir)?
|
||||
.fold((vec!["..".into()], vec![]), |(mut subdirs, mut files), entry|{
|
||||
let entry = entry.expect("failed to read drectory entry");
|
||||
let meta = entry.metadata().expect("failed to read entry metadata");
|
||||
if meta.is_file() {
|
||||
files.push(entry.file_name());
|
||||
} else if meta.is_dir() {
|
||||
subdirs.push(entry.file_name());
|
||||
}
|
||||
(subdirs, files)
|
||||
});
|
||||
subdirs.sort();
|
||||
files.sort();
|
||||
Ok((subdirs, files))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ pub fn draw_dialog (
|
|||
}
|
||||
|
||||
impl App {
|
||||
|
||||
pub fn get_dialog (&self, src: impl Language) -> Perhaps<Dialog> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":dialog/none" => Dialog::None,
|
||||
|
|
@ -64,31 +65,36 @@ impl App {
|
|||
)
|
||||
})).transpose()
|
||||
}
|
||||
/// Set modal dialog.
|
||||
|
||||
/// Set currently active modal dialog.
|
||||
///
|
||||
/// ```
|
||||
/// let previous: tek::Dialog = tek::App::default().set_dialog(tek::Dialog::welcome());
|
||||
/// let previous: tek::Dialog = tek::App::default().set_dialog(&tek::Dialog::welcome());
|
||||
/// ```
|
||||
pub fn set_dialog (&mut self, mut dialog: Dialog) -> Dialog {
|
||||
pub fn set_dialog (&mut self, dialog: &Dialog) -> Dialog {
|
||||
let mut dialog = dialog.clone();
|
||||
std::mem::swap(&mut self.dialog, &mut dialog);
|
||||
dialog
|
||||
}
|
||||
|
||||
pub fn inc (&mut self, axis: &ControlAxis) -> Perhaps<AppCommand> {
|
||||
Ok(match (&self.dialog, axis) {
|
||||
(Dialog::None, _) => todo!(),
|
||||
(Dialog::Menu(_, _), ControlAxis::Y) =>
|
||||
AppCommand::SetDialog { dialog: self.dialog.menu_next() }.act(self)?,
|
||||
AppCommand::SetDialog(self.dialog.menu_next()).act(self)?,
|
||||
_ => todo!()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dec (&mut self, axis: &ControlAxis) -> Perhaps<AppCommand> {
|
||||
Ok(match (&self.dialog, axis) {
|
||||
(Dialog::None, _) => None,
|
||||
(Dialog::Menu(_, _), ControlAxis::Y) =>
|
||||
AppCommand::SetDialog { dialog: self.dialog.menu_prev() }.act(self)?,
|
||||
AppCommand::SetDialog(self.dialog.menu_prev()).act(self)?,
|
||||
_ => todo!()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn confirm (&mut self) -> Perhaps<AppCommand> {
|
||||
Ok(match &self.dialog {
|
||||
Dialog::Menu(index, items) => {
|
||||
|
|
|
|||
371
src/tek.rs
371
src/tek.rs
|
|
@ -218,14 +218,26 @@ fn run_new_plain (config: Config) -> Usually<()> {
|
|||
Clock::new(&jack, *bpm)?,
|
||||
[].into_iter(),
|
||||
[].into_iter(),
|
||||
connect_midi_ins(&jack, &"M".to_string(), midi_from.as_ref(), Some(midi_from_re))?.into_iter(),
|
||||
connect_midi_outs(&jack, &"M".to_string(), midi_to.as_ref(), Some(midi_to_re))?.into_iter(),
|
||||
connect_midi_ins(
|
||||
&jack, &"M".to_string(), midi_from.as_ref(), Some(midi_from_re)
|
||||
)?.into_iter(),
|
||||
connect_midi_outs(
|
||||
&jack, &"M".to_string(), midi_to.as_ref(), Some(midi_to_re)
|
||||
)?.into_iter(),
|
||||
[].into_iter()
|
||||
.chain(connect_audio_ins(&jack, &"L".to_string(), &left_from, None)?.into_iter())
|
||||
.chain(connect_audio_ins(&jack, &"R".to_string(), &right_from, None)?.into_iter()),
|
||||
.chain(
|
||||
connect_audio_ins(&jack, &"L".to_string(), &left_from, None)?.into_iter()
|
||||
)
|
||||
.chain(
|
||||
connect_audio_ins(&jack, &"R".to_string(), &right_from, None)?.into_iter()
|
||||
),
|
||||
[].into_iter()
|
||||
.chain(connect_audio_outs(&jack, &"L".to_string(), &left_to, None)?.into_iter())
|
||||
.chain(connect_audio_outs(&jack, &"R".to_string(), &right_to, None)?.into_iter()));
|
||||
.chain(
|
||||
connect_audio_outs(&jack, &"L".to_string(), &left_to, None)?.into_iter()
|
||||
)
|
||||
.chain(
|
||||
connect_audio_outs(&jack, &"R".to_string(), &right_to, None)?.into_iter()
|
||||
));
|
||||
//&jack, Clock::new(&jack, *bpm)?, &lf, <, &rf, &rt, &mf, &mt, &mfr, &mtr)?;
|
||||
proj.tracks_add(tracks.unwrap_or(0), None, &[], &[])?;
|
||||
proj.scenes_add(scenes.unwrap_or(0))?;
|
||||
|
|
@ -476,12 +488,13 @@ mod config {
|
|||
let tail = expr.tail()?;
|
||||
let name = tail.head()?;
|
||||
let body = tail.tail()?;
|
||||
//println!("Config::load: {} {} {}", head.unwrap_or_default(), name.unwrap_or_default(), body.unwrap_or_default());
|
||||
match head {
|
||||
Some("mode") if let Some(name) = name => self.modes.add(&name, &body)?,
|
||||
Some("keys") if let Some(name) = name => load_bind(&self.binds, &name, &body)?,
|
||||
Some("view") if let Some(name) = name => load_view(&self.views, &name, &body)?,
|
||||
_ => return Err(format!("Config::load: expected view/keys/mode, got: {item:?}").into())
|
||||
_ => return Err(
|
||||
format!("Config::load: expected view/keys/mode, got: {item:?}").into()
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
|
|
@ -713,6 +726,7 @@ mod app {
|
|||
/// Error, if any
|
||||
pub error: Arc<RwLock<Option<Arc<str>>>>
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Create a new application instance from a backend, project, config, and mode
|
||||
///
|
||||
|
|
@ -856,55 +870,32 @@ mod app {
|
|||
})).transpose()
|
||||
}
|
||||
|
||||
/// FIXME: generalize. Set picked device in device pick dialog.
|
||||
///
|
||||
/// ```
|
||||
/// tek::App::default().device_pick(0);
|
||||
/// ```
|
||||
pub fn device_pick (&mut self, index: usize) {
|
||||
self.dialog = Dialog::Device(index);
|
||||
}
|
||||
|
||||
/// FIXME: generalize. Add device to current track.
|
||||
pub fn add_device (&mut self, index: usize) -> Usually<()> {
|
||||
match index {
|
||||
0 => {
|
||||
let name = self.jack.with_client(|c|c.name().to_string());
|
||||
let midi = self.project.track().expect("no active track").sequencer.midi_outs[0].port_name();
|
||||
let track = self.track().expect("no active track");
|
||||
let port = format!("{}/Sampler", &track.name);
|
||||
let connect = Connect::exact(format!("{name}:{midi}"));
|
||||
let sampler = if let Ok(sampler) = Sampler::new(
|
||||
&self.jack, &port, &[connect], &[&[], &[]], &[&[], &[]]
|
||||
) {
|
||||
self.dialog = Dialog::None;
|
||||
Device::Sampler(sampler)
|
||||
} else {
|
||||
self.dialog = Dialog::Message("Failed to add device.".into());
|
||||
return Err("failed to add device".into())
|
||||
};
|
||||
let track = self.track_mut().expect("no active track");
|
||||
track.devices.push(sampler);
|
||||
Ok(())
|
||||
},
|
||||
1 => {
|
||||
todo!();
|
||||
//Ok(())
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return reference to content browser if open.
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(tek::App::default().browser(), None);
|
||||
/// ```
|
||||
pub fn browser (&self) -> Option<&Browse> {
|
||||
if let Dialog::Browse(_, ref b) = self.dialog { Some(b) } else { None }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::bind::*;
|
||||
mod bind {
|
||||
use crate::*;
|
||||
|
||||
/// Define an enum containing commands, and implement [Command] trait for over given `State`.
|
||||
#[macro_export] macro_rules! def_command (
|
||||
($Command:ident: |$state:ident: $State:ty| {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant:ident$({$($arg:ident:$Arg:ty),+ $(,)?})?=>$body:expr),* $(,)?
|
||||
})=>{
|
||||
#[derive(Debug)] pub enum $Command {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant $({ $($arg: $Arg),* })?),*
|
||||
}
|
||||
impl ::tengri::dizzle::Act<$State> for $Command {
|
||||
fn act (&self, $state: &mut $State) -> Perhaps<Self> {
|
||||
match self {
|
||||
$(Self::$Variant $({ $($arg),* })? => $body,)*
|
||||
_ => unimplemented!("Act<{}>: {self:?}", stringify!($State)),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pub fn swap_value <T: Clone + PartialEq, U> (
|
||||
target: &mut T, value: &T, returned: impl Fn(T)->U
|
||||
|
|
@ -930,23 +921,6 @@ mod app {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn scan (dir: &PathBuf) -> Usually<(Vec<OsString>, Vec<OsString>)> {
|
||||
let (mut subdirs, mut files) = std::fs::read_dir(dir)?
|
||||
.fold((vec!["..".into()], vec![]), |(mut subdirs, mut files), entry|{
|
||||
let entry = entry.expect("failed to read drectory entry");
|
||||
let meta = entry.metadata().expect("failed to read entry metadata");
|
||||
if meta.is_file() {
|
||||
files.push(entry.file_name());
|
||||
} else if meta.is_dir() {
|
||||
subdirs.push(entry.file_name());
|
||||
}
|
||||
(subdirs, files)
|
||||
});
|
||||
subdirs.sort();
|
||||
files.sort();
|
||||
Ok((subdirs, files))
|
||||
}
|
||||
|
||||
tui_keys!(self: App, input {
|
||||
let commands = tek_commands_collect(self, input)?;
|
||||
let results = tek_commands_execute(self, commands)?;
|
||||
|
|
@ -1072,30 +1046,58 @@ mod app {
|
|||
|
||||
impl_debug!(Condition |self, w| { write!(w, "*") });
|
||||
|
||||
impl_default!(AppCommand: Self::Nop);
|
||||
#[tek_proc::command(App)]
|
||||
#[tek_proc::keyword(App)]
|
||||
#[derive(Debug, Default)]
|
||||
pub enum AppCommand {
|
||||
#[default]
|
||||
#[command(App::nop)]
|
||||
#[keyword("nop")]
|
||||
Nop,
|
||||
|
||||
def_command!(AppCommand: |app: App| {
|
||||
Nop => Ok(None),
|
||||
Cancel => todo!(), // TODO delegate:
|
||||
Confirm => app.confirm(),
|
||||
Inc { axis: ControlAxis } => app.inc(axis),
|
||||
Dec { axis: ControlAxis } => app.dec(axis),
|
||||
SetDialog { dialog: Dialog } => {
|
||||
swap_value(&mut app.dialog, dialog, |dialog|Self::SetDialog { dialog })
|
||||
},
|
||||
});
|
||||
#[command(App::cancel)]
|
||||
#[keyword("cancel")]
|
||||
Cancel,
|
||||
|
||||
impl<'a> Namespace<'a, AppCommand> for App {
|
||||
symbols!('a |app| -> AppCommand {
|
||||
"x/inc" => AppCommand::Inc { axis: ControlAxis::X },
|
||||
"x/dec" => AppCommand::Dec { axis: ControlAxis::X },
|
||||
"y/inc" => AppCommand::Inc { axis: ControlAxis::Y },
|
||||
"y/dec" => AppCommand::Dec { axis: ControlAxis::Y },
|
||||
"confirm" => AppCommand::Confirm,
|
||||
"cancel" => AppCommand::Cancel,
|
||||
});
|
||||
#[command(App::confirm)]
|
||||
#[keyword("confirm")]
|
||||
Confirm,
|
||||
|
||||
#[command(App::inc)]
|
||||
#[keyword("x/inc", ControlAxis::X)]
|
||||
#[keyword("y/inc", ControlAxis::Y)]
|
||||
Inc(ControlAxis),
|
||||
|
||||
#[command(App::dec)]
|
||||
#[keyword("x/dec", ControlAxis::X)]
|
||||
#[keyword("y/dec", ControlAxis::Y)]
|
||||
Dec(ControlAxis),
|
||||
|
||||
#[command(App::set_dialog | Self::SetDialog)]
|
||||
#[keyword("dialog")]
|
||||
SetDialog(Dialog),
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn nop (&mut self) -> Perhaps<AppCommand> {
|
||||
Ok(None)
|
||||
}
|
||||
fn cancel (&mut self) -> Perhaps<AppCommand> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
//impl<'a> Namespace<'a, AppCommand> for App {
|
||||
//symbols!('a |app| -> AppCommand {
|
||||
//"x/inc" => AppCommand::Inc { axis: ControlAxis::X },
|
||||
//"x/dec" => AppCommand::Dec { axis: ControlAxis::X },
|
||||
//"y/inc" => AppCommand::Inc { axis: ControlAxis::Y },
|
||||
//"y/dec" => AppCommand::Dec { axis: ControlAxis::Y },
|
||||
//"confirm" => AppCommand::Confirm,
|
||||
//"cancel" => AppCommand::Cancel,
|
||||
//});
|
||||
//}
|
||||
|
||||
/// A control axis.
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1107,6 +1109,52 @@ mod app {
|
|||
|
||||
//take!(DeviceCommand|state: Arrangement, iter|state.selected_device().as_ref()
|
||||
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||
}
|
||||
|
||||
pub use self::device::*;
|
||||
mod device {
|
||||
use crate::*;
|
||||
|
||||
impl App {
|
||||
/// FIXME: generalize. Set picked device in device pick dialog.
|
||||
///
|
||||
/// ```
|
||||
/// tek::App::default().device_pick(0);
|
||||
/// ```
|
||||
pub fn device_pick (&mut self, index: usize) {
|
||||
self.dialog = Dialog::Device(index);
|
||||
}
|
||||
|
||||
/// FIXME: generalize. Add device to current track.
|
||||
pub fn add_device (&mut self, index: usize) -> Usually<()> {
|
||||
match index {
|
||||
0 => {
|
||||
let name = self.jack.with_client(|c|c.name().to_string());
|
||||
let midi = self.project.track().expect("no active track").sequencer.midi_outs[0].port_name();
|
||||
let track = self.track().expect("no active track");
|
||||
let port = format!("{}/Sampler", &track.name);
|
||||
let connect = Connect::exact(format!("{name}:{midi}"));
|
||||
let sampler = if let Ok(sampler) = Sampler::new(
|
||||
&self.jack, &port, &[connect], &[&[], &[]], &[&[], &[]]
|
||||
) {
|
||||
self.dialog = Dialog::None;
|
||||
Device::Sampler(sampler)
|
||||
} else {
|
||||
self.dialog = Dialog::Message("Failed to add device.".into());
|
||||
return Err("failed to add device".into())
|
||||
};
|
||||
let track = self.track_mut().expect("no active track");
|
||||
track.devices.push(sampler);
|
||||
Ok(())
|
||||
},
|
||||
1 => {
|
||||
todo!();
|
||||
//Ok(())
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasJack<'static> for App { fn jack (&self) -> &Jack<'static> { &self.jack } }
|
||||
|
||||
|
|
@ -1158,12 +1206,12 @@ mod app {
|
|||
_ => { panic!("{event:?}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::device::*;
|
||||
mod device {
|
||||
use crate::*;
|
||||
def_command!(DeviceCommand: |device: Device| {});
|
||||
#[tek_proc::command(Device)]
|
||||
#[tek_proc::keyword(Device)]
|
||||
#[derive(Debug)]
|
||||
pub enum DeviceCommand {}
|
||||
|
||||
impl Device {
|
||||
pub fn name (&self) -> &str {
|
||||
match self {
|
||||
|
|
@ -1196,6 +1244,7 @@ mod device {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A device that can be plugged into the chain.
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1274,26 +1323,6 @@ mod device {
|
|||
#[cfg(feature = "plugin")] pub mod plugin;
|
||||
#[cfg(feature = "plugin")] pub use self::plugin::*;
|
||||
|
||||
def_command!(AudioInputCommand: |port: AudioInput| {
|
||||
Close => todo!(),
|
||||
Connect { audio_out: Arc<str> } => todo!(),
|
||||
});
|
||||
|
||||
def_command!(AudioOutputCommand: |port: AudioOutput| {
|
||||
Close => todo!(),
|
||||
Connect { audio_in: Arc<str> } => todo!(),
|
||||
});
|
||||
|
||||
def_command!(MidiInputCommand: |port: MidiInput| {
|
||||
Close => todo!(),
|
||||
Connect { midi_out: Arc<str> } => todo!(),
|
||||
});
|
||||
|
||||
def_command!(MidiOutputCommand: |port: MidiOutput| {
|
||||
Close => todo!(),
|
||||
Connect { midi_in: Arc<str> } => todo!(),
|
||||
});
|
||||
|
||||
pub struct Junction<T: JackPort>(T);
|
||||
|
||||
impl<T: JackPort> View<Tui> for Junction<T> {
|
||||
|
|
@ -1301,36 +1330,38 @@ mod device {
|
|||
T::KIND
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_status (project: &Arrangement) {
|
||||
println!("Name: {:?}", &project.name);
|
||||
println!("JACK: {:?}", &project.jack);
|
||||
println!("Buffer: {:?}", &project.clock.chunk);
|
||||
println!("Sample rate: {:?}", &project.clock.timebase.sr);
|
||||
println!("MIDI PPQ: {:?}", &project.clock.timebase.ppq);
|
||||
println!("Tempo: {:?}", &project.clock.timebase.bpm);
|
||||
println!("Quantize: {:?}", &project.clock.quant);
|
||||
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);
|
||||
#[tek_proc::command(AudioInput)]
|
||||
#[tek_proc::keyword(AudioInput)]
|
||||
#[derive(Debug)]
|
||||
pub enum AudioInputCommand {
|
||||
Close,
|
||||
Connect(Arc<str>),
|
||||
}
|
||||
println!("Scenes:");
|
||||
for (i, t) in project.scenes.iter().enumerate() {
|
||||
println!(" Scene {i}: {} {:?}", &t.name, &t.clips);
|
||||
|
||||
#[tek_proc::command(AudioOutput)]
|
||||
#[tek_proc::keyword(AudioOutput)]
|
||||
#[derive(Debug)]
|
||||
pub enum AudioOutputCommand {
|
||||
Close,
|
||||
Connect(Arc<str>),
|
||||
}
|
||||
|
||||
#[tek_proc::command(MidiInput)]
|
||||
#[tek_proc::keyword(MidiInput)]
|
||||
#[derive(Debug)]
|
||||
pub enum MidiInputCommand {
|
||||
Close,
|
||||
Connect(Arc<str>),
|
||||
}
|
||||
|
||||
#[tek_proc::command(MidiOutput)]
|
||||
#[tek_proc::keyword(MidiOutput)]
|
||||
#[derive(Debug)]
|
||||
pub enum MidiOutputCommand {
|
||||
Close,
|
||||
Connect(Arc<str>),
|
||||
}
|
||||
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 dawvert integration
|
||||
}
|
||||
|
||||
//pub fn tui (
|
||||
|
|
@ -1354,26 +1385,6 @@ pub fn print_status (project: &Arrangement) {
|
|||
//})?)?
|
||||
//}
|
||||
|
||||
/// Define an enum containing commands, and implement [Command] trait for over given `State`.
|
||||
#[macro_export] macro_rules! def_command (
|
||||
($Command:ident: |$state:ident: $State:ty| {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant:ident$({$($arg:ident:$Arg:ty),+ $(,)?})?=>$body:expr),* $(,)?
|
||||
})=>{
|
||||
#[derive(Debug)] pub enum $Command {
|
||||
// FIXME: support attrs (docstrings)
|
||||
$($Variant $({ $($arg: $Arg),* })?),*
|
||||
}
|
||||
impl ::tengri::dizzle::Act<$State> for $Command {
|
||||
fn act (&self, $state: &mut $State) -> Perhaps<Self> {
|
||||
match self {
|
||||
$(Self::$Variant $({ $($arg),* })? => $body,)*
|
||||
_ => unimplemented!("Act<{}>: {self:?}", stringify!($State)),
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pub use self::draw::*;
|
||||
mod draw {
|
||||
use crate::*;
|
||||
|
|
@ -1958,3 +1969,33 @@ mod draw {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn print_status (project: &Arrangement) {
|
||||
println!("Name: {:?}", &project.name);
|
||||
println!("JACK: {:?}", &project.jack);
|
||||
println!("Buffer: {:?}", &project.clock.chunk);
|
||||
println!("Sample rate: {:?}", &project.clock.timebase.sr);
|
||||
println!("MIDI PPQ: {:?}", &project.clock.timebase.ppq);
|
||||
println!("Tempo: {:?}", &project.clock.timebase.bpm);
|
||||
println!("Quantize: {:?}", &project.clock.quant);
|
||||
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 dawvert integration
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue