mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
double arc rwlock was silly
This commit is contained in:
parent
70794e3cb9
commit
d06b95df2c
3 changed files with 59 additions and 61 deletions
|
|
@ -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!([
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue