use crate::*; impl Content for PhrasePool { type Engine = Tui; fn content (&self) -> impl Widget { col!( "Phrases:", col!((i, phrase) in self.phrases.iter().enumerate() => format!("{i}")) ) .fill_xy() .bg(Color::Rgb(28, 35, 25)) .border(Lozenge(Style::default() .bg(Color::Rgb(40, 50, 30)) .fg(Color::Rgb(70, 80, 50)))) } } impl Sequencer { const H_KEYS_OFFSET: usize = 5; /// Select which pattern to display. This pre-renders it to the buffer at full resolution. pub fn show (&mut self, index: Option) { self.viewing_phrase = index; if let Some(phrase) = index.map(|index|self.phrases.get(index)).flatten() { let width = usize::MAX.min(phrase.read().unwrap().length); let mut buffer = BigBuffer::new(width, 64); let phrase = phrase.read().unwrap(); Self::fill_seq_bg(&mut buffer, phrase.length, self.ppq); Self::fill_seq_fg(&mut buffer, &phrase); self.buffer = buffer; } else { self.viewing_phrase = None; self.buffer = Default::default(); } } fn fill_seq_bg (buf: &mut BigBuffer, length: usize, ppq: usize) { for x in 0..buf.width { if x as usize >= length { break } let style = Style::default(); buf.get_mut(x, 0).map(|cell|{ cell.set_char('-'); cell.set_style(style); }); for y in 0 .. buf.height { buf.get_mut(x, y).map(|cell|{ cell.set_char(if ppq == 0 { '·' } else if x % (4 * ppq) == 0 { '│' } else if x % ppq == 0 { '╎' } else { '·' }); cell.set_fg(Color::Gray); cell.modifier = Modifier::DIM; }); } } } fn fill_seq_fg (buf: &mut BigBuffer, phrase: &Phrase) { let mut notes_on = [false;128]; for x in 0..buf.width { if x as usize >= phrase.length { break } if let Some(notes) = phrase.notes.get(x as usize) { if phrase.percussive { for note in notes { match note { MidiMessage::NoteOn { key, .. } => notes_on[key.as_int() as usize] = true, _ => {} } } } else { for note in notes { match note { MidiMessage::NoteOn { key, .. } => notes_on[key.as_int() as usize] = true, MidiMessage::NoteOff { key, .. } => notes_on[key.as_int() as usize] = false, _ => {} } } } for y in 0..buf.height/2 { if y >= 64 { break } if let Some(block) = half_block( notes_on[y as usize * 2], notes_on[y as usize * 2 + 1], ) { buf.get_mut(x, y).map(|cell|{ cell.set_char(block); cell.set_fg(Color::White); }); } } if phrase.percussive { notes_on.fill(false); } } } } pub(crate) fn style_focus (&self) -> Option