replace Phrase::looped with separate fields; draw them with backgrounds

This commit is contained in:
🪞👃🪞 2024-10-05 10:02:55 +03:00
parent 4c3ad62279
commit ea3edec96b
2 changed files with 31 additions and 21 deletions

View file

@ -691,12 +691,14 @@ pub type PhraseData = Vec<Vec<MidiMessage>>;
/// A MIDI sequence.
#[derive(Debug)]
pub struct Phrase {
pub name: Arc<RwLock<String>>,
pub length: usize,
pub notes: PhraseData,
pub looped: Option<(usize, usize)>,
pub name: Arc<RwLock<String>>,
pub length: usize,
pub notes: PhraseData,
pub loop_on: bool,
pub loop_start: usize,
pub loop_length: usize,
/// All notes are displayed with minimum length
pub percussive: bool
pub percussive: bool,
}
impl Default for Phrase {
fn default () -> Self { Self::new("", 0, None) }
@ -704,13 +706,18 @@ impl Default for Phrase {
impl Phrase {
pub fn new (name: &str, length: usize, notes: Option<PhraseData>) -> Self {
Self {
name: Arc::new(RwLock::new(name.into())),
name: Arc::new(RwLock::new(name.into())),
length,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
looped: Some((0, length)),
percussive: true,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
loop_on: true,
loop_start: 0,
loop_length: length,
percussive: true,
}
}
pub fn toggle_loop (&mut self) {
self.loop_on = !self.loop_on;
}
pub fn record_event (&mut self, pulse: usize, message: MidiMessage) {
if pulse >= self.length {
panic!("extend phrase first")

View file

@ -122,8 +122,8 @@ impl Handle<Tui> for Arranger<Tui> {
self.rename_selected();
},
// length: add a new scene
key!(KeyCode::Char('l')) => {
todo!();
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
phrase.write().unwrap().toggle_loop()
},
// color: set color of item at cursor
key!(KeyCode::Char('c')) => {
@ -774,22 +774,25 @@ impl Sequencer<Tui> {
impl Content for Sequencer<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
let field_bg = Color::Rgb(28, 35, 25);
let toolbar = Stack::down(move|add|{
add(&col!("Name:", self.name.read().unwrap().as_str()))?;
let name = format!("{:>9}", self.name.read().unwrap().as_str());
add(&col!("Track:", TuiStyle::bg(name.as_str(), field_bg)))?;
if let Some(phrase) = self.viewing_phrase
.map(|index|self.phrases.get(index))
.flatten()
{
let phrase = phrase.read().unwrap();
let length = phrase.length;
let looped = phrase.looped;
let phrase = phrase.read().unwrap();
let length = format!("{}q{}p", phrase.length / 96, phrase.length % 96);
let length = format!("{:>9}", &length);
let loop_on = format!("{:>9}", if phrase.loop_on { "on" } else { "off" });
let loop_start = format!("{:>9}", phrase.loop_start);
let loop_end = format!("{:>9}", phrase.loop_length);
add(&"")?;
add(&col!("Length: ", format!("{}q{}p", length / 96, length % 96).as_str()))?;
add(&"")?;
add(&col!("Loop [ ]", "From: ", " 1.1.1", "Length: ", " 1.0.0"))?;
add(&"")?;
add(&col!("Notes: ", "C#0-C#9 ", "[ /2 ]", "[ x2 ]",
"[ Rev ]", "[ Inv ]", "[ Dup ]"))?;
add(&col!("Length:", TuiStyle::bg(length.as_str(), field_bg)))?;
add(&col!("Loop:", TuiStyle::bg(loop_on.as_str(), field_bg)))?;
add(&col!("L. start:", TuiStyle::bg(loop_start.as_str(), field_bg)))?;
add(&col!("L. length:", TuiStyle::bg(loop_end.as_str(), field_bg)))?;
}
Ok(())
}).min_x(10);