mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
src -> app; move core libs to tengri
This commit is contained in:
parent
8465d64807
commit
bcc3f5809e
113 changed files with 132 additions and 5729 deletions
205
app/src/keys.rs
Normal file
205
app/src/keys.rs
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
use crate::*;
|
||||
pub const KEYS_APP: &str = include_str!("keys.edn");
|
||||
pub const KEYS_CLIP: &str = include_str!("keys_clip.edn");
|
||||
pub const KEYS_TRACK: &str = include_str!("keys_track.edn");
|
||||
pub const KEYS_SCENE: &str = include_str!("keys_scene.edn");
|
||||
pub const KEYS_MIX: &str = include_str!("keys_mix.edn");
|
||||
handle!(TuiIn: |self: Tek, input|Ok({
|
||||
// If editing, editor keys take priority
|
||||
if self.is_editing() {
|
||||
if self.editor.handle(input)? == Some(true) {
|
||||
return Ok(Some(true))
|
||||
}
|
||||
}
|
||||
// Handle from root keymap
|
||||
if let Some(command) = self.keys.command::<_, TekCommand, _>(self, input) {
|
||||
if let Some(undo) = command.execute(self)? { self.history.push(undo); }
|
||||
return Ok(Some(true))
|
||||
}
|
||||
// Handle from selection-dependent keymaps
|
||||
if let Some(command) = match self.selected() {
|
||||
Selection::Clip(_, _) => self.keys_clip,
|
||||
Selection::Track(_) => self.keys_track,
|
||||
Selection::Scene(_) => self.keys_scene,
|
||||
Selection::Mix => self.keys_mix,
|
||||
}.command::<_, TekCommand, _>(self, input) {
|
||||
if let Some(undo) = command.execute(self)? { self.history.push(undo); }
|
||||
return Ok(Some(true))
|
||||
}
|
||||
None
|
||||
}));
|
||||
#[derive(Clone, Debug)] pub enum TekCommand {
|
||||
Clip(ClipCommand),
|
||||
Clock(ClockCommand),
|
||||
Color(ItemPalette),
|
||||
Edit(Option<bool>),
|
||||
Editor(MidiEditCommand),
|
||||
Enqueue(Option<Arc<RwLock<MidiClip>>>),
|
||||
History(isize),
|
||||
Input(InputCommand),
|
||||
Launch,
|
||||
Output(OutputCommand),
|
||||
Pool(PoolCommand),
|
||||
Sampler(SamplerCommand),
|
||||
Scene(SceneCommand),
|
||||
Select(Selection),
|
||||
StopAll,
|
||||
Track(TrackCommand),
|
||||
Zoom(Option<usize>),
|
||||
}
|
||||
atom_command!(TekCommand: |app: Tek| {
|
||||
("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(ItemPalette::random())))
|
||||
("color" [c: Color] Some(Self::Color(c.map(ItemPalette::from).expect("no color"))))
|
||||
("enqueue" [c: Arc<RwLock<MidiClip>>] Some(Self::Enqueue(c)))
|
||||
("launch" [] Some(Self::Launch))
|
||||
("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: Selection] Some(t.map(Self::Select).expect("no selection")))
|
||||
("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)),
|
||||
}))
|
||||
});
|
||||
command!(|self: TekCommand, app: Tek|match self {
|
||||
Self::Zoom(_) => { println!("\n\rtodo: global zoom"); None },
|
||||
Self::History(delta) => { println!("\n\rtodo: undo/redo"); None },
|
||||
Self::Select(s) => {
|
||||
app.selected = s;
|
||||
// autoedit: load focused clip in editor.
|
||||
if let Some(ref mut editor) = app.editor {
|
||||
editor.set_clip(match app.selected {
|
||||
Selection::Clip(t, s) if let Some(Some(Some(clip))) = app
|
||||
.scenes.get(s).map(|s|s.clips.get(t)) => Some(clip),
|
||||
_ => None
|
||||
});
|
||||
}
|
||||
None
|
||||
},
|
||||
Self::Edit(value) => {
|
||||
if let Some(value) = value {
|
||||
if app.is_editing() != value {
|
||||
app.editing.store(value, Relaxed);
|
||||
}
|
||||
} else {
|
||||
app.editing.store(!app.is_editing(), Relaxed);
|
||||
};
|
||||
// autocreate: create new clip from pool when entering empty cell
|
||||
if let Some(ref pool) = app.pool {
|
||||
if app.is_editing() {
|
||||
if let Selection::Clip(t, s) = app.selected {
|
||||
if let Some(scene) = app.scenes.get_mut(s) {
|
||||
if let Some(slot) = scene.clips.get_mut(t) {
|
||||
if slot.is_none() {
|
||||
let (index, mut clip) = pool.add_new_clip();
|
||||
// autocolor: new clip colors from scene and track color
|
||||
clip.write().unwrap().color = ItemColor::random_near(
|
||||
app.tracks[t].color.base.mix(
|
||||
scene.color.base,
|
||||
0.5
|
||||
),
|
||||
0.2
|
||||
).into();
|
||||
if let Some(ref mut editor) = app.editor {
|
||||
editor.set_clip(Some(&clip));
|
||||
}
|
||||
*slot = Some(clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
},
|
||||
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(),
|
||||
//Self::Sampler(cmd) => app.sampler.as_mut()
|
||||
//.map(|sampler|cmd.delegate(sampler, Self::Sampler)).transpose()?.flatten(),
|
||||
//Self::Enqueue(clip) => app.player.as_mut()
|
||||
//.map(|player|{player.enqueue_next(clip.as_ref());None}).flatten(),
|
||||
Self::Launch => {
|
||||
use Selection::*;
|
||||
match app.selected {
|
||||
Track(t) => app.tracks[t].player.enqueue_next(None),
|
||||
Clip(t, s) => app.tracks[t].player.enqueue_next(app.scenes[s].clips[t].as_ref()),
|
||||
Scene(s) => {
|
||||
for t in 0..app.tracks.len() {
|
||||
app.tracks[t].player.enqueue_next(app.scenes[s].clips[t].as_ref())
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
None
|
||||
},
|
||||
Self::Color(palette) => {
|
||||
use Selection::*;
|
||||
Some(Self::Color(match app.selected {
|
||||
Mix => {
|
||||
let old = app.color;
|
||||
app.color = palette;
|
||||
old
|
||||
},
|
||||
Track(t) => {
|
||||
let old = app.tracks[t].color;
|
||||
app.tracks[t].color = palette;
|
||||
old
|
||||
}
|
||||
Scene(s) => {
|
||||
let old = app.scenes[s].color;
|
||||
app.scenes[s].color = palette;
|
||||
old
|
||||
}
|
||||
Clip(t, s) => {
|
||||
if let Some(ref clip) = app.scenes[s].clips[t] {
|
||||
let mut clip = clip.write().unwrap();
|
||||
let old = clip.color;
|
||||
clip.color = palette;
|
||||
old
|
||||
} else {
|
||||
return Ok(None)
|
||||
}
|
||||
}
|
||||
}))
|
||||
},
|
||||
Self::StopAll => {
|
||||
for track in 0..app.tracks.len(){app.tracks[track].player.enqueue_next(None);}
|
||||
None
|
||||
},
|
||||
Self::Pool(cmd) => if let Some(pool) = app.pool.as_mut() {
|
||||
let undo = cmd.clone().delegate(pool, Self::Pool)?;
|
||||
if let Some(editor) = app.editor.as_mut() {
|
||||
match cmd {
|
||||
// autoselect: automatically load selected clip in editor
|
||||
// autocolor: update color in all places simultaneously
|
||||
PoolCommand::Select(_) | PoolCommand::Clip(PoolClipCommand::SetColor(_, _)) =>
|
||||
editor.set_clip(pool.clip().as_ref()),
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
undo
|
||||
} else {
|
||||
None
|
||||
},
|
||||
_ => todo!("{self:?}")
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue