mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
euphuckingwrecka
This commit is contained in:
parent
3e9545fe26
commit
7746abc9ee
5 changed files with 92 additions and 86 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
(keys
|
(keys
|
||||||
(layer-if :focus-editor "./keys_editor.edn")
|
(layer-if :focus-editor "./keys_editor.edn")
|
||||||
|
(layer-if :focus-dialog "./keys_dialog.edn")
|
||||||
(layer-if :focus-message "./keys_message.edn")
|
(layer-if :focus-message "./keys_message.edn")
|
||||||
(layer-if :focus-device-add "./keys_device_add.edn")
|
(layer-if :focus-device-add "./keys_device_add.edn")
|
||||||
(layer-if :focus-browser "./keys_browser.edn")
|
(layer-if :focus-browser "./keys_browser.edn")
|
||||||
|
|
@ -21,6 +22,7 @@
|
||||||
(bsp/a :view-dialog
|
(bsp/a :view-dialog
|
||||||
(bsp/w :view-meters-output
|
(bsp/w :view-meters-output
|
||||||
(bsp/e :view-meters-input
|
(bsp/e :view-meters-input
|
||||||
|
(bsp/n :view-history
|
||||||
(bsp/n (fixed/y 2 :view-status-h2)
|
(bsp/n (fixed/y 2 :view-status-h2)
|
||||||
(bsp/n :view-tracks-inputs
|
(bsp/n :view-tracks-inputs
|
||||||
(bsp/s :view-tracks-devices
|
(bsp/s :view-tracks-devices
|
||||||
|
|
@ -28,4 +30,4 @@
|
||||||
(bsp/s :view-tracks-names
|
(bsp/s :view-tracks-names
|
||||||
(fill/xy (either :focus-editor
|
(fill/xy (either :focus-editor
|
||||||
(bsp/e :view-scenes-names :view-editor)
|
(bsp/e :view-scenes-names :view-editor)
|
||||||
:view-scenes)))))))))))
|
:view-scenes))))))))))))
|
||||||
|
|
|
||||||
0
config/keys_dialog.edn
Normal file
0
config/keys_dialog.edn
Normal file
|
|
@ -4,27 +4,69 @@ 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! 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 { ($cmd:expr) => {{ $cmd; None }}; }
|
||||||
macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); 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) {
|
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
||||||
|
impl App {
|
||||||
|
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
||||||
|
Ok(if let Some(command) = self.config.keys.command(self, input) {
|
||||||
// FIXME failed commands not persisted in undo history
|
// FIXME failed commands not persisted in undo history
|
||||||
let undo = command.clone().execute(self)?;
|
let undo = command.clone().execute(self)?;
|
||||||
self.history.push((command, undo));
|
self.history.push((command, undo));
|
||||||
Some(true)
|
Some(true)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}));
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
#[tengri_proc::command(App)]
|
#[tengri_proc::command(App)]
|
||||||
impl AppCommand {
|
impl AppCommand {
|
||||||
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
|
|
||||||
app.toggle_dialog(None);
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
fn toggle_editor (app: &mut App, value: bool) -> Perhaps<Self> {
|
fn toggle_editor (app: &mut App, value: bool) -> Perhaps<Self> {
|
||||||
app.toggle_editor(Some(value));
|
app.toggle_editor(Some(value));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
//fn color (app: &mut App, theme: ItemTheme) -> Perhaps<Self> {
|
fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps<Self> {
|
||||||
//Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme}))
|
Ok(if let Some(editor) = app.editor_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 dialog (app: &mut App, command: DialogCommand) -> Perhaps<Self> {
|
||||||
|
Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?)
|
||||||
|
}
|
||||||
|
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 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 pool (app: &mut App, command: PoolCommand) -> Perhaps<Self> {
|
||||||
|
let undo = command.clone().delegate(&mut app.pool, |command|AppCommand::Pool{command})?;
|
||||||
|
// update linked editor after pool action
|
||||||
|
match command {
|
||||||
|
// autoselect: automatically load selected clip in editor
|
||||||
|
PoolCommand::Select { .. } |
|
||||||
|
// autocolor: update color in all places simultaneously
|
||||||
|
PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => {
|
||||||
|
let clip = app.pool.clip().clone();
|
||||||
|
app.editor_mut().map(|editor|editor.set_clip(clip.as_ref()))
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
Ok(undo)
|
||||||
|
}
|
||||||
fn enqueue (app: &mut App, clip: Option<Arc<RwLock<MidiClip>>>) -> Perhaps<Self> {
|
fn enqueue (app: &mut App, clip: Option<Arc<RwLock<MidiClip>>>) -> Perhaps<Self> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
@ -34,10 +76,6 @@ impl AppCommand {
|
||||||
fn zoom (app: &mut App, zoom: usize) -> Perhaps<Self> {
|
fn zoom (app: &mut App, zoom: usize) -> Perhaps<Self> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
//fn launch (app: &mut App) -> Perhaps<Self> {
|
|
||||||
//app.project.launch();
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
fn select (app: &mut App, selection: Selection) -> Perhaps<Self> {
|
fn select (app: &mut App, selection: Selection) -> Perhaps<Self> {
|
||||||
*app.project.selection_mut() = selection;
|
*app.project.selection_mut() = selection;
|
||||||
//todo!
|
//todo!
|
||||||
|
|
@ -65,53 +103,13 @@ impl AppCommand {
|
||||||
app.tracks_stop_all();
|
app.tracks_stop_all();
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn dialog (app: &mut App, command: DialogCommand) -> Perhaps<Self> {
|
//fn color (app: &mut App, theme: ItemTheme) -> Perhaps<Self> {
|
||||||
Ok(command.delegate(&mut app.dialog, |command|Self::Dialog{command})?)
|
//Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme}))
|
||||||
}
|
//}
|
||||||
fn project (app: &mut App, command: ArrangementCommand) -> Perhaps<Self> {
|
//fn launch (app: &mut App) -> Perhaps<Self> {
|
||||||
Ok(command.delegate(&mut app.project, |command|Self::Project{command})?)
|
//app.project.launch();
|
||||||
}
|
//Ok(None)
|
||||||
fn clock (app: &mut App, command: ClockCommand) -> Perhaps<Self> {
|
//}
|
||||||
Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command}))
|
|
||||||
}
|
|
||||||
fn editor (app: &mut App, command: MidiEditCommand) -> Perhaps<Self> {
|
|
||||||
Ok(if let Some(editor) = app.editor_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 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 pool (app: &mut App, command: PoolCommand) -> Perhaps<Self> {
|
|
||||||
let undo = command.clone().delegate(
|
|
||||||
&mut app.pool,
|
|
||||||
|command|AppCommand::Pool{command}
|
|
||||||
)?;
|
|
||||||
// update linked editor after pool action
|
|
||||||
match command {
|
|
||||||
// autoselect: automatically load selected clip in editor
|
|
||||||
PoolCommand::Select { .. } |
|
|
||||||
// autocolor: update color in all places simultaneously
|
|
||||||
PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => {
|
|
||||||
let clip = app.pool.clip().clone();
|
|
||||||
app.editor_mut().map(|editor|editor.set_clip(clip.as_ref()))
|
|
||||||
},
|
|
||||||
_ => None
|
|
||||||
};
|
|
||||||
Ok(undo)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<'state> Context<'state, ClockCommand> for App {
|
impl<'state> Context<'state, ClockCommand> for App {
|
||||||
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClockCommand> {
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<ClockCommand> {
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,9 @@ impl App {
|
||||||
fn focus_editor (&self) -> bool {
|
fn focus_editor (&self) -> bool {
|
||||||
self.project.editor.is_some()
|
self.project.editor.is_some()
|
||||||
}
|
}
|
||||||
|
fn focus_dialog (&self) -> bool {
|
||||||
|
self.dialog.is_some()
|
||||||
|
}
|
||||||
fn focus_message (&self) -> bool {
|
fn focus_message (&self) -> bool {
|
||||||
matches!(self.dialog, Some(Dialog::Message(..)))
|
matches!(self.dialog, Some(Dialog::Message(..)))
|
||||||
}
|
}
|
||||||
|
|
@ -451,13 +454,11 @@ impl Configuration {
|
||||||
let cond = cond.unwrap();
|
let cond = cond.unwrap();
|
||||||
println!("ok");
|
println!("ok");
|
||||||
map.add_layer_if(
|
map.add_layer_if(
|
||||||
Box::new(move |state|{
|
Box::new(move |state: &App|{
|
||||||
let mut exp = exp.clone();
|
Context::get(state,
|
||||||
let value = Context::get(state, &mut format!(":{cond}").as_str().into()).unwrap_or(false);
|
&mut format!("{cond}").as_str().into())
|
||||||
if value {
|
.unwrap_or_else(||panic!(
|
||||||
panic!("layer-if cond={cond:?} exp={exp:?} value={value:?}");
|
"missing input layer conditional {cond} from {exp:?}"))
|
||||||
}
|
|
||||||
value
|
|
||||||
}),
|
}),
|
||||||
keys
|
keys
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,11 @@ impl App {
|
||||||
pub fn view_nil (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_nil (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
"nil"
|
"nil"
|
||||||
}
|
}
|
||||||
|
pub fn view_history (&self) -> impl Content<TuiOut> {
|
||||||
|
Fill::x(Align::w(self.history.last()
|
||||||
|
.map(|last|FieldH(self.color, format!("History ({})", self.history.len()),
|
||||||
|
Fill::x(Align::w(format!("{:?}", last.0)))))));
|
||||||
|
}
|
||||||
pub fn view_status_h2 (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_status_h2 (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
let theme = self.color;
|
let theme = self.color;
|
||||||
|
|
@ -24,25 +29,25 @@ impl App {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)));
|
)));
|
||||||
|
add(&" ");
|
||||||
{
|
{
|
||||||
let cache = self.view_cache.read().unwrap();
|
let cache = self.view_cache.read().unwrap();
|
||||||
add(&Fixed::x(16, Align::w(Bsp::s(
|
add(&Fixed::x(13, Align::w(Bsp::s(
|
||||||
FieldH(theme, "Beat", cache.beat.view.clone()),
|
FieldH(theme, "Beat", cache.beat.view.clone()),
|
||||||
FieldH(theme, "Time", cache.time.view.clone()),
|
FieldH(theme, "Time", cache.time.view.clone()),
|
||||||
))));
|
))));
|
||||||
add(&Fixed::x(16, Align::w(Bsp::s(
|
add(&Fixed::x(13, Align::w(Bsp::s(
|
||||||
Fill::x(Align::w(FieldH(theme, "BPM", cache.bpm.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "BPM", cache.bpm.view.clone()))),
|
||||||
Fill::x(Align::w(FieldH(theme, "SR ", cache.sr.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "SR ", cache.sr.view.clone()))),
|
||||||
))));
|
))));
|
||||||
add(&Fixed::x(16, Align::w(Bsp::s(
|
add(&Fixed::x(13, Align::w(Bsp::s(
|
||||||
Fill::x(Align::w(FieldH(theme, "Buf", cache.buf.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "Buf", cache.buf.view.clone()))),
|
||||||
Fill::x(Align::w(FieldH(theme, "Lat", cache.lat.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "Lat", cache.lat.view.clone()))),
|
||||||
))));
|
))));
|
||||||
add(&FieldV(theme, "Selection", Fill::x(Align::w(self.selection().describe(
|
add(&Fixed::x(16, FieldV(theme, "Selection", Align::w(self.selection().describe(
|
||||||
self.tracks(),
|
self.tracks(),
|
||||||
self.scenes()
|
self.scenes()
|
||||||
)))));
|
)))));
|
||||||
add(&FieldV(theme, "History", Fill::x(Align::w(format!("{}", self.history.len())))));
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue