mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: refactor command definitions
This commit is contained in:
parent
1b926b0338
commit
9f9de3fafb
9 changed files with 489 additions and 343 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -2301,6 +2301,7 @@ dependencies = [
|
|||
"symphonia",
|
||||
"tek_engine",
|
||||
"tengri",
|
||||
"tengri_proc",
|
||||
"uuid",
|
||||
"wavers",
|
||||
"winit",
|
||||
|
|
@ -2367,6 +2368,7 @@ dependencies = [
|
|||
name = "tengri_proc"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
|
|||
|
|
@ -17,180 +17,188 @@ handle!(TuiIn: |self: Tek, input|Ok(if let Some(command) = self.config.keys.comm
|
|||
None
|
||||
}));
|
||||
|
||||
expose!([self: Tek]
|
||||
([bool]
|
||||
(":mode-editor" self.is_editing())
|
||||
(":mode-message" matches!(self.dialog, Some(Dialog::Message(..))))
|
||||
(":mode-device-add" matches!(self.dialog, Some(Dialog::Device(..))))
|
||||
(":mode-clip" !self.is_editing() && self.selected.is_clip())
|
||||
(":mode-track" !self.is_editing() && self.selected.is_track())
|
||||
(":mode-scene" !self.is_editing() && self.selected.is_scene())
|
||||
(":mode-mix" !self.is_editing() && self.selected.is_mix())
|
||||
(":mode-pool-import" matches!(
|
||||
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
|
||||
Some(PoolMode::Import(..))))
|
||||
(":mode-pool-export" matches!(
|
||||
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
|
||||
Some(PoolMode::Export(..))))
|
||||
(":mode-pool-rename" matches!(
|
||||
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
|
||||
Some(PoolMode::Rename(..))))
|
||||
(":mode-pool-length" matches!(
|
||||
self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(),
|
||||
Some(PoolMode::Length(..)))))
|
||||
([isize])
|
||||
([Color])
|
||||
([Arc<RwLock<MidiClip>>])
|
||||
([u7]
|
||||
(":pitch" (self.editor().map(|e|e.note_pos()).unwrap() as u8).into()))
|
||||
([u16]
|
||||
(":w-sidebar" self.w_sidebar()))
|
||||
([usize]
|
||||
(":scene-last" self.scenes.len())
|
||||
(":track-last" self.tracks.len())
|
||||
(":device-kind" if let Some(Dialog::Device(index)) = self.dialog {
|
||||
#[tengri_proc::expose]
|
||||
impl Tek {
|
||||
fn focus_editor (&self) -> bool {
|
||||
self.is_editing()
|
||||
}
|
||||
fn focus_message (&self) -> bool {
|
||||
matches!(self.dialog, Some(Dialog::Message(..)))
|
||||
}
|
||||
fn focus_device_add (&self) -> bool {
|
||||
matches!(self.dialog, Some(Dialog::Device(..)))
|
||||
}
|
||||
fn focus_clip (&self) -> bool {
|
||||
!self.is_editing() && self.selected.is_clip()
|
||||
}
|
||||
fn focus_track (&self) -> bool {
|
||||
!self.is_editing() && self.selected.is_track()
|
||||
}
|
||||
fn focus_scene (&self) -> bool {
|
||||
!self.is_editing() && self.selected.is_scene()
|
||||
}
|
||||
fn focus_mix (&self) -> bool {
|
||||
!self.is_editing() && self.selected.is_mix()
|
||||
}
|
||||
fn focus_pool_import (&self) -> bool {
|
||||
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Import(..)))
|
||||
}
|
||||
fn focus_pool_export (&self) -> bool {
|
||||
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Export(..)))
|
||||
}
|
||||
fn focus_pool_rename (&self) -> bool {
|
||||
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Rename(..)))
|
||||
}
|
||||
fn focus_pool_length (&self) -> bool {
|
||||
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..)))
|
||||
}
|
||||
fn editor_pitch (&self) -> Option<u7> {
|
||||
(self.editor().map(|e|e.note_pos()).unwrap() as u8).into()
|
||||
}
|
||||
fn w_sidebar (&self) -> Option<u7> {
|
||||
self.w_sidebar()
|
||||
}
|
||||
fn scene_count (&self) -> Option<usize> {
|
||||
self.scenes.len()
|
||||
}
|
||||
fn scene_selected (&self) -> Option<usize> {
|
||||
self.selected.scene()
|
||||
}
|
||||
fn scene_select_next (&self) -> Selection {
|
||||
self.selected.scene_next(self.scenes.len())
|
||||
}
|
||||
fn scene_select_prev (&self) -> Selection {
|
||||
self.selected.scene_prev()
|
||||
}
|
||||
fn track_count (&self) -> Option<usize> {
|
||||
self.tracks.len()
|
||||
}
|
||||
fn track_selected (&self) -> Option<usize> {
|
||||
self.selected.track()
|
||||
}
|
||||
fn track_select_next (&self) -> Selection {
|
||||
self.selected.track_next(self.tracks.len())
|
||||
}
|
||||
fn track_select_prev (&self) -> Selection {
|
||||
self.selected.track_prev()
|
||||
}
|
||||
fn clip_selected (&self) -> Option<Arc<RwLock<MidiClip>>> {
|
||||
match self.selected {
|
||||
Selection::TrackClip { track, scene } => self.scenes[scene].clips[track].clone(),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
fn device_kind (&self) -> usize {
|
||||
if let Some(Dialog::Device(index)) = self.dialog {
|
||||
index
|
||||
} else {
|
||||
0
|
||||
})
|
||||
(":device-kind-prev" if let Some(Dialog::Device(index)) = self.dialog {
|
||||
}
|
||||
}
|
||||
fn device_kind_prev (&self) -> usize {
|
||||
if let Some(Dialog::Device(index)) = self.dialog {
|
||||
index.overflowing_sub(1).0.min(self.device_kinds().len().saturating_sub(1))
|
||||
} else {
|
||||
0
|
||||
})
|
||||
(":device-kind-next" if let Some(Dialog::Device(index)) = self.dialog {
|
||||
}
|
||||
}
|
||||
fn device_kind_next (&self) -> usize {
|
||||
if let Some(Dialog::Device(index)) = self.dialog {
|
||||
(index + 1) % self.device_kinds().len()
|
||||
} else {
|
||||
0
|
||||
}))
|
||||
([Option<usize>]
|
||||
(":scene" self.selected.scene())
|
||||
(":track" self.selected.track()))
|
||||
([MaybeClip]
|
||||
(":clip" match self.selected {
|
||||
Selection::TrackClip { track, scene } => self.scenes[scene].clips[track].clone(),
|
||||
_ => None
|
||||
}))
|
||||
([Selection]
|
||||
(":scene-next" self.selected.scene_next(self.scenes.len()))
|
||||
(":scene-prev" self.selected.scene_prev())
|
||||
(":track-next" self.selected.track_next(self.tracks.len()))
|
||||
(":track-prev" self.selected.track_prev())));
|
||||
expose!([self: MidiPool]
|
||||
([bool])
|
||||
([PathBuf])
|
||||
([Arc<str>])
|
||||
([MidiClip]
|
||||
(":new-clip" self.new_clip())
|
||||
(":cloned-clip" self.cloned_clip()))
|
||||
([usize]
|
||||
(":current" 0)
|
||||
(":after" 0)
|
||||
(":previous" 0)
|
||||
(":next" 0))
|
||||
([ItemColor]
|
||||
(":random-color" ItemColor::random())));
|
||||
expose!([self: MidiEditor]
|
||||
([bool]
|
||||
(":true" true)
|
||||
(":false" false)
|
||||
(":time-lock" self.time_lock().get())
|
||||
(":time-lock-toggle" !self.time_lock().get()))
|
||||
([usize]
|
||||
(":note-length" self.note_len())
|
||||
(":note-pos" self.note_pos())
|
||||
(":note-pos-next" self.note_pos() + 1)
|
||||
(":note-pos-prev" self.note_pos().saturating_sub(1))
|
||||
(":note-pos-next-octave" self.note_pos() + 12)
|
||||
(":note-pos-prev-octave" self.note_pos().saturating_sub(12))
|
||||
(":note-len" self.note_len())
|
||||
(":note-len-next" self.note_len() + 1)
|
||||
(":note-len-prev" self.note_len().saturating_sub(1))
|
||||
(":note-range" self.note_axis().get())
|
||||
(":note-range-prev" self.note_axis().get() + 1)
|
||||
(":note-range-next" self.note_axis().get().saturating_sub(1))
|
||||
(":time-pos" self.time_pos())
|
||||
(":time-pos-next" self.time_pos() + self.time_zoom().get())
|
||||
(":time-pos-prev" self.time_pos().saturating_sub(self.time_zoom().get()))
|
||||
(":time-zoom" self.time_zoom().get())
|
||||
(":time-zoom-next" self.time_zoom().get() + 1)
|
||||
(":time-zoom-prev" self.time_zoom().get().saturating_sub(1).max(1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impose!([app: Tek]
|
||||
(TekCommand:
|
||||
("menu" [] Some(Self::ToggleMenu))
|
||||
("help" [] Some(Self::ToggleHelp))
|
||||
("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" [] Some(Self::Color(ItemTheme::random())))
|
||||
("color" [c: Color] Some(Self::Color(c.map(ItemTheme::from).expect("no color"))))
|
||||
("enqueue" [c: Arc<RwLock<MidiClip>>] Some(Self::Enqueue(c)))
|
||||
("launch" [] Some(Self::Launch))
|
||||
("select" [t: Selection] Some(t.map(Self::Select).expect("no selection")))
|
||||
("clock" [,..a] ns!(ClockCommand, app.clock(), a, Self::Clock))
|
||||
("scene" [,..a] ns!(SceneCommand, app, a, Self::Scene))
|
||||
("track" [,..a] ns!(TrackCommand, app, a, Self::Track))
|
||||
("input" [,..a] ns!(InputCommand, app, a, Self::Input))
|
||||
("output" [,..a] ns!(OutputCommand, app, a, Self::Output))
|
||||
("clip" [,..a] ns!(ClipCommand, app, a, Self::Clip))
|
||||
("device" [,..a] ns!(DeviceCommand, app, a, Self::Device))
|
||||
("message" [,..a] ns!(MessageCommand, app, a, Self::Message))
|
||||
("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())
|
||||
("sampler" [,..a] app.sampler().map(|s|ns!(SamplerCommand, s, a, Self::Sampler)).flatten())
|
||||
("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 }) })))
|
||||
#[tengri_proc::expose]
|
||||
impl MidiPool {
|
||||
fn clip_new (&self) -> MidiClip {
|
||||
self.new_clip()
|
||||
}
|
||||
fn clip_cloned (&self) -> MidiClip {
|
||||
self.cloned_clip()
|
||||
}
|
||||
fn clip_index_current (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_after (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_previous (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_next (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn color_random (&self) -> ItemColor {
|
||||
ItemColor::random()
|
||||
}
|
||||
}
|
||||
|
||||
(ClipCommand:
|
||||
("edit" [a: MaybeClip] Some(Self::Edit(a.unwrap())))
|
||||
("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap(), b.unwrap(), ItemTheme::random())))
|
||||
("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap(), b.unwrap())))
|
||||
("get" [a: usize, b: usize] Some(Self::Get(a.unwrap(), b.unwrap())))
|
||||
("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap(), b.unwrap(), c.unwrap())))
|
||||
("put" [a: usize, b: usize, c: MaybeClip] Some(Self::Put(a.unwrap(), b.unwrap(), c.unwrap())))
|
||||
("delete" [a: usize, b: usize] Some(Self::Put(a.unwrap(), b.unwrap(), None))))
|
||||
|
||||
(InputCommand:
|
||||
("add" [] Some(Self::Add)))
|
||||
|
||||
(OutputCommand:
|
||||
("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()))))
|
||||
|
||||
(MessageCommand:
|
||||
("dismiss" [] Some(Self::Dismiss)))
|
||||
|
||||
(SceneCommand:
|
||||
("add" [] Some(Self::Add))
|
||||
("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap())))
|
||||
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemTheme::G[128])))
|
||||
("enqueue" [a: usize] Some(Self::Enqueue(a.unwrap())))
|
||||
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap()))))
|
||||
|
||||
(TrackCommand:
|
||||
("add" [] Some(Self::Add))
|
||||
("size" [a: usize] Some(Self::SetSize(a.unwrap())))
|
||||
("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemTheme::random())))
|
||||
("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap())))
|
||||
("stop" [a: usize] Some(Self::Stop(a.unwrap())))
|
||||
("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
|
||||
("play" [] Some(Self::TogglePlay))
|
||||
("solo" [] Some(Self::ToggleSolo))
|
||||
("rec" [] Some(Self::ToggleRec))
|
||||
("mon" [] Some(Self::ToggleMon))));
|
||||
#[tengri_proc::expose]
|
||||
impl MidiEditor {
|
||||
fn time_lock (&self) -> bool {
|
||||
self.time_lock().get()
|
||||
}
|
||||
fn time_lock_toggle (&self) -> bool {
|
||||
!self.time_lock().get()
|
||||
}
|
||||
fn note_length (&self) -> usize {
|
||||
self.note_len()
|
||||
}
|
||||
fn note_pos (&self) -> usize {
|
||||
self.note_pos()
|
||||
}
|
||||
fn note_pos_next (&self) -> usize {
|
||||
self.note_pos() + 1
|
||||
}
|
||||
fn note_pos_next_octave (&self) -> usize {
|
||||
self.note_pos() + 12
|
||||
}
|
||||
fn note_pos_prev (&self) -> usize {
|
||||
self.note_pos().saturating_sub(1)
|
||||
}
|
||||
fn note_pos_prev_octave (&self) -> usize {
|
||||
self.note_pos().saturating_sub(12)
|
||||
}
|
||||
fn note_len (&self) -> usize {
|
||||
self.note_len()
|
||||
}
|
||||
fn note_len_next (&self) -> usize {
|
||||
self.note_len() + 1
|
||||
}
|
||||
fn note_len_prev (&self) -> usize {
|
||||
self.note_len().saturating_sub(1)
|
||||
}
|
||||
fn note_range (&self) -> usize {
|
||||
self.note_axis()
|
||||
}
|
||||
fn note_range_next (&self) -> usize {
|
||||
self.note_axis() + 1
|
||||
}
|
||||
fn note_range_prev (&self) -> usize {
|
||||
self.note_axis().saturating_sub(1)
|
||||
}
|
||||
fn time_pos (&self) -> usize {
|
||||
self.time_pos()
|
||||
}
|
||||
fn time_pos_next (&self) -> usize {
|
||||
self.time_pos() + self.time_zoom().get()
|
||||
}
|
||||
fn time_pos_prev (&self) -> usize {
|
||||
self.time_pos().saturating_sub(self.time_zoom().get())
|
||||
}
|
||||
fn time_zoom (&self) -> usize {
|
||||
self.time_zoom()
|
||||
}
|
||||
fn time_zoom_next (&self) -> usize {
|
||||
self.time_zoom() + 1
|
||||
}
|
||||
fn time_zoom_prev (&self) -> usize {
|
||||
self.time_zoom().get().saturating_sub(1).max(1)
|
||||
}
|
||||
}
|
||||
|
||||
//#[tengri_proc::input(TuiIn)]
|
||||
//impl Tek {
|
||||
|
|
@ -204,77 +212,154 @@ impose!([app: Tek]
|
|||
//}
|
||||
//}
|
||||
|
||||
defcom!([self, app: Tek]
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl TekCommand {
|
||||
//(Sampler [cmd: SamplerCommand] app.sampler_mut().map(|s|cmd.delegate(s, Self::Sampler)).transpose()?.flatten())
|
||||
//(Scene [cmd: SceneCommand] cmd.delegate(app, Self::Scene)?)
|
||||
//(Track [cmd: TrackCommand] cmd.delegate(app, Self::Track)?)
|
||||
//(Output [cmd: OutputCommand] cmd.delegate(app, Self::Output)?)
|
||||
//(Input [cmd: InputCommand] cmd.delegate(app, Self::Input)?)
|
||||
//(Clip [cmd: ClipCommand] cmd.delegate(app, Self::Clip)?)
|
||||
//(Clock [cmd: ClockCommand] cmd.delegate(app, Self::Clock)?)
|
||||
//(Device [cmd: DeviceCommand] cmd.delegate(app, Self::Device)?)
|
||||
//(Message [cmd: MessageCommand] cmd.delegate(app, Self::Message)?)
|
||||
//(Editor [cmd: MidiEditCommand] delegate_to_editor(app, cmd)?)
|
||||
//(Pool [cmd: PoolCommand] delegate_to_pool(app, cmd)?)
|
||||
//(ToggleHelp [] cmd!(app.toggle_dialog(Some(Dialog::Help))))
|
||||
//(ToggleMenu [] cmd!(app.toggle_dialog(Some(Dialog::Menu))))
|
||||
//(Color [p: ItemTheme] app.set_color(Some(p)).map(Self::Color))
|
||||
//(Enqueue [c: MaybeClip] cmd_todo!("\n\rtodo: enqueue {c:?}"))
|
||||
//(History [d: isize] cmd_todo!("\n\rtodo: history {d:?}"))
|
||||
//(Zoom [z: Option<usize>] cmd_todo!("\n\rtodo: zoom {z:?}"))
|
||||
//(Edit [value: Option<bool>] cmd!(app.toggle_editor(value)))
|
||||
//(Launch [] cmd!(app.launch()))
|
||||
//(Select [s: Selection] cmd!(app.select(s)))
|
||||
//(StopAll [] cmd!(app.stop_all())))
|
||||
//("menu" [] Some(Self::ToggleMenu))
|
||||
//("help" [] Some(Self::ToggleHelp))
|
||||
//("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" [] Some(Self::Color(ItemTheme::random())))
|
||||
//("color" [c: Color] Some(Self::Color(c.map(ItemTheme::from).expect("no color"))))
|
||||
//("enqueue" [c: Arc<RwLock<MidiClip>>] Some(Self::Enqueue(c)))
|
||||
//("launch" [] Some(Self::Launch))
|
||||
//("select" [t: Selection] Some(t.map(Self::Select).expect("no selection")))
|
||||
//("clock" [,..a] ns!(ClockCommand, app.clock(), a, Self::Clock))
|
||||
//("scene" [,..a] ns!(SceneCommand, app, a, Self::Scene))
|
||||
//("track" [,..a] ns!(TrackCommand, app, a, Self::Track))
|
||||
//("input" [,..a] ns!(InputCommand, app, a, Self::Input))
|
||||
//("output" [,..a] ns!(OutputCommand, app, a, Self::Output))
|
||||
//("clip" [,..a] ns!(ClipCommand, app, a, Self::Clip))
|
||||
//("device" [,..a] ns!(DeviceCommand, app, a, Self::Device))
|
||||
//("message" [,..a] ns!(MessageCommand, app, a, Self::Message))
|
||||
//("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())
|
||||
//("sampler" [,..a] app.sampler().map(|s|ns!(SamplerCommand, s, a, Self::Sampler)).flatten())
|
||||
//("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 }) })))
|
||||
}
|
||||
|
||||
(TekCommand
|
||||
(Sampler [cmd: SamplerCommand] app.sampler_mut().map(|s|cmd.delegate(s, Self::Sampler)).transpose()?.flatten())
|
||||
(Scene [cmd: SceneCommand] cmd.delegate(app, Self::Scene)?)
|
||||
(Track [cmd: TrackCommand] cmd.delegate(app, Self::Track)?)
|
||||
(Output [cmd: OutputCommand] cmd.delegate(app, Self::Output)?)
|
||||
(Input [cmd: InputCommand] cmd.delegate(app, Self::Input)?)
|
||||
(Clip [cmd: ClipCommand] cmd.delegate(app, Self::Clip)?)
|
||||
(Clock [cmd: ClockCommand] cmd.delegate(app, Self::Clock)?)
|
||||
(Device [cmd: DeviceCommand] cmd.delegate(app, Self::Device)?)
|
||||
(Message [cmd: MessageCommand] cmd.delegate(app, Self::Message)?)
|
||||
(Editor [cmd: MidiEditCommand] delegate_to_editor(app, cmd)?)
|
||||
(Pool [cmd: PoolCommand] delegate_to_pool(app, cmd)?)
|
||||
(ToggleHelp [] cmd!(app.toggle_dialog(Some(Dialog::Help))))
|
||||
(ToggleMenu [] cmd!(app.toggle_dialog(Some(Dialog::Menu))))
|
||||
(Color [p: ItemTheme] app.set_color(Some(p)).map(Self::Color))
|
||||
(Enqueue [c: MaybeClip] cmd_todo!("\n\rtodo: enqueue {c:?}"))
|
||||
(History [d: isize] cmd_todo!("\n\rtodo: history {d:?}"))
|
||||
(Zoom [z: Option<usize>] cmd_todo!("\n\rtodo: zoom {z:?}"))
|
||||
(Edit [value: Option<bool>] cmd!(app.toggle_editor(value)))
|
||||
(Launch [] cmd!(app.launch()))
|
||||
(Select [s: Selection] cmd!(app.select(s)))
|
||||
(StopAll [] cmd!(app.stop_all())))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl InputCommand {
|
||||
fn add (&self, state: &mut tek) -> option<self> {
|
||||
state.midi_in_add()?;
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
(InputCommand
|
||||
(Add [] cmd!(app.midi_in_add()?)))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl OutputCommand {
|
||||
fn add (&self, state: &mut tek) -> option<self> {
|
||||
state.midi_out_add()?;
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
(OutputCommand
|
||||
(Add [] cmd!(app.midi_out_add()?)))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl DeviceCommand {
|
||||
//(Picker [] cmd!(app.device_picker_show()))
|
||||
//(Pick [i: usize] cmd!(app.device_pick(i)))
|
||||
//(Add [i: usize] cmd!(app.device_add(i))))
|
||||
//("picker" [] Some(Self::Picker))
|
||||
//("pick" [index: usize] Some(Self::Pick(index.unwrap())))
|
||||
//("add" [index: usize] Some(Self::Add(index.unwrap()))))
|
||||
}
|
||||
|
||||
(DeviceCommand
|
||||
(Picker [] cmd!(app.device_picker_show()))
|
||||
(Pick [i: usize] cmd!(app.device_pick(i)))
|
||||
(Add [i: usize] cmd!(app.device_add(i))))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl MessageCommand {
|
||||
//(Dismiss [] cmd!(app.message_dismiss())))
|
||||
//("dismiss" [] Some(Self::Dismiss)))
|
||||
}
|
||||
|
||||
(MessageCommand
|
||||
(Dismiss [] cmd!(app.message_dismiss())))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl TrackCommand {
|
||||
//(TogglePlay [] Some(Self::TogglePlay))
|
||||
//(ToggleSolo [] Some(Self::ToggleSolo))
|
||||
//(SetSize [t: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(SetZoom [z: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(Swap [a: usize, b: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(Del [index: usize] cmd!(app.track_del(index)))
|
||||
//(Stop [index: usize] cmd!(app.tracks[index].player.enqueue_next(None)))
|
||||
//(Add [] Some(Self::Del(app.track_add_focus()?)))
|
||||
//(SetColor [i: usize, c: ItemTheme] Some(Self::SetColor(i, app.track_set_color(i, c))))
|
||||
//(ToggleRec [] { app.track_toggle_record(); Some(Self::ToggleRec) })
|
||||
//(ToggleMon [] { app.track_toggle_monitor(); Some(Self::ToggleMon) }))
|
||||
//("add" [] Some(Self::Add))
|
||||
//("size" [a: usize] Some(Self::SetSize(a.unwrap())))
|
||||
//("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
//("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemTheme::random())))
|
||||
//("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap())))
|
||||
//("stop" [a: usize] Some(Self::Stop(a.unwrap())))
|
||||
//("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap())))
|
||||
//("play" [] Some(Self::TogglePlay))
|
||||
//("solo" [] Some(Self::ToggleSolo))
|
||||
//("rec" [] Some(Self::ToggleRec))
|
||||
//("mon" [] Some(Self::ToggleMon))));
|
||||
}
|
||||
|
||||
(TrackCommand
|
||||
(TogglePlay [] Some(Self::TogglePlay))
|
||||
(ToggleSolo [] Some(Self::ToggleSolo))
|
||||
(SetSize [t: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(SetZoom [z: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(Swap [a: usize, b: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(Del [index: usize] cmd!(app.track_del(index)))
|
||||
(Stop [index: usize] cmd!(app.tracks[index].player.enqueue_next(None)))
|
||||
(Add [] Some(Self::Del(app.track_add_focus()?)))
|
||||
(SetColor [i: usize, c: ItemTheme] Some(Self::SetColor(i, app.track_set_color(i, c))))
|
||||
(ToggleRec [] { app.track_toggle_record(); Some(Self::ToggleRec) })
|
||||
(ToggleMon [] { app.track_toggle_monitor(); Some(Self::ToggleMon) }))
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl SceneCommand {
|
||||
//(Swap [a: usize, b: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(SetSize [index: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(SetZoom [zoom: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(Enqueue [scene: usize] cmd!(app.scene_enqueue(scene)))
|
||||
//(Del [index: usize] cmd!(app.scene_del(index)))
|
||||
//(Add [] Some(Self::Del(app.scene_add_focus()?)))
|
||||
//(SetColor [i: usize, c: ItemTheme] Some(Self::SetColor(i, app.scene_set_color(i, c)))))
|
||||
//("add" [] Some(Self::Add))
|
||||
//("delete" [a: Option<usize>] Some(Self::Del(a.flatten().unwrap())))
|
||||
//("zoom" [a: usize] Some(Self::SetZoom(a.unwrap())))
|
||||
//("color" [a: usize] Some(Self::SetColor(a.unwrap(), ItemTheme::G[128])))
|
||||
//("enqueue" [a: usize] Some(Self::Enqueue(a.unwrap())))
|
||||
//("swap" [a: usize, b: usize] Some(Self::Swap(a.unwrap(), b.unwrap()))))
|
||||
}
|
||||
|
||||
(SceneCommand
|
||||
(Swap [a: usize, b: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(SetSize [index: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(SetZoom [zoom: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(Enqueue [scene: usize] cmd!(app.scene_enqueue(scene)))
|
||||
(Del [index: usize] cmd!(app.scene_del(index)))
|
||||
(Add [] Some(Self::Del(app.scene_add_focus()?)))
|
||||
(SetColor [i: usize, c: ItemTheme] Some(Self::SetColor(i, app.scene_set_color(i, c)))))
|
||||
|
||||
(ClipCommand
|
||||
(Get [a: usize, b: usize] cmd_todo!("\n\rtodo: clip: get: {a} {b}"))
|
||||
(Edit [clip: MaybeClip] cmd_todo!("\n\rtodo: clip: edit: {clip:?}"))
|
||||
(SetLoop [t: usize, s: usize, l: bool] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(Put [t: usize, s: usize, c: MaybeClip]
|
||||
Some(Self::Put(t, s, app.clip_put(t, s, c))))
|
||||
(Enqueue [t: usize, s: usize]
|
||||
cmd!(app.tracks[t].player.enqueue_next(app.scenes[s].clips[t].as_ref())))
|
||||
(SetColor [t: usize, s: usize, c: ItemTheme]
|
||||
app.clip_set_color(t, s, c).map(|o|Self::SetColor(t, s, o)))));
|
||||
#[tengri_proc::command(Tek)]
|
||||
impl ClipCommand {
|
||||
//(Get [a: usize, b: usize] cmd_todo!("\n\rtodo: clip: get: {a} {b}"))
|
||||
//(Edit [clip: MaybeClip] cmd_todo!("\n\rtodo: clip: edit: {clip:?}"))
|
||||
//(SetLoop [t: usize, s: usize, l: bool] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
//(Put [t: usize, s: usize, c: MaybeClip]
|
||||
//Some(Self::Put(t, s, app.clip_put(t, s, c))))
|
||||
//(Enqueue [t: usize, s: usize]
|
||||
//cmd!(app.tracks[t].player.enqueue_next(app.scenes[s].clips[t].as_ref())))
|
||||
//(SetColor [t: usize, s: usize, c: ItemTheme]
|
||||
//app.clip_set_color(t, s, c).map(|o|Self::SetColor(t, s, o)))));
|
||||
//("edit" [a: MaybeClip] Some(Self::Edit(a.unwrap())))
|
||||
//("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap(), b.unwrap(), ItemTheme::random())))
|
||||
//("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap(), b.unwrap())))
|
||||
//("get" [a: usize, b: usize] Some(Self::Get(a.unwrap(), b.unwrap())))
|
||||
//("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap(), b.unwrap(), c.unwrap())))
|
||||
//("put" [a: usize, b: usize, c: MaybeClip] Some(Self::Put(a.unwrap(), b.unwrap(), c.unwrap())))
|
||||
//("delete" [a: usize, b: usize] Some(Self::Put(a.unwrap(), b.unwrap(), None))))
|
||||
}
|
||||
|
||||
fn delegate_to_editor (app: &mut Tek, cmd: MidiEditCommand) -> Perhaps<TekCommand> {
|
||||
Ok(app.editor.as_mut().map(|editor|cmd.delegate(editor, TekCommand::Editor))
|
||||
|
|
|
|||
|
|
@ -76,13 +76,14 @@ impl Tek {
|
|||
)))
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Tek {
|
||||
fn view_dialog_menu (&self) -> impl Content<TuiOut> {
|
||||
let options = ||["Projects", "Settings", "Help", "Quit"].iter();
|
||||
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
|
||||
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
|
||||
}
|
||||
|
||||
fn view_dialog_help (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let bindings = ||self.config.keys.layers.iter()
|
||||
.filter_map(|a|(a.0)(self).then_some(a.1))
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ version = { workspace = true }
|
|||
|
||||
[dependencies]
|
||||
tengri = { workspace = true }
|
||||
tengri_proc = { workspace = true }
|
||||
|
||||
tek_engine = { workspace = true }
|
||||
|
||||
uuid = { workspace = true, optional = true }
|
||||
livi = { workspace = true, optional = true }
|
||||
symphonia = { workspace = true, optional = true }
|
||||
|
|
|
|||
|
|
@ -1,72 +1,165 @@
|
|||
use crate::*;
|
||||
|
||||
expose!([self: Sampler]
|
||||
([Arc<str>])
|
||||
([MaybeSample])
|
||||
([PathBuf])
|
||||
([f32])
|
||||
([u7]
|
||||
(":pitch" (self.note_pos() as u8).into()) // TODO
|
||||
(":sample" (self.note_pos() as u8).into()))
|
||||
([usize]
|
||||
(":sample-up" self.note_pos().min(119) + 8)
|
||||
(":sample-down" self.note_pos().max(8) - 8)
|
||||
(":sample-left" self.note_pos().min(126) + 1)
|
||||
(":sample-right" self.note_pos().max(1) - 1)));
|
||||
|
||||
impose!([state: Sampler]
|
||||
(FileBrowserCommand:
|
||||
("begin" [] Some(Self::Begin))
|
||||
("cancel" [] Some(Self::Cancel))
|
||||
("confirm" [] Some(Self::Confirm))
|
||||
("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path"))))
|
||||
("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter")))))
|
||||
(SamplerCommand:
|
||||
("import" [,..a]
|
||||
FileBrowserCommand::try_from_expr(state, a).map(Self::Import))
|
||||
("select" [i: usize]
|
||||
Some(Self::Select(i.expect("no index"))))
|
||||
("record/begin" [i: u7]
|
||||
Some(Self::RecordBegin(i.expect("no index"))))
|
||||
("record/cancel" []
|
||||
Some(Self::RecordCancel))
|
||||
("record/finish" []
|
||||
Some(Self::RecordFinish))
|
||||
("set/sample" [i: u7, s: MaybeSample]
|
||||
Some(Self::SetSample(i.expect("no index"), s.expect("no sampler"))))
|
||||
("set/start" [i: u7, s: usize]
|
||||
Some(Self::SetStart(i.expect("no index"), s.expect("no start"))))
|
||||
("set/gain" [i: u7, g: f32]
|
||||
Some(Self::SetGain(i.expect("no index"), g.expect("no gain"))))
|
||||
("note/on" [p: u7, v: u7]
|
||||
Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity"))))
|
||||
("note/off" [p: u7]
|
||||
Some(Self::NoteOff(p.expect("no pitch"))))));
|
||||
|
||||
macro_rules! cmd { ($cmd:expr) => {{ $cmd; None }}; }
|
||||
macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
|
||||
|
||||
defcom!([self, state: Sampler]
|
||||
(SamplerCommand
|
||||
(Select [i: usize] Some(Self::Select(state.set_note_pos(i))))
|
||||
(RecordBegin [p: u7] cmd!(state.begin_recording(p.as_int() as usize)))
|
||||
(RecordCancel [] cmd!(state.cancel_recording()))
|
||||
(RecordFinish [] cmd!(state.finish_recording()))
|
||||
(SetStart [p: u7, frame: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(SetGain [p: u7, gain: f32] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(NoteOn [p: u7, velocity: u7] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(NoteOff [p: u7] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
(SetSample [p: u7, s: MaybeSample] Some(Self::SetSample(p, state.set_sample(p, s))))
|
||||
(Import [c: FileBrowserCommand] match c {
|
||||
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
|
||||
},
|
||||
_ => {
|
||||
println!("\n\rtodo: import: filebrowser: {c:?}");
|
||||
None
|
||||
}
|
||||
})));
|
||||
#[tengri_proc::expose]
|
||||
impl Sampler {
|
||||
//fn file_browser_filter (&self) -> Arc<str> {
|
||||
//todo!()
|
||||
//}
|
||||
//fn file_browser_path (&self) -> PathBuf {
|
||||
//todo!();
|
||||
//}
|
||||
///// Immutable reference to sample at cursor.
|
||||
//fn sample_selected (&self) -> MaybeSample {
|
||||
//for (i, sample) in self.mapped.iter().enumerate() {
|
||||
//if i == self.cursor().0 {
|
||||
//return sample.as_ref()
|
||||
//}
|
||||
//}
|
||||
//for (i, sample) in self.unmapped.iter().enumerate() {
|
||||
//if i + self.mapped.len() == self.cursor().0 {
|
||||
//return Some(sample)
|
||||
//}
|
||||
//}
|
||||
//None
|
||||
//}
|
||||
//fn sample_gain (&self) -> f32 {
|
||||
//todo!()
|
||||
//}
|
||||
//fn sample_above () -> usize {
|
||||
//self.note_pos().min(119) + 8
|
||||
//}
|
||||
//fn sample_below () -> usize {
|
||||
//self.note_pos().max(8) - 8
|
||||
//}
|
||||
//fn sample_to_left () -> usize {
|
||||
//self.note_pos().min(126) + 1
|
||||
//}
|
||||
//fn sample_to_right () -> usize {
|
||||
//self.note_pos().max(1) - 1
|
||||
//}
|
||||
//fn selected_pitch () -> u7 {
|
||||
//(self.note_pos() as u8).into() // TODO
|
||||
//}
|
||||
//fn selected_sample () -> u7 { // TODO
|
||||
//(self.note_pos() as u8).into()
|
||||
//}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(Sampler)]
|
||||
impl SamplerCommand {
|
||||
//fn select (&self, state: &mut Sampler, i: usize) -> Option<Self> {
|
||||
//Self::Select(state.set_note_pos(i))
|
||||
//}
|
||||
///// Assign sample to pitch
|
||||
//fn set (&self, pitch: u7, sample: MaybeSample) -> Option<Self> {
|
||||
//let i = pitch.as_int() as usize;
|
||||
//let old = self.mapped[i].clone();
|
||||
//self.mapped[i] = sample;
|
||||
//Some(Self::Set(old))
|
||||
//}
|
||||
//fn record_begin (&self, state: &mut Sampler, pitch: u7) -> Option<Self> {
|
||||
//self.recording = Some((
|
||||
//pitch.as_int() as usize,
|
||||
//Arc::new(RwLock::new(Sample::new("Sample", 0, 0, vec![vec![];self.audio_ins.len()])))
|
||||
//));
|
||||
//None
|
||||
//}
|
||||
//fn record_cancel (&self, state: &mut Sampler) -> Option<Self> {
|
||||
//self.recording = None;
|
||||
//None
|
||||
//}
|
||||
//fn record_finish (&self, state: &mut Sampler) -> Option<Self> {
|
||||
//let recording = self.recording.take();
|
||||
//let _sample = if let Some((index, sample)) = recording {
|
||||
//let old = self.mapped[index].clone();
|
||||
//self.mapped[index] = Some(sample);
|
||||
//old
|
||||
//} else {
|
||||
//None
|
||||
//};
|
||||
//None
|
||||
//}
|
||||
//fn set_start (&self, state: &mut Sampler, pitch: u7, frame: usize) -> Option<Self> {
|
||||
//todo!()
|
||||
//}
|
||||
//fn set_gain (&self, state: &mut Sampler, pitch: u7, g: f32) -> Option<Self> {
|
||||
//todo!()
|
||||
//}
|
||||
//fn note_on (&self, state: &mut Sampler, pitch: u7, v: u7) -> Option<Self> {
|
||||
//todo!()
|
||||
//}
|
||||
//fn note_off (&self, state: &mut Sampler, pitch: u7) -> Option<Self> {
|
||||
//todo!()
|
||||
//}
|
||||
//fn set_sample (&self, state: &mut Sampler, pitch: u7, s: MaybeSample) -> Option<Self> {
|
||||
//Some(Self::SetSample(p, state.set_sample(p, s)))
|
||||
//}
|
||||
//fn import (&self, state: &mut Sampler, c: FileBrowserCommand) -> Option<Self> {
|
||||
//match c {
|
||||
//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
|
||||
//},
|
||||
//_ => {
|
||||
//println!("\n\rtodo: import: filebrowser: {c:?}");
|
||||
//None
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
////(Select [i: usize] Some(Self::Select(state.set_note_pos(i))))
|
||||
////(RecordBegin [p: u7] cmd!(state.begin_recording(p.as_int() as usize)))
|
||||
////(RecordCancel [] cmd!(state.cancel_recording()))
|
||||
////(RecordFinish [] cmd!(state.finish_recording()))
|
||||
////(SetStart [p: u7, frame: usize] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
////(SetGain [p: u7, gain: f32] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
////(NoteOn [p: u7, velocity: u7] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
////(NoteOff [p: u7] cmd_todo!("\n\rtodo: {self:?}"))
|
||||
////(SetSample [p: u7, s: MaybeSample] Some(Self::SetSample(p, state.set_sample(p, s))))
|
||||
////(Import [c: FileBrowserCommand] match c {
|
||||
////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
|
||||
////},
|
||||
////_ => {
|
||||
////println!("\n\rtodo: import: filebrowser: {c:?}");
|
||||
////None
|
||||
////}
|
||||
////})));
|
||||
////("import" [,..a]
|
||||
////FileBrowserCommand::try_from_expr(state, a).map(Self::Import))
|
||||
////("select" [i: usize]
|
||||
////Some(Self::Select(i.expect("no index"))))
|
||||
////("record/begin" [i: u7]
|
||||
////Some(Self::RecordBegin(i.expect("no index"))))
|
||||
////("record/cancel" []
|
||||
////Some(Self::RecordCancel))
|
||||
////("record/finish" []
|
||||
////Some(Self::RecordFinish))
|
||||
////("set/sample" [i: u7, s: MaybeSample]
|
||||
////Some(Self::SetSample(i.expect("no index"), s.expect("no sampler"))))
|
||||
////("set/start" [i: u7, s: usize]
|
||||
////Some(Self::SetStart(i.expect("no index"), s.expect("no start"))))
|
||||
////("set/gain" [i: u7, g: f32]
|
||||
////Some(Self::SetGain(i.expect("no index"), g.expect("no gain"))))
|
||||
////("note/on" [p: u7, v: u7]
|
||||
////Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity"))))
|
||||
////("note/off" [p: u7]
|
||||
////Some(Self::NoteOff(p.expect("no pitch"))))));
|
||||
}
|
||||
|
||||
#[tengri_proc::command(Sampler)]
|
||||
impl FileBrowserCommand {
|
||||
//("begin" [] Some(Self::Begin))
|
||||
//("cancel" [] Some(Self::Cancel))
|
||||
//("confirm" [] Some(Self::Confirm))
|
||||
//("select" [i: usize] Some(Self::Select(i.expect("no index"))))
|
||||
//("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path"))))
|
||||
//("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter")))))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,50 +77,10 @@ impl Sampler {
|
|||
..Default::default()
|
||||
})
|
||||
}
|
||||
pub fn cancel_recording (&mut self) {
|
||||
self.recording = None;
|
||||
}
|
||||
pub fn begin_recording (&mut self, index: usize) {
|
||||
self.recording = Some((
|
||||
index,
|
||||
Arc::new(RwLock::new(Sample::new("Sample", 0, 0, vec![vec![];self.audio_ins.len()])))
|
||||
));
|
||||
}
|
||||
pub fn finish_recording (&mut self) -> MaybeSample {
|
||||
let recording = self.recording.take();
|
||||
if let Some((index, sample)) = recording {
|
||||
let old = self.mapped[index].clone();
|
||||
self.mapped[index] = Some(sample);
|
||||
old
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
/// Immutable reference to sample at cursor.
|
||||
pub fn sample (&self) -> Option<&Arc<RwLock<Sample>>> {
|
||||
for (i, sample) in self.mapped.iter().enumerate() {
|
||||
if i == self.cursor().0 {
|
||||
return sample.as_ref()
|
||||
}
|
||||
}
|
||||
for (i, sample) in self.unmapped.iter().enumerate() {
|
||||
if i + self.mapped.len() == self.cursor().0 {
|
||||
return Some(sample)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
/// Value of cursor
|
||||
pub fn cursor (&self) -> (usize, usize) {
|
||||
(self.cursor.0.load(Relaxed), self.cursor.1.load(Relaxed))
|
||||
}
|
||||
/// Assign sample to pitch
|
||||
pub fn set_sample (&mut self, pitch: u7, sample: MaybeSample) -> MaybeSample {
|
||||
let i = pitch.as_int() as usize;
|
||||
let old = self.mapped[i].clone();
|
||||
self.mapped[i] = sample;
|
||||
old
|
||||
}
|
||||
}
|
||||
|
||||
impl NoteRange for Sampler {
|
||||
|
|
@ -189,4 +149,3 @@ pub enum SamplerMode {
|
|||
// Load sample from path
|
||||
Import(usize, FileBrowser),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ impl Sampler {
|
|||
Tui::fg_bg(fg, bg, format!("{note:3} {}", self.view_list_item(note, compact)))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn view_list_item (&self, note: usize, compact: bool) -> String {
|
||||
if compact {
|
||||
String::default()
|
||||
|
|
@ -87,6 +88,7 @@ impl Sampler {
|
|||
draw_list_item(&self.mapped[note])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view_sample (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||
Outer(true, Style::default().fg(Tui::g(96))).enclose(draw_viewer(if let Some((_, sample)) = &self.recording {
|
||||
Some(sample)
|
||||
|
|
@ -96,6 +98,7 @@ impl Sampler {
|
|||
None
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn status (&self, index: usize) -> impl Content<TuiOut> {
|
||||
draw_status(self.mapped[index].as_ref())
|
||||
}
|
||||
|
|
|
|||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit b543c43e68154f049019da648064f36af1537434
|
||||
Subproject commit 7df7cb839c14c0e010ce36519c75ffacc0e76c18
|
||||
Loading…
Add table
Add a link
Reference in a new issue