mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-08-28 12:56:57 +02:00
fix warnings, cleanup
This commit is contained in:
parent
406aabde6e
commit
da2099c52e
10 changed files with 379 additions and 450 deletions
|
|
@ -353,7 +353,7 @@ attribute!(command {
|
|||
let mut variants_filtered = item.variants.clone();
|
||||
variants_filtered.clear();
|
||||
for variant in item.variants.iter_mut() {
|
||||
let Variant { attrs, ident, fields, discriminant } = variant;
|
||||
let Variant { attrs, ident, fields, discriminant: _ } = variant;
|
||||
let mut attrs_filtered = attrs.clone();
|
||||
attrs_filtered.clear();
|
||||
for attr in attrs.iter() {
|
||||
|
|
@ -396,7 +396,7 @@ attribute!(command {
|
|||
panic!()
|
||||
};
|
||||
match fields {
|
||||
Fields::Named(fields) => todo!("named command fields"),
|
||||
Fields::Named(_fields) => todo!("named command fields"),
|
||||
Fields::Unnamed(fields) => {
|
||||
let mut params = quote! {};
|
||||
let mut values = quote! {};
|
||||
|
|
@ -455,9 +455,11 @@ attribute!(keyword {
|
|||
impl Parse for CustomAttributeItem {
|
||||
fn parse (input: ParseStream) -> Result<Self> {
|
||||
let mut item: ItemEnum = input.parse()?;
|
||||
for Variant { attrs, ident, fields, discriminant } in item.variants.iter_mut() {
|
||||
for Variant {
|
||||
attrs, ident: _, fields: _, discriminant: _
|
||||
} in item.variants.iter_mut() {
|
||||
attrs.retain(|attr|if let syn::Meta::List(MetaList {
|
||||
ref path, ref tokens, ..
|
||||
ref path, tokens: ref _tokens, ..
|
||||
}) = attr.meta && path == &Path::from(Ident::new(
|
||||
"keyword", Span::call_site()
|
||||
)) {
|
||||
|
|
@ -474,7 +476,7 @@ attribute!(keyword {
|
|||
fn to_tokens (&self, out: &mut TokenStream2) {
|
||||
let Self(
|
||||
CustomAttributeMeta(state),
|
||||
CustomAttributeItem(item, variants)
|
||||
CustomAttributeItem(item, _variants)
|
||||
) = self;
|
||||
let ident = &item.ident;
|
||||
let body = quote! {};
|
||||
|
|
|
|||
39
src/deps.rs
Normal file
39
src/deps.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
pub extern crate atomic_float;
|
||||
pub extern crate xdg;
|
||||
pub extern crate tengri;
|
||||
#[cfg(feature = "cli")]
|
||||
pub(crate) use ::clap::{self, Parser, Subcommand};
|
||||
#[allow(unused)]
|
||||
pub(crate) use ::{
|
||||
std::{
|
||||
cmp::Ord,
|
||||
collections::BTreeMap,
|
||||
error::Error,
|
||||
ffi::OsString,
|
||||
fmt::{Write, Debug, Formatter},
|
||||
fs::File,
|
||||
ops::{Add, Sub, Mul, Div, Rem},
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, RwLock, atomic::{AtomicBool, AtomicUsize, AtomicU64, Ordering::Relaxed}},
|
||||
time::Duration,
|
||||
thread::{spawn, JoinHandle},
|
||||
},
|
||||
xdg::{
|
||||
BaseDirectories,
|
||||
},
|
||||
tengri::{
|
||||
*,
|
||||
dizzle::*,
|
||||
midly::{
|
||||
Smf, TrackEventKind, MidiMessage, Error as MidiError,
|
||||
num::*,
|
||||
live::*,
|
||||
},
|
||||
crossterm::event::{Event, KeyEvent},
|
||||
ratatui::{
|
||||
self,
|
||||
prelude::{Rect, Style, Stylize, Buffer, Color::{self, *}},
|
||||
widgets::{Widget, canvas::{Canvas, Line}},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
|
||||
/// A scene consists of a set of clips to play together.
|
||||
|
|
@ -85,13 +84,13 @@ pub trait SceneController: HasScene
|
|||
+ Namespace<ItemTheme>
|
||||
{
|
||||
#[command(SetSize = "scene/size")]
|
||||
fn scene_set_size (&mut self, size: usize) -> Perhaps<SceneCommand>
|
||||
fn scene_set_size (&mut self, _size: usize) -> Perhaps<SceneCommand>
|
||||
where Self: Namespace<usize>
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
#[command(SetZoom = "scene/zoom")]
|
||||
fn scene_set_zoom (&mut self, size: usize) -> Perhaps<SceneCommand>
|
||||
fn scene_set_zoom (&mut self, _size: usize) -> Perhaps<SceneCommand>
|
||||
where Self: Namespace<usize>
|
||||
{
|
||||
todo!()
|
||||
|
|
|
|||
|
|
@ -104,19 +104,19 @@ pub trait TrackController: HasTrack
|
|||
Ok(None)
|
||||
}
|
||||
#[command(SetMute = "track/mute")]
|
||||
fn track_set_mute (&mut self, mute: Option<bool>) -> Perhaps<TrackCommand> {
|
||||
fn track_set_mute (&mut self, _mute: Option<bool>) -> Perhaps<TrackCommand> {
|
||||
todo!()
|
||||
}
|
||||
#[command(SetSolo = "track/solo")]
|
||||
fn track_set_solo (&mut self, solo: Option<bool>) -> Perhaps<TrackCommand> {
|
||||
fn track_set_solo (&mut self, _solo: Option<bool>) -> Perhaps<TrackCommand> {
|
||||
todo!()
|
||||
}
|
||||
#[command(SetSize = "track/size")]
|
||||
fn track_set_size (&mut self, size: usize) -> Perhaps<TrackCommand> {
|
||||
fn track_set_size (&mut self, _size: usize) -> Perhaps<TrackCommand> {
|
||||
todo!()
|
||||
}
|
||||
#[command(SetZoom = "track/zoom")]
|
||||
fn track_set_zoom (&mut self, zoom: usize) -> Perhaps<TrackCommand> {
|
||||
fn track_set_zoom (&mut self, _zoom: usize) -> Perhaps<TrackCommand> {
|
||||
todo!()
|
||||
}
|
||||
#[command(SetName = "track/name")]
|
||||
|
|
@ -313,7 +313,7 @@ pub trait TracksController: HasTracks
|
|||
fn tracks_add (&mut self) -> Perhaps<TracksCommand>
|
||||
where Self: HasScenes + HasJack<'static>
|
||||
{
|
||||
let (index, _) = self.tracks_add_one(None, None, [].into(), [].into())?;
|
||||
let (_index, _) = self.tracks_add_one(None, None, [].into(), [].into())?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ pub trait BrowseController:
|
|||
pub size: Sizer,
|
||||
}
|
||||
|
||||
pub(crate) struct EntriesIterator<'a, S: Screen> {
|
||||
pub browser: &'a Browse,
|
||||
pub offset: usize,
|
||||
pub length: usize,
|
||||
pub index: usize,
|
||||
_screen: std::marker::PhantomData<S>
|
||||
}
|
||||
//pub(crate) struct EntriesIterator<'a, S: Screen> {
|
||||
//pub browser: &'a Browse,
|
||||
//pub offset: usize,
|
||||
//pub length: usize,
|
||||
//pub index: usize,
|
||||
//_screen: std::marker::PhantomData<S>
|
||||
//}
|
||||
|
||||
#[derive(Clone, Debug)] pub enum BrowseTarget {
|
||||
SaveProject,
|
||||
|
|
@ -118,40 +118,37 @@ impl Browse {
|
|||
unreachable!()
|
||||
})
|
||||
}
|
||||
fn _todo_stub_path_buf (&self) -> PathBuf { todo!() }
|
||||
fn _todo_stub_usize (&self) -> usize { todo!() }
|
||||
fn _todo_stub_arc_str (&self) -> Arc<str> { todo!() }
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
iter_south_fixed(1, ||self.tui_entries(), |entry, _index|entry.origin_w().full_w())
|
||||
}
|
||||
fn tui_entries (&self) -> EntriesIterator<'_, Tui> {
|
||||
EntriesIterator {
|
||||
offset: 0,
|
||||
index: 0,
|
||||
length: self.dirs.len() + self.files.len(),
|
||||
browser: self,
|
||||
_screen: Default::default(),
|
||||
}
|
||||
}
|
||||
//fn tui (&self) -> impl Draw<Tui> {
|
||||
//iter_south_fixed(1, ||self.tui_entries(), |entry, _index|entry.origin_w().full_w())
|
||||
//}
|
||||
//fn tui_entries (&self) -> EntriesIterator<'_, Tui> {
|
||||
//EntriesIterator {
|
||||
//offset: 0,
|
||||
//index: 0,
|
||||
//length: self.dirs.len() + self.files.len(),
|
||||
//browser: self,
|
||||
//_screen: Default::default(),
|
||||
//}
|
||||
//}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EntriesIterator<'a, Tui> {
|
||||
type Item = impl Draw<Tui>;
|
||||
fn next (&mut self) -> Option<Self::Item> {
|
||||
let dirs = self.browser.dirs.len();
|
||||
let files = self.browser.files.len();
|
||||
let index = self.index;
|
||||
if self.index < dirs {
|
||||
self.index += 1;
|
||||
Some(bold(true, self.browser.dirs[index].1.as_str()))
|
||||
} else if self.index < dirs + files {
|
||||
self.index += 1;
|
||||
Some(bold(false, self.browser.files[index - dirs].1.as_str()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
//impl<'a> Iterator for EntriesIterator<'a, Tui> {
|
||||
//type Item = impl Draw<Tui>;
|
||||
//fn next (&mut self) -> Option<Self::Item> {
|
||||
//let dirs = self.browser.dirs.len();
|
||||
//let files = self.browser.files.len();
|
||||
//let index = self.index;
|
||||
//if self.index < dirs {
|
||||
//self.index += 1;
|
||||
//Some(bold(true, self.browser.dirs[index].1.as_str()))
|
||||
//} else if self.index < dirs + files {
|
||||
//self.index += 1;
|
||||
//Some(bold(false, self.browser.files[index - dirs].1.as_str()))
|
||||
//} else {
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
impl PartialEq for BrowseTarget {
|
||||
fn eq (&self, other: &Self) -> bool {
|
||||
|
|
|
|||
|
|
@ -416,18 +416,6 @@ impl Clock {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clock {
|
||||
fn _todo_provide_u32 (&self) -> u32 {
|
||||
todo!()
|
||||
}
|
||||
fn _todo_provide_opt_u32 (&self) -> Option<u32> {
|
||||
todo!()
|
||||
}
|
||||
fn _todo_provide_f64 (&self) -> f64 {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl_has!(Clock: |self: Track|self.sequencer.clock);
|
||||
impl_default!(Timebase: Self::new(48000f64, 150f64, DEFAULT_PPQ));
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,6 @@ impl MidiEditor {
|
|||
self.mode.redraw();
|
||||
}
|
||||
}
|
||||
fn _todo_opt_clip_stub (&self) -> Option<Arc<RwLock<MidiClip>>> { todo!() }
|
||||
fn clip_length (&self) -> usize { self.clip().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1) }
|
||||
fn note_length (&self) -> usize { self.get_note_len() }
|
||||
fn note_pos (&self) -> usize { self.get_note_pos() }
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ pub trait PoolController: HasPool
|
|||
}
|
||||
|
||||
#[command(CropSet = "crop/set")]
|
||||
fn crop_set (&mut self, length: usize) -> Perhaps<PoolCommand> {
|
||||
fn crop_set (&mut self, _length: usize) -> Perhaps<PoolCommand> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut _focus))
|
||||
= self.pool_mut().mode_mut().clone()
|
||||
{
|
||||
|
|
@ -233,7 +233,7 @@ pub trait PoolController: HasPool
|
|||
clip.write().unwrap().length = *length;
|
||||
}
|
||||
*self.pool_mut().mode_mut() = None;
|
||||
return Ok(old_length.map(|length|PoolCommand::CropSet { length }))
|
||||
return Ok(old_length.map(|l|PoolCommand::CropSet { _length: l }))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
|
@ -429,12 +429,6 @@ impl ClipLength {
|
|||
}
|
||||
|
||||
impl Pool {
|
||||
fn _todo_usize_ (&self) -> usize { todo!() }
|
||||
fn _todo_bool_ (&self) -> bool { todo!() }
|
||||
fn _todo_clip_ (&self) -> MidiClip { todo!() }
|
||||
fn _todo_path_ (&self) -> PathBuf { todo!() }
|
||||
fn _todo_color_ (&self) -> ItemColor { todo!() }
|
||||
fn _todo_str_ (&self) -> Arc<str> { todo!() }
|
||||
fn _clip_new (&self) -> MidiClip { self.new_clip() }
|
||||
fn _clip_cloned (&self) -> MidiClip { self.cloned_clip() }
|
||||
fn _clip_index_current (&self) -> usize { 0 }
|
||||
|
|
@ -445,44 +439,44 @@ impl Pool {
|
|||
}
|
||||
|
||||
impl<'a> PoolView<'a> {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
let Self(pool) = self;
|
||||
//let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||g(32).into());
|
||||
//let on_bg = |x|x;//below(Repeat(" "), bg(color.darkest.term, x));
|
||||
//let border = |x|x;//Outer(Style::default().fg(color.dark.term).bg(color.darkest.term)).enclose(x);
|
||||
//let height = pool.clips.read().unwrap().len() as u16;
|
||||
iter(
|
||||
||pool.clips().clone().into_iter(),
|
||||
move|clip: Arc<RwLock<MidiClip>>, i: usize|{
|
||||
let MidiClip { ref name, color, length, .. } = *clip.read().unwrap();
|
||||
let item_height = 1;
|
||||
let _item_offset = i as u16 * item_height;
|
||||
let selected = i == pool.clip_index();
|
||||
let b = if selected { color.light.term } else { color.base.term };
|
||||
let f = color.lightest.term;
|
||||
let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") };
|
||||
let length = if false { String::default() } else { format!("{length} ") };
|
||||
bg(b, below!(
|
||||
fg(f, bold(selected, name)).origin_w().full_w(),
|
||||
fg(f, bold(selected, length)).origin_e().full_w(),
|
||||
when(selected, bold(true, fg(g(255), "▶"))).origin_w().full_w(),
|
||||
when(selected, bold(true, fg(g(255), "◀"))).origin_e().full_w(),
|
||||
)).exact_h(1)
|
||||
}).origin_n().full_h().exact_w(20)
|
||||
}
|
||||
//fn tui (&self) -> impl Draw<Tui> {
|
||||
//let Self(pool) = self;
|
||||
////let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||g(32).into());
|
||||
////let on_bg = |x|x;//below(Repeat(" "), bg(color.darkest.term, x));
|
||||
////let border = |x|x;//Outer(Style::default().fg(color.dark.term).bg(color.darkest.term)).enclose(x);
|
||||
////let height = pool.clips.read().unwrap().len() as u16;
|
||||
//iter(
|
||||
//||pool.clips().clone().into_iter(),
|
||||
//move|clip: Arc<RwLock<MidiClip>>, i: usize|{
|
||||
//let MidiClip { ref name, color, length, .. } = *clip.read().unwrap();
|
||||
//let item_height = 1;
|
||||
//let _item_offset = i as u16 * item_height;
|
||||
//let selected = i == pool.clip_index();
|
||||
//let b = if selected { color.light.term } else { color.base.term };
|
||||
//let f = color.lightest.term;
|
||||
//let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") };
|
||||
//let length = if false { String::default() } else { format!("{length} ") };
|
||||
//bg(b, below!(
|
||||
//fg(f, bold(selected, name)).origin_w().full_w(),
|
||||
//fg(f, bold(selected, length)).origin_e().full_w(),
|
||||
//when(selected, bold(true, fg(g(255), "▶"))).origin_w().full_w(),
|
||||
//when(selected, bold(true, fg(g(255), "◀"))).origin_e().full_w(),
|
||||
//)).exact_h(1)
|
||||
//}).origin_n().full_h().exact_w(20)
|
||||
//}
|
||||
}
|
||||
|
||||
impl ClipLength {
|
||||
fn tui (&self) -> impl Draw<Tui> {
|
||||
use ClipLengthFocus::*;
|
||||
let bars = format!("{}", self.bars());
|
||||
let beats = format!("{}", self.beats());
|
||||
let ticks = format!("{:>02}", self.ticks());
|
||||
match self.focus {
|
||||
None => east!(" ", bars, ".", beats, ".", ticks),
|
||||
Some(Bar) => east!("[", bars, "]", beats, ".", ticks),
|
||||
Some(Beat) => east!(" ", bars, "[", beats, "]", ticks),
|
||||
Some(Tick) => east!(" ", bars, ".", beats, "[", ticks),
|
||||
}
|
||||
}
|
||||
//fn tui (&self) -> impl Draw<Tui> {
|
||||
//use ClipLengthFocus::*;
|
||||
//let bars = format!("{}", self.bars());
|
||||
//let beats = format!("{}", self.beats());
|
||||
//let ticks = format!("{:>02}", self.ticks());
|
||||
//match self.focus {
|
||||
//None => east!(" ", bars, ".", beats, ".", ticks),
|
||||
//Some(Bar) => east!("[", bars, "]", beats, ".", ticks),
|
||||
//Some(Beat) => east!(" ", bars, "[", beats, "]", ticks),
|
||||
//Some(Tick) => east!(" ", bars, ".", beats, "[", ticks),
|
||||
//}
|
||||
//}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ pub trait MidiClipController: HasMidiClip
|
|||
{
|
||||
|
||||
#[command(SetColor = "clip/color")]
|
||||
fn clip_set_color (&mut self, color: Option<ItemTheme>) -> Perhaps<MidiClipCommand> {
|
||||
fn clip_set_color (&mut self, _color: Option<ItemTheme>) -> Perhaps<MidiClipCommand> {
|
||||
//(SetColor [t: usize, s: usize, c: ItemTheme]
|
||||
//clip.clip_set_color(t, s, c).map(|o|Self::SetColor(t, s, o)))));
|
||||
//("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap(), b.unwrap(), ItemTheme::random())))
|
||||
|
|
@ -271,7 +271,7 @@ pub trait MidiClipController: HasMidiClip
|
|||
}
|
||||
|
||||
#[command(SetLoop = "clip/loop")]
|
||||
fn clip_toggle_loop (&mut self, looping: Option<bool>) -> Perhaps<MidiClipCommand> {
|
||||
fn clip_toggle_loop (&mut self, _looping: Option<bool>) -> Perhaps<MidiClipCommand> {
|
||||
//(SetLoop [t: usize, s: usize, l: bool] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap(), b.unwrap(), c.unwrap())))
|
||||
todo!()
|
||||
|
|
@ -362,14 +362,6 @@ impl PartialEq for MidiClip {
|
|||
|
||||
impl Eq for MidiClip {}
|
||||
|
||||
impl MidiClip {
|
||||
fn _todo_opt_bool_stub_ (&self) -> Option<bool> { todo!() }
|
||||
fn _todo_bool_stub_ (&self) -> bool { todo!() }
|
||||
fn _todo_usize_stub_ (&self) -> usize { todo!() }
|
||||
fn _todo_arc_str_stub_ (&self) -> Arc<str> { todo!() }
|
||||
fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() }
|
||||
fn _todo_opt_item_theme_stub (&self) -> Option<ItemTheme> { todo!() }
|
||||
}
|
||||
impl_has!(Sequencer: |self: Track| self.sequencer);
|
||||
impl_has!(Clock: |self: Sequencer| self.clock);
|
||||
impl_has!(Vec<MidiInput>: |self: Sequencer| self.midi_ins);
|
||||
|
|
|
|||
579
src/tek.rs
579
src/tek.rs
|
|
@ -1,44 +1,6 @@
|
|||
#![allow(clippy::unit_arg)]
|
||||
#![feature(impl_trait_in_assoc_type)] // Used by EntriesIterator; TODO remove
|
||||
pub extern crate atomic_float;
|
||||
pub extern crate xdg;
|
||||
pub extern crate tengri;
|
||||
#[cfg(feature = "cli")]
|
||||
pub(crate) use ::clap::{self, Parser, Subcommand};
|
||||
#[allow(unused)]
|
||||
pub(crate) use ::{
|
||||
std::{
|
||||
cmp::Ord,
|
||||
collections::BTreeMap,
|
||||
error::Error,
|
||||
ffi::OsString,
|
||||
fmt::{Write, Debug, Formatter},
|
||||
fs::File,
|
||||
ops::{Add, Sub, Mul, Div, Rem},
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, RwLock, atomic::{AtomicBool, AtomicUsize, AtomicU64, Ordering::Relaxed}},
|
||||
time::Duration,
|
||||
thread::{spawn, JoinHandle},
|
||||
},
|
||||
xdg::{
|
||||
BaseDirectories,
|
||||
},
|
||||
tengri::{
|
||||
*,
|
||||
dizzle::*,
|
||||
midly::{
|
||||
Smf, TrackEventKind, MidiMessage, Error as MidiError,
|
||||
num::*,
|
||||
live::*,
|
||||
},
|
||||
crossterm::event::{Event, KeyEvent},
|
||||
ratatui::{
|
||||
self,
|
||||
prelude::{Rect, Style, Stylize, Buffer, Color::{self, *}},
|
||||
widgets::{Widget, canvas::{Canvas, Line}},
|
||||
},
|
||||
},
|
||||
};
|
||||
//#![feature(impl_trait_in_assoc_type)] // Used by EntriesIterator; TODO remove
|
||||
mod deps; pub use self::deps::*;
|
||||
|
||||
/// Banner.
|
||||
pub(crate) const HEADER: &'static str = r#"
|
||||
|
|
@ -88,6 +50,27 @@ fn run_new_plain (config: Config) -> Usually<()> {
|
|||
})?)
|
||||
}
|
||||
|
||||
//pub fn tui (
|
||||
//app: Arc<RwLock<App>>,
|
||||
//jack: Jack,
|
||||
//sync_lead: &bool,
|
||||
//sync_follow: &bool,
|
||||
//) -> Usually<()> {
|
||||
//// Run the [Tui] and [Jack] threads with the [App] state.
|
||||
//Tui::run_main(&jack.run(move|jack|{
|
||||
//// Between jack init and app's first cycle:
|
||||
////jack.sync_lead(*sync_lead, |mut state|{
|
||||
////let clock = app.write().unwrap().clock();
|
||||
////clock.playhead.update_from_sample(state.position.frame() as f64);
|
||||
////state.position.bbt = Some(clock.bbt());
|
||||
////state.position
|
||||
////})?;
|
||||
////jack.sync_follow(*sync_follow)?;
|
||||
//// FIXME: They don't work properly.
|
||||
//Ok(app)
|
||||
//})?)?
|
||||
//}
|
||||
|
||||
#[cfg(feature = "cli")] pub mod cli {
|
||||
use crate::*;
|
||||
|
||||
|
|
@ -174,7 +157,7 @@ fn run_new_plain (config: Config) -> Usually<()> {
|
|||
#[arg(short='n', long)] name: Option<String>,
|
||||
/// Whether to attempt to become transport master
|
||||
#[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='y', long, default_value_t = true)] sync_follow: bool,
|
||||
/// Initial tempo in beats per minute
|
||||
#[arg(short='b', long, default_value = None)] bpm: Option<f64>,
|
||||
|
|
@ -238,14 +221,8 @@ fn run_new_plain (config: Config) -> Usually<()> {
|
|||
.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_many(tracks.unwrap_or(0), None, [].into(), [].into())?;
|
||||
proj.scenes_add_many(scenes.unwrap_or(0))?;
|
||||
//if matches!(self, Action::Status) {
|
||||
//// Show status and exit
|
||||
//tek_print_status(&proj);
|
||||
//return Ok(())
|
||||
//}
|
||||
Ok(proj)
|
||||
}
|
||||
}
|
||||
|
|
@ -325,11 +302,14 @@ mod config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
/// Default configuration directory.
|
||||
const CONFIG_DIR: &'static str = "tek";
|
||||
/// Default configuration subdirectory.
|
||||
const CONFIG_SUB: &'static str = "v0";
|
||||
/// Default configuration file name.
|
||||
const CONFIG: &'static str = "tek.edn";
|
||||
/// Default configuration contents.
|
||||
const DEFAULTS: &'static str = include_str!("tek.edn");
|
||||
|
||||
/// Create a new app configuration from a set of XDG base directories,
|
||||
pub fn new (dirs: Option<BaseDirectories>) -> Self {
|
||||
Self {
|
||||
|
|
@ -340,20 +320,20 @@ mod config {
|
|||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create, initialize, and watch a new configuration.
|
||||
pub fn watched <T> (callback: impl FnOnce(Arc<Self>)->T) -> Usually<T> {
|
||||
let config = Self::init_new(None)?;
|
||||
Self::watch(config.clone(), None)?;
|
||||
let result = callback(config);
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Create and initialize a new configuration.
|
||||
pub fn init_new (_dirs: Option<BaseDirectories>) -> Usually<Arc<Self>> {
|
||||
let config = Arc::new(Self::new(None));
|
||||
config.init()?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
/// Watch a config's file for changes.
|
||||
pub fn watch (config: Arc<Self>, poll: Option<Duration>) -> Usually<()> {
|
||||
let handler = {
|
||||
let config = config.clone();
|
||||
|
|
@ -383,19 +363,18 @@ mod config {
|
|||
Err(format!("no config path").into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the config file.
|
||||
fn find_file (&self) -> Option<PathBuf> {
|
||||
self.dirs.find_config_file(Self::CONFIG)
|
||||
}
|
||||
|
||||
/// Place config file in default location.
|
||||
fn place_file (&self) -> Result<PathBuf, std::io::Error> {
|
||||
self.dirs.place_config_file(Self::CONFIG)
|
||||
}
|
||||
|
||||
/// Get path to config file.
|
||||
fn get_file (&self) -> Option<PathBuf> {
|
||||
self.dirs.get_config_file(Self::CONFIG)
|
||||
}
|
||||
|
||||
/// Write initial contents of configuration.
|
||||
pub fn init (&self) -> Usually<()> {
|
||||
//println!("\r\ninit {}", quanta::Clock::new().raw());
|
||||
|
|
@ -405,13 +384,9 @@ mod config {
|
|||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Write initial contents of a configuration file.
|
||||
pub fn load (
|
||||
&self,
|
||||
path: &str,
|
||||
defaults: &str,
|
||||
mut each: impl FnMut(&Self, &str)->Usually<()>
|
||||
pub fn load <F: FnMut(&Self, &str)->Usually<()>> (
|
||||
&self, path: &str, defaults: &str, mut each: F
|
||||
) -> Usually<()> {
|
||||
self.stamp.store(quanta::Clock::new().raw(), Relaxed);
|
||||
if self.find_file().is_none() {
|
||||
|
|
@ -426,19 +401,18 @@ mod config {
|
|||
return Err(format!("{path}: not found").into())
|
||||
})
|
||||
}
|
||||
|
||||
/// Add statements to configuration from [Dsl] source.
|
||||
pub fn add (&self, dsl: impl Language) -> Usually<&Self> {
|
||||
dsl.each(|item|self.add_one(item))?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Make this configuration empty.
|
||||
fn clear (&self) {
|
||||
*self.modes.0.write().unwrap() = Default::default();
|
||||
*self.views.write().unwrap() = Default::default();
|
||||
*self.binds.write().unwrap() = Default::default();
|
||||
}
|
||||
|
||||
/// Add one entry to the configuration.
|
||||
fn add_one (&self, item: impl Language) -> Usually<()> {
|
||||
if let Some(expr) = item.expr()? {
|
||||
let head = expr.head()?;
|
||||
|
|
@ -458,74 +432,35 @@ mod config {
|
|||
return Err(format!("Config::load: expected expr, got: {item:?}").into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a mode by name.
|
||||
pub fn get_mode (&self, mode: impl AsRef<str>) -> Option<Arc<Mode<Arc<str>>>> {
|
||||
self.modes.get(mode)
|
||||
}
|
||||
|
||||
/// Print the configuration.
|
||||
pub fn print (&self) {
|
||||
use ::ansi_term::Color::*;
|
||||
println!("{:?}", self.dirs);
|
||||
for (k, v) in self.views.read().unwrap().iter() {
|
||||
println!("{} {} {v}", Green.paint("VIEW"), Green.bold().paint(format!("{k:<16}")));
|
||||
}
|
||||
for (k, v) in self.binds.read().unwrap().iter() {
|
||||
println!("{} {}", Green.paint("BIND"), Green.bold().paint(format!("{k:<16}")));
|
||||
for (k, v) in v.0.iter() {
|
||||
print!("{} ", &Yellow.paint(match &k.0 {
|
||||
Event::Key(KeyEvent { modifiers, .. }) =>
|
||||
format!("{:>16}", format!("{modifiers}")),
|
||||
_ => unimplemented!()
|
||||
}));
|
||||
print!("{}", &Yellow.bold().paint(match &k.0 {
|
||||
Event::Key(KeyEvent { code, .. }) =>
|
||||
format!("{:<10}", format!("{code}")),
|
||||
_ => unimplemented!()
|
||||
}));
|
||||
for v in v.iter() {
|
||||
print!(" => {:?}", v.commands);
|
||||
print!(" {}", v.condition.as_ref().map(|x|format!("{x:?}")).unwrap_or_default());
|
||||
println!(" {}", v.description.as_ref().map(|x|x.as_ref()).unwrap_or_default());
|
||||
//println!(" {:?}", v.source);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.modes.for_each(|k, v|{
|
||||
println!();
|
||||
for v in v.name.iter() { print!("{}", Green.bold().paint(format!("{v} "))); }
|
||||
for v in v.info.iter() { print!("\n{}", Green.paint(format!("{v}"))); }
|
||||
print!("\n{} {}", Blue.paint("TOOL"), Green.bold().paint(format!("{k:<16}")));
|
||||
print!("\n{}", Blue.paint("KEYS"));
|
||||
for v in v.keys.iter() { print!("{}", Green.paint(format!(" {v}"))); }
|
||||
println!();
|
||||
v.modes.for_each(|k, v|{
|
||||
print!("{} {} {:?}", Blue.paint("MODE"), Green.bold().paint(format!("{k:<16}")), v.name);
|
||||
print!( " INFO={:?}", v.info);
|
||||
print!( " VIEW={:?}", v.view);
|
||||
println!(" KEYS={:?}", v.keys);
|
||||
});
|
||||
print!("{}", Blue.paint("VIEW"));
|
||||
for v in v.view.iter() { print!("{}", Green.paint(format!(" {v}"))); }
|
||||
println!();
|
||||
});
|
||||
print_config(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Modes {
|
||||
/// Register a mode.
|
||||
pub fn add (&self, name: &impl AsRef<str>, body: &impl Language) -> Usually<()> {
|
||||
let mut mode = Mode::default();
|
||||
body.each(|item|mode.add(item))?;
|
||||
self.0.write().unwrap().insert(name.as_ref().into(), Arc::new(mode));
|
||||
Ok(())
|
||||
}
|
||||
/// Get a mode by name.
|
||||
pub fn get (&self, name: impl AsRef<str>) -> Option<Arc<Mode<Arc<str>>>> {
|
||||
self.0.read().unwrap().get(name.as_ref()).cloned()
|
||||
}
|
||||
/// Run something for each mode.
|
||||
pub fn for_each <T> (&self, mut ator: impl FnMut(&str, &Mode<Arc<str>>)->T) {
|
||||
for (k, v) in self.0.read().unwrap().iter() {
|
||||
let _ = ator(k.as_ref(), v.as_ref());
|
||||
}
|
||||
}
|
||||
/// Count modes.
|
||||
pub fn len (&self) -> usize {
|
||||
self.0.read().unwrap().len()
|
||||
}
|
||||
|
|
@ -562,34 +497,24 @@ mod config {
|
|||
} else {
|
||||
return Err(format!("Mode::add: unexpected: {dsl:?}").into());
|
||||
})
|
||||
|
||||
//DslParse(dsl, ||Err(format!("Mode::add: unexpected: {dsl:?}").into()))
|
||||
//.word(|word|self.add_view(word))
|
||||
//.expr(|expr|expr.head(|head|{
|
||||
////println!("Mode::add: {head} {:?}", expr.tail());
|
||||
//let tail = expr.tail()?.map(|x|x.trim()).unwrap_or("");
|
||||
//match head {
|
||||
//"name" => self.add_name(tail),
|
||||
//"info" => self.add_info(tail),
|
||||
//"keys" => self.add_keys(tail)?,
|
||||
//"mode" => self.add_mode(tail)?,
|
||||
//_ => self.add_view(tail),
|
||||
//};
|
||||
//}))
|
||||
}
|
||||
|
||||
/// Add a name to the mode.
|
||||
fn add_name (&mut self, dsl: impl Language) -> Perhaps<()> {
|
||||
Ok(dsl.src()?.map(|src|self.name.push(src.into())))
|
||||
}
|
||||
/// Add a description to the mode.
|
||||
fn add_info (&mut self, dsl: impl Language) -> Perhaps<()> {
|
||||
Ok(dsl.src()?.map(|src|self.info.push(src.into())))
|
||||
}
|
||||
/// Add a view definition to the mode.
|
||||
fn add_view (&mut self, dsl: impl Language) -> Perhaps<()> {
|
||||
Ok(dsl.src()?.map(|src|self.view.push(src.into())))
|
||||
}
|
||||
/// Add a keyboard input bindin to the mode.
|
||||
fn add_keys (&mut self, dsl: impl Language) -> Perhaps<()> {
|
||||
Ok(Some(dsl.each(|expr|{ self.keys.push(expr.trim().into()); Ok(()) })?))
|
||||
}
|
||||
/// Add a submode to the mode.
|
||||
fn add_mode (&mut self, dsl: impl Language) -> Perhaps<()> {
|
||||
Ok(Some(if let Some(id) = dsl.head()? {
|
||||
self.modes.add(&id, &dsl.tail())?;
|
||||
|
|
@ -639,30 +564,27 @@ mod app {
|
|||
/// let _ = app.project.h_scenes();
|
||||
/// ```
|
||||
#[derive(Default, Debug)]
|
||||
#[namespace(Arc<[Connect]> App::get_arc_array_connect)]
|
||||
#[namespace(Arc<str> App::get_arc_str)]
|
||||
#[namespace(Color App::get_color)]
|
||||
#[namespace(ControlAxis App::get_axis)]
|
||||
#[namespace(Dialog App::get_dialog)]
|
||||
#[namespace(MidiClip)]
|
||||
#[namespace(ItemColor)]
|
||||
#[namespace(ItemTheme)]
|
||||
#[namespace(Option<Arc<RwLock<MidiClip>>> App::get_clip)]
|
||||
#[namespace(Option<Arc<[Connect]>> App::get_opt_arc_array_connect)]
|
||||
#[namespace(Option<Arc<str>> App::get_opt_arc_str)]
|
||||
#[namespace(Option<ItemTheme> App::get_opt_itemtheme)]
|
||||
#[namespace(Option<Vec<Option<Arc<RwLock<MidiClip>>>>> App::get_opt_vec_opt_arc_rwlock_midiclip)]
|
||||
#[namespace(Option<u16> App::get_opt_u16)]
|
||||
#[namespace(Option<u7> App::get_opt_u7)]
|
||||
#[namespace(Option<usize> App::get_opt_usize)]
|
||||
#[namespace(Option<bool> App::get_opt_bool)]
|
||||
#[namespace(Selection App::get_selection)]
|
||||
#[namespace(bool App::get_bool)]
|
||||
#[namespace(u16 App::get_u16)]
|
||||
#[namespace(PathBuf App::get_path_buf)]
|
||||
#[namespace(isize)]
|
||||
#[namespace(u8)]
|
||||
#[namespace(usize App::get_usize)]
|
||||
#[namespace(Arc<[Connect]> get_arc_array_connect)]
|
||||
#[namespace(Arc<str> get_arc_str)]
|
||||
#[namespace(Color get_color)]
|
||||
#[namespace(ControlAxis get_axis)]
|
||||
#[namespace(Option<Arc<[Connect]>> get_opt_arc_array_connect)]
|
||||
#[namespace(Option<Arc<str>> get_opt_arc_str)]
|
||||
#[namespace(Option<ItemTheme> get_opt_itemtheme)]
|
||||
#[namespace(Option<Vec<Option<Arc<RwLock<MidiClip>>>>> get_opt_vec_opt_arc_rwlock_midiclip)]
|
||||
#[namespace(Option<u16> get_opt_u16)]
|
||||
#[namespace(Option<usize> get_opt_usize)]
|
||||
#[namespace(Option<bool> get_opt_bool)]
|
||||
#[namespace(bool get_bool)]
|
||||
#[namespace(u16 get_u16)]
|
||||
#[namespace(PathBuf get_path_buf)]
|
||||
#[namespace(usize get_usize)]
|
||||
#[namespace(Dialog App::get_dialog)]
|
||||
pub struct App {
|
||||
/// Exit flag
|
||||
pub exit: Exit,
|
||||
|
|
@ -701,10 +623,7 @@ mod app {
|
|||
/// let tek = tek::App::new(None, proj, conf, "hello");
|
||||
/// ```
|
||||
pub fn new (
|
||||
exit: Option<Exit>,
|
||||
project: Arrangement,
|
||||
config: Arc<Config>,
|
||||
mode: impl AsRef<str>
|
||||
exit: Option<Exit>, project: Arrangement, config: Arc<Config>, mode: impl AsRef<str>
|
||||
) -> Self {
|
||||
App {
|
||||
exit: exit.unwrap_or_default(),
|
||||
|
|
@ -717,157 +636,144 @@ mod app {
|
|||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_path_buf (&self, src: impl Language) -> Perhaps<PathBuf> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_arc_str (&self, src: impl Language) -> Perhaps<Arc<str>> {
|
||||
Ok(src.src()?.map(|x|x.into()))
|
||||
}
|
||||
|
||||
fn get_u16 (&self, src: impl Language) -> Perhaps<u16> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":w/sidebar") => self.project.w_sidebar(self.editor().is_some()),
|
||||
Some(":h/sample-detail") => 6.max(self.size.h() as u16 * 3 / 9),
|
||||
_ => return try_to_u16(src)
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_usize (&self, src: impl Language) -> Perhaps<usize> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":scene-count") => self.scenes().len(),
|
||||
Some(":track-count") => self.tracks().len(),
|
||||
Some(":device-kind") => self.dialog.device_kind().unwrap_or(0),
|
||||
Some(":device-kind/next") => self.dialog.device_kind_next().unwrap_or(0),
|
||||
Some(":device-kind/prev") => self.dialog.device_kind_prev().unwrap_or(0),
|
||||
_ => return try_to_usize(src)
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_bool (&self, src: impl Language) -> Perhaps<bool> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
"Y" => true,
|
||||
"N" => false,
|
||||
":mode/editor" => self.project.editor.is_some(),
|
||||
":focused/dialog" => !matches!(self.dialog, Dialog::None),
|
||||
":focused/message" => matches!(self.dialog, Dialog::Message(..)),
|
||||
":focused/add_device" => matches!(self.dialog, Dialog::Device(..)),
|
||||
":focused/browser" => self.dialog.browser().is_some(),
|
||||
":focused/pool/import" => matches!(self.pool.mode, Some(PoolMode::Import(..))),
|
||||
":focused/pool/export" => matches!(self.pool.mode, Some(PoolMode::Export(..))),
|
||||
":focused/pool/rename" => matches!(self.pool.mode, Some(PoolMode::Rename(..))),
|
||||
":focused/pool/length" => matches!(self.pool.mode, Some(PoolMode::Length(..))),
|
||||
":focused/clip" => !self.editor_focused() && matches!(self.selection(), Selection::TrackClip{..}),
|
||||
":focused/track" => !self.editor_focused() && matches!(self.selection(), Selection::Track(..)),
|
||||
":focused/scene" => !self.editor_focused() && matches!(self.selection(), Selection::Scene(..)),
|
||||
":focused/mix" => !self.editor_focused() && matches!(self.selection(), Selection::Mix),
|
||||
_ => return Err(format!("not bool: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_selection (&self, src: impl Language) -> Perhaps<Selection> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":select/scene" => self.selection().select_scene(self.tracks().len()),
|
||||
":select/scene/next" => self.selection().select_scene_next(self.scenes().len()),
|
||||
":select/scene/prev" => self.selection().select_scene_prev(),
|
||||
":select/track" => self.selection().select_track(self.tracks().len()),
|
||||
":select/track/next" => self.selection().select_track_next(self.tracks().len()),
|
||||
":select/track/prev" => self.selection().select_track_prev(),
|
||||
_ => return Err(format!("not selection: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_color (&self, src: impl Language) -> Perhaps<Color> {
|
||||
if let Some(expr) = src.expr()? {
|
||||
match (expr.head()?, expr.tail()?) {
|
||||
(Some("g"), Some(tail)) => {
|
||||
let n = try_to_u8(tail.head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not gray"))?;
|
||||
Ok(Some(Color::Rgb(n, n, n)))
|
||||
},
|
||||
(Some("rgb"), Some(tail)) => {
|
||||
let r = try_to_u8(tail.head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not red"))?;
|
||||
let g = try_to_u8(tail.tail().head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not green"))?;
|
||||
let b = try_to_u8(tail.tail().tail().head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not blue"))?;
|
||||
Ok(Some(Color::Rgb(r, g, b)))
|
||||
},
|
||||
(Some(_), _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
(None, _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
}
|
||||
} else if let Ok(Some(sym)) = src.word() {
|
||||
Ok(match sym {
|
||||
":color/bg" => Some(Color::Rgb(28, 32, 36)),
|
||||
":color/fg" => Some(Color::Rgb(98, 92, 96)),
|
||||
_ => return Err(format!("not a color: {sym}").into())
|
||||
})
|
||||
} else {
|
||||
return Err(format!("not a color: {:?}", src.src()?).into())
|
||||
fn get_arc_str (_: &App, src: impl Language) -> Perhaps<Arc<str>> {
|
||||
Ok(src.src()?.map(|x|x.into()))
|
||||
}
|
||||
fn get_u16 (state: &App, src: impl Language) -> Perhaps<u16> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":w/sidebar") => state.project.w_sidebar(state.editor().is_some()),
|
||||
Some(":h/sample-detail") => 6.max(state.size.h() as u16 * 3 / 9),
|
||||
_ => return try_to_u16(src)
|
||||
}))
|
||||
}
|
||||
fn get_usize (state: &App, src: impl Language) -> Perhaps<usize> {
|
||||
Ok(Some(match src.word()? {
|
||||
Some(":scene-count") => state.scenes().len(),
|
||||
Some(":track-count") => state.tracks().len(),
|
||||
Some(":device-kind") => state.dialog.device_kind().unwrap_or(0),
|
||||
Some(":device-kind/next") => state.dialog.device_kind_next().unwrap_or(0),
|
||||
Some(":device-kind/prev") => state.dialog.device_kind_prev().unwrap_or(0),
|
||||
_ => return try_to_usize(src)
|
||||
}))
|
||||
}
|
||||
fn get_bool (state: &App, src: impl Language) -> Perhaps<bool> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
"Y" => true,
|
||||
"N" => false,
|
||||
":mode/editor" => state.project.editor.is_some(),
|
||||
":focused/dialog" => !matches!(state.dialog, Dialog::None),
|
||||
":focused/message" => matches!(state.dialog, Dialog::Message(..)),
|
||||
":focused/add_device" => matches!(state.dialog, Dialog::Device(..)),
|
||||
":focused/browser" => state.dialog.browser().is_some(),
|
||||
":focused/pool/import" => matches!(state.pool.mode, Some(PoolMode::Import(..))),
|
||||
":focused/pool/export" => matches!(state.pool.mode, Some(PoolMode::Export(..))),
|
||||
":focused/pool/rename" => matches!(state.pool.mode, Some(PoolMode::Rename(..))),
|
||||
":focused/pool/length" => matches!(state.pool.mode, Some(PoolMode::Length(..))),
|
||||
":focused/clip" => !state.editor_focused() && matches!(state.selection(), Selection::TrackClip{..}),
|
||||
":focused/track" => !state.editor_focused() && matches!(state.selection(), Selection::Track(..)),
|
||||
":focused/scene" => !state.editor_focused() && matches!(state.selection(), Selection::Scene(..)),
|
||||
":focused/mix" => !state.editor_focused() && matches!(state.selection(), Selection::Mix),
|
||||
_ => return Err(format!("not bool: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
#[allow(unused)]
|
||||
fn get_selection (state: &App, src: impl Language) -> Perhaps<Selection> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":select/scene" => state.selection().select_scene(state.tracks().len()),
|
||||
":select/scene/next" => state.selection().select_scene_next(state.scenes().len()),
|
||||
":select/scene/prev" => state.selection().select_scene_prev(),
|
||||
":select/track" => state.selection().select_track(state.tracks().len()),
|
||||
":select/track/next" => state.selection().select_track_next(state.tracks().len()),
|
||||
":select/track/prev" => state.selection().select_track_prev(),
|
||||
_ => return Err(format!("not selection: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
fn get_color (_: &App, src: impl Language) -> Perhaps<Color> {
|
||||
if let Some(expr) = src.expr()? {
|
||||
match (expr.head()?, expr.tail()?) {
|
||||
(Some("g"), Some(tail)) => {
|
||||
let n = try_to_u8(tail.head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not gray"))?;
|
||||
Ok(Some(Color::Rgb(n, n, n)))
|
||||
},
|
||||
(Some("rgb"), Some(tail)) => {
|
||||
let r = try_to_u8(tail.head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not red"))?;
|
||||
let g = try_to_u8(tail.tail().head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not green"))?;
|
||||
let b = try_to_u8(tail.tail().tail().head().map_err(Into::into))?
|
||||
.ok_or(LanguageError::Domain("not blue"))?;
|
||||
Ok(Some(Color::Rgb(r, g, b)))
|
||||
},
|
||||
(Some(_), _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
(None, _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
}
|
||||
} else if let Ok(Some(sym)) = src.word() {
|
||||
Ok(match sym {
|
||||
":color/bg" => Some(Color::Rgb(28, 32, 36)),
|
||||
":color/fg" => Some(Color::Rgb(98, 92, 96)),
|
||||
_ => return Err(format!("not a color: {sym}").into())
|
||||
})
|
||||
} else {
|
||||
return Err(format!("not a color: {:?}", src.src()?).into())
|
||||
}
|
||||
|
||||
fn get_opt_u7 (&self, src: impl Language) -> Perhaps<Option<u7>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":editor/pitch" => Some((
|
||||
self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8
|
||||
).into()),
|
||||
_ => return Err(format!("unknown midi note: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_opt_u16 (&self, _src: impl Language) -> Perhaps<Option<u16>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn get_opt_usize (&self, src: impl Language) -> Perhaps<Option<usize>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/scene" => self.selection().scene(),
|
||||
":selected/track" => self.selection().track(),
|
||||
_ => return Err(format!("unknown opt<usize>: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_clip (&self, src: impl Language) -> Perhaps<Option<Arc<RwLock<MidiClip>>>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/clip" if let Selection::TrackClip { track, scene } = self.selection() =>
|
||||
self.scenes()[*scene].clips[*track].clone(),
|
||||
_ => return Err(format!("not a clip: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_axis (&self, src: impl Language) -> Perhaps<ControlAxis> {
|
||||
Ok(src.word()?.map(|word|Ok(match word {
|
||||
":x" => ControlAxis::X,
|
||||
":y" => ControlAxis::Y,
|
||||
_ => return Err(format!("unknown axis {word}"))
|
||||
})).transpose()?)
|
||||
}
|
||||
|
||||
fn get_opt_itemtheme (&self, src: impl Language) -> Perhaps<Option<ItemTheme>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_vec_opt_arc_rwlock_midiclip (&self, src: impl Language) -> Perhaps<Option<Vec<Option<Arc<RwLock<MidiClip>>>>>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_arc_array_connect (&self, src: impl Language) -> Perhaps<Option<Arc<[Connect]>>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_arc_array_connect (&self, src: impl Language) -> Perhaps<Arc<[Connect]>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_opt_arc_str (&self, src: impl Language) -> Perhaps<Option<Arc<str>>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_opt_bool (&self, src: impl Language) -> Perhaps<Option<bool>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
}
|
||||
#[allow(unused)]
|
||||
fn get_opt_u7 (state: &App, src: impl Language) -> Perhaps<Option<u7>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":editor/pitch" => Some((
|
||||
state.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8
|
||||
).into()),
|
||||
_ => return Err(format!("unknown midi note: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
fn get_opt_usize (state: &App, src: impl Language) -> Perhaps<Option<usize>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/scene" => state.selection().scene(),
|
||||
":selected/track" => state.selection().track(),
|
||||
_ => return Err(format!("unknown opt<usize>: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
#[allow(unused)]
|
||||
fn get_clip (state: &App, src: impl Language) -> Perhaps<Option<Arc<RwLock<MidiClip>>>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/clip" if let Selection::TrackClip { track, scene } = state.selection() =>
|
||||
state.scenes()[*scene].clips[*track].clone(),
|
||||
_ => return Err(format!("not a clip: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
fn get_axis (_: &App, src: impl Language) -> Perhaps<ControlAxis> {
|
||||
Ok(src.word()?.map(|word|Ok(match word {
|
||||
":x" => ControlAxis::X,
|
||||
":y" => ControlAxis::Y,
|
||||
_ => return Err(format!("unknown axis {word}"))
|
||||
})).transpose()?)
|
||||
}
|
||||
fn get_opt_u16 (_: &App, _src: impl Language) -> Perhaps<Option<u16>> {
|
||||
Ok(None)
|
||||
}
|
||||
fn get_opt_itemtheme (_: &App, _: impl Language) -> Perhaps<Option<ItemTheme>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_vec_opt_arc_rwlock_midiclip (_: &App, _: impl Language) -> Perhaps<Option<Vec<Option<Arc<RwLock<MidiClip>>>>>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_arc_array_connect (_: &App, _: impl Language) -> Perhaps<Option<Arc<[Connect]>>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_arc_array_connect (_: &App, _: impl Language) -> Perhaps<Arc<[Connect]>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_arc_str (_: &App, _: impl Language) -> Perhaps<Option<Arc<str>>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_opt_bool (_: &App, _: impl Language) -> Perhaps<Option<bool>> {
|
||||
todo!()
|
||||
}
|
||||
fn get_path_buf (_: &App, _: impl Language) -> Perhaps<PathBuf> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -959,19 +865,6 @@ mod bind {
|
|||
}
|
||||
}
|
||||
|
||||
//#[derive(Clone, Debug)]
|
||||
//pub enum AppCommand {
|
||||
//Axis(AxisCommand),
|
||||
//Browse(BrowseCommand),
|
||||
//Dialog(DialogCommand),
|
||||
//MidiClip(MidiClipCommand),
|
||||
//Pool(PoolCommand),
|
||||
//Scene(SceneCommand),
|
||||
//Scenes(ScenesCommand),
|
||||
//Track(TrackCommand),
|
||||
//Tracks(TracksCommand),
|
||||
//}
|
||||
|
||||
impl_from!(AppCommand: |x: AxisCommand| AppCommand::Axis { command: x });
|
||||
impl_from!(AppCommand: |x: BrowseCommand| AppCommand::Browse { command: x });
|
||||
impl_from!(AppCommand: |x: DialogCommand| AppCommand::Dialog { command: x });
|
||||
|
|
@ -1401,27 +1294,6 @@ mod device {
|
|||
#[cfg(feature = "plugin")] pub use self::plugin::*;
|
||||
}
|
||||
|
||||
//pub fn tui (
|
||||
//app: Arc<RwLock<App>>,
|
||||
//jack: Jack,
|
||||
//sync_lead: &bool,
|
||||
//sync_follow: &bool,
|
||||
//) -> Usually<()> {
|
||||
//// Run the [Tui] and [Jack] threads with the [App] state.
|
||||
//Tui::run_main(&jack.run(move|jack|{
|
||||
//// Between jack init and app's first cycle:
|
||||
////jack.sync_lead(*sync_lead, |mut state|{
|
||||
////let clock = app.write().unwrap().clock();
|
||||
////clock.playhead.update_from_sample(state.position.frame() as f64);
|
||||
////state.position.bbt = Some(clock.bbt());
|
||||
////state.position
|
||||
////})?;
|
||||
////jack.sync_follow(*sync_follow)?;
|
||||
//// FIXME: They don't work properly.
|
||||
//Ok(app)
|
||||
//})?)?
|
||||
//}
|
||||
|
||||
pub use self::draw::*;
|
||||
mod draw {
|
||||
use crate::*;
|
||||
|
|
@ -1698,6 +1570,53 @@ mod draw {
|
|||
|
||||
}
|
||||
|
||||
pub fn print_config (config: &Config) {
|
||||
use ::ansi_term::Color::*;
|
||||
println!("{:?}", config.dirs);
|
||||
for (k, v) in config.views.read().unwrap().iter() {
|
||||
println!("{} {} {v}", Green.paint("VIEW"), Green.bold().paint(format!("{k:<16}")));
|
||||
}
|
||||
for (k, v) in config.binds.read().unwrap().iter() {
|
||||
println!("{} {}", Green.paint("BIND"), Green.bold().paint(format!("{k:<16}")));
|
||||
for (k, v) in v.0.iter() {
|
||||
print!("{} ", &Yellow.paint(match &k.0 {
|
||||
Event::Key(KeyEvent { modifiers, .. }) =>
|
||||
format!("{:>16}", format!("{modifiers}")),
|
||||
_ => unimplemented!()
|
||||
}));
|
||||
print!("{}", &Yellow.bold().paint(match &k.0 {
|
||||
Event::Key(KeyEvent { code, .. }) =>
|
||||
format!("{:<10}", format!("{code}")),
|
||||
_ => unimplemented!()
|
||||
}));
|
||||
for v in v.iter() {
|
||||
print!(" => {:?}", v.commands);
|
||||
print!(" {}", v.condition.as_ref().map(|x|format!("{x:?}")).unwrap_or_default());
|
||||
println!(" {}", v.description.as_ref().map(|x|x.as_ref()).unwrap_or_default());
|
||||
//println!(" {:?}", v.source);
|
||||
}
|
||||
}
|
||||
}
|
||||
config.modes.for_each(|k, v|{
|
||||
println!();
|
||||
for v in v.name.iter() { print!("{}", Green.bold().paint(format!("{v} "))); }
|
||||
for v in v.info.iter() { print!("\n{}", Green.paint(format!("{v}"))); }
|
||||
print!("\n{} {}", Blue.paint("TOOL"), Green.bold().paint(format!("{k:<16}")));
|
||||
print!("\n{}", Blue.paint("KEYS"));
|
||||
for v in v.keys.iter() { print!("{}", Green.paint(format!(" {v}"))); }
|
||||
println!();
|
||||
v.modes.for_each(|k, v|{
|
||||
print!("{} {} {:?}", Blue.paint("MODE"), Green.bold().paint(format!("{k:<16}")), v.name);
|
||||
print!( " INFO={:?}", v.info);
|
||||
print!( " VIEW={:?}", v.view);
|
||||
println!(" KEYS={:?}", v.keys);
|
||||
});
|
||||
print!("{}", Blue.paint("VIEW"));
|
||||
for v in v.view.iter() { print!("{}", Green.paint(format!(" {v}"))); }
|
||||
println!();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn print_status (project: &Arrangement) {
|
||||
println!("Name: {:?}", &project.name);
|
||||
println!("JACK: {:?}", &project.jack);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue