midi: return old values from cursor traits

This commit is contained in:
🪞👃🪞 2025-04-27 17:07:09 +03:00
parent 397e71edee
commit e9c825e865
6 changed files with 76 additions and 92 deletions

View file

@ -160,14 +160,14 @@ impl NoteRange for MidiEditor {
impl NotePoint for MidiEditor { impl NotePoint for MidiEditor {
fn note_len (&self) -> usize { self.mode.note_len() } fn note_len (&self) -> usize { self.mode.note_len() }
fn set_note_len (&self, x: usize) { self.mode.set_note_len(x) } fn set_note_len (&self, x: usize) -> usize { self.mode.set_note_len(x) }
fn note_pos (&self) -> usize { self.mode.note_pos() } fn note_pos (&self) -> usize { self.mode.note_pos() }
fn set_note_pos (&self, x: usize) { self.mode.set_note_pos(x) } fn set_note_pos (&self, x: usize) -> usize { self.mode.set_note_pos(x) }
} }
impl TimePoint for MidiEditor { impl TimePoint for MidiEditor {
fn time_pos (&self) -> usize { self.mode.time_pos() } fn time_pos (&self) -> usize { self.mode.time_pos() }
fn set_time_pos (&self, x: usize) { self.mode.set_time_pos(x) } fn set_time_pos (&self, x: usize) -> usize { self.mode.set_time_pos(x) }
} }
impl MidiViewer for MidiEditor { impl MidiViewer for MidiEditor {

View file

@ -7,7 +7,7 @@ pub struct MidiPointModel {
/// Note coordinate of cursor /// Note coordinate of cursor
pub note_pos: Arc<AtomicUsize>, pub note_pos: Arc<AtomicUsize>,
/// Length of note that will be inserted, in pulses /// Length of note that will be inserted, in pulses
pub note_len: Arc<AtomicUsize>, pub note_len: Arc<AtomicUsize>,
} }
impl Default for MidiPointModel { impl Default for MidiPointModel {
@ -21,30 +21,52 @@ impl Default for MidiPointModel {
} }
pub trait NotePoint { pub trait NotePoint {
fn note_len (&self) -> usize; /// Get the current length of the note cursor.
fn set_note_len (&self, x: usize); fn note_len (&self) -> usize;
fn note_pos (&self) -> usize; /// Set the length of the note cursor, returning the previous value.
fn set_note_pos (&self, x: usize); fn set_note_len (&self, x: usize) -> usize;
fn note_end (&self) -> usize { self.note_pos() + self.note_len() } /// Get the current pitch of the note cursor.
fn note_pos (&self) -> usize;
/// Set the current pitch fo the note cursor, returning the previous value.
fn set_note_pos (&self, x: usize) -> usize;
} }
pub trait TimePoint { pub trait TimePoint {
fn time_pos (&self) -> usize; /// Get the current time position of the note cursor.
fn set_time_pos (&self, x: usize); fn time_pos (&self) -> usize;
/// Set the current time position of the note cursor, returning the previous value.
fn set_time_pos (&self, x: usize) -> usize;
} }
pub trait MidiPoint: NotePoint + TimePoint {} pub trait MidiPoint: NotePoint + TimePoint {
/// Get the current end of the note cursor.
fn note_end (&self) -> usize {
self.time_pos() + self.note_len()
}
}
impl<T: NotePoint + TimePoint> MidiPoint for T {} impl<T: NotePoint + TimePoint> MidiPoint for T {}
impl NotePoint for MidiPointModel { impl NotePoint for MidiPointModel {
fn note_len (&self) -> usize { self.note_len.load(Relaxed)} fn note_len (&self) -> usize {
fn set_note_len (&self, x: usize) { self.note_len.store(x, Relaxed) } self.note_len.load(Relaxed)
fn note_pos (&self) -> usize { self.note_pos.load(Relaxed).min(127) } }
fn set_note_pos (&self, x: usize) { self.note_pos.store(x.min(127), Relaxed) } fn set_note_len (&self, x: usize) -> usize {
self.note_len.swap(x, Relaxed)
}
fn note_pos (&self) -> usize {
self.note_pos.load(Relaxed).min(127)
}
fn set_note_pos (&self, x: usize) -> usize {
self.note_pos.swap(x.min(127), Relaxed)
}
} }
impl TimePoint for MidiPointModel { impl TimePoint for MidiPointModel {
fn time_pos (&self) -> usize { self.time_pos.load(Relaxed) } fn time_pos (&self) -> usize {
fn set_time_pos (&self, x: usize) { self.time_pos.store(x, Relaxed) } self.time_pos.load(Relaxed)
}
fn set_time_pos (&self, x: usize) -> usize {
self.time_pos.swap(x, Relaxed)
}
} }

View file

@ -242,14 +242,14 @@ impl NoteRange for PianoHorizontal {
impl NotePoint for PianoHorizontal { impl NotePoint for PianoHorizontal {
fn note_len (&self) -> usize { self.point.note_len() } fn note_len (&self) -> usize { self.point.note_len() }
fn set_note_len (&self, x: usize) { self.point.set_note_len(x) } fn set_note_len (&self, x: usize) -> usize { self.point.set_note_len(x) }
fn note_pos (&self) -> usize { self.point.note_pos() } fn note_pos (&self) -> usize { self.point.note_pos() }
fn set_note_pos (&self, x: usize) { self.point.set_note_pos(x) } fn set_note_pos (&self, x: usize) -> usize { self.point.set_note_pos(x) }
} }
impl TimePoint for PianoHorizontal { impl TimePoint for PianoHorizontal {
fn time_pos (&self) -> usize { self.point.time_pos() } fn time_pos (&self) -> usize { self.point.time_pos() }
fn set_time_pos (&self, x: usize) { self.point.set_time_pos(x) } fn set_time_pos (&self, x: usize) -> usize { self.point.set_time_pos(x) }
} }
impl MidiViewer for PianoHorizontal { impl MidiViewer for PianoHorizontal {

View file

@ -14,38 +14,45 @@ expose!([self: Sampler]
impose!([state: Sampler] impose!([state: Sampler]
(FileBrowserCommand: (FileBrowserCommand:
("begin" [] Some(Self::Begin)) ("begin" [] Some(Self::Begin))
("cancel" [] Some(Self::Cancel)) ("cancel" [] Some(Self::Cancel))
("confirm" [] Some(Self::Confirm)) ("confirm" [] Some(Self::Confirm))
("select" [i: usize] Some(Self::Select(i.expect("no index")))) ("select" [i: usize] Some(Self::Select(i.expect("no index"))))
("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path")))) ("chdir" [p: PathBuf] Some(Self::Chdir(p.expect("no path"))))
("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter"))))) ("filter" [f: Arc<str>] Some(Self::Filter(f.expect("no filter")))))
(SamplerCommand: (SamplerCommand:
("import" [,..a] ("import" [,..a]
FileBrowserCommand::try_from_expr(state, a).map(Self::Import)) FileBrowserCommand::try_from_expr(state, a).map(Self::Import))
("select" [i: usize] ("select" [i: usize]
Some(Self::Select(i.expect("no index")))) Some(Self::Select(i.expect("no index"))))
("record/begin" [i: u7] ("record/begin" [i: u7]
Some(Self::RecordBegin(i.expect("no index")))) Some(Self::RecordBegin(i.expect("no index"))))
("record/cancel" [] ("record/cancel" []
Some(Self::RecordCancel)) Some(Self::RecordCancel))
("record/finish" [] ("record/finish" []
Some(Self::RecordFinish)) Some(Self::RecordFinish))
("set/sample" [i: u7, s: Option<Arc<RwLock<Sample>>>] ("set/sample" [i: u7, s: Option<Arc<RwLock<Sample>>>]
Some(Self::SetSample(i.expect("no index"), s.expect("no sampler")))) Some(Self::SetSample(i.expect("no index"), s.expect("no sampler"))))
("set/start" [i: u7, s: usize] ("set/start" [i: u7, s: usize]
Some(Self::SetStart(i.expect("no index"), s.expect("no start")))) Some(Self::SetStart(i.expect("no index"), s.expect("no start"))))
("set/gain" [i: u7, g: f32] ("set/gain" [i: u7, g: f32]
Some(Self::SetGain(i.expect("no index"), g.expect("no gain")))) Some(Self::SetGain(i.expect("no index"), g.expect("no gain"))))
("note/on" [p: u7, v: u7] ("note/on" [p: u7, v: u7]
Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity")))) Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity"))))
("note/off" [p: u7] ("note/off" [p: u7]
Some(Self::NoteOff(p.expect("no pitch")))))); Some(Self::NoteOff(p.expect("no pitch"))))));
defcom! { |self, state: Sampler| defcom!([self, state: Sampler]
SamplerCommand { (SamplerCommand
(Select [i: usize] Some(Self::Select(state.set_note_pos(i))))
Import(cmd: FileBrowserCommand) => match cmd { (RecordBegin [p: u7] { state.begin_recording(p.as_int() as usize); None })
(RecordCancel [] { state.cancel_recording(); None })
(RecordFinish [] { state.finish_recording(); None })
(SetStart [pitch: u7, frame: usize] { println!("\n\rtodo: {self:?}"); None })
(SetGain [pitch: u7, gain: f32] { println!("\n\rtodo: {self:?}"); None })
(NoteOn [pitch: u7, velocity: u7] { println!("\n\rtodo: {self:?}"); None })
(NoteOff [pitch: u7] { println!("\n\rtodo: {self:?}"); None })
(Import [cmd: FileBrowserCommand] match cmd {
FileBrowserCommand::Begin => { FileBrowserCommand::Begin => {
//let voices = &state.state.voices; //let voices = &state.state.voices;
//let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![]))); //let sample = Arc::new(RwLock::new(Sample::new("", 0, 0, vec![])));
@ -56,56 +63,10 @@ defcom! { |self, state: Sampler|
println!("\n\rtodo: import: filebrowser: {cmd:?}"); println!("\n\rtodo: import: filebrowser: {cmd:?}");
None None
} }
} })
(SetSample [pitch: u7, sample: Option<Arc<RwLock<Sample>>>] {
Select(index: usize) => {
let old = state.note_pos();
state.set_note_pos(index);
Some(Self::Select(old))
}
RecordBegin(pitch: u7) => {
state.begin_recording(pitch.as_int() as usize);
None
}
RecordCancel => {
state.cancel_recording();
None
}
RecordFinish => {
state.finish_recording();
None
}
SetSample(pitch: u7, sample: Option<Arc<RwLock<Sample>>>) => {
let i = pitch.as_int() as usize; let i = pitch.as_int() as usize;
let old = state.mapped[i].clone(); let old = state.mapped[i].clone();
state.mapped[i] = sample; state.mapped[i] = sample;
Some(Self::SetSample(pitch, old)) Some(Self::SetSample(pitch, old))
} })));
SetStart(pitch: u7, frame: usize) => {
println!("\n\rtodo: {self:?}");
None
}
SetGain(pitch: u7, gain: f32) => {
println!("\n\rtodo: {self:?}");
None
}
NoteOn(pitch: u7, velocity: u7) => {
println!("\n\rtodo: {self:?}");
None
}
NoteOff(pitch: u7) => {
println!("\n\rtodo: {self:?}");
None
}
}
}

View file

@ -123,15 +123,16 @@ impl NoteRange for Sampler {
} }
impl NotePoint for Sampler { impl NotePoint for Sampler {
fn note_len (&self) -> usize {0/*TODO*/} fn note_len (&self) -> usize { 0/*TODO*/ }
fn set_note_len (&self, x: usize) {} fn set_note_len (&self, x: usize) -> usize { 0 /*TODO*/ }
fn note_pos (&self) -> usize { fn note_pos (&self) -> usize {
self.note_pt.load(Relaxed) self.note_pt.load(Relaxed)
} }
fn set_note_pos (&self, x: usize) { fn set_note_pos (&self, x: usize) -> usize {
self.note_pt.store(x, Relaxed); let old = self.note_pt.swap(x, Relaxed);
self.cursor.0.store(x % 8, Relaxed); self.cursor.0.store(x % 8, Relaxed);
self.cursor.1.store(x / 8, Relaxed); self.cursor.1.store(x / 8, Relaxed);
old
} }
} }