double arc rwlock was silly

This commit is contained in:
🪞👃🪞 2024-12-14 20:48:55 +01:00
parent 70794e3cb9
commit d06b95df2c
3 changed files with 59 additions and 61 deletions

View file

@ -137,9 +137,7 @@ pub fn to_sequencer_command (state: &SequencerTui, input: &TuiInput) -> Option<S
// E: Toggle between editing currently playing or other phrase
key_pat!(Char('e')) => if let Some((_, Some(playing_phrase))) = state.player.play_phrase() {
let editing_phrase = state.editor.phrase()
.read().unwrap().as_ref()
.map(|p|p.read().unwrap().clone());
let editing_phrase = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone());
let selected_phrase = state.phrases.phrase().clone();
if Some(selected_phrase.read().unwrap().clone()) != editing_phrase {
Editor(Show(Some(selected_phrase)))
@ -183,7 +181,7 @@ render!(|self: SequencerTui|lay!([self.size, Tui::split_up(false, 1,
PhraseSelector::play_phrase(&self.player),
PhraseSelector::next_phrase(&self.player),
]), Tui::split_up(false, 2,
PhraseSelector::edit_phrase(&self.editor.phrase.read().unwrap()),
PhraseSelector::edit_phrase(self.editor.phrase()),
PhraseListView::from(self),
))),
col!([

View file

@ -27,25 +27,15 @@ pub enum PhraseCommand {
impl InputToCommand<Tui, PhraseEditorModel> for PhraseCommand {
fn input_to_command (state: &PhraseEditorModel, from: &TuiInput) -> Option<Self> {
let length = ||state
.phrase()
.read()
.unwrap()
.as_ref()
.map(|p|p.read().unwrap().length)
.unwrap_or(1);
let length = ||state.phrase().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1);
let range = state.range();
let note_lo = ||range.note_lo.load(Relaxed);
let time_start = ||range.time_start.load(Relaxed);
let time_zoom = ||range.time_zoom();
let point = state.point();
let note_point = ||point.note_point();
let time_point = ||point.time_point();
let note_len = ||point.note_len();
Some(match from.event() {
key_pat!(Ctrl-Alt-Up) => SetNoteScroll(note_point() + 3),
key_pat!(Ctrl-Alt-Down) => SetNoteScroll(note_point().saturating_sub(3)),
@ -88,7 +78,7 @@ impl Command<PhraseEditorModel> for PhraseCommand {
let range = state.range();
let point = state.point();
match self {
Show(phrase) => { state.set_phrase(phrase); },
Show(phrase) => { state.set_phrase(phrase.as_ref()); },
PutNote => { state.put_note(false); },
AppendNote => { state.put_note(true); },
SetTimeZoom(x) => { range.set_time_zoom(x); },
@ -114,51 +104,51 @@ impl Command<PhraseEditorModel> for PhraseCommand {
/// Contains state for viewing and editing a phrase
pub struct PhraseEditorModel {
/// Phrase being played
pub phrase: Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>,
/// Renders the phrase
pub mode: Box<dyn PhraseViewMode>,
}
impl Default for PhraseEditorModel {
fn default () -> Self {
let phrase = Arc::new(RwLock::new(None));
let mode = PianoHorizontal::new(&phrase);
Self { phrase, mode: Box::new(mode) }
Self { mode: Box::new(PianoHorizontal::new(None)) }
}
}
render!(|self: PhraseEditorModel|self.mode);
pub trait PhraseViewMode: Render<Tui> + Debug + Send + Sync {
fn range (&self) -> &PhraseEditorRange;
fn point (&self) -> &PhraseEditorPoint;
fn range (&self) -> &PhraseEditorRange;
fn point (&self) -> &PhraseEditorPoint;
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize);
fn redraw (&mut self);
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>;
fn set_phrase (&mut self, phrase: Option<Arc<RwLock<Phrase>>>) {
*self.phrase().write().unwrap() = phrase;
fn redraw (&mut self);
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<Phrase>>>;
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
*self.phrase_mut() = phrase.map(|p|p.clone());
self.redraw();
}
}
impl PhraseViewMode for PhraseEditorModel {
fn range (&self) -> &PhraseEditorRange {
fn range (&self) -> &PhraseEditorRange {
self.mode.range()
}
fn point (&self) -> &PhraseEditorPoint {
fn point (&self) -> &PhraseEditorPoint {
self.mode.point()
}
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize) {
self.mode.buffer_size(phrase)
}
fn redraw (&mut self) {
fn redraw (&mut self) {
self.mode.redraw()
}
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>> {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
self.mode.phrase()
}
fn set_phrase (&mut self, phrase: Option<Arc<RwLock<Phrase>>>) {
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<Phrase>>> {
self.mode.phrase_mut()
}
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
self.mode.set_phrase(phrase)
}
}
@ -264,25 +254,32 @@ impl PhraseEditorPoint {
impl PhraseEditorModel {
/// Put note at current position
pub fn put_note (&mut self, advance: bool) {
if let Some(phrase) = &*self.phrase.read().unwrap() {
let point = self.point().clone();
let note_len = point.note_len.load(Relaxed);
let time = point.time_point.load(Relaxed);
let note = point.note_point.load(Relaxed);
let mut redraw = false;
if let Some(phrase) = self.phrase() {
let mut phrase = phrase.write().unwrap();
let key: u7 = u7::from(note as u8);
let note_start = self.point().time_point();
let note_point = self.point().note_point();
let note_len = self.point().note_len();
let note_end = note_start + note_len;
let key: u7 = u7::from(note_point as u8);
let vel: u7 = 100.into();
let start = time;
let end = (start + note_len) % phrase.length;
phrase.notes[time].push(MidiMessage::NoteOn { key, vel });
phrase.notes[end].push(MidiMessage::NoteOff { key, vel });
self.mode.redraw();
if advance {
let time = point.time_point.load(Relaxed);
let length = phrase.length;
let forward = |time|(time + note_len) % length;
point.set_time_point(forward(time));
let length = phrase.length;
let note_end = note_end % length;
let note_on = MidiMessage::NoteOn { key, vel };
if !phrase.notes[note_start].iter().any(|msg|*msg == note_on) {
phrase.notes[note_start].push(note_on);
}
let note_off = MidiMessage::NoteOff { key, vel };
if !phrase.notes[note_end].iter().any(|msg|*msg == note_off) {
phrase.notes[note_end].push(note_off);
}
if advance {
self.point().set_time_point(note_end);
}
redraw = true;
}
if redraw {
self.mode.redraw();
}
}
}
@ -295,8 +292,8 @@ impl From<&Arc<RwLock<Phrase>>> for PhraseEditorModel {
impl From<Option<Arc<RwLock<Phrase>>>> for PhraseEditorModel {
fn from (phrase: Option<Arc<RwLock<Phrase>>>) -> Self {
let model = Self::default();
*model.phrase.write().unwrap() = phrase;
let mut model = Self::default();
*model.phrase_mut() = phrase;
model
}
}

View file

@ -3,7 +3,7 @@ use super::*;
/// A phrase, rendered as a horizontal piano roll.
pub struct PianoHorizontal {
phrase: Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>,
phrase: Option<Arc<RwLock<Phrase>>>,
/// Buffer where the whole phrase is rerendered on change
buffer: BigBuffer,
/// Width and height of notes area at last render
@ -17,13 +17,13 @@ pub struct PianoHorizontal {
}
impl PianoHorizontal {
pub fn new (phrase: &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>) -> Self {
pub fn new (phrase: Option<&Arc<RwLock<Phrase>>>) -> Self {
let size = Measure::new();
let mut range = PhraseEditorRange::default();
range.time_axis = size.x.clone();
range.note_axis = size.y.clone();
let phrase = phrase.clone();
let color = phrase.read().unwrap().as_ref()
let phrase = phrase.map(|p|p.clone());
let color = phrase.as_ref()
.map(|p|p.read().unwrap().color)
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
Self {
@ -242,9 +242,12 @@ impl PianoHorizontal {
}
impl PhraseViewMode for PianoHorizontal {
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>> {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
&self.phrase
}
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<Phrase>>> {
&mut self.phrase
}
fn range (&self) -> &PhraseEditorRange {
&self.range
}
@ -256,9 +259,10 @@ impl PhraseViewMode for PianoHorizontal {
(phrase.length / self.range.time_zoom(), 128)
}
fn redraw (&mut self) {
let buffer = if let Some(phrase) = &*self.phrase().read().unwrap() {
let buffer = if let Some(phrase) = self.phrase.as_ref() {
let phrase = phrase.read().unwrap();
let mut buffer = BigBuffer::from(self.buffer_size(&phrase));
let buf_size = self.buffer_size(&phrase);
let mut buffer = BigBuffer::from(buf_size);
let note_len = self.point.note_len();
let time_zoom = self.range.time_zoom();
PianoHorizontal::draw_bg(&mut buffer, &phrase, time_zoom, note_len);
@ -269,10 +273,9 @@ impl PhraseViewMode for PianoHorizontal {
};
self.buffer = buffer
}
fn set_phrase (&mut self, phrase: Option<Arc<RwLock<Phrase>>>) {
*self.phrase().write().unwrap() = phrase;
self.color = self.phrase.read().unwrap().as_ref()
.map(|p|p.read().unwrap().color)
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
*self.phrase_mut() = phrase.map(|p|p.clone());
self.color = phrase.map(|p|p.read().unwrap().color.clone())
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
self.redraw();
}