phrase 0; stop all; loop_on->looped; remove trailers

This commit is contained in:
🪞👃🪞 2024-12-17 00:55:21 +01:00
parent ce523d9e45
commit 775fea2c08
8 changed files with 23 additions and 14 deletions

View file

@ -117,7 +117,7 @@ pub struct Phrase {
/// Notes in phrase
pub notes: PhraseData,
/// Whether to loop the phrase or play it once
pub loop_on: bool,
pub looped: bool,
/// Start of loop
pub loop_start: usize,
/// Length of loop
@ -134,7 +134,7 @@ pub type PhraseData = Vec<Vec<MidiMessage>>;
impl Phrase {
pub fn new (
name: impl AsRef<str>,
loop_on: bool,
looped: bool,
length: usize,
notes: Option<PhraseData>,
color: Option<ItemPalette>,
@ -145,7 +145,7 @@ impl Phrase {
ppq: PPQ,
length,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
loop_on,
looped,
loop_start: 0,
loop_length: length,
percussive: true,
@ -161,7 +161,7 @@ impl Phrase {
clone.uuid = uuid::Uuid::new_v4();
clone
}
pub fn toggle_loop (&mut self) { self.loop_on = !self.loop_on; }
pub fn toggle_loop (&mut self) { self.looped = !self.looped; }
pub fn record_event (&mut self, pulse: usize, message: MidiMessage) {
if pulse >= self.length { panic!("extend phrase first") }
self.notes[pulse].push(message);
@ -180,7 +180,16 @@ impl Phrase {
impl Default for Phrase {
fn default () -> Self {
Self::new("null", false, 0, None, Some(ItemColor::from(Color::Rgb(0, 0, 0)).into()))
Self::new(
"Stop",
false,
1,
Some(vec![vec![MidiMessage::Controller {
controller: 123.into(),
value: 0.into()
}]]),
Some(ItemColor::from(Color::Rgb(32, 32, 32)).into())
)
}
}

View file

@ -27,11 +27,11 @@ pub enum Align<L> {
/// Draw at upper left corner of contaier
NW(L),
/// Draw at center of upper edge of container
N(L),
N(L),
/// Draw at right left corner of contaier
NE(L),
/// Draw at center of left edge of container
W(L),
W(L),
/// Draw at center of right edge of container
E(L),
/// Draw at lower left corner of container

View file

@ -7,7 +7,7 @@ pub trait LayoutMinMax<E: Engine> {
Min::X(x, w)
}
fn min_y <W: Render<E>> (y: E::Unit, w: W) -> Min<E, W> {
Min::Y(y, w)
Min::Y(y, w)
}
fn min_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Min<E, W> {
Min::XY(x, y, w)

View file

@ -259,7 +259,7 @@ impl Tui {
//selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, {
//row! {
//"BPM ",
//format!("{}.{:03}", *bpm as usize, (bpm * 1000.0) % 1000.0)
//format!("{}.{:03}", *bpm as usize, (bpm * 1000.0) % 1000.0)
//}
//})),
//selected.wrap(TransportFocus::Sync, &Outset::X(1u16, row! {

View file

@ -1288,7 +1288,7 @@ impl ArrangerSelection {
match self {
Clip(_, s) => Some(*s),
Scene(s) => Some(*s),
_ => None
_ => None
}
}
}

View file

@ -134,7 +134,7 @@ impl AddSampleModal {
voices: voices.clone(),
_search: None
})
}
}
fn rescan (&mut self) -> Usually<()> {
scan(&self.dir).map(|(subdirs, files)|{
self.subdirs = subdirs;

View file

@ -233,7 +233,7 @@ impl std::fmt::Debug for PhraseEditorModel {
pub struct PhraseEditStatus<'a>(pub &'a PhraseEditorModel);
render!(|self:PhraseEditStatus<'a>|row!(|add|{
let (color, name, length, looped) = if let Some(phrase) = self.0.phrase().as_ref().map(|p|p.read().unwrap()) {
(phrase.color, phrase.name.clone(), phrase.length, phrase.loop_on)
(phrase.color, phrase.name.clone(), phrase.length, phrase.looped)
} else {
(ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false)
};

View file

@ -242,7 +242,7 @@ render!(|self: PhraseListView<'a>|{
let mut row2 = format!(" {name}");
if let Some(PhraseListMode::Rename(phrase, _)) = mode {
if i == *phrase {
row2 = format!("{row2}");
row2 = format!("{row2}");
}
};
row2
@ -310,7 +310,7 @@ impl PhraseSelector {
(time, name.clone(), color)
} else if let Some((_, Some(phrase))) = state.play_phrase() {
let phrase = phrase.read().unwrap();
if phrase.loop_on {
if phrase.looped {
(" ".into(), phrase.name.clone(), phrase.color.clone())
} else {
(" ".into(), " ".into(), TuiTheme::g(64).into())