diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index b0db4c6f..aa33ef34 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -17,8 +17,7 @@ handle!(TuiIn: |self: Tek, input|Ok(if let Some(command) = self.config.keys.comm None })); -#[tengri_proc::expose] -impl Tek { +#[tengri_proc::expose] impl Tek { fn focus_editor (&self) -> bool { self.is_editing() } @@ -161,8 +160,7 @@ impl Tek { } } -#[tengri_proc::expose] -impl MidiPool { +#[tengri_proc::expose] impl MidiPool { fn clip_new (&self) -> MidiClip { self.new_clip() } @@ -186,8 +184,7 @@ impl MidiPool { } } -#[tengri_proc::expose] -impl MidiEditor { +#[tengri_proc::expose] impl MidiEditor { fn time_lock (&self) -> bool { self.get_time_lock() } @@ -256,27 +253,26 @@ impl MidiEditor { } } -#[tengri_proc::command(Tek)] -impl TekCommand { - fn toggle_help (&self, tek: &mut Tek, value: bool) -> Perhaps { +#[tengri_proc::command(Tek)] impl TekCommand { + fn toggle_help (tek: &mut Tek, value: bool) -> Perhaps { tek.toggle_dialog(Some(Dialog::Help)); Ok(None) } - fn toggle_menu (&self, tek: &mut Tek, value: bool) -> Perhaps { + fn toggle_menu (tek: &mut Tek, value: bool) -> Perhaps { tek.toggle_dialog(Some(Dialog::Menu)); Ok(None) } - fn toggle_edit (&self, tek: &mut Tek, value: bool) -> Perhaps { + fn toggle_edit (tek: &mut Tek, value: bool) -> Perhaps { tek.toggle_editor(Some(value)); Ok(None) } - fn editor (&self, tek: &mut Tek, command: MidiEditCommand) -> Perhaps { + fn editor (tek: &mut Tek, command: MidiEditCommand) -> Perhaps { Ok(tek.editor.as_mut().map(|editor|command.execute(editor)) .transpose()? .flatten() .map(|undo|Self::Editor { command: undo })) } - fn pool (&self, tek: &mut Tek, command: PoolCommand) -> Perhaps { + fn pool (tek: &mut Tek, command: PoolCommand) -> Perhaps { Ok(if let Some(pool) = tek.pool.as_mut() { let undo = command.clone().delegate(pool, |command|TekCommand::Pool{command})?; // update linked editor after pool action @@ -293,53 +289,53 @@ impl TekCommand { None }) } - fn sampler (&self, tek: &mut Tek, ref command: SamplerCommand) -> Perhaps { + fn sampler (tek: &mut Tek, command: SamplerCommand) -> Perhaps { Ok(tek.sampler_mut() .map(|s|command.delegate(s, |command|Self::Sampler{command})) .transpose()? .flatten()) } - fn scene (&self, tek: &mut Tek, command: SceneCommand) -> Perhaps { + fn scene (tek: &mut Tek, command: SceneCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Scene{command})?) } - fn track (&self, tek: &mut Tek, command: TrackCommand) -> Perhaps { + fn track (tek: &mut Tek, command: TrackCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Track{command})?) } - fn input (&self, tek: &mut Tek, command: InputCommand) -> Perhaps { + fn input (tek: &mut Tek, command: InputCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Input{command})?) } - fn output (&self, tek: &mut Tek, command: OutputCommand) -> Perhaps { + fn output (tek: &mut Tek, command: OutputCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Output{command})?) } - fn clip (&self, tek: &mut Tek, command: ClipCommand) -> Perhaps { + fn clip (tek: &mut Tek, command: ClipCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Clip{command})?) } - fn clock (&self, tek: &mut Tek, command: ClockCommand) -> Perhaps { - Ok(command.delegate(tek, |command|Self::Clock{command})?) + fn clock (tek: &mut Tek, command: ClockCommand) -> Perhaps { + Ok(command.execute(&mut tek.clock)?.map(|command|Self::Clock{command})) } - fn device (&self, tek: &mut Tek, command: DeviceCommand) -> Perhaps { + fn device (tek: &mut Tek, command: DeviceCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Device{command})?) } - fn message (&self, tek: &mut Tek, command: MessageCommand) -> Perhaps { + fn message (tek: &mut Tek, command: MessageCommand) -> Perhaps { Ok(command.delegate(tek, |command|Self::Message{command})?) } - fn color (&self, tek: &mut Tek, theme: ItemTheme) -> Perhaps { + fn color (tek: &mut Tek, theme: ItemTheme) -> Perhaps { Ok(tek.set_color(Some(theme)).map(|theme|Self::Color{theme})) } - fn enqueue (&self, tek: &mut Tek, clip: Option>>) -> Perhaps { + fn enqueue (tek: &mut Tek, clip: Option>>) -> Perhaps { todo!() } - fn history (&self, tek: &mut Tek, delta: isize) -> Perhaps { + fn history (tek: &mut Tek, delta: isize) -> Perhaps { todo!() } - fn zoom (&self, tek: &mut Tek, zoom: usize) -> Perhaps { + fn zoom (tek: &mut Tek, zoom: usize) -> Perhaps { todo!() } - fn launch (&self, tek: &mut Tek) -> Perhaps { + fn launch (tek: &mut Tek) -> Perhaps { tek.launch(); Ok(None) } - fn select (&self, tek: &mut Tek, selection: Selection) -> Perhaps { + fn select (tek: &mut Tek, selection: Selection) -> Perhaps { tek.select(selection); Ok(None) //("select" [t: usize, s: usize] Some(match (t.expect("no track"), s.expect("no scene")) { @@ -348,129 +344,169 @@ impl TekCommand { //(0, s) => Self::Select(Selection::Scene(s)), //(t, s) => Self::Select(Selection::TrackClip { track: t, scene: s }) }))) } - fn stop_all (&self, tek: &mut Tek) -> Perhaps { + fn stop_all (tek: &mut Tek) -> Perhaps { tek.stop_all(); Ok(None) } } -#[tengri_proc::command(Tek)] -impl InputCommand { - fn add (&self, tek: &mut Tek) -> Perhaps { +#[tengri_proc::command(Tek)] impl InputCommand { + fn add (tek: &mut Tek) -> Perhaps { tek.midi_in_add()?; Ok(None) } } -#[tengri_proc::command(Tek)] -impl OutputCommand { - fn add (&self, tek: &mut Tek) -> Perhaps { +#[tengri_proc::command(Tek)] impl OutputCommand { + fn add (tek: &mut Tek) -> Perhaps { tek.midi_out_add()?; Ok(None) } } -#[tengri_proc::command(Tek)] -impl DeviceCommand { - fn picker (&self, tek: &mut Tek) -> Perhaps { +#[tengri_proc::command(Tek)] impl DeviceCommand { + fn picker (tek: &mut Tek) -> Perhaps { tek.device_picker_show(); Ok(None) } - fn pick (&self, tek: &mut Tek, i: usize) -> Perhaps { + fn pick (tek: &mut Tek, i: usize) -> Perhaps { tek.device_pick(i); Ok(None) } - fn add (&self, tek: &mut Tek, i: usize) -> Perhaps { + fn add (tek: &mut Tek, i: usize) -> Perhaps { tek.device_add(i); Ok(None) } } -#[tengri_proc::command(Tek)] -impl MessageCommand { - fn dismiss (&self, tek: &mut Tek) -> Perhaps { +#[tengri_proc::command(Tek)] impl MessageCommand { + fn dismiss (tek: &mut Tek) -> Perhaps { tek.message_dismiss(); Ok(None) } } -#[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] 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::command(Tek)] impl TrackCommand { + fn toggle_play (tek: &mut Tek) -> Perhaps { + todo!() + } + fn toggle_solo (tek: &mut Tek) -> Perhaps { + todo!() + } + fn toggle_rec (tek: &mut Tek) -> Perhaps { + tek.track_toggle_record(); + Ok(Some(Self::ToggleRec)) + } + fn toggle_mon (tek: &mut Tek) -> Perhaps { + tek.track_toggle_monitor(); + Ok(Some(Self::ToggleMon)) + } + fn set_size (tek: &mut Tek, size: usize) -> Perhaps { + todo!() + } + fn set_zoom (tek: &mut Tek, zoom: usize) -> Perhaps { + todo!() + } + fn swap (tek: &mut Tek, index: usize, other: usize) -> Perhaps { + todo!(); + Ok(Some(Self::Swap { index, other })) + } + fn del (tek: &mut Tek, index: usize) -> Perhaps { + tek.track_del(index); + Ok(None) + } + fn stop (tek: &mut Tek, index: usize) -> Perhaps { + tek.tracks[index].player.enqueue_next(None); + Ok(None) + } + fn add (tek: &mut Tek) -> Perhaps { + Ok(Some(Self::Del { index: tek.track_add_focus()? })) + } + fn set_color (tek: &mut Tek, index: usize, color: ItemTheme) -> Perhaps { + Ok(Some(Self::SetColor { index, color: tek.track_set_color(index, color) })) + } } -#[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] 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())))) +#[tengri_proc::command(Tek)] impl SceneCommand { + fn add (tek: &mut Tek) -> Perhaps { + todo!() + } + fn del (tek: &mut Tek, index: usize) -> Perhaps { + tek.scene_del(index); + Ok(None) + } + fn enqueue (tek: &mut Tek, index: usize) -> Perhaps { + tek.scene_enqueue(index); + Ok(None) + } + fn set_color (tek: &mut Tek, index: usize, color: ItemTheme) -> Perhaps { + Ok(Some(Self::SetColor { index, color: tek.scene_set_color(index, color) })) + } + fn set_size (tek: &mut Tek, index: usize, size: usize) -> Perhaps { + todo!() + } + fn set_zoom (tek: &mut Tek, index: usize, zoom: usize) -> Perhaps { + todo!() + } + fn swap (tek: &mut Tek, index: usize, other: usize) -> Perhaps { + todo!(); + Ok(Some(Self::Swap { index, other })) + } } -#[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()))) +#[tengri_proc::command(Tek)] impl ClipCommand { + fn get (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(Get [a: usize, b: usize] cmd_todo!("\n\rtodo: clip: get: {a} {b}")) + //("get" [a: usize, b: usize] Some(Self::Get(a.unwrap(), b.unwrap()))) + todo!() + } + fn edit (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(Edit [clip: MaybeClip] cmd_todo!("\n\rtodo: clip: edit: {clip:?}")) + //("edit" [a: MaybeClip] Some(Self::Edit(a.unwrap()))) + todo!() + } + fn set_loop (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(SetLoop [t: usize, s: usize, l: bool] cmd_todo!("\n\rtodo: {self:?}")) + //("loop" [a: usize, b: usize, c: bool] Some(Self::SetLoop(a.unwrap(), b.unwrap(), c.unwrap()))) + todo!() + } + fn put (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(Put [t: usize, s: usize, c: MaybeClip] + //Some(Self::Put(t, s, app.clip_put(t, s, c)))) + //("put" [a: usize, b: usize, c: MaybeClip] Some(Self::Put(a.unwrap(), b.unwrap(), c.unwrap()))) + todo!() + } + fn del (tek: &mut Tek, a: usize, b: usize) -> Perhaps { //("delete" [a: usize, b: usize] Some(Self::Put(a.unwrap(), b.unwrap(), None)))) + todo!() + } + fn enqueue (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(Enqueue [t: usize, s: usize] + //cmd!(app.tracks[t].player.enqueue_next(app.scenes[s].clips[t].as_ref()))) + //("enqueue" [a: usize, b: usize] Some(Self::Enqueue(a.unwrap(), b.unwrap()))) + todo!() + } + fn set_color (tek: &mut Tek, a: usize, b: usize) -> Perhaps { + //(SetColor [t: usize, s: usize, c: ItemTheme] + //app.clip_set_color(t, s, c).map(|o|Self::SetColor(t, s, o))))); + //("color" [a: usize, b: usize] Some(Self::SetColor(a.unwrap(), b.unwrap(), ItemTheme::random()))) + todo!() + } } -#[tengri_proc::command(MidiPool)] -impl PoolCommand { +#[tengri_proc::command(MidiPool)] impl PoolCommand { /// Toggle visibility of pool - fn show (&self, pool: &mut MidiPool, visible: bool) -> Perhaps { + fn show (pool: &mut MidiPool, visible: bool) -> Perhaps { pool.visible = visible; - Ok(Some(Self::Show(!visible))) + Ok(Some(Self::Show { visible: !visible })) } /// Select a clip from the clip pool - fn select (&self, pool: &mut MidiPool, index: usize) -> Perhaps { + fn select (pool: &mut MidiPool, index: usize) -> Perhaps { pool.set_clip_index(index); Ok(None) } /// Rename a clip - fn rename (&self, pool: &mut MidiPool, command: ClipRenameCommand) -> Perhaps { + fn rename (pool: &mut MidiPool, command: ClipRenameCommand) -> Perhaps { Ok(match command { ClipRenameCommand::Begin => { pool.begin_clip_rename(); @@ -480,7 +516,7 @@ impl PoolCommand { }) } /// Change the length of a clip - fn length (&self, pool: &mut MidiPool, command: ClipLengthCommand) -> Perhaps { + fn length (pool: &mut MidiPool, command: ClipLengthCommand) -> Perhaps { Ok(match command { ClipLengthCommand::Begin => { pool.begin_clip_length(); @@ -490,9 +526,9 @@ impl PoolCommand { }) } /// Import from file - fn import (&self, pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps { + fn import (pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps { Ok(match command { - ClipImportCommand::Begin => { + FileBrowserCommand::Begin => { pool.begin_import(); None }, @@ -500,9 +536,9 @@ impl PoolCommand { }) } /// Export to file - fn export (&self, pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps { + fn export (pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps { Ok(match command { - ClipExportCommand::Begin => { + FileBrowserCommand::Begin => { pool.begin_export(); None }, @@ -510,14 +546,13 @@ impl PoolCommand { }) } /// Update the contents of the clip pool - fn clip (&self, pool: &mut MidiPool, command: PoolClipCommand) -> Perhaps { - command.execute(pool)?.map(|command|Self::Clip{command}) + fn clip (pool: &mut MidiPool, command: PoolClipCommand) -> Perhaps { + Ok(command.execute(pool)?.map(|command|Self::Clip{command})) } } -#[tengri_proc::command(MidiPool)] -impl PoolClipCommand { - fn add (&self, pool: &mut MidiPool, index: usize, clip: MidiClip) -> Perhaps { +#[tengri_proc::command(MidiPool)] impl PoolClipCommand { + fn add (pool: &mut MidiPool, index: usize, clip: MidiClip) -> Perhaps { let mut index = index; let clip = Arc::new(RwLock::new(clip)); let mut clips = pool.clips_mut(); @@ -527,17 +562,17 @@ impl PoolClipCommand { } else { clips.insert(index, clip); } - Ok(Some(Self::Delete(index))) + Ok(Some(Self::Delete { index })) } - fn delete (&self, pool: &mut MidiPool, index: usize) -> Perhaps { + fn delete (pool: &mut MidiPool, index: usize) -> Perhaps { let clip = pool.clips_mut().remove(index).read().unwrap().clone(); - Ok(Some(Self::Add(index, clip))) + Ok(Some(Self::Add { index, clip })) } - fn swap (&self, pool: &mut MidiPool, index: usize, other: usize) -> Perhaps { + fn swap (pool: &mut MidiPool, index: usize, other: usize) -> Perhaps { pool.clips_mut().swap(index, other); - Ok(Some(Self::Swap(index, other))) + Ok(Some(Self::Swap { index, other })) } - fn import (&self, pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps { + fn import (pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps { let bytes = std::fs::read(&path)?; let smf = Smf::parse(bytes.as_slice())?; let mut t = 0u32; @@ -554,50 +589,49 @@ impl PoolClipCommand { for event in events.iter() { clip.notes[event.0 as usize].push(event.2); } - Self::Add(index, clip).execute(pool)? + Ok(Self::Add { index, clip }.execute(pool)?) } - fn export (&self, pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps { + fn export (pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps { todo!("export clip to midi file"); } - fn set_name (&self, pool: &mut MidiPool, index: usize, name: Arc) -> Perhaps { + fn set_name (pool: &mut MidiPool, index: usize, name: Arc) -> Perhaps { let clip = &mut pool.clips_mut()[index]; let old_name = clip.read().unwrap().name.clone(); clip.write().unwrap().name = name; - Ok(Some(Self::SetName(index, old_name))) + Ok(Some(Self::SetName { index, name: old_name })) } - fn set_length (&self, pool: &mut MidiPool, index: usize, length: usize) -> Perhaps { + fn set_length (pool: &mut MidiPool, index: usize, length: usize) -> Perhaps { let clip = &mut pool.clips_mut()[index]; let old_len = clip.read().unwrap().length; clip.write().unwrap().length = length; - Ok(Some(Self::SetLength(index, old_len))) + Ok(Some(Self::SetLength { index, length: old_len })) } - fn set_color (&self, pool: &mut MidiPool, index: usize, color: ItemColor) -> Perhaps { + fn set_color (pool: &mut MidiPool, index: usize, color: ItemColor) -> Perhaps { let mut color = ItemTheme::from(color); std::mem::swap(&mut color, &mut pool.clips()[index].write().unwrap().color); - Ok(Some(Self::SetColor(index, color.base))) + Ok(Some(Self::SetColor { index, color: color.base })) } } -#[tengri_proc::command(MidiPool)] -impl ClipRenameCommand { - fn begin (&self, pool: &mut MidiPool) -> Perhaps { +#[tengri_proc::command(MidiPool)] impl ClipRenameCommand { + fn begin (pool: &mut MidiPool) -> Perhaps { unreachable!(); } - fn cancel (&self, pool: &mut MidiPool) -> Perhaps { + fn cancel (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() { pool.clips()[clip].write().unwrap().name = old_name.clone().into(); } return Ok(None) } - fn confirm (&self, pool: &mut MidiPool) -> Perhaps { + fn confirm (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() { let old_name = old_name.clone(); - pool.mode_mut() = None; - return Ok(Some(Self::Set(old_name))) + *pool.mode_mut() = None; + return Ok(Some(Self::Set { value: old_name })) } return Ok(None) } - fn set (&self, pool: &mut MidiPool, value: Arc) -> Perhaps { + fn set (pool: &mut MidiPool, value: Arc) -> Perhaps { if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() { pool.clips()[clip].write().unwrap().name = value; } @@ -605,18 +639,17 @@ impl ClipRenameCommand { } } -#[tengri_proc::command(MidiPool)] -impl ClipLengthCommand { - fn begin (&self, pool: &mut MidiPool) -> Perhaps { +#[tengri_proc::command(MidiPool)] impl ClipLengthCommand { + fn begin (pool: &mut MidiPool) -> Perhaps { unreachable!() } - fn cancel (&self, pool: &mut MidiPool) -> Perhaps { + fn cancel (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Length(..)) = pool.mode_mut().clone() { *pool.mode_mut() = None; } Ok(None) } - fn set (&self, pool: &mut MidiPool, length: usize) -> Perhaps { + fn set (pool: &mut MidiPool, length: usize) -> Perhaps { if let Some(PoolMode::Length(clip, ref mut length, ref mut focus)) = pool.mode_mut().clone() { @@ -624,14 +657,14 @@ impl ClipLengthCommand { { let clip = pool.clips()[clip].clone();//.write().unwrap(); old_length = Some(clip.read().unwrap().length); - clip.write().unwrap().length = length; + clip.write().unwrap().length = *length; } - pool.mode_mut() = None; + *pool.mode_mut() = None; return Ok(old_length.map(|length|Self::Set { length })) } Ok(None) } - fn next (&self, pool: &mut MidiPool) -> Perhaps { + fn next (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Length(clip, ref mut length, ref mut focus)) = pool.mode_mut().clone() { @@ -639,7 +672,7 @@ impl ClipLengthCommand { } Ok(None) } - fn prev (&self, pool: &mut MidiPool) -> Perhaps { + fn prev (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Length(clip, ref mut length, ref mut focus)) = pool.mode_mut().clone() { @@ -647,102 +680,110 @@ impl ClipLengthCommand { } Ok(None) } - fn inc (&self, pool: &mut MidiPool) -> Perhaps { + fn inc (pool: &mut MidiPool) -> Perhaps { if let Some(PoolMode::Length(clip, ref mut length, ref mut focus)) = pool.mode_mut().clone() { match focus { - Bar => { *length += 4 * PPQ }, - Beat => { *length += PPQ }, - Tick => { *length += 1 }, + ClipLengthFocus::Bar => { *length += 4 * PPQ }, + ClipLengthFocus::Beat => { *length += PPQ }, + ClipLengthFocus::Tick => { *length += 1 }, } } Ok(None) } - fn dec (&self, pool: &mut MidiPool) -> Perhaps { - if let Some( - PoolMode::Length(clip, ref mut length, ref mut focus) - ) = pool.mode_mut().clone() { + fn dec (pool: &mut MidiPool) -> Perhaps { + if let Some(PoolMode::Length(clip, ref mut length, ref mut focus)) + = pool.mode_mut().clone() + { match focus { - Bar => { *length = length.saturating_sub(4 * PPQ) }, - Beat => { *length = length.saturating_sub(PPQ) }, - Tick => { *length = length.saturating_sub(1) }, + ClipLengthFocus::Bar => { *length = length.saturating_sub(4 * PPQ) }, + ClipLengthFocus::Beat => { *length = length.saturating_sub(PPQ) }, + ClipLengthFocus::Tick => { *length = length.saturating_sub(1) }, } } Ok(None) } } -#[tengri_proc::command(MidiPool)] -impl FileBrowserCommand { - fn begin (&self, pool: &mut MidiPool) -> Perhaps { +#[tengri_proc::command(MidiPool)] impl FileBrowserCommand { + fn begin (pool: &mut MidiPool) -> Perhaps { unreachable!(); } - fn cancel (&self, pool: &mut MidiPool) -> Perhaps { + fn cancel (pool: &mut MidiPool) -> Perhaps { pool.mode = None; Ok(None) } - fn confirm (&self, pool: &mut MidiPool) -> Perhaps { + fn confirm (pool: &mut MidiPool) -> Perhaps { Ok(match pool.mode { Some(PoolMode::Import(index, ref mut browser)) => { if browser.is_file() { - let index = *index; let path = browser.path(); pool.mode = None; - PoolClipCommand::Import(index, path).execute(pool)?; + let _undo = PoolClipCommand::import(pool, index, path)?; + None } else if browser.is_dir() { - pool.mode = Some(PoolMode::Import(*index, browser.chdir()?)); + pool.mode = Some(PoolMode::Import(index, browser.chdir()?)); + None + } else { + None } }, - Some(PoolMode::Export(index, ref mut browser)) => match self { - Cancel => { pool.mode = None; }, - _ => unreachable!() + Some(PoolMode::Export(index, ref mut browser)) => { + todo!() }, _ => unreachable!(), }) } - fn select (&self, pool: &mut MidiPool, index: usize) -> Perhaps { - Ok(match pool.mode { - Some(PoolMode::Import(index, ref mut browser)) => { browser.index = index; }, - Some(PoolMode::Export(index, ref mut browser)) => { browser.index = index; }, - _ => unreachable!(), - }) - } - fn chdir (&self, pool: &mut MidiPool, dir: PathBuf) -> Perhaps { + fn select (pool: &mut MidiPool, index: usize) -> Perhaps { Ok(match pool.mode { Some(PoolMode::Import(index, ref mut browser)) => { - pool.mode = Some(PoolMode::Import(*index, FileBrowser::new(Some(dir))?)); + browser.index = index; + None }, Some(PoolMode::Export(index, ref mut browser)) => { - pool.mode = Some(PoolMode::Export(*index, FileBrowser::new(Some(dir))?)); + browser.index = index; + None }, _ => unreachable!(), }) } - fn filter (&self, pool: &mut MidiPool, filter: Arc) -> Perhaps { + fn chdir (pool: &mut MidiPool, dir: PathBuf) -> Perhaps { + Ok(match pool.mode { + Some(PoolMode::Import(index, ref mut browser)) => { + pool.mode = Some(PoolMode::Import(index, FileBrowser::new(Some(dir))?)); + None + }, + Some(PoolMode::Export(index, ref mut browser)) => { + pool.mode = Some(PoolMode::Export(index, FileBrowser::new(Some(dir))?)); + None + }, + _ => unreachable!(), + }) + } + fn filter (pool: &mut MidiPool, filter: Arc) -> Perhaps { todo!() } } -#[tengri_proc::command(MidiEditor)] -impl MidiEditCommand { +#[tengri_proc::command(MidiEditor)] impl MidiEditCommand { // TODO: 1-9 seek markers that by default start every 8th of the clip - fn note_append (&self, editor: &mut MidiEditor) -> Perhaps { + fn note_append (editor: &mut MidiEditor) -> Perhaps { editor.put_note(true); Ok(None) } - fn note_put (&self, editor: &mut MidiEditor) -> Perhaps { + fn note_put (editor: &mut MidiEditor) -> Perhaps { editor.put_note(false); Ok(None) } - fn note_del (&self, editor: &mut MidiEditor) -> Perhaps { + fn note_del (editor: &mut MidiEditor) -> Perhaps { todo!() } - fn note_pos (&self, editor: &mut MidiEditor, pos: usize) -> Perhaps { + fn note_pos (editor: &mut MidiEditor, pos: usize) -> Perhaps { editor.set_note_pos(pos.min(127)); Ok(None) } - fn note_len (&self, editor: &mut MidiEditor, value: usize) -> Perhaps { + fn note_len (editor: &mut MidiEditor, value: usize) -> Perhaps { //let note_len = editor.get_note_len(); //let time_zoom = editor.get_time_zoom(); editor.set_note_len(value); @@ -751,28 +792,28 @@ impl MidiEditCommand { //} Ok(None) } - fn note_scroll (&self, editor: &mut MidiEditor, value: usize) { + fn note_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps { editor.set_note_lo(value.min(127)); Ok(None) } - fn time_pos (&self, editor: &mut MidiEditor, value: usize) -> Perhaps { + fn time_pos (editor: &mut MidiEditor, value: usize) -> Perhaps { editor.set_time_pos(value); Ok(None) } - fn time_scroll (&self, editor: &mut MidiEditor, value: usize) -> Perhaps { + fn time_scroll (editor: &mut MidiEditor, value: usize) -> Perhaps { editor.set_time_start(value); Ok(None) } - fn time_zoom (&self, editor: &mut MidiEditor, value: usize) -> Perhaps { - editor.time_zoom().set(value); + fn time_zoom (editor: &mut MidiEditor, value: usize) -> Perhaps { + editor.set_time_zoom(value); editor.redraw(); Ok(None) } - fn time_lock (&self, editor: &mut MidiEditor, value: bool) -> Perhaps { + fn time_lock (editor: &mut MidiEditor, value: bool) -> Perhaps { editor.set_time_lock(value); Ok(None) } - fn show (&self, editor: &mut MidiEditor, clip: Option>>) -> Perhaps { + fn show (editor: &mut MidiEditor, clip: Option>>) -> Perhaps { editor.set_clip(clip.as_ref()); Ok(None) } diff --git a/crates/app/src/model/editor.rs b/crates/app/src/model/editor.rs index 9a9d5836..fec878b1 100644 --- a/crates/app/src/model/editor.rs +++ b/crates/app/src/model/editor.rs @@ -53,9 +53,9 @@ impl MidiEditor { let mut redraw = false; if let Some(clip) = self.clip() { let mut clip = clip.write().unwrap(); - let note_start = self.time_pos(); - let note_pos = self.note_pos(); - let note_len = self.note_len(); + let note_start = self.get_time_pos(); + let note_pos = self.get_note_pos(); + let note_len = self.get_note_len(); let note_end = note_start + (note_len.saturating_sub(1)); let key: u7 = u7::from(note_pos as u8); let vel: u7 = 100.into(); diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index d1377bee..2f1bfdd9 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -1195,8 +1195,8 @@ impl MidiViewer for PianoHorizontal { let clip = clip.read().unwrap(); let buf_size = self.buffer_size(&clip); let mut buffer = BigBuffer::from(buf_size); - let note_len = self.note_len(); - let time_zoom = self.time_zoom().get(); + let note_len = self.get_note_len(); + let time_zoom = self.get_time_zoom(); self.time_len().set(clip.length); PianoHorizontal::draw_bg(&mut buffer, &clip, time_zoom, note_len); PianoHorizontal::draw_fg(&mut buffer, &clip, time_zoom); diff --git a/crates/device/src/clock/clock_api.rs b/crates/device/src/clock/clock_api.rs index 097867fc..6faceb11 100644 --- a/crates/device/src/clock/clock_api.rs +++ b/crates/device/src/clock/clock_api.rs @@ -12,15 +12,15 @@ impl Command for ClockCommand { #[tengri_proc::command(Clock)] impl ClockCommand { - fn play (self, state: &mut Clock, position: Option) -> Perhaps { + fn play (state: &mut Clock, position: Option) -> Perhaps { state.play_from(position)?; Ok(None) // TODO Some(Pause(previousPosition)) } - fn pause (self, state: &mut Clock, position: Option) -> Perhaps { + fn pause (state: &mut Clock, position: Option) -> Perhaps { state.pause_at(position)?; Ok(None) } - fn toggle_playback (self, state: &mut Clock, position: Option) -> Perhaps { + fn toggle_playback (state: &mut Clock, position: Option) -> Perhaps { if state.is_rolling() { state.pause_at(position)?; } else { @@ -28,25 +28,25 @@ impl ClockCommand { } Ok(None) } - fn seek_usec (self, state: &mut Clock, usec: f64) -> Perhaps { + fn seek_usec (state: &mut Clock, usec: f64) -> Perhaps { state.playhead.update_from_usec(usec); Ok(None) } - fn seek_sample (self, state: &mut Clock, sample: f64) -> Perhaps { + fn seek_sample (state: &mut Clock, sample: f64) -> Perhaps { state.playhead.update_from_sample(sample); Ok(None) } - fn seek_pulse (self, state: &mut Clock, pulse: f64) -> Perhaps { + fn seek_pulse (state: &mut Clock, pulse: f64) -> Perhaps { state.playhead.update_from_pulse(pulse); Ok(None) } - fn set_bpm (self, state: &mut Clock, bpm: f64) -> Perhaps { + fn set_bpm (state: &mut Clock, bpm: f64) -> Perhaps { Ok(Some(Self::SetBpm { bpm: state.timebase().bpm.set(bpm) })) } - fn set_quant (self, state: &mut Clock, quant: f64) -> Perhaps { + fn set_quant (state: &mut Clock, quant: f64) -> Perhaps { Ok(Some(Self::SetQuant { quant: state.quant.set(quant) })) } - fn set_sync (self, state: &mut Clock, sync: f64) -> Perhaps { + fn set_sync (state: &mut Clock, sync: f64) -> Perhaps { Ok(Some(Self::SetSync { sync: state.sync.set(sync) })) } } diff --git a/crates/engine/src/note/note_range.rs b/crates/engine/src/note/note_range.rs index 6804bd7a..40e7acc0 100644 --- a/crates/engine/src/note/note_range.rs +++ b/crates/engine/src/note/note_range.rs @@ -37,14 +37,23 @@ pub trait TimeRange { fn get_time_zoom (&self) -> usize { self.time_zoom().load(Ordering::Relaxed) } + fn set_time_zoom (&self, value: usize) -> usize { + self.time_zoom().swap(value, Ordering::Relaxed) + } fn time_lock (&self) -> &AtomicBool; fn get_time_lock (&self) -> bool { self.time_lock().load(Ordering::Relaxed) } + fn set_time_lock (&self, value: bool) -> bool { + self.time_lock().swap(value, Ordering::Relaxed) + } fn time_start (&self) -> &AtomicUsize; fn get_time_start (&self) -> usize { self.time_start().load(Ordering::Relaxed) } + fn set_time_start (&self, value: usize) -> usize { + self.time_start().swap(value, Ordering::Relaxed) + } fn time_axis (&self) -> &AtomicUsize; fn get_time_axis (&self) -> usize { self.time_axis().load(Ordering::Relaxed) diff --git a/deps/tengri b/deps/tengri index 2a6087e1..a16603fb 160000 --- a/deps/tengri +++ b/deps/tengri @@ -1 +1 @@ -Subproject commit 2a6087e1c7086f09b1ade22c84ff62642df7c723 +Subproject commit a16603fbc88a41c0cb4a315383cb647b0f9bb2b5