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 /// Notes in phrase
pub notes: PhraseData, pub notes: PhraseData,
/// Whether to loop the phrase or play it once /// Whether to loop the phrase or play it once
pub loop_on: bool, pub looped: bool,
/// Start of loop /// Start of loop
pub loop_start: usize, pub loop_start: usize,
/// Length of loop /// Length of loop
@ -134,7 +134,7 @@ pub type PhraseData = Vec<Vec<MidiMessage>>;
impl Phrase { impl Phrase {
pub fn new ( pub fn new (
name: impl AsRef<str>, name: impl AsRef<str>,
loop_on: bool, looped: bool,
length: usize, length: usize,
notes: Option<PhraseData>, notes: Option<PhraseData>,
color: Option<ItemPalette>, color: Option<ItemPalette>,
@ -145,7 +145,7 @@ impl Phrase {
ppq: PPQ, ppq: PPQ,
length, length,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]), notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
loop_on, looped,
loop_start: 0, loop_start: 0,
loop_length: length, loop_length: length,
percussive: true, percussive: true,
@ -161,7 +161,7 @@ impl Phrase {
clone.uuid = uuid::Uuid::new_v4(); clone.uuid = uuid::Uuid::new_v4();
clone 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) { pub fn record_event (&mut self, pulse: usize, message: MidiMessage) {
if pulse >= self.length { panic!("extend phrase first") } if pulse >= self.length { panic!("extend phrase first") }
self.notes[pulse].push(message); self.notes[pulse].push(message);
@ -180,7 +180,16 @@ impl Phrase {
impl Default for Phrase { impl Default for Phrase {
fn default () -> Self { 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 /// Draw at upper left corner of contaier
NW(L), NW(L),
/// Draw at center of upper edge of container /// Draw at center of upper edge of container
N(L), N(L),
/// Draw at right left corner of contaier /// Draw at right left corner of contaier
NE(L), NE(L),
/// Draw at center of left edge of container /// Draw at center of left edge of container
W(L), W(L),
/// Draw at center of right edge of container /// Draw at center of right edge of container
E(L), E(L),
/// Draw at lower left corner of container /// Draw at lower left corner of container

View file

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

View file

@ -259,7 +259,7 @@ impl Tui {
//selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, { //selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, {
//row! { //row! {
//"BPM ", //"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! { //selected.wrap(TransportFocus::Sync, &Outset::X(1u16, row! {

View file

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

View file

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

View file

@ -233,7 +233,7 @@ impl std::fmt::Debug for PhraseEditorModel {
pub struct PhraseEditStatus<'a>(pub &'a PhraseEditorModel); pub struct PhraseEditStatus<'a>(pub &'a PhraseEditorModel);
render!(|self:PhraseEditStatus<'a>|row!(|add|{ 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()) { 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 { } else {
(ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false) (ItemPalette::from(TuiTheme::g(64)), String::new(), 0, false)
}; };

View file

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