wip: unfuck arranger more

This commit is contained in:
🪞👃🪞 2025-01-06 21:42:33 +01:00
parent f920d17058
commit abc1cc8fce
4 changed files with 110 additions and 66 deletions

View file

@ -29,6 +29,7 @@ pub struct Arranger {
pub midi_buf: Vec<Vec<Vec<u8>>>,
pub editor: MidiEditor,
pub perf: PerfModel,
pub compact: bool,
}
impl Arranger {
pub fn selected (&self) -> ArrangerSelection {
@ -94,6 +95,7 @@ from_jack!(|jack| Arranger {
note_buf: vec![],
perf: PerfModel::default(),
jack: jack.clone(),
compact: false,
}
});
impl Arranger {
@ -104,20 +106,64 @@ impl Arranger {
}
}
}
render!(TuiOut: (self: Arranger) => {
let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
let color = self.color;
let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
Bsp::n(TransportView::new(true, &self.clock),
Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
Bsp::n(Fill::x(Fixed::y(20,
Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
Bsp::a(
Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
self.size.of(layout)
});
//render!(TuiOut: (self: Arranger) => {
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
//let color = self.color;
//let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
//Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
//Bsp::n(TransportView::new(true, &self.clock),
//Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
//Bsp::n(Fill::x(Fixed::y(20,
//Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
//Bsp::a(
//Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
//Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
//self.size.of(layout)
//});
render!(TuiOut: (self: Arranger) => self.size.of(
Bsp::s(self.toolbar_view(),
Bsp::n(self.selector_view(),
Bsp::n(self.status_view(),
Bsp::w(self.pool_view(), Fill::xy(&self.editor)))))));
impl Arranger {
fn toolbar_view (&self) -> impl Content<TuiOut> + use<'_> {
Fill::x(Fixed::y(2, Align::x(TransportView::new(true, &self.clock))))
}
fn status_view (&self) -> impl Content<TuiOut> + use<'_> {
let edit_clip = MidiEditClip(&self.editor);
//let selectors = When(false, Bsp::e(ClipSelected::play_phrase(&self.player), ClipSelected::next_phrase(&self.player)));
row!(/*selectors,*/ edit_clip, MidiEditStatus(&self.editor))
}
fn selector_view (&self) -> impl Content<TuiOut> + use<'_> {
row!(
//ClipSelected::play_phrase(&self.player),
//ClipSelected::next_phrase(&self.player),
MidiEditClip(&self.editor),
MidiEditStatus(&self.editor),
)
}
fn pool_view (&self) -> impl Content<TuiOut> + use<'_> {
let w = self.size.w();
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
let pool_w = if self.pool.visible { phrase_w } else { 0 };
let pool = Pull::y(1, Fill::y(Align::e(PoolView(self.pool.visible, &self.pool))));
Fixed::x(pool_w, Align::e(Fill::y(PoolView(self.compact, &self.pool))))
}
}
//render!(TuiOut: (self: Arranger) => {
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
//let color = self.color;
//let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
//Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
//Bsp::n(TransportView::new(true, &self.clock),
//Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
//Bsp::n(Fill::x(Fixed::y(20,
//Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
//Bsp::a(
//Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
//Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
//self.size.of(layout)
//});
audio!(|self: Arranger, client, scope|{
// Start profiling cycle
let t0 = self.perf.get_t0();

View file

@ -62,7 +62,6 @@ pub mod plugin; pub use self::plugin::*;
pub mod pool; pub use self::pool::*;
pub mod sampler; pub use self::sampler::*;
pub mod sequencer; pub use self::sequencer::*;
pub mod status; pub use self::status::*;
pub use ::atomic_float;
pub(crate) use atomic_float::*;

View file

@ -175,3 +175,53 @@ command!(|self: SequencerCommand, state: Sequencer|match self {
None
},
});
/// Status bar for sequencer app
#[derive(Clone)]
pub struct SequencerStatus {
pub(crate) width: usize,
pub(crate) cpu: Option<String>,
pub(crate) size: String,
pub(crate) playing: bool,
}
from!(|state:&Sequencer|SequencerStatus = {
let samples = state.clock.chunk.load(Relaxed);
let rate = state.clock.timebase.sr.get();
let buffer = samples as f64 / rate;
let width = state.size.w();
Self {
width,
playing: state.clock.is_rolling(),
cpu: state.perf.percentage().map(|cpu|format!("{cpu:.01}%")),
size: format!("{}x{}│", width, state.size.h()),
}
});
render!(TuiOut: (self: SequencerStatus) => Fixed::y(2, lay!(
Self::help(),
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
)));
impl SequencerStatus {
fn help () -> impl Content<TuiOut> {
let single = |binding, command|row!(" ", col!(
Tui::fg(TuiTheme::yellow(), binding),
command
));
let double = |(b1, c1), (b2, c2)|col!(
row!(" ", Tui::fg(TuiTheme::yellow(), b1), " ", c1,),
row!(" ", Tui::fg(TuiTheme::yellow(), b2), " ", c2,),
);
Tui::fg_bg(TuiTheme::g(255), TuiTheme::g(50), row!(
single("SPACE", "play/pause"),
double(("▲▼▶◀", "cursor"), ("Ctrl", "scroll"), ),
double(("a", "append"), ("s", "set note"),),
double((",.", "length"), ("<>", "triplet"), ),
double(("[]", "phrase"), ("{}", "order"), ),
double(("q", "enqueue"), ("e", "edit"), ),
double(("c", "color"), ("", ""),),
))
}
fn stats (&self) -> impl Content<TuiOut> + use<'_> {
row!(&self.cpu, &self.size)
}
}

View file

@ -1,51 +0,0 @@
use crate::*;
/// Status bar for sequencer app
#[derive(Clone)]
pub struct SequencerStatus {
pub(crate) width: usize,
pub(crate) cpu: Option<String>,
pub(crate) size: String,
pub(crate) playing: bool,
}
from!(|state:&Sequencer|SequencerStatus = {
let samples = state.clock.chunk.load(Relaxed);
let rate = state.clock.timebase.sr.get();
let buffer = samples as f64 / rate;
let width = state.size.w();
Self {
width,
playing: state.clock.is_rolling(),
cpu: state.perf.percentage().map(|cpu|format!("{cpu:.01}%")),
size: format!("{}x{}│", width, state.size.h()),
}
});
render!(TuiOut: (self: SequencerStatus) => Fixed::y(2, lay!(
Self::help(),
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
)));
impl SequencerStatus {
fn help () -> impl Content<TuiOut> {
let single = |binding, command|row!(" ", col!(
Tui::fg(TuiTheme::yellow(), binding),
command
));
let double = |(b1, c1), (b2, c2)|col!(
row!(" ", Tui::fg(TuiTheme::yellow(), b1), " ", c1,),
row!(" ", Tui::fg(TuiTheme::yellow(), b2), " ", c2,),
);
Tui::fg_bg(TuiTheme::g(255), TuiTheme::g(50), row!(
single("SPACE", "play/pause"),
double(("▲▼▶◀", "cursor"), ("Ctrl", "scroll"), ),
double(("a", "append"), ("s", "set note"),),
double((",.", "length"), ("<>", "triplet"), ),
double(("[]", "phrase"), ("{}", "order"), ),
double(("q", "enqueue"), ("e", "edit"), ),
double(("c", "color"), ("", ""),),
))
}
fn stats (&self) -> impl Content<TuiOut> + use<'_> {
row!(&self.cpu, &self.size)
}
}