mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
enable adding midi ins and outs
This commit is contained in:
parent
76cefdca61
commit
5d6592bbdf
12 changed files with 171 additions and 165 deletions
|
|
@ -70,7 +70,7 @@ pub const fn peek_src <'a> (source: &'a str) -> Option<Token<'a>> {
|
|||
_ => token.error(Unexpected(c))
|
||||
},
|
||||
Sym(_) => match c {
|
||||
'a'..='z'|'0'..='9'|'-' => token.grow_sym(),
|
||||
'a'..='z'|'A'..='Z'|'0'..='9'|'-' => token.grow_sym(),
|
||||
' '|'\n'|'\r'|'\t'|')' => return Some(token),
|
||||
_ => token.error(Unexpected(c))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,3 +16,13 @@ pub trait Command<S>: Send + Sync + Sized {
|
|||
Ok(self.execute(state)?.map(wrap))
|
||||
}
|
||||
}
|
||||
impl<S, T: Command<S>> Command<S> for Option<T> {
|
||||
fn execute (self, _: &mut S) -> Perhaps<Self> {
|
||||
Ok(None)
|
||||
}
|
||||
fn delegate <U> (self, _: &mut S, _: impl Fn(Self)->U) -> Perhaps<U>
|
||||
where Self: Sized
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command<C>> AtomCommand<'a, C> for T {}
|
|||
$(let $arg: Option<$type> = Context::<$type>::get($state, &$arg.value);)?
|
||||
)*
|
||||
$(let $rest = iter.clone();)?
|
||||
return Some($command)
|
||||
return $command
|
||||
},)*
|
||||
_ => None
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ impl<'a, C, T: TryFromAtom<'a, C> + Command<C>> AtomCommand<'a, C> for T {}
|
|||
$(let $arg: Option<$type> = Context::<$type>::get($state, &$arg.value);)?
|
||||
)*
|
||||
$(let $rest = iter.clone();)?
|
||||
return Some($command)
|
||||
return $command
|
||||
}),*
|
||||
_ => None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,15 +184,15 @@ impl MidiViewer for MidiEditor {
|
|||
fn set_clip (&mut self, p: Option<&Arc<RwLock<MidiClip>>>) { self.mode.set_clip(p) }
|
||||
}
|
||||
atom_command!(MidiEditCommand: |state: MidiEditor| {
|
||||
("note/append" [] Self::AppendNote)
|
||||
("note/put" [] Self::PutNote)
|
||||
("note/del" [] Self::DelNote)
|
||||
("note/pos" [a: usize] Self::SetNoteCursor(a.expect("no note cursor")))
|
||||
("note/len" [a: usize] Self::SetNoteLength(a.expect("no note length")))
|
||||
("time/pos" [a: usize] Self::SetTimeCursor(a.expect("no time cursor")))
|
||||
("time/zoom" [a: usize] Self::SetTimeZoom(a.expect("no time zoom")))
|
||||
("time/lock" [a: bool] Self::SetTimeLock(a.expect("no time lock")))
|
||||
("time/lock" [] Self::SetTimeLock(!state.time_lock().get()))
|
||||
("note/append" [] Some(Self::AppendNote))
|
||||
("note/put" [] Some(Self::PutNote))
|
||||
("note/del" [] Some(Self::DelNote))
|
||||
("note/pos" [a: usize] Some(Self::SetNoteCursor(a.expect("no note cursor"))))
|
||||
("note/len" [a: usize] Some(Self::SetNoteLength(a.expect("no note length"))))
|
||||
("time/pos" [a: usize] Some(Self::SetTimeCursor(a.expect("no time cursor"))))
|
||||
("time/zoom" [a: usize] Some(Self::SetTimeZoom(a.expect("no time zoom"))))
|
||||
("time/lock" [a: bool] Some(Self::SetTimeLock(a.expect("no time lock"))))
|
||||
("time/lock" [] Some(Self::SetTimeLock(!state.time_lock().get())))
|
||||
});
|
||||
#[derive(Clone, Debug)] pub enum MidiEditCommand {
|
||||
// TODO: 1-9 seek markers that by default start every 8th of the clip
|
||||
|
|
|
|||
|
|
@ -265,13 +265,13 @@ provide!(ItemColor: |self: MidiPool| {
|
|||
Clip(PoolClipCommand),
|
||||
}
|
||||
atom_command!(PoolCommand: |state: MidiPool| {
|
||||
("show" [a: bool] Self::Show(a.expect("no flag")))
|
||||
("select" [i: usize] Self::Select(i.expect("no index")))
|
||||
("rename" [,..a] ClipRenameCommand::try_from_expr(state, a).map(Self::Rename).expect("invalid command"))
|
||||
("length" [,..a] ClipLengthCommand::try_from_expr(state, a).map(Self::Length).expect("invalid command"))
|
||||
("import" [,..a] FileBrowserCommand::try_from_expr(state, a).map(Self::Import).expect("invalid command"))
|
||||
("export" [,..a] FileBrowserCommand::try_from_expr(state, a).map(Self::Export).expect("invalid command"))
|
||||
("clip" [,..a] PoolClipCommand::try_from_expr(state, a).map(Self::Clip).expect("invalid command"))
|
||||
("show" [a: bool] Some(Self::Show(a.expect("no flag"))))
|
||||
("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
("rename" [,..a] ClipRenameCommand::try_from_expr(state, a).map(Self::Rename))
|
||||
("length" [,..a] ClipLengthCommand::try_from_expr(state, a).map(Self::Length))
|
||||
("import" [,..a] FileBrowserCommand::try_from_expr(state, a).map(Self::Import))
|
||||
("export" [,..a] FileBrowserCommand::try_from_expr(state, a).map(Self::Export))
|
||||
("clip" [,..a] PoolClipCommand::try_from_expr(state, a).map(Self::Clip))
|
||||
});
|
||||
command!(|self: PoolCommand, state: MidiPool|{
|
||||
use PoolCommand::*;
|
||||
|
|
@ -300,14 +300,22 @@ command!(|self: PoolCommand, state: MidiPool|{
|
|||
SetColor(usize, ItemColor),
|
||||
}
|
||||
atom_command!(PoolClipCommand: |state: MidiPool| {
|
||||
("add" [i: usize, c: MidiClip] Self::Add(i.expect("no index"), c.expect("no clip")))
|
||||
("delete" [i: usize] Self::Delete(i.expect("no index")))
|
||||
("swap" [a: usize, b: usize] Self::Swap(a.expect("no index"), b.expect("no index")))
|
||||
("import" [i: usize, p: PathBuf] Self::Import(i.expect("no index"), p.expect("no path")))
|
||||
("export" [i: usize, p: PathBuf] Self::Export(i.expect("no index"), p.expect("no path")))
|
||||
("set-name" [i: usize, n: Arc<str>] Self::SetName(i.expect("no index"), n.expect("no name")))
|
||||
("set-length" [i: usize, l: usize] Self::SetLength(i.expect("no index"), l.expect("no length")))
|
||||
("set-color" [i: usize, c: ItemColor] Self::SetColor(i.expect("no index"), c.expect("no color")))
|
||||
("add" [i: usize, c: MidiClip]
|
||||
Some(Self::Add(i.expect("no index"), c.expect("no clip"))))
|
||||
("delete" [i: usize]
|
||||
Some(Self::Delete(i.expect("no index"))))
|
||||
("swap" [a: usize, b: usize]
|
||||
Some(Self::Swap(a.expect("no index"), b.expect("no index"))))
|
||||
("import" [i: usize, p: PathBuf]
|
||||
Some(Self::Import(i.expect("no index"), p.expect("no path"))))
|
||||
("export" [i: usize, p: PathBuf]
|
||||
Some(Self::Export(i.expect("no index"), p.expect("no path"))))
|
||||
("set-name" [i: usize, n: Arc<str>]
|
||||
Some(Self::SetName(i.expect("no index"), n.expect("no name"))))
|
||||
("set-length" [i: usize, l: usize]
|
||||
Some(Self::SetLength(i.expect("no index"), l.expect("no length"))))
|
||||
("set-color" [i: usize, c: ItemColor]
|
||||
Some(Self::SetColor(i.expect("no index"), c.expect("no color"))))
|
||||
});
|
||||
impl<T: HasClips> Command<T> for PoolClipCommand {
|
||||
fn execute (self, model: &mut T) -> Perhaps<Self> {
|
||||
|
|
@ -381,10 +389,10 @@ impl<T: HasClips> Command<T> for PoolClipCommand {
|
|||
Set(Arc<str>),
|
||||
}
|
||||
atom_command!(ClipRenameCommand: |state: MidiPool| {
|
||||
("begin" [] Self::Begin)
|
||||
("cancel" [] Self::Cancel)
|
||||
("confirm" [] Self::Confirm)
|
||||
("set" [n: Arc<str>] Self::Set(n.expect("no name")))
|
||||
("begin" [] Some(Self::Begin))
|
||||
("cancel" [] Some(Self::Cancel))
|
||||
("confirm" [] Some(Self::Confirm))
|
||||
("set" [n: Arc<str>] Some(Self::Set(n.expect("no name"))))
|
||||
});
|
||||
command!(|self: ClipRenameCommand, state: MidiPool|{
|
||||
use ClipRenameCommand::*;
|
||||
|
|
@ -421,13 +429,13 @@ command!(|self: ClipRenameCommand, state: MidiPool|{
|
|||
Dec,
|
||||
}
|
||||
atom_command!(ClipLengthCommand: |state: MidiPool| {
|
||||
("begin" [] Self::Begin)
|
||||
("cancel" [] Self::Cancel)
|
||||
("next" [] Self::Next)
|
||||
("prev" [] Self::Prev)
|
||||
("inc" [] Self::Inc)
|
||||
("dec" [] Self::Dec)
|
||||
("set" [l: usize] Self::Set(l.expect("no length")))
|
||||
("begin" [] Some(Self::Begin))
|
||||
("cancel" [] Some(Self::Cancel))
|
||||
("next" [] Some(Self::Next))
|
||||
("prev" [] Some(Self::Prev))
|
||||
("inc" [] Some(Self::Inc))
|
||||
("dec" [] Some(Self::Dec))
|
||||
("set" [l: usize] Some(Self::Set(l.expect("no length"))))
|
||||
});
|
||||
command!(|self: ClipLengthCommand, state: MidiPool|{
|
||||
use ClipLengthCommand::*;
|
||||
|
|
@ -467,12 +475,12 @@ command!(|self: ClipLengthCommand, state: MidiPool|{
|
|||
None
|
||||
});
|
||||
atom_command!(FileBrowserCommand: |state: MidiPool| {
|
||||
("begin" [] Self::Begin)
|
||||
("cancel" [] Self::Cancel)
|
||||
("confirm" [] Self::Confirm)
|
||||
("select" [i: usize] Self::Select(i.expect("no index")))
|
||||
("chdir" [p: PathBuf] Self::Chdir(p.expect("no path")))
|
||||
("filter" [f: Arc<str>] Self::Filter(f.expect("no filter")))
|
||||
("begin" [] Some(Self::Begin))
|
||||
("cancel" [] Some(Self::Cancel))
|
||||
("confirm" [] Some(Self::Confirm))
|
||||
("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path"))))
|
||||
("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter"))))
|
||||
});
|
||||
command!(|self: FileBrowserCommand, state: MidiPool|{
|
||||
use PoolMode::*;
|
||||
|
|
|
|||
|
|
@ -662,28 +662,19 @@ pub enum SamplerMode {
|
|||
Sample(SamplerCommand),
|
||||
}
|
||||
atom_command!(SamplerTuiCommand: |state: SamplerTui| {
|
||||
("select" [i: usize] Self::Select(i.expect("no index")))
|
||||
("import" [,..a] if let Some(command) = FileBrowserCommand::try_from_expr(state, a) {
|
||||
Self::Import(command)
|
||||
} else {
|
||||
return None
|
||||
})
|
||||
("sample" [,..a] if let Some(command) = SamplerCommand::try_from_expr(&state.state, a) {
|
||||
Self::Sample(command)
|
||||
} else {
|
||||
return None
|
||||
})
|
||||
});
|
||||
("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
("import" [,..a] FileBrowserCommand::try_from_expr(state, a).map(Self::Import))
|
||||
("sample" [,..a] SamplerCommand::try_from_expr(&state.state, a).map(Self::Sample)) });
|
||||
provide!(usize: |self: SamplerTui| {});
|
||||
provide!(PathBuf: |self: SamplerTui| {});
|
||||
provide!(Arc<str>: |self: SamplerTui| {});
|
||||
atom_command!(FileBrowserCommand: |state: SamplerTui| {
|
||||
("begin" [] Self::Begin)
|
||||
("cancel" [] Self::Cancel)
|
||||
("confirm" [] Self::Confirm)
|
||||
("select" [i: usize] Self::Select(i.expect("no index")))
|
||||
("chdir" [p: PathBuf] Self::Chdir(p.expect("no path")))
|
||||
("filter" [f: Arc<str>] Self::Filter(f.expect("no filter")))
|
||||
("begin" [] Some(Self::Begin))
|
||||
("cancel" [] Some(Self::Cancel))
|
||||
("confirm" [] Some(Self::Confirm))
|
||||
("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path"))))
|
||||
("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter"))))
|
||||
});
|
||||
#[derive(Clone, Debug)] pub enum SamplerCommand {
|
||||
RecordBegin(u7),
|
||||
|
|
@ -697,21 +688,21 @@ atom_command!(FileBrowserCommand: |state: SamplerTui| {
|
|||
}
|
||||
atom_command!(SamplerCommand: |state: Sampler| {
|
||||
("record/begin" [i: u7]
|
||||
Self::RecordBegin(i.expect("no index")))
|
||||
Some(Self::RecordBegin(i.expect("no index"))))
|
||||
("record/cancel" []
|
||||
Self::RecordCancel)
|
||||
Some(Self::RecordCancel))
|
||||
("record/finish" []
|
||||
Self::RecordFinish)
|
||||
Some(Self::RecordFinish))
|
||||
("set/sample" [i: u7, s: Option<Arc<RwLock<Sample>>>]
|
||||
Self::SetSample(i.expect("no index"), s.expect("no sampler")))
|
||||
Some(Self::SetSample(i.expect("no index"), s.expect("no sampler"))))
|
||||
("set/start" [i: u7, s: usize]
|
||||
Self::SetStart(i.expect("no index"), s.expect("no start")))
|
||||
Some(Self::SetStart(i.expect("no index"), s.expect("no start"))))
|
||||
("set/gain" [i: u7, g: f32]
|
||||
Self::SetGain(i.expect("no index"), g.expect("no garin")))
|
||||
Some(Self::SetGain(i.expect("no index"), g.expect("no garin"))))
|
||||
("note/on" [p: u7, v: u7]
|
||||
Self::NoteOn(p.expect("no pitch"), v.expect("no velocity")))
|
||||
Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity"))))
|
||||
("note/off" [p: u7]
|
||||
Self::NoteOff(p.expect("no pitch")))
|
||||
Some(Self::NoteOff(p.expect("no pitch"))))
|
||||
});
|
||||
provide!(u7: |self: Sampler| {});
|
||||
provide!(Option<Arc<RwLock<Sample>>>: |self: Sampler| {});
|
||||
|
|
|
|||
|
|
@ -7,3 +7,5 @@
|
|||
(@t select :track 0)
|
||||
(@tab edit :clip)
|
||||
(@c color)
|
||||
(@shift-I input add)
|
||||
(@shift-O output add)
|
||||
|
|
|
|||
119
tek/src/keys.rs
119
tek/src/keys.rs
|
|
@ -38,6 +38,8 @@ handle!(TuiIn: |self: Tek, input|Ok({
|
|||
Editor(MidiEditCommand),
|
||||
Enqueue(Option<Arc<RwLock<MidiClip>>>),
|
||||
History(isize),
|
||||
Input(InputCommand),
|
||||
Output(OutputCommand),
|
||||
Pool(PoolCommand),
|
||||
Sampler(SamplerCommand),
|
||||
Scene(SceneCommand),
|
||||
|
|
@ -47,34 +49,29 @@ handle!(TuiIn: |self: Tek, input|Ok({
|
|||
Zoom(Option<usize>),
|
||||
}
|
||||
atom_command!(TekCommand: |app: Tek| {
|
||||
("stop" [] Self::StopAll)
|
||||
("undo" [d: usize] Self::History(-(d.unwrap_or(0)as isize)))
|
||||
("redo" [d: usize] Self::History(d.unwrap_or(0) as isize))
|
||||
("zoom" [z: usize] Self::Zoom(z))
|
||||
("edit" [] Self::Edit(None))
|
||||
("edit" [c: bool] Self::Edit(c))
|
||||
("color" [c: Color] Self::Color(c.map(ItemPalette::from).unwrap_or_default()))
|
||||
("enqueue" [c: Arc<RwLock<MidiClip>>] Self::Enqueue(c))
|
||||
("select" [t: usize, s: usize] match (t.expect("no track"), s.expect("no scene")) {
|
||||
("stop" [] Some(Self::StopAll))
|
||||
("undo" [d: usize] Some(Self::History(-(d.unwrap_or(0)as isize))))
|
||||
("redo" [d: usize] Some(Self::History(d.unwrap_or(0) as isize)))
|
||||
("zoom" [z: usize] Some(Self::Zoom(z)))
|
||||
("edit" [] Some(Self::Edit(None)))
|
||||
("edit" [c: bool] Some(Self::Edit(c)))
|
||||
("color" [c: Color] Some(Self::Color(c.map(ItemPalette::from).unwrap_or_default())))
|
||||
("enqueue" [c: Arc<RwLock<MidiClip>>] Some(Self::Enqueue(c)))
|
||||
("clip" [,..a] ClipCommand::try_from_expr(app, a).map(Self::Clip))
|
||||
("clock" [,..a] ClockCommand::try_from_expr(app.clock(), a).map(Self::Clock))
|
||||
("editor" [,..a] MidiEditCommand::try_from_expr(app.editor.as_ref().expect("no editor"), a).map(Self::Editor))
|
||||
("pool" [,..a] PoolCommand::try_from_expr(app.pool.as_ref().expect("no pool"), a).map(Self::Pool))
|
||||
//("sampler" [,..a] Self::Sampler( //SamplerCommand::try_from_expr(app.sampler().as_ref().expect("no sampler"), a).expect("invalid command")))
|
||||
("scene" [,..a] SceneCommand::try_from_expr(app, a).map(Self::Scene))
|
||||
("track" [,..a] TrackCommand::try_from_expr(app, a).map(Self::Track))
|
||||
("input" [,..a] InputCommand::try_from_expr(app, a).map(Self::Input))
|
||||
("output" [,..a] OutputCommand::try_from_expr(app, a).map(Self::Output))
|
||||
("select" [t: usize, s: usize] Some(match (t.expect("no track"), s.expect("no scene")) {
|
||||
(0, 0) => Self::Select(Selection::Mix),
|
||||
(t, 0) => Self::Select(Selection::Track(t)),
|
||||
(0, s) => Self::Select(Selection::Scene(s)),
|
||||
(t, s) => Self::Select(Selection::Clip(t, s)),
|
||||
})
|
||||
("clip" [,..a] Self::Clip(
|
||||
ClipCommand::try_from_expr(app, a).expect("invalid command: {a:?}")))
|
||||
("clock" [,..a] Self::Clock(
|
||||
ClockCommand::try_from_expr(app.clock(), a).expect("invalid command")))
|
||||
("editor" [,..a] Self::Editor(
|
||||
MidiEditCommand::try_from_expr(app.editor.as_ref().expect("no editor"), a).expect("invalid command")))
|
||||
("pool" [,..a] Self::Pool(
|
||||
PoolCommand::try_from_expr(app.pool.as_ref().expect("no pool"), a).expect("invalid command")))
|
||||
//("sampler" [,..a] Self::Sampler(
|
||||
//SamplerCommand::try_from_expr(app.sampler().as_ref().expect("no sampler"), a).expect("invalid command")))
|
||||
("scene" [,..a] Self::Scene(
|
||||
SceneCommand::try_from_expr(app, a).expect("invalid command")))
|
||||
("track" [,..a] Self::Track(
|
||||
TrackCommand::try_from_expr(app, a).expect("invalid command")))
|
||||
}))
|
||||
});
|
||||
command!(|self: TekCommand, app: Tek|match self {
|
||||
Self::Zoom(_) => { println!("\n\rtodo: global zoom"); None },
|
||||
|
|
@ -130,6 +127,8 @@ command!(|self: TekCommand, app: Tek|match self {
|
|||
Self::Clock(cmd) => cmd.delegate(app, Self::Clock)?,
|
||||
Self::Scene(cmd) => cmd.delegate(app, Self::Scene)?,
|
||||
Self::Track(cmd) => cmd.delegate(app, Self::Track)?,
|
||||
Self::Input(cmd) => cmd.delegate(app, Self::Input)?,
|
||||
Self::Output(cmd) => cmd.delegate(app, Self::Output)?,
|
||||
Self::Clip(cmd) => cmd.delegate(app, Self::Clip)?,
|
||||
Self::Editor(cmd) => app.editor.as_mut()
|
||||
.map(|editor|cmd.delegate(editor, Self::Editor)).transpose()?.flatten(),
|
||||
|
|
@ -192,6 +191,26 @@ command!(|self: TekCommand, app: Tek|match self {
|
|||
},
|
||||
_ => todo!("{self:?}")
|
||||
});
|
||||
#[derive(Clone, Debug)] pub enum InputCommand { Add }
|
||||
atom_command!(InputCommand: |app: Tek| {
|
||||
("add" [] Some(Self::Add))
|
||||
});
|
||||
command!(|self: InputCommand, app: Tek|match self {
|
||||
Self::Add => {
|
||||
app.midi_ins.push(JackMidiIn::new(&app.jack, &format!("M/{}", app.midi_ins.len()), &[])?);
|
||||
None
|
||||
},
|
||||
});
|
||||
#[derive(Clone, Debug)] pub enum OutputCommand { Add }
|
||||
atom_command!(OutputCommand: |app: Tek| {
|
||||
("add" [] Some(Self::Add))
|
||||
});
|
||||
command!(|self: OutputCommand, app: Tek|match self {
|
||||
Self::Add => {
|
||||
app.midi_outs.push(JackMidiOut::new(&app.jack, &format!("{}/M", app.midi_outs.len()), &[])?);
|
||||
None
|
||||
},
|
||||
});
|
||||
#[derive(Clone, Debug)] pub enum TrackCommand {
|
||||
Add,
|
||||
Del(usize),
|
||||
|
|
@ -206,17 +225,17 @@ command!(|self: TekCommand, app: Tek|match self {
|
|||
ToggleMonitor,
|
||||
}
|
||||
atom_command!(TrackCommand: |app: Tek| {
|
||||
("add" [] Self::Add)
|
||||
("size" [a: usize] Self::SetSize(a.unwrap()))
|
||||
("zoom" [a: usize] Self::SetZoom(a.unwrap()))
|
||||
("color" [a: usize] Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random()))
|
||||
("del" [a: usize] Self::Del(a.unwrap().saturating_sub(1)))
|
||||
("stop" [a: usize] Self::Stop(a.unwrap().saturating_sub(1)))
|
||||
("swap" [a: usize, b: usize] Self::Swap(a.unwrap(), b.unwrap()))
|
||||
("play" [] Self::TogglePlay)
|
||||
("solo" [] Self::ToggleSolo)
|
||||
("rec" [] Self::ToggleRecord)
|
||||
("mon" [] Self::ToggleMonitor)
|
||||
("add" [] Some(Self::Add))
|
||||
("size" [a: usize] Some(Self::SetSize(a.unwrap())))
|
||||
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
("color" [a: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random())))
|
||||
("del" [a: usize] Some(Self::Del(a.unwrap().saturating_sub(1))))
|
||||
("stop" [a: usize] Some(Self::Stop(a.unwrap().saturating_sub(1))))
|
||||
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
|
||||
("play" [] Some(Self::TogglePlay))
|
||||
("solo" [] Some(Self::ToggleSolo))
|
||||
("rec" [] Some(Self::ToggleRecord))
|
||||
("mon" [] Some(Self::ToggleMonitor))
|
||||
});
|
||||
command!(|self: TrackCommand, app: Tek|match self {
|
||||
Self::Add => {
|
||||
|
|
@ -266,12 +285,12 @@ command!(|self: TrackCommand, app: Tek|match self {
|
|||
Enqueue(usize),
|
||||
}
|
||||
atom_command!(SceneCommand: |app: Tek| {
|
||||
("add" [] Self::Add)
|
||||
("del" [a: usize] Self::Del(0))
|
||||
("zoom" [a: usize] Self::SetZoom(a.unwrap()))
|
||||
("color" [a: usize] Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random()))
|
||||
("enqueue" [a: usize] Self::Enqueue(a.unwrap().saturating_sub(1)))
|
||||
("swap" [a: usize, b: usize] Self::Swap(a.unwrap(), b.unwrap()))
|
||||
("add" [] Some(Self::Add))
|
||||
("del" [a: usize] Some(Self::Del(0)))
|
||||
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
("color" [a: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), ItemPalette::random())))
|
||||
("enqueue" [a: usize] Some(Self::Enqueue(a.unwrap().saturating_sub(1))))
|
||||
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
|
||||
});
|
||||
command!(|self: SceneCommand, app: Tek|match self {
|
||||
Self::Add => {
|
||||
|
|
@ -307,18 +326,12 @@ command!(|self: SceneCommand, app: Tek|match self {
|
|||
SetColor(usize, usize, ItemPalette),
|
||||
}
|
||||
atom_command!(ClipCommand: |app: Tek| {
|
||||
("get" [a: usize ,b: usize]
|
||||
Self::Get(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1)))
|
||||
("put" [a: usize, b: usize, c: Option<Arc<RwLock<MidiClip>>>]
|
||||
Self::Put(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap()))
|
||||
("enqueue" [a: usize, b: usize]
|
||||
Self::Enqueue(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1)))
|
||||
("edit" [a: Option<Arc<RwLock<MidiClip>>>]
|
||||
Self::Edit(a.unwrap()))
|
||||
("loop" [a: usize, b: usize, c: bool]
|
||||
Self::SetLoop(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap()))
|
||||
("color" [a: usize, b: usize]
|
||||
Self::SetColor(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), ItemPalette::random()))
|
||||
("get" [a: usize ,b: usize] Some(Self::Get(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1))))
|
||||
("put" [a: usize, b: usize, c: Option<Arc<RwLock<MidiClip>>>] Some(Self::Put(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap())))
|
||||
("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1))))
|
||||
("edit" [a: Option<Arc<RwLock<MidiClip>>>] Some(Self::Edit(a.unwrap())))
|
||||
("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), c.unwrap())))
|
||||
("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap().saturating_sub(1), b.unwrap().saturating_sub(1), ItemPalette::random())))
|
||||
});
|
||||
command!(|self: ClipCommand, app: Tek|match self {
|
||||
Self::Get(track, scene) => { todo!() },
|
||||
|
|
|
|||
|
|
@ -128,15 +128,6 @@ impl Tek {
|
|||
name,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
//let midi_in = JackMidiIn::new(&self.jack, &format!("{}I", &track.name), midi_from)?;
|
||||
//midi_in.connect_to_matching()?;
|
||||
//track.player.midi_ins.push(midi_in);
|
||||
|
||||
//let midi_out = JackMidiOut::new(&self.jack, &format!("{}O", &track.name), midi_to)?;
|
||||
//midi_out.connect_to_matching()?;
|
||||
//track.player.midi_outs.push(midi_out);
|
||||
|
||||
self.tracks_mut().push(track);
|
||||
let len = self.tracks().len();
|
||||
let index = len - 1;
|
||||
|
|
|
|||
|
|
@ -197,15 +197,10 @@ impl Tek {
|
|||
let conn = move|conn: &PortConnect|{
|
||||
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, conn.info()))))
|
||||
};
|
||||
let header: ThunkBox<_> = io_header!(
|
||||
self,
|
||||
" I ",
|
||||
" midi ins",
|
||||
self.midi_ins.len(),
|
||||
self.midi_ins().get(0).map(move|input: &JackMidiIn|Bsp::s(
|
||||
let header: ThunkBox<_> = io_header!(self, " I ", " midi ins", self.midi_ins.len(),
|
||||
Map::new(||self.midi_ins.iter(), move|input, index|map_south(index as u16, 1u16, Bsp::s(
|
||||
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(input.name())))),
|
||||
input.conn().get(0).map(conn)
|
||||
)));
|
||||
input.conn().get(0).map(conn)))));
|
||||
let cells: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
||||
let rec = track.player.recording;
|
||||
let mon = track.player.monitoring;
|
||||
|
|
@ -229,15 +224,11 @@ impl Tek {
|
|||
let bg = Tui::g(64);
|
||||
let mut h = 2.max(1 + self.midi_outs.len());
|
||||
for midi_out in self.midi_outs.iter() { h += midi_out.conn().len() }
|
||||
let header: ThunkBox<_> = io_header!(
|
||||
self,
|
||||
" O ",
|
||||
" midi outs",
|
||||
self.midi_outs.len(),
|
||||
self.midi_outs().get(0).map(move|output: &JackMidiOut|Bsp::s(
|
||||
let header: ThunkBox<_> = io_header!(self, " O ", " midi outs", self.midi_outs.len(),
|
||||
Map::new(||self.midi_outs.iter(), move|output, index|map_south(index as u16, 1u16, Bsp::s(
|
||||
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(output.name())))),
|
||||
output.conn().get(0).map(|connect|Fill::x(Align::w(Tui::bold(false,
|
||||
Tui::fg_bg(fg, bg, connect.info()))))))));
|
||||
Tui::fg_bg(fg, bg, connect.info())))))))));
|
||||
let mute = false;
|
||||
let solo = false;
|
||||
let cells: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@ pub enum ClockCommand {
|
|||
provide_num!(u32: |self: Clock| {});
|
||||
provide!(f64: |self: Clock| {});
|
||||
atom_command!(ClockCommand: |state: Clock| {
|
||||
("play" [] Self::Play(None))
|
||||
("play" [t: u32] Self::Play(t))
|
||||
("pause" [] Self::Pause(None))
|
||||
("pause" [t: u32] Self::Pause(t))
|
||||
("toggle" [] if state.is_rolling() { Self::Pause(None) } else { Self::Play(None) })
|
||||
("toggle" [t: u32] if state.is_rolling() { Self::Pause(t) } else { Self::Play(t) })
|
||||
("seek/usec" [t: f64] Self::SeekUsec(t.expect("no usec")))
|
||||
("seek/pulse" [t: f64] Self::SeekPulse(t.expect("no pulse")))
|
||||
("seek/sample" [t: f64] Self::SeekSample(t.expect("no sample")))
|
||||
("set/bpm" [t: f64] Self::SetBpm(t.expect("no bpm")))
|
||||
("set/sync" [t: f64] Self::SetSync(t.expect("no sync")))
|
||||
("set/quant" [t: f64] Self::SetQuant(t.expect("no quant")))
|
||||
("play" [] Some(Self::Play(None)))
|
||||
("play" [t: u32] Some(Self::Play(t)))
|
||||
("pause" [] Some(Self::Pause(None)))
|
||||
("pause" [t: u32] Some(Self::Pause(t)))
|
||||
("toggle" [] Some(if state.is_rolling() { Self::Pause(None) } else { Self::Play(None) }))
|
||||
("toggle" [t: u32] Some(if state.is_rolling() { Self::Pause(t) } else { Self::Play(t) }))
|
||||
("seek/usec" [t: f64] Some(Self::SeekUsec(t.expect("no usec"))))
|
||||
("seek/pulse" [t: f64] Some(Self::SeekPulse(t.expect("no pulse"))))
|
||||
("seek/sample" [t: f64] Some(Self::SeekSample(t.expect("no sample"))))
|
||||
("set/bpm" [t: f64] Some(Self::SetBpm(t.expect("no bpm"))))
|
||||
("set/sync" [t: f64] Some(Self::SetSync(t.expect("no sync"))))
|
||||
("set/quant" [t: f64] Some(Self::SetQuant(t.expect("no quant"))))
|
||||
});
|
||||
impl<T: HasClock> Command<T> for ClockCommand {
|
||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ handle!(TuiIn: |self: Example, input|{
|
|||
});
|
||||
enum ExampleCommand { Next, Previous }
|
||||
atom_command!(ExampleCommand: |app: Example| {
|
||||
(":prev" [] Self::Previous)
|
||||
(":next" [] Self::Next)
|
||||
(":prev" [] Some(Self::Previous))
|
||||
(":next" [] Some(Self::Next))
|
||||
});
|
||||
command!(|self: ExampleCommand, state: Example|match self {
|
||||
Self::Next =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue