mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-04-04 05:10:44 +02:00
wip: what is up with the arranger after all
This commit is contained in:
parent
abc1cc8fce
commit
7ff731133c
5 changed files with 156 additions and 124 deletions
134
src/arranger.rs
134
src/arranger.rs
|
|
@ -5,14 +5,14 @@ mod arranger_scene; pub(crate) use self::arranger_scene::*;
|
|||
mod arranger_select; pub(crate) use self::arranger_select::*;
|
||||
mod arranger_track; pub(crate) use self::arranger_track::*;
|
||||
mod arranger_mode; pub(crate) use self::arranger_mode::*;
|
||||
mod arranger_v; #[allow(unused)] pub(crate) use self::arranger_v::*;
|
||||
mod arranger_h;
|
||||
mod arranger_v_clips; pub(crate) use self::arranger_v_clips::*;
|
||||
mod arranger_v_cursor; pub(crate) use self::arranger_v_cursor::*;
|
||||
mod arranger_v_head; pub(crate) use self::arranger_v_head::*;
|
||||
mod arranger_v_io; pub(crate) use self::arranger_v_io::*;
|
||||
mod arranger_v_sep; pub(crate) use self::arranger_v_sep::*;
|
||||
|
||||
pub(crate) const HEADER_H: u16 = 5;
|
||||
pub(crate) const SCENES_W_OFFSET: u16 = 3;
|
||||
|
||||
/// Root view for standalone `tek_arranger`
|
||||
pub struct Arranger {
|
||||
jack: Arc<RwLock<JackConnection>>,
|
||||
|
|
@ -98,14 +98,14 @@ from_jack!(|jack| Arranger {
|
|||
compact: false,
|
||||
}
|
||||
});
|
||||
impl Arranger {
|
||||
fn render_mode (state: &Self) -> impl Content<TuiOut> + use<'_> {
|
||||
match state.mode {
|
||||
ArrangerMode::H => todo!("horizontal arranger"),
|
||||
ArrangerMode::V(factor) => Self::render_mode_v(state, factor),
|
||||
}
|
||||
}
|
||||
}
|
||||
//impl Arranger {
|
||||
//fn render_mode (state: &Self) -> impl Content<TuiOut> + use<'_> {
|
||||
//match state.mode {
|
||||
//ArrangerMode::H => todo!("horizontal arranger"),
|
||||
//ArrangerMode::V(factor) => Self::render_mode_v(state, factor),
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//render!(TuiOut: (self: Arranger) => {
|
||||
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
|
||||
//let color = self.color;
|
||||
|
|
@ -122,17 +122,38 @@ impl Arranger {
|
|||
//});
|
||||
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)))))));
|
||||
Bsp::n(self.selector_view(),
|
||||
Bsp::s(Align::nw(Fill::x(Fixed::y(3, self.header()))),
|
||||
Bsp::s(Align::nw(Fill::x(Fixed::y(1, self.ins()))),
|
||||
Bsp::n(Align::nw(Fill::x(Fixed::y(1, self.outs()))),
|
||||
Bsp::w(self.pool_view(), Fill::xy(lay!(
|
||||
Align::nw(Fill::xy(Tui::bg(self.color.darkest.rgb, " "))),
|
||||
Align::nw(Fill::xy(ArrangerVColSep::from(self))),
|
||||
Align::nw(Fill::xy(ArrangerVRowSep::from((self, 1)))),
|
||||
Align::nw(Fill::xy(ArrangerVCursor::from((self, 1)))),
|
||||
Align::nw(Fill::xy(":")))))))))))));
|
||||
//"todo:"))))))));
|
||||
//Bsp::s(
|
||||
//Align::nw(Fixed::y(1, Fill::x(ArrangerVIns::from(self)))),
|
||||
//Bsp::s(
|
||||
//Fixed::y(20, Align::nw(ArrangerVClips::new(self, 1))),
|
||||
//Fill::x(Fixed::y(1, ArrangerVOuts::from(self)))))))))))));
|
||||
//Bsp::s(
|
||||
//Bsp::s(
|
||||
//Bsp::s(
|
||||
//Fill::xy(ArrangerVClips::new(self, 1)),
|
||||
//Fill::x(ArrangerVOuts::from(self)))))
|
||||
|
||||
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))
|
||||
ArrangerStatus::from(self)
|
||||
//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!(
|
||||
|
|
@ -149,6 +170,87 @@ impl Arranger {
|
|||
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))))
|
||||
}
|
||||
fn header (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
|
||||
fn row <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOut> {
|
||||
row!(Tui::fg(color.light.rgb, "▎"), Tui::fg(color.lightest.rgb, field))
|
||||
}
|
||||
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
|
||||
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
|
||||
let color = track.color();
|
||||
Push::x(x1 as u16, Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, col!(
|
||||
row(color, Self::format_name(track, w)),
|
||||
row(color, Self::format_elapsed(track, self.clock().timebase())),
|
||||
row(color, Self::format_until_next(track, &self.clock().playhead)),
|
||||
)))))
|
||||
}))
|
||||
}
|
||||
/// name and width of track
|
||||
fn format_name (track: &ArrangerTrack, _w: usize) -> impl Content<TuiOut> {
|
||||
let name = track.name().read().unwrap().clone();
|
||||
Tui::bold(true, Tui::fg(track.color.lightest.rgb, name))
|
||||
}
|
||||
/// beats elapsed
|
||||
fn format_elapsed (track: &ArrangerTrack, timebase: &Arc<Timebase>) -> impl Content<TuiOut> {
|
||||
let mut result = String::new();
|
||||
if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() {
|
||||
let length = phrase.read().unwrap().length;
|
||||
let elapsed = track.player.pulses_since_start().unwrap();
|
||||
let elapsed = timebase.format_beats_1_short(
|
||||
(elapsed as usize % length) as f64
|
||||
);
|
||||
result = format!("+{elapsed:>}")
|
||||
}
|
||||
result
|
||||
}
|
||||
/// beats until switchover
|
||||
fn format_until_next (track: &ArrangerTrack, current: &Arc<Moment>)
|
||||
-> Option<impl Content<TuiOut>>
|
||||
{
|
||||
let timebase = ¤t.timebase;
|
||||
let mut result = String::new();
|
||||
if let Some((t, _)) = track.player.next_phrase().as_ref() {
|
||||
let target = t.pulse.get();
|
||||
let current = current.pulse.get();
|
||||
if target > current {
|
||||
let remaining = target - current;
|
||||
result = format!("-{:>}", timebase.format_beats_0_short(remaining))
|
||||
}
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
fn ins (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
|
||||
fn row <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOut> {
|
||||
row!(Tui::fg(color.light.rgb, "▎"), Tui::fg(color.lightest.rgb, field))
|
||||
}
|
||||
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
|
||||
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
|
||||
let color = track.color();
|
||||
let input = Self::format_input(track);
|
||||
Push::x(x1 as u16, Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, row(color, Self::format_input(track).ok())))))
|
||||
}))
|
||||
}
|
||||
fn format_input (track: &ArrangerTrack) -> Usually<impl Content<TuiOut>> {
|
||||
Ok(format!(">{}", track.player.midi_ins().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
fn outs (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let scenes_w = SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16;
|
||||
fn row <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOut> {
|
||||
row!(Tui::fg(color.light.rgb, "▎"), Tui::fg(color.lightest.rgb, field))
|
||||
}
|
||||
Push::x(scenes_w, Map(||ArrangerTrack::with_widths(self.tracks.as_slice()), |(_, track, x1, x2), i| {
|
||||
let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
|
||||
let color = track.color();
|
||||
Push::x(x2 as u16, Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, row(color, Self::format_output(track).ok())))))
|
||||
}))
|
||||
}
|
||||
/// output port
|
||||
fn format_output (track: &ArrangerTrack) -> Usually<impl Content<TuiOut>> {
|
||||
Ok(format!("<{}", track.player.midi_outs().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
}
|
||||
//render!(TuiOut: (self: Arranger) => {
|
||||
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue