mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: unfuck arranger more
This commit is contained in:
parent
f920d17058
commit
abc1cc8fce
4 changed files with 110 additions and 66 deletions
|
|
@ -29,6 +29,7 @@ pub struct Arranger {
|
||||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
pub editor: MidiEditor,
|
pub editor: MidiEditor,
|
||||||
pub perf: PerfModel,
|
pub perf: PerfModel,
|
||||||
|
pub compact: bool,
|
||||||
}
|
}
|
||||||
impl Arranger {
|
impl Arranger {
|
||||||
pub fn selected (&self) -> ArrangerSelection {
|
pub fn selected (&self) -> ArrangerSelection {
|
||||||
|
|
@ -94,6 +95,7 @@ from_jack!(|jack| Arranger {
|
||||||
note_buf: vec![],
|
note_buf: vec![],
|
||||||
perf: PerfModel::default(),
|
perf: PerfModel::default(),
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
|
compact: false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
impl Arranger {
|
impl Arranger {
|
||||||
|
|
@ -104,20 +106,64 @@ impl Arranger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render!(TuiOut: (self: Arranger) => {
|
//render!(TuiOut: (self: Arranger) => {
|
||||||
let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
|
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
|
||||||
let color = self.color;
|
//let color = self.color;
|
||||||
let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
|
//let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
|
||||||
Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
|
//Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
|
||||||
Bsp::n(TransportView::new(true, &self.clock),
|
//Bsp::n(TransportView::new(true, &self.clock),
|
||||||
Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
|
//Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
|
||||||
Bsp::n(Fill::x(Fixed::y(20,
|
//Bsp::n(Fill::x(Fixed::y(20,
|
||||||
Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
|
//Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
|
||||||
Bsp::a(
|
//Bsp::a(
|
||||||
Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
|
//Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
|
||||||
Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
|
//Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
|
||||||
self.size.of(layout)
|
//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|{
|
audio!(|self: Arranger, client, scope|{
|
||||||
// Start profiling cycle
|
// Start profiling cycle
|
||||||
let t0 = self.perf.get_t0();
|
let t0 = self.perf.get_t0();
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ pub mod plugin; pub use self::plugin::*;
|
||||||
pub mod pool; pub use self::pool::*;
|
pub mod pool; pub use self::pool::*;
|
||||||
pub mod sampler; pub use self::sampler::*;
|
pub mod sampler; pub use self::sampler::*;
|
||||||
pub mod sequencer; pub use self::sequencer::*;
|
pub mod sequencer; pub use self::sequencer::*;
|
||||||
pub mod status; pub use self::status::*;
|
|
||||||
|
|
||||||
pub use ::atomic_float;
|
pub use ::atomic_float;
|
||||||
pub(crate) use atomic_float::*;
|
pub(crate) use atomic_float::*;
|
||||||
|
|
|
||||||
|
|
@ -175,3 +175,53 @@ command!(|self: SequencerCommand, state: Sequencer|match self {
|
||||||
None
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue