device picker
Some checks are pending
/ build (push) Waiting to run

This commit is contained in:
🪞👃🪞 2025-05-04 16:23:50 +03:00
parent 55b6745d4d
commit a77536c234
6 changed files with 93 additions and 13 deletions

View file

@ -11,6 +11,7 @@
:arranger)))))) :arranger))))))
(keys (keys
(layer-if :mode-device-add "./keys_device_add.edn")
(layer-if :mode-pool-import "./keys_pool_file.edn") (layer-if :mode-pool-import "./keys_pool_file.edn")
(layer-if :mode-pool-export "./keys_pool_file.edn") (layer-if :mode-pool-export "./keys_pool_file.edn")
(layer-if :mode-pool-rename "./keys_clip_rename.edn") (layer-if :mode-pool-rename "./keys_clip_rename.edn")

View file

@ -1,11 +1,12 @@
(@t select :track 0) (@c color)
(@tab edit :clip) (@q launch)
(@c color) (@t select :track 0)
(@q launch) (@tab edit :clip)
(@shift-I input add) (@shift-I input add)
(@shift-O output add) (@shift-O output add)
(@shift-S scene add) (@shift-S scene add)
(@shift-T track add) (@shift-T track add)
(@shift-Z device picker)
(@up select :scene-prev) (@up select :scene-prev)
(@w select :scene-prev) (@w select :scene-prev)

View file

@ -0,0 +1,4 @@
(@esc device select-cancel)
(@up device pick :device-kind-prev)
(@down device pick :device-kind-next)
(@enter device add :device-kind)

View file

@ -20,6 +20,7 @@ handle!(TuiIn: |self: Tek, input|Ok(if let Some(command) = self.config.keys.comm
expose!([self: Tek] expose!([self: Tek]
([bool] ([bool]
(":mode-editor" self.is_editing()) (":mode-editor" self.is_editing())
(":mode-device-add" matches!(self.modal, Some(Modal::Device(..))))
(":mode-clip" !self.is_editing() && self.selected.is_clip()) (":mode-clip" !self.is_editing() && self.selected.is_clip())
(":mode-track" !self.is_editing() && self.selected.is_track()) (":mode-track" !self.is_editing() && self.selected.is_track())
(":mode-scene" !self.is_editing() && self.selected.is_scene()) (":mode-scene" !self.is_editing() && self.selected.is_scene())
@ -45,7 +46,22 @@ expose!([self: Tek]
(":w-sidebar" self.w_sidebar())) (":w-sidebar" self.w_sidebar()))
([usize] ([usize]
(":scene-last" self.scenes.len()) (":scene-last" self.scenes.len())
(":track-last" self.tracks.len())) (":track-last" self.tracks.len())
(":device-kind" if let Some(Modal::Device(index)) = self.modal {
index
} else {
0
})
(":device-kind-prev" if let Some(Modal::Device(index)) = self.modal {
index.overflowing_sub(1).0.min(self.device_kinds().len().saturating_sub(1))
} else {
0
})
(":device-kind-next" if let Some(Modal::Device(index)) = self.modal {
(index + 1) % self.device_kinds().len()
} else {
0
}))
([Option<usize>] ([Option<usize>]
(":scene" self.selected.scene()) (":scene" self.selected.scene())
(":track" self.selected.track())) (":track" self.selected.track()))
@ -120,6 +136,7 @@ impose!([app: Tek]
("input" [,..a] ns!(InputCommand, app, a, Self::Input)) ("input" [,..a] ns!(InputCommand, app, a, Self::Input))
("output" [,..a] ns!(OutputCommand, app, a, Self::Output)) ("output" [,..a] ns!(OutputCommand, app, a, Self::Output))
("clip" [,..a] ns!(ClipCommand, app, a, Self::Clip)) ("clip" [,..a] ns!(ClipCommand, app, a, Self::Clip))
("device" [,..a] ns!(DeviceCommand, app, a, Self::Device))
("pool" [,..a] app.pool.as_ref().map(|p|ns!(PoolCommand, p, a, Self::Pool)).flatten()) ("pool" [,..a] app.pool.as_ref().map(|p|ns!(PoolCommand, p, a, Self::Pool)).flatten())
("editor" [,..a] app.editor().map(|e|ns!(MidiEditCommand, e, a, Self::Editor)).flatten()) ("editor" [,..a] app.editor().map(|e|ns!(MidiEditCommand, e, a, Self::Editor)).flatten())
("sampler" [,..a] app.sampler().map(|s|ns!(SamplerCommand, s, a, Self::Sampler)).flatten()) ("sampler" [,..a] app.sampler().map(|s|ns!(SamplerCommand, s, a, Self::Sampler)).flatten())
@ -144,6 +161,11 @@ impose!([app: Tek]
(OutputCommand: (OutputCommand:
("add" [] Some(Self::Add))) ("add" [] Some(Self::Add)))
(DeviceCommand:
("picker" [] Some(Self::Picker))
("pick" [index: usize] Some(Self::Pick(index.unwrap())))
("add" [index: usize] Some(Self::Add(index.unwrap()))))
(SceneCommand: (SceneCommand:
("add" [] Some(Self::Add)) ("add" [] Some(Self::Add))
("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap()))) ("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap())))
@ -175,6 +197,7 @@ defcom!([self, app: Tek]
(Input [cmd: InputCommand] cmd.delegate(app, Self::Input)?) (Input [cmd: InputCommand] cmd.delegate(app, Self::Input)?)
(Clip [cmd: ClipCommand] cmd.delegate(app, Self::Clip)?) (Clip [cmd: ClipCommand] cmd.delegate(app, Self::Clip)?)
(Clock [cmd: ClockCommand] cmd.delegate(app, Self::Clock)?) (Clock [cmd: ClockCommand] cmd.delegate(app, Self::Clock)?)
(Device [cmd: DeviceCommand] cmd.delegate(app, Self::Device)?)
(Editor [cmd: MidiEditCommand] delegate_to_editor(app, cmd)?) (Editor [cmd: MidiEditCommand] delegate_to_editor(app, cmd)?)
(Pool [cmd: PoolCommand] delegate_to_pool(app, cmd)?) (Pool [cmd: PoolCommand] delegate_to_pool(app, cmd)?)
(ToggleHelp [] cmd!(app.toggle_modal(Some(Modal::Help)))) (ToggleHelp [] cmd!(app.toggle_modal(Some(Modal::Help))))
@ -189,10 +212,15 @@ defcom!([self, app: Tek]
(StopAll [] cmd!(app.stop_all()))) (StopAll [] cmd!(app.stop_all())))
(InputCommand (InputCommand
(Add [] cmd!(app.add_midi_in()?))) (Add [] cmd!(app.midi_in_add()?)))
(OutputCommand (OutputCommand
(Add [] cmd!(app.add_midi_out()?))) (Add [] cmd!(app.midi_out_add()?)))
(DeviceCommand
(Picker [] cmd!(app.device_picker_show()))
(Pick [i: usize] cmd!(app.device_pick(i)))
(Add [i: usize] cmd!(app.device_add(i))))
(TrackCommand (TrackCommand
(TogglePlay [] Some(Self::TogglePlay)) (TogglePlay [] Some(Self::TogglePlay))

View file

@ -383,16 +383,50 @@ impl Tek {
}) })
} }
pub(crate) fn add_midi_in (&mut self) -> Usually<()> { pub(crate) fn midi_in_add (&mut self) -> Usually<()> {
self.midi_ins.push(JackMidiIn::new(&self.jack, &format!("M/{}", self.midi_ins.len()), &[])?); self.midi_ins.push(JackMidiIn::new(&self.jack, &format!("M/{}", self.midi_ins.len()), &[])?);
Ok(()) Ok(())
} }
pub(crate) fn add_midi_out (&mut self) -> Usually<()> { pub(crate) fn midi_out_add (&mut self) -> Usually<()> {
self.midi_outs.push(JackMidiOut::new(&self.jack, &format!("{}/M", self.midi_outs.len()), &[])?); self.midi_outs.push(JackMidiOut::new(&self.jack, &format!("{}/M", self.midi_outs.len()), &[])?);
Ok(()) Ok(())
} }
pub(crate) fn device_picker_show (&mut self) {
self.modal = Some(Modal::Device(0));
}
pub(crate) fn device_pick (&mut self, index: usize) {
self.modal = Some(Modal::Device(index));
}
pub(crate) fn device_add (&mut self, index: usize) -> Usually<()> {
match index {
0 => {
let jack = self.jack.clone();
self.track_mut()
.expect("no active track")
.devices
.push({
let sampler = Sampler::new(&jack, &"sampler", &[], &[&[], &[]], &[&[], &[]])?;
Device::Sampler(sampler)
});
self.modal = None;
Ok(())
},
1 => todo!(),
_ => unreachable!(),
}
}
pub(crate) fn device_kinds (&self) -> &'static [&'static str] {
&[
"Sampler",
"Plugin (LV2)",
]
}
} }
has_size!(<TuiOut>|self: Tek|&self.size); has_size!(<TuiOut>|self: Tek|&self.size);
@ -424,6 +458,7 @@ pub trait HasSelection {
pub enum Modal { pub enum Modal {
Help, Help,
Menu, Menu,
Device(usize)
} }
/// Represents the current user selection in the arranger /// Represents the current user selection in the arranger

View file

@ -70,6 +70,7 @@ impl Tek {
.enclose(self.modal.map(|modal|match modal { .enclose(self.modal.map(|modal|match modal {
Modal::Menu => self.view_modal_menu().boxed(), Modal::Menu => self.view_modal_menu().boxed(),
Modal::Help => self.view_modal_help().boxed(), Modal::Help => self.view_modal_help().boxed(),
Modal::Device(index) => self.view_modal_device(index).boxed(),
})) }))
))) )))
)) ))
@ -109,6 +110,16 @@ impl Tek {
Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1, bindings, binding))) Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1, bindings, binding)))
} }
fn view_modal_device (&self, index: usize) -> impl Content<TuiOut> + use<'_> {
let choices = ||self.device_kinds().iter();
let choice = move|label, i|
Fill::x(Tui::bg(if i == index { Rgb(64,128,32) } else { Rgb(0,0,0) },
Bsp::e(if i == index { "[ " } else { " " },
Bsp::w(if i == index { " ]" } else { " " },
label))));
Bsp::s(Tui::bold(true, "Add device"), Map::south(1, choices, choice))
}
/// Spacing between tracks. /// Spacing between tracks.
pub(crate) const TRACK_SPACING: usize = 0; pub(crate) const TRACK_SPACING: usize = 0;