mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
remove some old macros
This commit is contained in:
parent
a82f73d475
commit
f1c7512cbb
18 changed files with 306 additions and 361 deletions
|
|
@ -120,7 +120,7 @@ impl<T: Content<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<T
|
|||
if ::crossterm::event::poll(poll).is_ok() {
|
||||
let event = ::crossterm::event::read().unwrap();
|
||||
match event {
|
||||
key_pat!(Ctrl-KeyCode::Char('c')) => {
|
||||
kpat!(Ctrl-KeyCode::Char('c')) => {
|
||||
exited.store(true, Relaxed);
|
||||
},
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -61,20 +61,11 @@ pub const fn shift (event: Event) -> Event {
|
|||
event
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! key_pat {
|
||||
(Ctrl-Alt-$code:pat) => { key_event_pat!($code, KeyModifiers::CONTROL | KeyModifiers::ALT) };
|
||||
(Ctrl-$code:pat) => { key_event_pat!($code, KeyModifiers::CONTROL) };
|
||||
(Alt-$code:pat) => { key_event_pat!($code, KeyModifiers::ALT) };
|
||||
(Shift-$code:pat) => { key_event_pat!($code, KeyModifiers::SHIFT) };
|
||||
($code:pat) => { crossterm::event::Event::Key(KeyEvent {
|
||||
code: $code,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE
|
||||
}) };
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! key_event_pat {
|
||||
#[macro_export] macro_rules! kpat {
|
||||
(Ctrl-Alt-$code:pat) => { kpat!($code, KeyModifiers::CONTROL | KeyModifiers::ALT) };
|
||||
(Ctrl-$code:pat) => { kpat!($code, KeyModifiers::CONTROL) };
|
||||
(Alt-$code:pat) => { kpat!($code, KeyModifiers::ALT) };
|
||||
(Shift-$code:pat) => { kpat!($code, KeyModifiers::SHIFT) };
|
||||
($code:pat) => {
|
||||
crossterm::event::Event::Key(KeyEvent {
|
||||
code: $code,
|
||||
|
|
@ -102,14 +93,6 @@ pub const fn shift (event: Event) -> Event {
|
|||
($code:expr) => { key_event_expr!($code) };
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! key_expr {
|
||||
(Ctrl-Alt-$code:ident) => { key_event_expr!($code, KeyModifiers::CONTROL | KeyModifiers::ALT) };
|
||||
(Ctrl-$code:ident) => { key_event_expr!($code, KeyModifiers::CONTROL) };
|
||||
(Alt-$code:ident) => { key_event_expr!($code, KeyModifiers::ALT) };
|
||||
(Shift-$code:ident) => { key_event_expr!($code, KeyModifiers::SHIFT) };
|
||||
($code:ident) => { key_event_expr!($code) };
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! key_event_expr {
|
||||
($code:expr, $modifiers: expr) => {
|
||||
crossterm::event::Event::Key(KeyEvent {
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ impl Handle<Tui> for Demo<Tui> {
|
|||
fn handle (&mut self, from: &TuiIn) -> Perhaps<bool> {
|
||||
use KeyCode::{PageUp, PageDown};
|
||||
match from.event() {
|
||||
key_expr!(PageUp) => {
|
||||
kexp!(PageUp) => {
|
||||
self.index = (self.index + 1) % self.items.len();
|
||||
},
|
||||
key_expr!(PageDown) => {
|
||||
kexp!(PageDown) => {
|
||||
self.index = if self.index > 1 {
|
||||
self.index - 1
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -69,78 +69,78 @@ keymap!(KEYS_ARRANGER = |state: ArrangerTui, input: Event| ArrangerCommand {
|
|||
let s_len = state.scenes.len();
|
||||
match state.selected() {
|
||||
Selected::Clip(t, s) => match input {
|
||||
key_pat!(Char('g')) => Some(Cmd::Phrases(PoolCommand::Select(0))),
|
||||
key_pat!(Char('q')) => Some(Cmd::Clip(Clip::Enqueue(t, s))),
|
||||
key_pat!(Char(',')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
key_pat!(Char('.')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
key_pat!(Char('<')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
key_pat!(Char('>')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
key_pat!(Char('p')) => Some(Cmd::Clip(Clip::Put(t, s, Some(state.pool.phrase().clone())))),
|
||||
key_pat!(Char('l')) => Some(Cmd::Clip(ArrangerClipCommand::SetLoop(t, s, false))),
|
||||
key_pat!(Delete) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
kpat!(Char('g')) => Some(Cmd::Phrases(PoolCommand::Select(0))),
|
||||
kpat!(Char('q')) => Some(Cmd::Clip(Clip::Enqueue(t, s))),
|
||||
kpat!(Char(',')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
kpat!(Char('.')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
kpat!(Char('<')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
kpat!(Char('>')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
kpat!(Char('p')) => Some(Cmd::Clip(Clip::Put(t, s, Some(state.pool.phrase().clone())))),
|
||||
kpat!(Char('l')) => Some(Cmd::Clip(ArrangerClipCommand::SetLoop(t, s, false))),
|
||||
kpat!(Delete) => Some(Cmd::Clip(Clip::Put(t, s, None))),
|
||||
|
||||
key_pat!(Up) => Some(Cmd::Select(
|
||||
kpat!(Up) => Some(Cmd::Select(
|
||||
if s > 0 { Selected::Clip(t, s - 1) } else { Selected::Track(t) })),
|
||||
key_pat!(Down) => Some(Cmd::Select(
|
||||
kpat!(Down) => Some(Cmd::Select(
|
||||
Selected::Clip(t, (s + 1).min(s_len.saturating_sub(1))))),
|
||||
key_pat!(Left) => Some(Cmd::Select(
|
||||
kpat!(Left) => Some(Cmd::Select(
|
||||
if t > 0 { Selected::Clip(t - 1, s) } else { Selected::Scene(s) })),
|
||||
key_pat!(Right) => Some(Cmd::Select(
|
||||
kpat!(Right) => Some(Cmd::Select(
|
||||
Selected::Clip((t + 1).min(t_len.saturating_sub(1)), s))),
|
||||
|
||||
_ => None
|
||||
},
|
||||
Selected::Scene(s) => match input {
|
||||
key_pat!(Char(',')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
|
||||
key_pat!(Char('.')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
|
||||
key_pat!(Char('<')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
|
||||
key_pat!(Char('>')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
|
||||
key_pat!(Char('q')) => Some(Cmd::Scene(Scene::Enqueue(s))),
|
||||
key_pat!(Delete) => Some(Cmd::Scene(Scene::Delete(s))),
|
||||
key_pat!(Char('c')) => Some(Cmd::Scene(Scene::SetColor(s, ItemPalette::random()))),
|
||||
kpat!(Char(',')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
|
||||
kpat!(Char('.')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
|
||||
kpat!(Char('<')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
|
||||
kpat!(Char('>')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
|
||||
kpat!(Char('q')) => Some(Cmd::Scene(Scene::Enqueue(s))),
|
||||
kpat!(Delete) => Some(Cmd::Scene(Scene::Delete(s))),
|
||||
kpat!(Char('c')) => Some(Cmd::Scene(Scene::SetColor(s, ItemPalette::random()))),
|
||||
|
||||
key_pat!(Up) => Some(
|
||||
kpat!(Up) => Some(
|
||||
Cmd::Select(if s > 0 { Selected::Scene(s - 1) } else { Selected::Mix })),
|
||||
key_pat!(Down) => Some(
|
||||
kpat!(Down) => Some(
|
||||
Cmd::Select(Selected::Scene((s + 1).min(s_len.saturating_sub(1))))),
|
||||
key_pat!(Left) =>
|
||||
kpat!(Left) =>
|
||||
return None,
|
||||
key_pat!(Right) => Some(
|
||||
kpat!(Right) => Some(
|
||||
Cmd::Select(Selected::Clip(0, s))),
|
||||
|
||||
_ => None
|
||||
},
|
||||
Selected::Track(t) => match input {
|
||||
key_pat!(Char(',')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
|
||||
key_pat!(Char('.')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
|
||||
key_pat!(Char('<')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
|
||||
key_pat!(Char('>')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
|
||||
key_pat!(Delete) => Some(Cmd::Track(Track::Delete(t))),
|
||||
key_pat!(Char('c')) => Some(Cmd::Track(Track::SetColor(t, ItemPalette::random()))),
|
||||
kpat!(Char(',')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
|
||||
kpat!(Char('.')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
|
||||
kpat!(Char('<')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
|
||||
kpat!(Char('>')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
|
||||
kpat!(Delete) => Some(Cmd::Track(Track::Delete(t))),
|
||||
kpat!(Char('c')) => Some(Cmd::Track(Track::SetColor(t, ItemPalette::random()))),
|
||||
|
||||
key_pat!(Up) =>
|
||||
kpat!(Up) =>
|
||||
return None,
|
||||
key_pat!(Down) => Some(
|
||||
kpat!(Down) => Some(
|
||||
Cmd::Select(Selected::Clip(t, 0))),
|
||||
key_pat!(Left) => Some(
|
||||
kpat!(Left) => Some(
|
||||
Cmd::Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix })),
|
||||
key_pat!(Right) => Some(
|
||||
kpat!(Right) => Some(
|
||||
Cmd::Select(Selected::Track((t + 1).min(t_len.saturating_sub(1))))),
|
||||
|
||||
_ => None
|
||||
},
|
||||
Selected::Mix => match input {
|
||||
key_pat!(Delete) => Some(Cmd::Clear),
|
||||
key_pat!(Char('0')) => Some(Cmd::StopAll),
|
||||
key_pat!(Char('c')) => Some(Cmd::Color(ItemPalette::random())),
|
||||
kpat!(Delete) => Some(Cmd::Clear),
|
||||
kpat!(Char('0')) => Some(Cmd::StopAll),
|
||||
kpat!(Char('c')) => Some(Cmd::Color(ItemPalette::random())),
|
||||
|
||||
key_pat!(Up) =>
|
||||
kpat!(Up) =>
|
||||
return None,
|
||||
key_pat!(Down) => Some(
|
||||
kpat!(Down) => Some(
|
||||
Cmd::Select(Selected::Scene(0))),
|
||||
key_pat!(Left) =>
|
||||
kpat!(Left) =>
|
||||
return None,
|
||||
key_pat!(Right) => Some(
|
||||
kpat!(Right) => Some(
|
||||
Cmd::Select(Selected::Track(0))),
|
||||
|
||||
_ => None
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ use crate::*;
|
|||
fallback: None,
|
||||
bindings: &[ $(($key, &|$state|Some($handler)),)* ]
|
||||
};
|
||||
input_to_command!($Command: |state: $State, input: $Input|{
|
||||
$KEYS.handle(state, input)?
|
||||
});
|
||||
input_to_command!($Command: |state: $State, input: $Input|$KEYS.handle(state, input)?);
|
||||
};
|
||||
(
|
||||
$KEYS:ident = |$state:ident: $State:ty, $input:ident: $Input:ty| $Command:ty
|
||||
|
|
@ -22,9 +20,7 @@ use crate::*;
|
|||
fallback: Some(&|$state, $input|Some($default)),
|
||||
bindings: &[ $(($key, &|$state|Some($handler)),)* ]
|
||||
};
|
||||
input_to_command!($Command: |state: $State, input: $Input|{
|
||||
$KEYS.handle(state, input)?
|
||||
});
|
||||
input_to_command!($Command: |state: $State, input: $Input|$KEYS.handle(state, input)?);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
32
src/file.rs
32
src/file.rs
|
|
@ -119,30 +119,30 @@ input_to_command!(FileBrowserCommand: |state: PoolModel, input: Event|{
|
|||
use KeyCode::{Up, Down, Left, Right, Enter, Esc, Backspace, Char};
|
||||
if let Some(PoolMode::Import(_index, browser)) = &state.mode {
|
||||
match input {
|
||||
key_pat!(Up) => Select(browser.index.overflowing_sub(1).0
|
||||
kpat!(Up) => Select(browser.index.overflowing_sub(1).0
|
||||
.min(browser.len().saturating_sub(1))),
|
||||
key_pat!(Down) => Select(browser.index.saturating_add(1)
|
||||
kpat!(Down) => Select(browser.index.saturating_add(1)
|
||||
% browser.len()),
|
||||
key_pat!(Right) => Chdir(browser.cwd.clone()),
|
||||
key_pat!(Left) => Chdir(browser.cwd.clone()),
|
||||
key_pat!(Enter) => Confirm,
|
||||
key_pat!(Char(_)) => { todo!() },
|
||||
key_pat!(Backspace) => { todo!() },
|
||||
key_pat!(Esc) => Cancel,
|
||||
kpat!(Right) => Chdir(browser.cwd.clone()),
|
||||
kpat!(Left) => Chdir(browser.cwd.clone()),
|
||||
kpat!(Enter) => Confirm,
|
||||
kpat!(Char(_)) => { todo!() },
|
||||
kpat!(Backspace) => { todo!() },
|
||||
kpat!(Esc) => Cancel,
|
||||
_ => return None
|
||||
}
|
||||
} else if let Some(PoolMode::Export(_index, browser)) = &state.mode {
|
||||
match input {
|
||||
key_pat!(Up) => Select(browser.index.overflowing_sub(1).0
|
||||
kpat!(Up) => Select(browser.index.overflowing_sub(1).0
|
||||
.min(browser.len())),
|
||||
key_pat!(Down) => Select(browser.index.saturating_add(1)
|
||||
kpat!(Down) => Select(browser.index.saturating_add(1)
|
||||
% browser.len()),
|
||||
key_pat!(Right) => Chdir(browser.cwd.clone()),
|
||||
key_pat!(Left) => Chdir(browser.cwd.clone()),
|
||||
key_pat!(Enter) => Confirm,
|
||||
key_pat!(Char(_)) => { todo!() },
|
||||
key_pat!(Backspace) => { todo!() },
|
||||
key_pat!(Esc) => Cancel,
|
||||
kpat!(Right) => Chdir(browser.cwd.clone()),
|
||||
kpat!(Left) => Chdir(browser.cwd.clone()),
|
||||
kpat!(Enter) => Confirm,
|
||||
kpat!(Char(_)) => { todo!() },
|
||||
kpat!(Backspace) => { todo!() },
|
||||
kpat!(Esc) => Cancel,
|
||||
_ => return None
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
20
src/focus.rs
20
src/focus.rs
|
|
@ -248,16 +248,16 @@ pub trait FocusWrap<T> {
|
|||
|
||||
pub fn to_focus_command <T: Send + Sync> (input: &TuiIn) -> Option<FocusCommand<T>> {
|
||||
Some(match input.event() {
|
||||
key_pat!(Tab) => FocusCommand::Next,
|
||||
key_pat!(Shift-Tab) => FocusCommand::Prev,
|
||||
key_pat!(BackTab) => FocusCommand::Prev,
|
||||
key_pat!(Shift-BackTab) => FocusCommand::Prev,
|
||||
key_pat!(Up) => FocusCommand::Up,
|
||||
key_pat!(Down) => FocusCommand::Down,
|
||||
key_pat!(Left) => FocusCommand::Left,
|
||||
key_pat!(Right) => FocusCommand::Right,
|
||||
key_pat!(Enter) => FocusCommand::Enter,
|
||||
key_pat!(Esc) => FocusCommand::Exit,
|
||||
kpat!(Tab) => FocusCommand::Next,
|
||||
kpat!(Shift-Tab) => FocusCommand::Prev,
|
||||
kpat!(BackTab) => FocusCommand::Prev,
|
||||
kpat!(Shift-BackTab) => FocusCommand::Prev,
|
||||
kpat!(Up) => FocusCommand::Up,
|
||||
kpat!(Down) => FocusCommand::Down,
|
||||
kpat!(Left) => FocusCommand::Left,
|
||||
kpat!(Right) => FocusCommand::Right,
|
||||
kpat!(Enter) => FocusCommand::Enter,
|
||||
kpat!(Esc) => FocusCommand::Exit,
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub(crate) use ::tek_layout::{
|
|||
Engine, Size, Area,
|
||||
Output, Content, Thunk, render,
|
||||
Input, Handle, handle,
|
||||
kexp, key_pat, key_event_pat, key_event_expr,
|
||||
kexp, kpat,
|
||||
tui::{
|
||||
Tui,
|
||||
TuiIn, key, ctrl, shift, alt,
|
||||
|
|
|
|||
|
|
@ -181,8 +181,8 @@ keymap!(KEYS_MIDI_EDITOR = |s: MidiEditor, _input: Event| MidiEditCommand {
|
|||
key(Char('.')) => SetNoteLength(Note::next(s.note_len())),
|
||||
key(Char('<')) => SetNoteLength(Note::prev(s.note_len())),
|
||||
key(Char('>')) => SetNoteLength(Note::next(s.note_len())),
|
||||
//// TODO: key_pat!(Char('/')) => // toggle 3plet
|
||||
//// TODO: key_pat!(Char('?')) => // toggle dotted
|
||||
//// TODO: kpat!(Char('/')) => // toggle 3plet
|
||||
//// TODO: kpat!(Char('?')) => // toggle dotted
|
||||
});
|
||||
|
||||
impl MidiEditor {
|
||||
|
|
|
|||
10
src/mixer.rs
10
src/mixer.rs
|
|
@ -213,15 +213,15 @@ handle!(<Tui>|self: Mixer, engine|{
|
|||
handle!(<Tui>|self:MixerTrack,from|{
|
||||
match from.event() {
|
||||
//, NONE, "chain_cursor_up", "move cursor up", || {
|
||||
key_pat!(KeyCode::Up) => {
|
||||
kpat!(KeyCode::Up) => {
|
||||
Ok(Some(true))
|
||||
},
|
||||
// , NONE, "chain_cursor_down", "move cursor down", || {
|
||||
key_pat!(KeyCode::Down) => {
|
||||
kpat!(KeyCode::Down) => {
|
||||
Ok(Some(true))
|
||||
},
|
||||
// Left, NONE, "chain_cursor_left", "move cursor left", || {
|
||||
key_pat!(KeyCode::Left) => {
|
||||
kpat!(KeyCode::Left) => {
|
||||
//if let Some(track) = app.arranger.track_mut() {
|
||||
//track.device = track.device.saturating_sub(1);
|
||||
//return Ok(true)
|
||||
|
|
@ -229,7 +229,7 @@ handle!(<Tui>|self:MixerTrack,from|{
|
|||
Ok(Some(true))
|
||||
},
|
||||
// , NONE, "chain_cursor_right", "move cursor right", || {
|
||||
key_pat!(KeyCode::Right) => {
|
||||
kpat!(KeyCode::Right) => {
|
||||
//if let Some(track) = app.arranger.track_mut() {
|
||||
//track.device = (track.device + 1).min(track.devices.len().saturating_sub(1));
|
||||
//return Ok(true)
|
||||
|
|
@ -237,7 +237,7 @@ handle!(<Tui>|self:MixerTrack,from|{
|
|||
Ok(Some(true))
|
||||
},
|
||||
// , NONE, "chain_mode_switch", "switch the display mode", || {
|
||||
key_pat!(KeyCode::Char('`')) => {
|
||||
kpat!(KeyCode::Char('`')) => {
|
||||
//app.chain_mode = !app.chain_mode;
|
||||
Ok(Some(true))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -200,29 +200,29 @@ fn draw_header (state: &Plugin, to: &mut TuiOut, x: u16, y: u16, w: u16) {
|
|||
|
||||
handle!(<Tui>|self:Plugin, from|{
|
||||
match from.event() {
|
||||
key_pat!(KeyCode::Up) => {
|
||||
kpat!(KeyCode::Up) => {
|
||||
self.selected = self.selected.saturating_sub(1);
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::Down) => {
|
||||
kpat!(KeyCode::Down) => {
|
||||
self.selected = (self.selected + 1).min(match &self.plugin {
|
||||
Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1,
|
||||
_ => unimplemented!()
|
||||
});
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::PageUp) => {
|
||||
kpat!(KeyCode::PageUp) => {
|
||||
self.selected = self.selected.saturating_sub(8);
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::PageDown) => {
|
||||
kpat!(KeyCode::PageDown) => {
|
||||
self.selected = (self.selected + 10).min(match &self.plugin {
|
||||
Some(PluginKind::LV2(LV2Plugin { port_list, .. })) => port_list.len() - 1,
|
||||
_ => unimplemented!()
|
||||
});
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::Char(',')) => {
|
||||
kpat!(KeyCode::Char(',')) => {
|
||||
match self.plugin.as_mut() {
|
||||
Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => {
|
||||
let index = port_list[self.selected].index;
|
||||
|
|
@ -234,7 +234,7 @@ handle!(<Tui>|self:Plugin, from|{
|
|||
}
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::Char('.')) => {
|
||||
kpat!(KeyCode::Char('.')) => {
|
||||
match self.plugin.as_mut() {
|
||||
Some(PluginKind::LV2(LV2Plugin { port_list, ref mut instance, .. })) => {
|
||||
let index = port_list[self.selected].index;
|
||||
|
|
@ -246,7 +246,7 @@ handle!(<Tui>|self:Plugin, from|{
|
|||
}
|
||||
Ok(Some(true))
|
||||
},
|
||||
key_pat!(KeyCode::Char('g')) => {
|
||||
kpat!(KeyCode::Char('g')) => {
|
||||
match self.plugin {
|
||||
//Some(PluginKind::LV2(ref mut plugin)) => {
|
||||
//plugin.ui_thread = Some(run_lv2_ui(LV2PluginUI::new()?)?);
|
||||
|
|
|
|||
26
src/pool.rs
26
src/pool.rs
|
|
@ -117,42 +117,42 @@ fn to_phrases_command (state: &PoolModel, input: &Event) -> Option<PoolCommand>
|
|||
let index = state.phrase_index();
|
||||
let count = state.phrases().len();
|
||||
Some(match input {
|
||||
key_pat!(Char('n')) => Cmd::Rename(PhraseRenameCommand::Begin),
|
||||
key_pat!(Char('t')) => Cmd::Length(PhraseLengthCommand::Begin),
|
||||
key_pat!(Char('m')) => Cmd::Import(FileBrowserCommand::Begin),
|
||||
key_pat!(Char('x')) => Cmd::Export(FileBrowserCommand::Begin),
|
||||
key_pat!(Char('c')) => Cmd::Phrase(PhrasePoolCommand::SetColor(index, ItemColor::random())),
|
||||
key_pat!(Char('[')) | key_pat!(Up) => Cmd::Select(
|
||||
kpat!(Char('n')) => Cmd::Rename(PhraseRenameCommand::Begin),
|
||||
kpat!(Char('t')) => Cmd::Length(PhraseLengthCommand::Begin),
|
||||
kpat!(Char('m')) => Cmd::Import(FileBrowserCommand::Begin),
|
||||
kpat!(Char('x')) => Cmd::Export(FileBrowserCommand::Begin),
|
||||
kpat!(Char('c')) => Cmd::Phrase(PhrasePoolCommand::SetColor(index, ItemColor::random())),
|
||||
kpat!(Char('[')) | kpat!(Up) => Cmd::Select(
|
||||
index.overflowing_sub(1).0.min(state.phrases().len() - 1)
|
||||
),
|
||||
key_pat!(Char(']')) | key_pat!(Down) => Cmd::Select(
|
||||
kpat!(Char(']')) | kpat!(Down) => Cmd::Select(
|
||||
index.saturating_add(1) % state.phrases().len()
|
||||
),
|
||||
key_pat!(Char('<')) => if index > 1 {
|
||||
kpat!(Char('<')) => if index > 1 {
|
||||
state.set_phrase_index(state.phrase_index().saturating_sub(1));
|
||||
Cmd::Phrase(PhrasePoolCommand::Swap(index - 1, index))
|
||||
} else {
|
||||
return None
|
||||
},
|
||||
key_pat!(Char('>')) => if index < count.saturating_sub(1) {
|
||||
kpat!(Char('>')) => if index < count.saturating_sub(1) {
|
||||
state.set_phrase_index(state.phrase_index() + 1);
|
||||
Cmd::Phrase(PhrasePoolCommand::Swap(index + 1, index))
|
||||
} else {
|
||||
return None
|
||||
},
|
||||
key_pat!(Delete) => if index > 0 {
|
||||
kpat!(Delete) => if index > 0 {
|
||||
state.set_phrase_index(index.min(count.saturating_sub(1)));
|
||||
Cmd::Phrase(PhrasePoolCommand::Delete(index))
|
||||
} else {
|
||||
return None
|
||||
},
|
||||
key_pat!(Char('a')) | key_pat!(Shift-Char('A')) => Cmd::Phrase(PhrasePoolCommand::Add(count, MidiClip::new(
|
||||
kpat!(Char('a')) | kpat!(Shift-Char('A')) => Cmd::Phrase(PhrasePoolCommand::Add(count, MidiClip::new(
|
||||
String::from("Clip"), true, 4 * PPQ, None, Some(ItemPalette::random())
|
||||
))),
|
||||
key_pat!(Char('i')) => Cmd::Phrase(PhrasePoolCommand::Add(index + 1, MidiClip::new(
|
||||
kpat!(Char('i')) => Cmd::Phrase(PhrasePoolCommand::Add(index + 1, MidiClip::new(
|
||||
String::from("Clip"), true, 4 * PPQ, None, Some(ItemPalette::random())
|
||||
))),
|
||||
key_pat!(Char('d')) | key_pat!(Shift-Char('D')) => {
|
||||
kpat!(Char('d')) | kpat!(Shift-Char('D')) => {
|
||||
let mut phrase = state.phrases()[index].read().unwrap().duplicate();
|
||||
phrase.color = ItemPalette::random_near(phrase.color, 0.25);
|
||||
Cmd::Phrase(PhrasePoolCommand::Add(index + 1, phrase))
|
||||
|
|
|
|||
|
|
@ -130,12 +130,12 @@ command!(|self:PhraseLengthCommand,state:PoolModel|{
|
|||
input_to_command!(PhraseLengthCommand: |state: PoolModel, input: Event|{
|
||||
if let Some(PoolMode::Length(_, length, _)) = state.phrases_mode() {
|
||||
match input {
|
||||
key_pat!(Up) => Self::Inc,
|
||||
key_pat!(Down) => Self::Dec,
|
||||
key_pat!(Right) => Self::Next,
|
||||
key_pat!(Left) => Self::Prev,
|
||||
key_pat!(Enter) => Self::Set(*length),
|
||||
key_pat!(Esc) => Self::Cancel,
|
||||
kpat!(Up) => Self::Inc,
|
||||
kpat!(Down) => Self::Dec,
|
||||
kpat!(Right) => Self::Next,
|
||||
kpat!(Left) => Self::Prev,
|
||||
kpat!(Enter) => Self::Set(*length),
|
||||
kpat!(Esc) => Self::Cancel,
|
||||
_ => return None
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -39,18 +39,18 @@ impl InputToCommand<Event, PoolModel> for PhraseRenameCommand {
|
|||
use KeyCode::{Char, Backspace, Enter, Esc};
|
||||
if let Some(PoolMode::Rename(_, ref old_name)) = state.phrases_mode() {
|
||||
Some(match input {
|
||||
key_pat!(Char(c)) => {
|
||||
kpat!(Char(c)) => {
|
||||
let mut new_name = old_name.clone();
|
||||
new_name.push(*c);
|
||||
Self::Set(new_name)
|
||||
},
|
||||
key_pat!(Backspace) => {
|
||||
kpat!(Backspace) => {
|
||||
let mut new_name = old_name.clone();
|
||||
new_name.pop();
|
||||
Self::Set(new_name)
|
||||
},
|
||||
key_pat!(Enter) => Self::Confirm,
|
||||
key_pat!(Esc) => Self::Cancel,
|
||||
kpat!(Enter) => Self::Confirm,
|
||||
kpat!(Esc) => Self::Cancel,
|
||||
_ => return None
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
151
src/sampler.rs
151
src/sampler.rs
|
|
@ -1,10 +1,12 @@
|
|||
mod sample; pub use self::sample::*;
|
||||
mod voice; pub use self::voice::*;
|
||||
mod sampler_tui; pub use self::sampler_tui::*;
|
||||
mod sampler_status; pub use self::sampler_status::*;
|
||||
mod sample_import; pub use self::sample_import::*;
|
||||
mod sample_list; pub use self::sample_list::*;
|
||||
mod sample_viewer; pub use self::sample_viewer::*;
|
||||
mod sampler_audio; pub use self::sampler_audio::*;
|
||||
mod sampler_command; pub use self::sampler_command::*;
|
||||
mod sampler_status; pub use self::sampler_status::*;
|
||||
mod sampler_tui; pub use self::sampler_tui::*;
|
||||
mod voice; pub use self::voice::*;
|
||||
|
||||
use crate::*;
|
||||
use KeyCode::Char;
|
||||
|
|
@ -88,146 +90,3 @@ impl Sampler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SamplerCommand {
|
||||
RecordBegin(u7),
|
||||
RecordCancel,
|
||||
RecordFinish,
|
||||
SetSample(u7, Option<Arc<RwLock<Sample>>>),
|
||||
SetStart(u7, usize),
|
||||
SetGain(f32),
|
||||
NoteOn(u7, u7),
|
||||
NoteOff(u7),
|
||||
}
|
||||
|
||||
command!(|self: SamplerCommand, state: Sampler|match self {
|
||||
Self::SetSample(index, sample) => {
|
||||
let i = index.as_int() as usize;
|
||||
let old = state.mapped[i].clone();
|
||||
state.mapped[i] = sample;
|
||||
Some(Self::SetSample(index, old))
|
||||
},
|
||||
Self::RecordBegin(index) => {
|
||||
state.begin_recording(index.as_int() as usize);
|
||||
None
|
||||
},
|
||||
Self::RecordCancel => {
|
||||
state.cancel_recording();
|
||||
None
|
||||
},
|
||||
Self::RecordFinish => {
|
||||
state.finish_recording();
|
||||
None
|
||||
},
|
||||
_ => todo!()
|
||||
});
|
||||
|
||||
audio!(|self: SamplerTui, client, scope|{
|
||||
SamplerAudio(&mut self.state).process(client, scope)
|
||||
});
|
||||
|
||||
pub struct SamplerAudio<'a>(pub &'a mut Sampler);
|
||||
|
||||
audio!(|self: SamplerAudio<'a>, _client, scope|{
|
||||
self.0.process_midi_in(scope);
|
||||
self.0.clear_output_buffer();
|
||||
self.0.process_audio_out(scope);
|
||||
self.0.write_output_buffer(scope);
|
||||
self.0.process_audio_in(scope);
|
||||
Control::Continue
|
||||
});
|
||||
|
||||
impl Sampler {
|
||||
|
||||
pub fn process_audio_in (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { audio_ins, input_meter, recording, .. } = self;
|
||||
if audio_ins.len() != input_meter.len() {
|
||||
*input_meter = vec![0.0;audio_ins.len()];
|
||||
}
|
||||
if let Some((_, sample)) = recording {
|
||||
let mut sample = sample.write().unwrap();
|
||||
if sample.channels.len() != audio_ins.len() {
|
||||
panic!("channel count mismatch");
|
||||
}
|
||||
let iterator = audio_ins.iter().zip(input_meter).zip(sample.channels.iter_mut());
|
||||
let mut length = 0;
|
||||
for ((input, meter), channel) in iterator {
|
||||
let slice = input.as_slice(scope);
|
||||
length = length.max(slice.len());
|
||||
let total: f32 = slice.iter().map(|x|x.abs()).sum();
|
||||
let count = slice.len() as f32;
|
||||
*meter = 10. * (total / count).log10();
|
||||
channel.extend_from_slice(slice);
|
||||
}
|
||||
sample.end += length;
|
||||
} else {
|
||||
for (input, meter) in audio_ins.iter().zip(input_meter) {
|
||||
let slice = input.as_slice(scope);
|
||||
let total: f32 = slice.iter().map(|x|x.abs()).sum();
|
||||
let count = slice.len() as f32;
|
||||
*meter = 10. * (total / count).log10();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create [Voice]s from [Sample]s in response to MIDI input.
|
||||
pub fn process_midi_in (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { midi_in, mapped, voices, .. } = self;
|
||||
for RawMidi { time, bytes } in midi_in.iter(scope) {
|
||||
if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() {
|
||||
match message {
|
||||
MidiMessage::NoteOn { ref key, ref vel } => {
|
||||
if let Some(ref sample) = mapped[key.as_int() as usize] {
|
||||
voices.write().unwrap().push(Sample::play(sample, time as usize, vel));
|
||||
}
|
||||
},
|
||||
MidiMessage::Controller { controller, value } => {
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Zero the output buffer.
|
||||
pub fn clear_output_buffer (&mut self) {
|
||||
for buffer in self.buffer.iter_mut() {
|
||||
buffer.fill(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mix all currently playing samples into the output.
|
||||
pub fn process_audio_out (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { ref mut buffer, voices, output_gain, .. } = self;
|
||||
let channel_count = buffer.len();
|
||||
voices.write().unwrap().retain_mut(|voice|{
|
||||
for index in 0..scope.n_frames() as usize {
|
||||
if let Some(frame) = voice.next() {
|
||||
for (channel, sample) in frame.iter().enumerate() {
|
||||
// Averaging mixer:
|
||||
//self.buffer[channel % channel_count][index] = (
|
||||
//(self.buffer[channel % channel_count][index] + sample * self.output_gain) / 2.0
|
||||
//);
|
||||
buffer[channel % channel_count][index] += sample * *output_gain;
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
/// Write output buffer to output ports.
|
||||
pub fn write_output_buffer (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { ref mut audio_outs, buffer, .. } = self;
|
||||
for (i, port) in audio_outs.iter_mut().enumerate() {
|
||||
let buffer = &buffer[i];
|
||||
for (i, value) in port.as_mut_slice(scope).iter_mut().enumerate() {
|
||||
*value = *buffer.get(i).unwrap_or(&0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
111
src/sampler/sampler_audio.rs
Normal file
111
src/sampler/sampler_audio.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
use crate::*;
|
||||
|
||||
audio!(|self: SamplerTui, client, scope|{
|
||||
SamplerAudio(&mut self.state).process(client, scope)
|
||||
});
|
||||
|
||||
pub struct SamplerAudio<'a>(pub &'a mut Sampler);
|
||||
|
||||
audio!(|self: SamplerAudio<'a>, _client, scope|{
|
||||
self.0.process_midi_in(scope);
|
||||
self.0.clear_output_buffer();
|
||||
self.0.process_audio_out(scope);
|
||||
self.0.write_output_buffer(scope);
|
||||
self.0.process_audio_in(scope);
|
||||
Control::Continue
|
||||
});
|
||||
|
||||
impl Sampler {
|
||||
|
||||
pub fn process_audio_in (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { audio_ins, input_meter, recording, .. } = self;
|
||||
if audio_ins.len() != input_meter.len() {
|
||||
*input_meter = vec![0.0;audio_ins.len()];
|
||||
}
|
||||
if let Some((_, sample)) = recording {
|
||||
let mut sample = sample.write().unwrap();
|
||||
if sample.channels.len() != audio_ins.len() {
|
||||
panic!("channel count mismatch");
|
||||
}
|
||||
let iterator = audio_ins.iter().zip(input_meter).zip(sample.channels.iter_mut());
|
||||
let mut length = 0;
|
||||
for ((input, meter), channel) in iterator {
|
||||
let slice = input.as_slice(scope);
|
||||
length = length.max(slice.len());
|
||||
let total: f32 = slice.iter().map(|x|x.abs()).sum();
|
||||
let count = slice.len() as f32;
|
||||
*meter = 10. * (total / count).log10();
|
||||
channel.extend_from_slice(slice);
|
||||
}
|
||||
sample.end += length;
|
||||
} else {
|
||||
for (input, meter) in audio_ins.iter().zip(input_meter) {
|
||||
let slice = input.as_slice(scope);
|
||||
let total: f32 = slice.iter().map(|x|x.abs()).sum();
|
||||
let count = slice.len() as f32;
|
||||
*meter = 10. * (total / count).log10();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create [Voice]s from [Sample]s in response to MIDI input.
|
||||
pub fn process_midi_in (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { midi_in, mapped, voices, .. } = self;
|
||||
for RawMidi { time, bytes } in midi_in.iter(scope) {
|
||||
if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() {
|
||||
match message {
|
||||
MidiMessage::NoteOn { ref key, ref vel } => {
|
||||
if let Some(ref sample) = mapped[key.as_int() as usize] {
|
||||
voices.write().unwrap().push(Sample::play(sample, time as usize, vel));
|
||||
}
|
||||
},
|
||||
MidiMessage::Controller { controller, value } => {
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Zero the output buffer.
|
||||
pub fn clear_output_buffer (&mut self) {
|
||||
for buffer in self.buffer.iter_mut() {
|
||||
buffer.fill(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Mix all currently playing samples into the output.
|
||||
pub fn process_audio_out (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { ref mut buffer, voices, output_gain, .. } = self;
|
||||
let channel_count = buffer.len();
|
||||
voices.write().unwrap().retain_mut(|voice|{
|
||||
for index in 0..scope.n_frames() as usize {
|
||||
if let Some(frame) = voice.next() {
|
||||
for (channel, sample) in frame.iter().enumerate() {
|
||||
// Averaging mixer:
|
||||
//self.buffer[channel % channel_count][index] = (
|
||||
//(self.buffer[channel % channel_count][index] + sample * self.output_gain) / 2.0
|
||||
//);
|
||||
buffer[channel % channel_count][index] += sample * *output_gain;
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
/// Write output buffer to output ports.
|
||||
pub fn write_output_buffer (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { ref mut audio_outs, buffer, .. } = self;
|
||||
for (i, port) in audio_outs.iter_mut().enumerate() {
|
||||
let buffer = &buffer[i];
|
||||
for (i, value) in port.as_mut_slice(scope).iter_mut().enumerate() {
|
||||
*value = *buffer.get(i).unwrap_or(&0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
71
src/sampler/sampler_command.rs
Normal file
71
src/sampler/sampler_command.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
use crate::*;
|
||||
|
||||
handle!(<Tui>|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input.event()));
|
||||
|
||||
pub enum SamplerTuiCommand {
|
||||
Import(FileBrowserCommand),
|
||||
Select(usize),
|
||||
Sample(SamplerCommand),
|
||||
}
|
||||
|
||||
pub enum SamplerCommand {
|
||||
RecordBegin(u7),
|
||||
RecordCancel,
|
||||
RecordFinish,
|
||||
SetSample(u7, Option<Arc<RwLock<Sample>>>),
|
||||
SetStart(u7, usize),
|
||||
SetGain(f32),
|
||||
NoteOn(u7, u7),
|
||||
NoteOff(u7),
|
||||
}
|
||||
|
||||
input_to_command!(SamplerTuiCommand: |state: SamplerTui, input: Event|match state.mode{
|
||||
Some(SamplerMode::Import(..)) => Self::Import(
|
||||
FileBrowserCommand::input_to_command(state, input)?
|
||||
),
|
||||
_ => match input {
|
||||
// load sample
|
||||
kpat!(Shift-Char('L')) => Self::Import(FileBrowserCommand::Begin),
|
||||
kpat!(KeyCode::Up) => Self::Select(state.note_point().overflowing_add(1).0.min(127)),
|
||||
kpat!(KeyCode::Down) => Self::Select(state.note_point().overflowing_sub(1).0.min(127)),
|
||||
_ => return None
|
||||
}
|
||||
});
|
||||
|
||||
command!(|self: SamplerTuiCommand, state: SamplerTui|match self {
|
||||
Self::Import(FileBrowserCommand::Begin) => {
|
||||
let voices = &state.state.voices;
|
||||
let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
|
||||
state.mode = Some(SamplerMode::Import(0, FileBrowser::new(None)?));
|
||||
None
|
||||
},
|
||||
Self::Select(index) => {
|
||||
let old = state.note_point();
|
||||
state.set_note_point(index);
|
||||
Some(Self::Select(old))
|
||||
},
|
||||
Self::Sample(cmd) => cmd.execute(&mut state.state)?.map(Self::Sample),
|
||||
_ => todo!()
|
||||
});
|
||||
|
||||
command!(|self: SamplerCommand, state: Sampler|match self {
|
||||
Self::SetSample(index, sample) => {
|
||||
let i = index.as_int() as usize;
|
||||
let old = state.mapped[i].clone();
|
||||
state.mapped[i] = sample;
|
||||
Some(Self::SetSample(index, old))
|
||||
},
|
||||
Self::RecordBegin(index) => {
|
||||
state.begin_recording(index.as_int() as usize);
|
||||
None
|
||||
},
|
||||
Self::RecordCancel => {
|
||||
state.cancel_recording();
|
||||
None
|
||||
},
|
||||
Self::RecordFinish => {
|
||||
state.finish_recording();
|
||||
None
|
||||
},
|
||||
_ => todo!()
|
||||
});
|
||||
|
|
@ -31,19 +31,6 @@ impl SamplerTui {
|
|||
}
|
||||
}
|
||||
|
||||
//from_jack!(|jack|SamplerTui{
|
||||
//Self {
|
||||
//cursor: (0, 0),
|
||||
//editing: None,
|
||||
//mode: None,
|
||||
//size: Measure::new(),
|
||||
//note_lo: 36.into(),
|
||||
//note_pt: 36.into(),
|
||||
//color: ItemPalette::from(Color::Rgb(64, 128, 32)),
|
||||
//state: Sampler::new(jack, &"sampler", &[], &[&[], &[]], &[&[], &[]])?,
|
||||
//}
|
||||
//});
|
||||
|
||||
render!(Tui: (self: SamplerTui) => {
|
||||
let keys_width = 5;
|
||||
let keys = move||"";//SamplerKeys(self);
|
||||
|
|
@ -102,65 +89,3 @@ pub enum SamplerMode {
|
|||
// Load sample from path
|
||||
Import(usize, FileBrowser),
|
||||
}
|
||||
|
||||
handle!(<Tui>|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input.event()));
|
||||
|
||||
pub enum SamplerTuiCommand {
|
||||
Import(FileBrowserCommand),
|
||||
SelectNote(usize),
|
||||
SelectField(usize),
|
||||
Sample(SamplerCommand),
|
||||
}
|
||||
|
||||
input_to_command!(SamplerTuiCommand: |state: SamplerTui, input: Event| match state.mode {
|
||||
Some(SamplerMode::Import(..)) => Self::Import(
|
||||
FileBrowserCommand::input_to_command(state, input)?
|
||||
),
|
||||
_ => match input {
|
||||
// load sample
|
||||
key_pat!(Shift-Char('L')) => {
|
||||
Self::Import(FileBrowserCommand::Begin)
|
||||
},
|
||||
key_pat!(KeyCode::Up) => {
|
||||
Self::SelectNote(state.note_point().overflowing_add(1).0.min(127))
|
||||
},
|
||||
key_pat!(KeyCode::Down) => {
|
||||
Self::SelectNote(state.note_point().overflowing_sub(1).0.min(127))
|
||||
},
|
||||
_ => return None
|
||||
}
|
||||
//key_pat!(KeyCode::Char('p')) => if let Some(sample) = self.sample() {
|
||||
//voices.write().unwrap().push(Sample::play(sample, 0, &100.into()));
|
||||
//},
|
||||
//key_pat!(KeyCode::Char('a')) => {
|
||||
//let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
|
||||
//self.mode = None;//Some(Exit::boxed(AddSampleModal::new(&sample, &voices)?));
|
||||
//unmapped.push(sample);
|
||||
//},
|
||||
//key_pat!(KeyCode::Char('r')) => if let Some(sample) = self.sample() {
|
||||
//self.mode = None;//Some(Exit::boxed(AddSampleModal::new(&sample, &voices)?));
|
||||
//},
|
||||
//key_pat!(KeyCode::Enter) => if let Some(sample) = self.sample() {
|
||||
//self.editing = Some(sample.clone());
|
||||
//},
|
||||
//_ => {
|
||||
//return Ok(None)
|
||||
//}
|
||||
//}
|
||||
});
|
||||
|
||||
command!(|self: SamplerTuiCommand, state: SamplerTui|match self {
|
||||
Self::Import(FileBrowserCommand::Begin) => {
|
||||
let voices = &state.state.voices;
|
||||
let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
|
||||
state.mode = Some(SamplerMode::Import(0, FileBrowser::new(None)?));
|
||||
None
|
||||
},
|
||||
Self::SelectNote(index) => {
|
||||
let old = state.note_point();
|
||||
state.set_note_point(index);
|
||||
Some(Self::SelectNote(old))
|
||||
},
|
||||
Self::Sample(cmd) => cmd.execute(&mut state.state)?.map(Self::Sample),
|
||||
_ => todo!()
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue