mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +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
|
// E: Toggle between editing currently playing or other phrase
|
||||||
key_pat!(Char('e')) => if let Some((_, Some(playing_phrase))) = state.player.play_phrase() {
|
key_pat!(Char('e')) => if let Some((_, Some(playing_phrase))) = state.player.play_phrase() {
|
||||||
let editing_phrase = state.editor.phrase()
|
let editing_phrase = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone());
|
||||||
.read().unwrap().as_ref()
|
|
||||||
.map(|p|p.read().unwrap().clone());
|
|
||||||
let selected_phrase = state.phrases.phrase().clone();
|
let selected_phrase = state.phrases.phrase().clone();
|
||||||
if Some(selected_phrase.read().unwrap().clone()) != editing_phrase {
|
if Some(selected_phrase.read().unwrap().clone()) != editing_phrase {
|
||||||
Editor(Show(Some(selected_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::play_phrase(&self.player),
|
||||||
PhraseSelector::next_phrase(&self.player),
|
PhraseSelector::next_phrase(&self.player),
|
||||||
]), Tui::split_up(false, 2,
|
]), Tui::split_up(false, 2,
|
||||||
PhraseSelector::edit_phrase(&self.editor.phrase.read().unwrap()),
|
PhraseSelector::edit_phrase(self.editor.phrase()),
|
||||||
PhraseListView::from(self),
|
PhraseListView::from(self),
|
||||||
))),
|
))),
|
||||||
col!([
|
col!([
|
||||||
|
|
|
||||||
|
|
@ -27,25 +27,15 @@ pub enum PhraseCommand {
|
||||||
|
|
||||||
impl InputToCommand<Tui, PhraseEditorModel> for PhraseCommand {
|
impl InputToCommand<Tui, PhraseEditorModel> for PhraseCommand {
|
||||||
fn input_to_command (state: &PhraseEditorModel, from: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &PhraseEditorModel, from: &TuiInput) -> Option<Self> {
|
||||||
|
let length = ||state.phrase().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1);
|
||||||
let length = ||state
|
|
||||||
.phrase()
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.as_ref()
|
|
||||||
.map(|p|p.read().unwrap().length)
|
|
||||||
.unwrap_or(1);
|
|
||||||
|
|
||||||
let range = state.range();
|
let range = state.range();
|
||||||
let note_lo = ||range.note_lo.load(Relaxed);
|
let note_lo = ||range.note_lo.load(Relaxed);
|
||||||
let time_start = ||range.time_start.load(Relaxed);
|
let time_start = ||range.time_start.load(Relaxed);
|
||||||
let time_zoom = ||range.time_zoom();
|
let time_zoom = ||range.time_zoom();
|
||||||
|
|
||||||
let point = state.point();
|
let point = state.point();
|
||||||
let note_point = ||point.note_point();
|
let note_point = ||point.note_point();
|
||||||
let time_point = ||point.time_point();
|
let time_point = ||point.time_point();
|
||||||
let note_len = ||point.note_len();
|
let note_len = ||point.note_len();
|
||||||
|
|
||||||
Some(match from.event() {
|
Some(match from.event() {
|
||||||
key_pat!(Ctrl-Alt-Up) => SetNoteScroll(note_point() + 3),
|
key_pat!(Ctrl-Alt-Up) => SetNoteScroll(note_point() + 3),
|
||||||
key_pat!(Ctrl-Alt-Down) => SetNoteScroll(note_point().saturating_sub(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 range = state.range();
|
||||||
let point = state.point();
|
let point = state.point();
|
||||||
match self {
|
match self {
|
||||||
Show(phrase) => { state.set_phrase(phrase); },
|
Show(phrase) => { state.set_phrase(phrase.as_ref()); },
|
||||||
PutNote => { state.put_note(false); },
|
PutNote => { state.put_note(false); },
|
||||||
AppendNote => { state.put_note(true); },
|
AppendNote => { state.put_note(true); },
|
||||||
SetTimeZoom(x) => { range.set_time_zoom(x); },
|
SetTimeZoom(x) => { range.set_time_zoom(x); },
|
||||||
|
|
@ -114,51 +104,51 @@ impl Command<PhraseEditorModel> for PhraseCommand {
|
||||||
|
|
||||||
/// Contains state for viewing and editing a phrase
|
/// Contains state for viewing and editing a phrase
|
||||||
pub struct PhraseEditorModel {
|
pub struct PhraseEditorModel {
|
||||||
/// Phrase being played
|
|
||||||
pub phrase: Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>,
|
|
||||||
/// Renders the phrase
|
/// Renders the phrase
|
||||||
pub mode: Box<dyn PhraseViewMode>,
|
pub mode: Box<dyn PhraseViewMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PhraseEditorModel {
|
impl Default for PhraseEditorModel {
|
||||||
fn default () -> Self {
|
fn default () -> Self {
|
||||||
let phrase = Arc::new(RwLock::new(None));
|
Self { mode: Box::new(PianoHorizontal::new(None)) }
|
||||||
let mode = PianoHorizontal::new(&phrase);
|
|
||||||
Self { phrase, mode: Box::new(mode) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render!(|self: PhraseEditorModel|self.mode);
|
render!(|self: PhraseEditorModel|self.mode);
|
||||||
|
|
||||||
pub trait PhraseViewMode: Render<Tui> + Debug + Send + Sync {
|
pub trait PhraseViewMode: Render<Tui> + Debug + Send + Sync {
|
||||||
fn range (&self) -> &PhraseEditorRange;
|
fn range (&self) -> &PhraseEditorRange;
|
||||||
fn point (&self) -> &PhraseEditorPoint;
|
fn point (&self) -> &PhraseEditorPoint;
|
||||||
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize);
|
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize);
|
||||||
fn redraw (&mut self);
|
fn redraw (&mut self);
|
||||||
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>>;
|
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
||||||
fn set_phrase (&mut self, phrase: Option<Arc<RwLock<Phrase>>>) {
|
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<Phrase>>>;
|
||||||
*self.phrase().write().unwrap() = phrase;
|
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
|
||||||
|
*self.phrase_mut() = phrase.map(|p|p.clone());
|
||||||
self.redraw();
|
self.redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhraseViewMode for PhraseEditorModel {
|
impl PhraseViewMode for PhraseEditorModel {
|
||||||
fn range (&self) -> &PhraseEditorRange {
|
fn range (&self) -> &PhraseEditorRange {
|
||||||
self.mode.range()
|
self.mode.range()
|
||||||
}
|
}
|
||||||
fn point (&self) -> &PhraseEditorPoint {
|
fn point (&self) -> &PhraseEditorPoint {
|
||||||
self.mode.point()
|
self.mode.point()
|
||||||
}
|
}
|
||||||
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize) {
|
fn buffer_size (&self, phrase: &Phrase) -> (usize, usize) {
|
||||||
self.mode.buffer_size(phrase)
|
self.mode.buffer_size(phrase)
|
||||||
}
|
}
|
||||||
fn redraw (&mut self) {
|
fn redraw (&mut self) {
|
||||||
self.mode.redraw()
|
self.mode.redraw()
|
||||||
}
|
}
|
||||||
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>> {
|
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
|
||||||
self.mode.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)
|
self.mode.set_phrase(phrase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -264,25 +254,32 @@ impl PhraseEditorPoint {
|
||||||
impl PhraseEditorModel {
|
impl PhraseEditorModel {
|
||||||
/// Put note at current position
|
/// Put note at current position
|
||||||
pub fn put_note (&mut self, advance: bool) {
|
pub fn put_note (&mut self, advance: bool) {
|
||||||
if let Some(phrase) = &*self.phrase.read().unwrap() {
|
let mut redraw = false;
|
||||||
let point = self.point().clone();
|
if let Some(phrase) = self.phrase() {
|
||||||
let note_len = point.note_len.load(Relaxed);
|
|
||||||
let time = point.time_point.load(Relaxed);
|
|
||||||
let note = point.note_point.load(Relaxed);
|
|
||||||
let mut phrase = phrase.write().unwrap();
|
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 vel: u7 = 100.into();
|
||||||
let start = time;
|
let length = phrase.length;
|
||||||
let end = (start + note_len) % phrase.length;
|
let note_end = note_end % length;
|
||||||
phrase.notes[time].push(MidiMessage::NoteOn { key, vel });
|
let note_on = MidiMessage::NoteOn { key, vel };
|
||||||
phrase.notes[end].push(MidiMessage::NoteOff { key, vel });
|
if !phrase.notes[note_start].iter().any(|msg|*msg == note_on) {
|
||||||
self.mode.redraw();
|
phrase.notes[note_start].push(note_on);
|
||||||
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 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 {
|
impl From<Option<Arc<RwLock<Phrase>>>> for PhraseEditorModel {
|
||||||
fn from (phrase: Option<Arc<RwLock<Phrase>>>) -> Self {
|
fn from (phrase: Option<Arc<RwLock<Phrase>>>) -> Self {
|
||||||
let model = Self::default();
|
let mut model = Self::default();
|
||||||
*model.phrase.write().unwrap() = phrase;
|
*model.phrase_mut() = phrase;
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use super::*;
|
||||||
|
|
||||||
/// A phrase, rendered as a horizontal piano roll.
|
/// A phrase, rendered as a horizontal piano roll.
|
||||||
pub struct PianoHorizontal {
|
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 where the whole phrase is rerendered on change
|
||||||
buffer: BigBuffer,
|
buffer: BigBuffer,
|
||||||
/// Width and height of notes area at last render
|
/// Width and height of notes area at last render
|
||||||
|
|
@ -17,13 +17,13 @@ pub struct PianoHorizontal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 size = Measure::new();
|
||||||
let mut range = PhraseEditorRange::default();
|
let mut range = PhraseEditorRange::default();
|
||||||
range.time_axis = size.x.clone();
|
range.time_axis = size.x.clone();
|
||||||
range.note_axis = size.y.clone();
|
range.note_axis = size.y.clone();
|
||||||
let phrase = phrase.clone();
|
let phrase = phrase.map(|p|p.clone());
|
||||||
let color = phrase.read().unwrap().as_ref()
|
let color = phrase.as_ref()
|
||||||
.map(|p|p.read().unwrap().color)
|
.map(|p|p.read().unwrap().color)
|
||||||
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
|
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -242,9 +242,12 @@ impl PianoHorizontal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhraseViewMode for PianoHorizontal {
|
impl PhraseViewMode for PianoHorizontal {
|
||||||
fn phrase (&self) -> &Arc<RwLock<Option<Arc<RwLock<Phrase>>>>> {
|
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
|
||||||
&self.phrase
|
&self.phrase
|
||||||
}
|
}
|
||||||
|
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrase
|
||||||
|
}
|
||||||
fn range (&self) -> &PhraseEditorRange {
|
fn range (&self) -> &PhraseEditorRange {
|
||||||
&self.range
|
&self.range
|
||||||
}
|
}
|
||||||
|
|
@ -256,9 +259,10 @@ impl PhraseViewMode for PianoHorizontal {
|
||||||
(phrase.length / self.range.time_zoom(), 128)
|
(phrase.length / self.range.time_zoom(), 128)
|
||||||
}
|
}
|
||||||
fn redraw (&mut self) {
|
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 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 note_len = self.point.note_len();
|
||||||
let time_zoom = self.range.time_zoom();
|
let time_zoom = self.range.time_zoom();
|
||||||
PianoHorizontal::draw_bg(&mut buffer, &phrase, time_zoom, note_len);
|
PianoHorizontal::draw_bg(&mut buffer, &phrase, time_zoom, note_len);
|
||||||
|
|
@ -269,10 +273,9 @@ impl PhraseViewMode for PianoHorizontal {
|
||||||
};
|
};
|
||||||
self.buffer = buffer
|
self.buffer = buffer
|
||||||
}
|
}
|
||||||
fn set_phrase (&mut self, phrase: Option<Arc<RwLock<Phrase>>>) {
|
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
|
||||||
*self.phrase().write().unwrap() = phrase;
|
*self.phrase_mut() = phrase.map(|p|p.clone());
|
||||||
self.color = self.phrase.read().unwrap().as_ref()
|
self.color = phrase.map(|p|p.read().unwrap().color.clone())
|
||||||
.map(|p|p.read().unwrap().color)
|
|
||||||
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
|
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
|
||||||
self.redraw();
|
self.redraw();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue