mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
157 lines
5.7 KiB
Rust
157 lines
5.7 KiB
Rust
use crate::*;
|
|
use std::path::PathBuf;
|
|
|
|
type MaybeClip = Option<Arc<RwLock<MidiClip>>>;
|
|
|
|
macro_rules! ns { ($C:ty, $s:expr, $a:expr, $W:expr) => { <$C>::try_from_expr($s, $a).map($W) } }
|
|
macro_rules! cmd { ($cmd:expr) => {{ $cmd; None }}; }
|
|
macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
|
|
|
|
handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.command(self, input) {
|
|
let undo = command.execute(self)?;
|
|
if let Some(undo) = undo {
|
|
self.history.push(undo);
|
|
}
|
|
Some(true)
|
|
} else {
|
|
None
|
|
}));
|
|
|
|
#[tengri_proc::command(App)] impl AppCommand {
|
|
fn dialog (app: &mut App, dialog: Option<Dialog>) -> Perhaps<Self> {
|
|
app.toggle_dialog(dialog);
|
|
Ok(None)
|
|
}
|
|
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
|
|
app.toggle_dialog(None);
|
|
Ok(None)
|
|
}
|
|
fn toggle_editor (app: &mut App, value: bool) -> Perhaps<Self> {
|
|
app.toggle_editor(Some(value));
|
|
Ok(None)
|
|
}
|
|
//fn color (app: &mut App, theme: ItemTheme) -> Perhaps<Self> {
|
|
//Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme}))
|
|
//}
|
|
fn enqueue (app: &mut App, clip: Option<Arc<RwLock<MidiClip>>>) -> Perhaps<Self> {
|
|
todo!()
|
|
}
|
|
fn history (app: &mut App, delta: isize) -> Perhaps<Self> {
|
|
todo!()
|
|
}
|
|
fn zoom (app: &mut App, zoom: usize) -> Perhaps<Self> {
|
|
todo!()
|
|
}
|
|
//fn launch (app: &mut App) -> Perhaps<Self> {
|
|
//app.project.launch();
|
|
//Ok(None)
|
|
//}
|
|
fn select (app: &mut App, selection: Selection) -> Perhaps<Self> {
|
|
*app.project.selection_mut() = selection;
|
|
if let Some(ref mut editor) = app.editor {
|
|
editor.set_clip(match app.project.selection() {
|
|
Selection::TrackClip { track, scene } if let Some(Some(Some(clip))) = app
|
|
.project
|
|
.scenes.get(*scene)
|
|
.map(|s|s.clips.get(*track))
|
|
=>
|
|
Some(clip),
|
|
_ =>
|
|
None
|
|
});
|
|
}
|
|
Ok(None)
|
|
//("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::TrackClip { track: t, scene: s }) })))
|
|
// autoedit: load focused clip in editor.
|
|
}
|
|
fn stop_all (app: &mut App) -> Perhaps<Self> {
|
|
app.tracks_stop_all();
|
|
Ok(None)
|
|
}
|
|
fn sampler (app: &mut App, command: SamplerCommand) -> Perhaps<Self> {
|
|
Ok(app.project.sampler_mut()
|
|
.map(|s|command.delegate(s, |command|Self::Sampler{command}))
|
|
.transpose()?
|
|
.flatten())
|
|
}
|
|
fn project (app: &mut App, command: ArrangementCommand) -> Perhaps<Self> {
|
|
Ok(command.delegate(&mut app.project, |command|Self::Project{command})?)
|
|
}
|
|
fn clock (app: &mut App, command: ClockCommand) -> Perhaps<Self> {
|
|
Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command}))
|
|
}
|
|
fn message (app: &mut App, command: MessageCommand) -> Perhaps<Self> {
|
|
Ok(command.delegate(app, |command|Self::Message{command})?)
|
|
}
|
|
fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps<Self> {
|
|
Ok(if let Some(editor) = app.editor.as_mut() {
|
|
let undo = command.clone().delegate(editor, |command|AppCommand::Editor{command})?;
|
|
// update linked sampler after editor action
|
|
app.project.sampler_mut().map(|sampler|match command {
|
|
// autoselect: automatically select sample in sampler
|
|
MidiEditCommand::SetNotePos { pos } => { sampler.set_note_pos(pos); },
|
|
_ => {}
|
|
});
|
|
undo
|
|
} else {
|
|
None
|
|
})
|
|
}
|
|
fn pool (app: &mut App, command: PoolCommand) -> Perhaps<Self> {
|
|
let undo = command.clone().delegate(
|
|
&mut app.project.pool,
|
|
|command|AppCommand::Pool{command}
|
|
)?;
|
|
// update linked editor after pool action
|
|
app.editor.as_mut().map(|editor|match command {
|
|
// autoselect: automatically load selected clip in editor
|
|
PoolCommand::Select { .. } |
|
|
// autocolor: update color in all places simultaneously
|
|
PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } =>
|
|
editor.set_clip(app.project.pool.clip().as_ref()),
|
|
_ => {}
|
|
});
|
|
Ok(undo)
|
|
}
|
|
}
|
|
|
|
impl<'state> Context<'state, ClockCommand> for App {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClockCommand> {
|
|
Context::get(&self.clock(), iter)
|
|
}
|
|
}
|
|
|
|
impl<'state> Context<'state, MidiEditCommand> for App {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<MidiEditCommand> {
|
|
self.editor().map(|e|Context::get(e, iter)).flatten()
|
|
}
|
|
}
|
|
|
|
impl<'state> Context<'state, PoolCommand> for App {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<PoolCommand> {
|
|
Context::get(&self.project.pool, iter)
|
|
}
|
|
}
|
|
|
|
impl<'state> Context<'state, SamplerCommand> for App {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<SamplerCommand> {
|
|
self.project.sampler().map(|p|Context::get(p, iter)).flatten()
|
|
}
|
|
}
|
|
|
|
impl<'state> Context<'state, ArrangementCommand> for App {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ArrangementCommand> {
|
|
Context::get(&self.project, iter)
|
|
}
|
|
}
|
|
|
|
#[tengri_proc::command(App)] impl MessageCommand {
|
|
fn dismiss (app: &mut App) -> Perhaps<Self> {
|
|
app.dialog = None;
|
|
Ok(None)
|
|
}
|
|
}
|