mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
separate Input and Output impls
This commit is contained in:
parent
a6efde40f8
commit
0e821e098f
77 changed files with 465 additions and 454 deletions
|
|
@ -24,7 +24,7 @@ pub struct ArrangerTui {
|
|||
pub selected: ArrangerSelection,
|
||||
pub mode: ArrangerMode,
|
||||
pub color: ItemPalette,
|
||||
pub size: Measure<Tui>,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
pub editor: MidiEditor,
|
||||
|
|
@ -97,14 +97,14 @@ from_jack!(|jack| ArrangerTui {
|
|||
}
|
||||
});
|
||||
impl ArrangerTui {
|
||||
fn render_mode (state: &Self) -> impl Content<Tui> + use<'_> {
|
||||
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!(Tui: (self: ArrangerTui) => {
|
||||
render!(TuiOut: (self: ArrangerTui) => {
|
||||
let pool_size = if self.pool.visible { self.splits[1] } else { 0 };
|
||||
let with_pool = |x|Bsp::w(Fixed::x(pool_size, PoolView(self.pool.visible, &self.pool)), x);
|
||||
let status = ArrangerStatus::from(self);
|
||||
|
|
@ -164,4 +164,4 @@ audio!(|self: ArrangerTui, client, scope|{
|
|||
has_clock!(|self: ArrangerTui|&self.clock);
|
||||
has_phrases!(|self: ArrangerTui|self.pool.phrases);
|
||||
has_editor!(|self: ArrangerTui|self.editor);
|
||||
handle!(<Tui>|self: ArrangerTui, input|ArrangerCommand::execute_with_state(self, input.event()));
|
||||
handle!(TuiIn: |self: ArrangerTui, input|ArrangerCommand::execute_with_state(self, input.event()));
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub enum ArrangerClipCommand {
|
|||
SetColor(usize, usize, ItemPalette),
|
||||
}
|
||||
|
||||
//handle!(<Tui>|self: ArrangerTui, input|ArrangerCommand::execute_with_state(self, input.event()));
|
||||
//handle!(TuiIn: |self: ArrangerTui, input|ArrangerCommand::execute_with_state(self, input.event()));
|
||||
//input_to_command!(ArrangerCommand: |state: ArrangerTui, input: Event|{KEYS_ARRANGER.handle(state, input)?});
|
||||
|
||||
keymap!(KEYS_ARRANGER = |state: ArrangerTui, input: Event| ArrangerCommand {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub enum ArrangerMode {
|
|||
/// Tracks are rows
|
||||
H,
|
||||
}
|
||||
impl<E: Engine> Content<E> for ArrangerMode {}
|
||||
impl<E: Output> Content<E> for ArrangerMode {}
|
||||
/// Arranger display mode can be cycled
|
||||
impl ArrangerMode {
|
||||
/// Cycle arranger display mode
|
||||
|
|
@ -21,6 +21,6 @@ impl ArrangerMode {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn any_size <E: Engine> (_: E::Size) -> Perhaps<E::Size>{
|
||||
fn any_size <E: Output> (_: E::Size) -> Perhaps<E::Size>{
|
||||
Ok(Some([0.into(),0.into()].into()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::*;
|
|||
pub(crate) const HEADER_H: u16 = 5;
|
||||
pub(crate) const SCENES_W_OFFSET: u16 = 3;
|
||||
impl ArrangerTui {
|
||||
pub fn render_mode_v (state: &ArrangerTui, factor: usize) -> impl Content<Tui> + use<'_> {
|
||||
pub fn render_mode_v (state: &ArrangerTui, factor: usize) -> impl Content<TuiOut> + use<'_> {
|
||||
lay!(
|
||||
ArrangerVColSep::from(state),
|
||||
ArrangerVRowSep::from((state, factor)),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
use super::*;
|
||||
|
||||
pub struct ArrangerVClips<'a> {
|
||||
size: &'a Measure<Tui>,
|
||||
size: &'a Measure<TuiOut>,
|
||||
scenes: &'a Vec<ArrangerScene>,
|
||||
tracks: &'a Vec<ArrangerTrack>,
|
||||
rows: Vec<(usize, usize)>,
|
||||
|
|
@ -17,8 +17,8 @@ impl<'a> ArrangerVClips<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl<'a> Content<Tui> for ArrangerVClips<'a> {
|
||||
fn content (&self) -> impl Render<Tui> {
|
||||
impl<'a> Content<TuiOut> for ArrangerVClips<'a> {
|
||||
fn content (&self) -> impl Render<TuiOut> {
|
||||
let iter = ||self.scenes.iter().zip(self.rows.iter().map(|row|row.0));
|
||||
let col = Map(iter, |(scene, pulses), i|Self::format_scene(self.tracks, scene, pulses));
|
||||
Fill::xy(col)
|
||||
|
|
@ -28,7 +28,7 @@ impl<'a> ArrangerVClips<'a> {
|
|||
|
||||
fn format_scene (
|
||||
tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, pulses: usize
|
||||
) -> impl Content<Tui> + use<'a> {
|
||||
) -> impl Content<TuiOut> + use<'a> {
|
||||
let height = 1.max((pulses / PPQ) as u16);
|
||||
let playing = scene.is_playing(tracks);
|
||||
let icon = Tui::bg(
|
||||
|
|
@ -45,7 +45,7 @@ impl<'a> ArrangerVClips<'a> {
|
|||
|
||||
fn format_clip (
|
||||
scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16
|
||||
) -> impl Content<Tui> + use<'a> {
|
||||
) -> impl Content<TuiOut> + use<'a> {
|
||||
scene.clips.get(index).map(|clip|clip.as_ref().map(|phrase|{
|
||||
let phrase = phrase.read().unwrap();
|
||||
let mut bg = TuiTheme::border_bg();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
|
|||
sub_modifier: Modifier::DIM
|
||||
}),
|
||||
});
|
||||
impl Content<Tui> for ArrangerVCursor {
|
||||
impl Content<TuiOut> for ArrangerVCursor {
|
||||
fn render (&self, to: &mut TuiOut) {
|
||||
let area = to.area();
|
||||
let focused = true;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ from!(<'a>|state: &'a ArrangerTui|ArrangerVHead<'a> = Self { // A
|
|||
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
|
||||
});
|
||||
|
||||
render!(Tui: (self: ArrangerVHead<'a>) => {
|
||||
fn row <T: Content<Tui>> (color: ItemPalette, field: T) -> impl Content<Tui> {
|
||||
render!(TuiOut: (self: ArrangerVHead<'a>) => {
|
||||
fn row <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOut> {
|
||||
row!(Tui::fg(color.light.rgb, "▎"), Tui::fg(color.lightest.rgb, field))
|
||||
}
|
||||
Some(Push::x(self.scenes_w,
|
||||
|
|
@ -38,22 +38,22 @@ render!(Tui: (self: ArrangerVHead<'a>) => {
|
|||
|
||||
impl ArrangerVHead<'_> {
|
||||
/// name and width of track
|
||||
fn format_name (track: &ArrangerTrack, _w: usize) -> impl Content<Tui> {
|
||||
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))
|
||||
}
|
||||
/// input port
|
||||
fn format_input (track: &ArrangerTrack) -> Usually<impl Content<Tui>> {
|
||||
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())))
|
||||
}
|
||||
/// output port
|
||||
fn format_output (track: &ArrangerTrack) -> Usually<impl Content<Tui>> {
|
||||
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())))
|
||||
}
|
||||
/// beats elapsed
|
||||
fn format_elapsed (track: &ArrangerTrack, timebase: &Arc<Timebase>) -> impl Content<Tui> {
|
||||
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;
|
||||
|
|
@ -67,7 +67,7 @@ impl ArrangerVHead<'_> {
|
|||
}
|
||||
/// beats until switchover
|
||||
fn format_until_next (track: &ArrangerTrack, current: &Arc<Moment>)
|
||||
-> Option<impl Content<Tui>>
|
||||
-> Option<impl Content<TuiOut>>
|
||||
{
|
||||
let timebase = ¤t.timebase;
|
||||
let mut result = String::new();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
use super::*;
|
||||
|
||||
pub struct ArrangerVIns<'a> {
|
||||
size: &'a Measure<Tui>,
|
||||
size: &'a Measure<TuiOut>,
|
||||
tracks: &'a Vec<ArrangerTrack>,
|
||||
}
|
||||
|
||||
|
|
@ -11,10 +11,10 @@ from!(<'a>|args: &'a ArrangerTui|ArrangerVIns<'a> = Self {
|
|||
tracks: &args.tracks,
|
||||
});
|
||||
|
||||
render!(Tui: (self: ArrangerVIns<'a>) => "");
|
||||
render!(TuiOut: (self: ArrangerVIns<'a>) => "");
|
||||
|
||||
pub struct ArrangerVOuts<'a> {
|
||||
size: &'a Measure<Tui>,
|
||||
size: &'a Measure<TuiOut>,
|
||||
tracks: &'a Vec<ArrangerTrack>,
|
||||
}
|
||||
|
||||
|
|
@ -23,4 +23,4 @@ from!(<'a>|args: &'a ArrangerTui|ArrangerVOuts<'a> = Self {
|
|||
tracks: &args.tracks,
|
||||
});
|
||||
|
||||
render!(Tui: (self: ArrangerVOuts<'a>) => "");
|
||||
render!(TuiOut: (self: ArrangerVOuts<'a>) => "");
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from!(|state:&ArrangerTui|ArrangerVColSep = Self {
|
|||
cols: ArrangerTrack::widths(&state.tracks),
|
||||
scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&state.scenes) as u16,
|
||||
});
|
||||
render!(Tui: |self: ArrangerVColSep, to| {
|
||||
render!(TuiOut: |self: ArrangerVColSep, to| {
|
||||
let style = Some(Style::default().fg(self.fg));
|
||||
for x in self.cols.iter().map(|col|col.1) {
|
||||
let x = self.scenes_w + to.area().x() + x as u16;
|
||||
|
|
@ -29,7 +29,7 @@ from!(|args:(&ArrangerTui, usize)|ArrangerVRowSep = Self {
|
|||
fg: TuiTheme::separator_fg(false),
|
||||
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
|
||||
});
|
||||
render!(Tui: |self: ArrangerVRowSep, to|for y in self.rows.iter().map(|row|row.1) {
|
||||
render!(TuiOut: |self: ArrangerVRowSep, to|for y in self.rows.iter().map(|row|row.1) {
|
||||
let y = to.area().y() + (y / PPQ) as u16 + 1;
|
||||
if y >= to.buffer.area.height { break }
|
||||
for x in to.area().x()..to.area().x2().saturating_sub(2) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub struct TransportTui {
|
|||
}
|
||||
has_clock!(|self: TransportTui|&self.clock);
|
||||
audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope));
|
||||
render!(Tui: (self: TransportTui) => TransportView {
|
||||
render!(TuiOut: (self: TransportTui) => TransportView {
|
||||
compact: false,
|
||||
clock: &self.clock
|
||||
});
|
||||
|
|
@ -25,7 +25,7 @@ impl<'a> TransportView<'a> {
|
|||
Self { compact, clock }
|
||||
}
|
||||
}
|
||||
render!(Tui: (self: TransportView<'a>) => Outer(
|
||||
render!(TuiOut: (self: TransportView<'a>) => Outer(
|
||||
Style::default().fg(TuiTheme::g(255))
|
||||
).enclose(row!(
|
||||
OutputStats::new(self.compact, self.clock),
|
||||
|
|
@ -36,7 +36,7 @@ render!(Tui: (self: TransportView<'a>) => Outer(
|
|||
)));
|
||||
|
||||
pub struct PlayPause { pub compact: bool, pub playing: bool }
|
||||
render!(Tui: (self: PlayPause) => Tui::bg(
|
||||
render!(TuiOut: (self: PlayPause) => Tui::bg(
|
||||
if self.playing{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
|
||||
Either(self.compact,
|
||||
Thunk::new(||Fixed::x(9, Either(self.playing,
|
||||
|
|
@ -59,7 +59,7 @@ impl BeatStats {
|
|||
Self { compact, bpm: format!("{:.3}", clock.timebase.bpm.get()), beat, time }
|
||||
}
|
||||
}
|
||||
render!(Tui: (self: BeatStats) => Either(self.compact,
|
||||
render!(TuiOut: (self: BeatStats) => Either(self.compact,
|
||||
row!(
|
||||
FieldV(TuiTheme::g(128).into(), "BPM", &self.bpm),
|
||||
FieldV(TuiTheme::g(128).into(), "Beat", &self.beat),
|
||||
|
|
@ -88,7 +88,7 @@ impl OutputStats {
|
|||
}
|
||||
}
|
||||
}
|
||||
render!(Tui: (self: OutputStats) => Either(self.compact,
|
||||
render!(TuiOut: (self: OutputStats) => Either(self.compact,
|
||||
row!(
|
||||
FieldV(TuiTheme::g(128).into(), "SR", &self.sample_rate),
|
||||
FieldV(TuiTheme::g(128).into(), "Buf", &self.buffer_size),
|
||||
|
|
@ -100,7 +100,7 @@ render!(Tui: (self: OutputStats) => Either(self.compact,
|
|||
Bsp::e(Tui::fg(TuiTheme::g(255), format!("{:.3}ms", self.latency)), " latency"),
|
||||
)));
|
||||
|
||||
handle!(<Tui>|self: TransportTui, input|ClockCommand::execute_with_state(self, input.event()));
|
||||
handle!(TuiIn: |self: TransportTui, input|ClockCommand::execute_with_state(self, input.event()));
|
||||
keymap!(TRANSPORT_KEYS = |state: TransportTui, input: Event| ClockCommand {
|
||||
key(Char(' ')) =>
|
||||
if state.clock().is_stopped() { Play(None) } else { Pause(None) },
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use crate::*;
|
|||
pub struct Field<T, U>(pub ItemPalette, pub T, pub U)
|
||||
where T: AsRef<str> + Send + Sync, U: AsRef<str> + Send + Sync;
|
||||
|
||||
impl<T, U> Content<Tui> for Field<T, U>
|
||||
impl<T, U> Content<TuiOut> for Field<T, U>
|
||||
where T: AsRef<str> + Send + Sync, U: AsRef<str> + Send + Sync
|
||||
{
|
||||
fn content (&self) -> impl Render<Tui> {
|
||||
fn content (&self) -> impl Render<TuiOut> {
|
||||
let ItemPalette { darkest, dark, lighter, lightest, .. } = self.0;
|
||||
row!(
|
||||
Tui::fg_bg(dark.rgb, darkest.rgb, "▐"),
|
||||
|
|
@ -20,10 +20,10 @@ impl<T, U> Content<Tui> for Field<T, U>
|
|||
pub struct FieldV<T, U>(pub ItemPalette, pub T, pub U)
|
||||
where T: AsRef<str> + Send + Sync, U: AsRef<str> + Send + Sync;
|
||||
|
||||
impl<T, U> Content<Tui> for FieldV<T, U>
|
||||
impl<T, U> Content<TuiOut> for FieldV<T, U>
|
||||
where T: AsRef<str> + Send + Sync, U: AsRef<str> + Send + Sync
|
||||
{
|
||||
fn content (&self) -> impl Render<Tui> {
|
||||
fn content (&self) -> impl Render<TuiOut> {
|
||||
let ItemPalette { darkest, dark, lighter, lightest, .. } = self.0;
|
||||
let sep1 = Tui::bg(darkest.rgb, Tui::fg(dark.rgb, "▐"));
|
||||
let sep2 = Tui::bg(darkest.rgb, Tui::fg(dark.rgb, "▌"));
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub struct FileBrowser {
|
|||
pub filter: String,
|
||||
pub index: usize,
|
||||
pub scroll: usize,
|
||||
pub size: Measure<Tui>
|
||||
pub size: Measure<TuiOut>
|
||||
}
|
||||
/// Commands supported by [FileBrowser]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
@ -20,7 +20,7 @@ pub enum FileBrowserCommand {
|
|||
Chdir(PathBuf),
|
||||
Filter(String),
|
||||
}
|
||||
render!(Tui: (self: FileBrowser) => /*Stack::down(|add|{
|
||||
render!(TuiOut: (self: FileBrowser) => /*Stack::down(|add|{
|
||||
let mut i = 0;
|
||||
for (_, name) in self.dirs.iter() {
|
||||
if i >= self.scroll {
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ impl<T: FocusGrid + HasEnter> FocusOrder for T {
|
|||
}
|
||||
|
||||
pub trait FocusWrap<T> {
|
||||
fn wrap <W: Content<Tui>> (self, focus: T, content: &'_ W) -> impl Content<Tui> + '_;
|
||||
fn wrap <W: Content<TuiOut>> (self, focus: T, content: &'_ W) -> impl Content<TuiOut> + '_;
|
||||
}
|
||||
|
||||
pub fn to_focus_command <T: Send + Sync> (input: &TuiIn) -> Option<FocusCommand<T>> {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub struct Groovebox {
|
|||
pub sampler: Sampler,
|
||||
|
||||
pub compact: bool,
|
||||
pub size: Measure<Tui>,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
|
|
@ -61,7 +61,7 @@ impl Groovebox {
|
|||
|
||||
has_clock!(|self: Groovebox|self.player.clock());
|
||||
|
||||
impl EdnViewData<Tui> for &Groovebox {
|
||||
impl EdnViewData<TuiOut> for &Groovebox {
|
||||
fn get_bool (&self, item: EdnItem<&str>) -> bool { todo!() }
|
||||
fn get_unit (&self, item: EdnItem<&str>) -> u16 {
|
||||
use EdnItem::*;
|
||||
|
|
@ -70,13 +70,13 @@ impl EdnViewData<Tui> for &Groovebox {
|
|||
":samples-w" => if self.compact { 4 } else { 11 },
|
||||
":samples-y" => if self.compact { 1 } else { 0 },
|
||||
":pool-w" => if self.compact { 5 } else {
|
||||
let w = self.size.w();
|
||||
let w = self.size.w();
|
||||
if w > 60 { 20 } else if w > 40 { 15 } else { 10 }
|
||||
},
|
||||
_ => 0
|
||||
}
|
||||
}
|
||||
fn get_content <'a> (&'a self, item: EdnItem<&str>) -> RenderBox<'a, Tui> {
|
||||
fn get_content <'a> (&'a self, item: EdnItem<&str>) -> RenderBox<'a, TuiOut> {
|
||||
use EdnItem::*;
|
||||
match item.to_str() {
|
||||
":input-meter-l" => Box::new(Meter("L/", self.sampler.input_meter[0])),
|
||||
|
|
@ -94,7 +94,7 @@ impl EdnViewData<Tui> for &Groovebox {
|
|||
":sample-stat" => Box::new(SamplerStatus(&self.sampler, self.editor.note_point())),
|
||||
":samples-view" => Box::new(SampleList::new(self.compact, &self.sampler, &self.editor)),
|
||||
|
||||
_ => Box::new(())
|
||||
_ => panic!("{item:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -119,12 +119,12 @@ from!(|state: &Groovebox|GrooveboxStatus = {
|
|||
size: format!("{}x{}│", width, state.size.h()),
|
||||
}
|
||||
});
|
||||
render!(Tui: (self: GrooveboxStatus) => Fixed::y(2, lay!(
|
||||
render!(TuiOut: (self: GrooveboxStatus) => Fixed::y(2, lay!(
|
||||
Self::help(),
|
||||
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
|
||||
)));
|
||||
impl GrooveboxStatus {
|
||||
fn help () -> impl Content<Tui> {
|
||||
fn help () -> impl Content<TuiOut> {
|
||||
let single = |binding, command|row!(" ", col!(
|
||||
Tui::fg(TuiTheme::yellow(), binding),
|
||||
command
|
||||
|
|
@ -143,7 +143,7 @@ impl GrooveboxStatus {
|
|||
double(("c", "color"), ("", ""),),
|
||||
))
|
||||
}
|
||||
fn stats (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn stats (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
row!(&self.cpu, &self.size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ command!(|self: GrooveboxCommand, state: Groovebox|match self {
|
|||
},
|
||||
});
|
||||
|
||||
handle!(<Tui>|self: Groovebox, input|
|
||||
handle!(TuiIn: |self: Groovebox, input|
|
||||
GrooveboxCommand::execute_with_state(self, input.event()));
|
||||
|
||||
keymap!(<'a> KEYS_GROOVEBOX = |state: Groovebox, input: Event| GrooveboxCommand {
|
||||
|
|
|
|||
|
|
@ -6,28 +6,28 @@ use EdnItem::*;
|
|||
|
||||
const EDN: &'static str = include_str!("groovebox.edn");
|
||||
|
||||
//impl Content<Tui> for Groovebox {
|
||||
//fn content (&self) -> impl Render<Tui> {
|
||||
//self.size.of(EdnView::new(self, EDN).expect("failed to build view"))
|
||||
//}
|
||||
//}
|
||||
impl Content<TuiOut> for Groovebox {
|
||||
fn content (&self) -> impl Render<TuiOut> {
|
||||
self.size.of(EdnView::new(self, EDN).expect("failed to build view"))
|
||||
}
|
||||
}
|
||||
|
||||
render!(Tui: (self: Groovebox) => self.size.of(
|
||||
Bsp::s(self.toolbar_view(),
|
||||
Bsp::n(self.selector_view(),
|
||||
Bsp::n(self.sample_view(),
|
||||
Bsp::n(self.status_view(),
|
||||
Bsp::w(self.pool_view(), Fill::xy(Bsp::e(self.sampler_view(), &self.editor)))))))));
|
||||
//render!(TuiOut: (self: Groovebox) => self.size.of(
|
||||
//Bsp::s(self.toolbar_view(),
|
||||
//Bsp::n(self.selector_view(),
|
||||
//Bsp::n(self.sample_view(),
|
||||
//Bsp::n(self.status_view(),
|
||||
//Bsp::w(self.pool_view(), Fill::xy(Bsp::e(self.sampler_view(), &self.editor)))))))));
|
||||
|
||||
impl Groovebox {
|
||||
fn toolbar_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn toolbar_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
Fill::x(Fixed::y(2, lay!(
|
||||
Align::w(Meter("L/", self.sampler.input_meter[0])),
|
||||
Align::e(Meter("R/", self.sampler.input_meter[1])),
|
||||
Align::x(TransportView::new(true, &self.player.clock)),
|
||||
)))
|
||||
}
|
||||
fn selector_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn selector_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
row!(
|
||||
ClipSelected::play_phrase(&self.player),
|
||||
ClipSelected::next_phrase(&self.player),
|
||||
|
|
@ -35,23 +35,23 @@ impl Groovebox {
|
|||
MidiEditStatus(&self.editor),
|
||||
)
|
||||
}
|
||||
fn sample_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn sample_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let note_pt = self.editor.note_point();
|
||||
let sample_h = if self.compact { 0 } else { 5 };
|
||||
Max::y(sample_h, Fill::xy(
|
||||
SampleViewer::from_sampler(&self.sampler, note_pt)))
|
||||
}
|
||||
fn status_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn status_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let note_pt = self.editor.note_point();
|
||||
Align::w(Fixed::y(1, SamplerStatus(&self.sampler, note_pt)))
|
||||
}
|
||||
fn pool_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn pool_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let w = self.size.w();
|
||||
let pool_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
|
||||
Fixed::x(if self.compact { 5 } else { pool_w },
|
||||
PoolView(self.compact, &self.pool))
|
||||
}
|
||||
fn sampler_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn sampler_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let sampler_w = if self.compact { 4 } else { 11 };
|
||||
let sampler_y = if self.compact { 1 } else { 0 };
|
||||
Fixed::x(sampler_w, Push::y(sampler_y, Fill::y(
|
||||
|
|
@ -59,7 +59,7 @@ impl Groovebox {
|
|||
}
|
||||
}
|
||||
|
||||
//render!(Tui: (self: Groovebox) => self.size.of(
|
||||
//render!(TuiOut: (self: Groovebox) => self.size.of(
|
||||
//Bsp::s(self.toolbar_view(),
|
||||
//Bsp::n(self.selector_view(),
|
||||
//Bsp::n(self.sample_view(),
|
||||
|
|
@ -68,8 +68,8 @@ impl Groovebox {
|
|||
|
||||
//const GROOVEBOX_EDN: &'static str = include_str!("groovebox.edn");
|
||||
|
||||
//impl Content<Tui> for Groovebox {
|
||||
//fn content (&self) -> impl Content<Tui> {
|
||||
//impl Content<TuiOut> for Groovebox {
|
||||
//fn content (&self) -> impl Content<TuiOut> {
|
||||
//EdnView::parse(self.edn.as_slice())
|
||||
//}
|
||||
//}
|
||||
|
|
@ -119,17 +119,17 @@ impl Groovebox {
|
|||
//}
|
||||
|
||||
////impl Groovebox {
|
||||
////fn status_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
////fn status_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
////let note_pt = self.editor.note_point();
|
||||
////Align::w(Fixed::y(1, ))
|
||||
////}
|
||||
////fn pool_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
////fn pool_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
////let w = self.size.w();
|
||||
////let pool_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
|
||||
////Fixed::x(if self.compact { 5 } else { pool_w },
|
||||
////)
|
||||
////}
|
||||
////fn sampler_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
////fn sampler_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
////let sampler_w = if self.compact { 4 } else { 11 };
|
||||
////let sampler_y = if self.compact { 1 } else { 0 };
|
||||
////Fixed::x(sampler_w, Push::y(sampler_y, Fill::y(
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ impl JackConnection {
|
|||
/// * This allows user code to connect to JACK
|
||||
/// * While user code retains clone of the
|
||||
/// [Arc<RwLock<JackConnection>>] that is
|
||||
/// passed to `init`, the audio engine is running.
|
||||
/// passed to `init`, the audio engine is running.
|
||||
pub fn activate_with <T: Audio + 'static> (
|
||||
self,
|
||||
init: impl FnOnce(&Arc<RwLock<JackConnection>>)->Usually<T>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ pub mod jack; pub use self::jack::*;
|
|||
pub mod meter; pub use self::meter::*;
|
||||
pub mod midi; pub use self::midi::*;
|
||||
pub mod mixer; pub use self::mixer::*;
|
||||
pub mod piano; pub use self::piano::*;
|
||||
pub mod piano; pub use self::piano::*;
|
||||
pub mod plugin; pub use self::plugin::*;
|
||||
pub mod pool; pub use self::pool::*;
|
||||
pub mod sampler; pub use self::sampler::*;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct Meter<'a>(pub &'a str, pub f32);
|
||||
|
||||
render!(Tui: (self: Meter<'a>) => col!(
|
||||
render!(TuiOut: (self: Meter<'a>) => col!(
|
||||
Field(TuiTheme::g(128).into(), self.0, format!("{:>+9.3}", self.1)),
|
||||
Fixed::xy(if self.1 >= 0.0 { 13 }
|
||||
else if self.1 >= -1.0 { 12 }
|
||||
else if self.1 >= -2.0 { 11 }
|
||||
else if self.1 >= -2.0 { 11 }
|
||||
else if self.1 >= -3.0 { 10 }
|
||||
else if self.1 >= -4.0 { 9 }
|
||||
else if self.1 >= -6.0 { 8 }
|
||||
|
|
@ -22,7 +21,6 @@ render!(Tui: (self: Meter<'a>) => col!(
|
|||
else { Color::Green }, ()))));
|
||||
|
||||
pub struct Meters<'a>(pub &'a[f32]);
|
||||
|
||||
render!(Tui: (self: Meters<'a>) => col!(
|
||||
render!(TuiOut: (self: Meters<'a>) => col!(
|
||||
format!("L/{:>+9.3}", self.0[0]),
|
||||
format!("R/{:>+9.3}", self.0[1])));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub trait HasEditor {
|
|||
/// Contains state for viewing and editing a phrase
|
||||
pub struct MidiEditor {
|
||||
pub mode: PianoHorizontal,
|
||||
pub size: Measure<Tui>
|
||||
pub size: Measure<TuiOut>
|
||||
}
|
||||
|
||||
from!(|phrase: &Arc<RwLock<MidiClip>>|MidiEditor = {
|
||||
|
|
@ -40,9 +40,9 @@ impl Default for MidiEditor {
|
|||
}
|
||||
}
|
||||
|
||||
has_size!(<Tui>|self: MidiEditor|&self.size);
|
||||
has_size!(<TuiOut>|self: MidiEditor|&self.size);
|
||||
|
||||
render!(Tui: (self: MidiEditor) => {
|
||||
render!(TuiOut: (self: MidiEditor) => {
|
||||
self.autoscroll();
|
||||
self.autozoom();
|
||||
Fill::xy(Bsp::b(&self.size, &self.mode))
|
||||
|
|
@ -147,7 +147,7 @@ pub enum MidiEditCommand {
|
|||
Show(Option<Arc<RwLock<MidiClip>>>),
|
||||
}
|
||||
|
||||
handle!(<Tui>|self: MidiEditor, input|MidiEditCommand::execute_with_state(self, input.event()));
|
||||
handle!(TuiIn: |self: MidiEditor, input|MidiEditCommand::execute_with_state(self, input.event()));
|
||||
|
||||
keymap!(KEYS_MIDI_EDITOR = |s: MidiEditor, _input: Event| MidiEditCommand {
|
||||
key(Up) => SetNoteCursor(s.note_point() + 1),
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ pub trait MidiPlaybackApi: HasPlayPhrase + HasClock + HasMidiOuts {
|
|||
phrase: &RwLock<MidiClip>,
|
||||
pulse: usize,
|
||||
sample: usize,
|
||||
note_buf: &mut Vec<u8>,
|
||||
note_buf: &mut Vec<u8>,
|
||||
out: &mut [Vec<Vec<u8>>],
|
||||
notes: &mut [bool;128]
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct MidiEditClip<'a>(pub &'a MidiEditor);
|
||||
render!(Tui: (self: MidiEditClip<'a>) => {
|
||||
render!(TuiOut: (self: MidiEditClip<'a>) => {
|
||||
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.looped)
|
||||
} else {
|
||||
|
|
@ -14,7 +14,7 @@ render!(Tui: (self: MidiEditClip<'a>) => {
|
|||
});
|
||||
|
||||
pub struct MidiEditStatus<'a>(pub &'a MidiEditor);
|
||||
render!(Tui: (self: MidiEditStatus<'a>) => {
|
||||
render!(TuiOut: (self: MidiEditStatus<'a>) => {
|
||||
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.looped)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
|
||||
pub trait MidiViewer: HasSize<Tui> + MidiRange + MidiPoint + Debug + Send + Sync {
|
||||
pub trait MidiViewer: HasSize<TuiOut> + MidiRange + MidiPoint + Debug + Send + Sync {
|
||||
fn buffer_size (&self, phrase: &MidiClip) -> (usize, usize);
|
||||
fn redraw (&self);
|
||||
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>>;
|
||||
|
|
|
|||
14
src/mixer.rs
14
src/mixer.rs
|
|
@ -96,7 +96,7 @@ pub struct TrackView<'a> {
|
|||
pub entered: bool,
|
||||
}
|
||||
|
||||
impl<'a> Content<Tui> for TrackView<'a> {
|
||||
impl<'a> Content<TuiOut> for TrackView<'a> {
|
||||
fn render (&self, to: &mut TuiOut) {
|
||||
todo!();
|
||||
//let mut area = to.area();
|
||||
|
|
@ -127,8 +127,8 @@ impl<'a> Content<Tui> for TrackView<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
//impl Content<Tui> for Mixer<Tui> {
|
||||
//fn content (&self) -> impl Content<Tui> {
|
||||
//impl Content<TuiOut> for Mixer<Tui> {
|
||||
//fn content (&self) -> impl Content<TuiOut> {
|
||||
//Stack::right(|add| {
|
||||
//for channel in self.tracks.iter() {
|
||||
//add(channel)?;
|
||||
|
|
@ -138,8 +138,8 @@ impl<'a> Content<Tui> for TrackView<'a> {
|
|||
//}
|
||||
//}
|
||||
|
||||
//impl Content<Tui> for Track<Tui> {
|
||||
//fn content (&self) -> impl Content<Tui> {
|
||||
//impl Content<TuiOut> for Track<Tui> {
|
||||
//fn content (&self) -> impl Content<TuiOut> {
|
||||
//TrackView {
|
||||
//chain: Some(&self),
|
||||
//direction: tek_core::Direction::Right,
|
||||
|
|
@ -162,7 +162,7 @@ impl<'a> Content<Tui> for TrackView<'a> {
|
|||
//}
|
||||
//}
|
||||
|
||||
handle!(<Tui>|self: Mixer, engine|{
|
||||
handle!(TuiIn: |self: Mixer, engine|{
|
||||
if let crossterm::event::Event::Key(event) = engine.event() {
|
||||
|
||||
match event.code {
|
||||
|
|
@ -210,7 +210,7 @@ handle!(<Tui>|self: Mixer, engine|{
|
|||
Ok(None)
|
||||
});
|
||||
|
||||
handle!(<Tui>|self:MixerTrack,from|{
|
||||
handle!(TuiIn: |self:MixerTrack,from|{
|
||||
match from.event() {
|
||||
//, NONE, "chain_cursor_up", "move cursor up", || {
|
||||
kpat!(KeyCode::Up) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub struct PianoHorizontal {
|
|||
/// Buffer where the whole phrase is rerendered on change
|
||||
buffer: Arc<RwLock<BigBuffer>>,
|
||||
/// Size of actual notes area
|
||||
size: Measure<Tui>,
|
||||
size: Measure<TuiOut>,
|
||||
/// The display window
|
||||
range: MidiRangeModel,
|
||||
/// The note cursor
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub(crate) fn note_y_iter (note_lo: usize, note_hi: usize, y0: u16) -> impl Iter
|
|||
(note_lo..=note_hi).rev().enumerate().map(move|(y, n)|(y, y0 + y as u16, n))
|
||||
}
|
||||
|
||||
render!(Tui: (self: PianoHorizontal) => Bsp::s(
|
||||
render!(TuiOut: (self: PianoHorizontal) => Bsp::s(
|
||||
Fixed::y(1, Bsp::e(
|
||||
Fixed::x(self.keys_width, ""),
|
||||
Fill::x(PianoHorizontalTimeline(self)),
|
||||
|
|
@ -81,7 +81,7 @@ impl PianoHorizontal {
|
|||
}
|
||||
}
|
||||
|
||||
has_size!(<Tui>|self:PianoHorizontal|&self.size);
|
||||
has_size!(<TuiOut>|self:PianoHorizontal|&self.size);
|
||||
|
||||
impl TimeRange for PianoHorizontal {
|
||||
fn time_len (&self) -> &AtomicUsize { self.range.time_len() }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
use super::*;
|
||||
|
||||
pub struct PianoHorizontalCursor<'a>(pub(crate) &'a PianoHorizontal);
|
||||
render!(Tui: |self: PianoHorizontalCursor<'a>, render|{
|
||||
render!(TuiOut: |self: PianoHorizontalCursor<'a>, render|{
|
||||
let style = Some(Style::default().fg(self.0.color.lightest.rgb));
|
||||
let note_hi = self.0.note_hi();
|
||||
let note_len = self.0.note_len();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use super::*;
|
|||
|
||||
pub struct PianoHorizontalKeys<'a>(pub(crate) &'a PianoHorizontal);
|
||||
|
||||
render!(Tui: |self: PianoHorizontalKeys<'a>, to|{
|
||||
render!(TuiOut: |self: PianoHorizontalKeys<'a>, to|{
|
||||
let state = self.0;
|
||||
let color = state.color;
|
||||
let note_lo = state.note_lo().get();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use super::*;
|
|||
|
||||
pub struct PianoHorizontalNotes<'a>(pub(crate) &'a PianoHorizontal);
|
||||
|
||||
render!(Tui: |self: PianoHorizontalNotes<'a>, render|{
|
||||
render!(TuiOut: |self: PianoHorizontalNotes<'a>, render|{
|
||||
let time_start = self.0.time_start().get();
|
||||
let note_axis = self.0.note_axis().get();
|
||||
let note_lo = self.0.note_lo().get();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
use super::*;
|
||||
|
||||
pub struct PianoHorizontalTimeline<'a>(pub(crate) &'a PianoHorizontal);
|
||||
render!(Tui: |self: PianoHorizontalTimeline<'a>, render|{
|
||||
render!(TuiOut: |self: PianoHorizontalTimeline<'a>, render|{
|
||||
let [x, y, w, h] = render.area();
|
||||
let style = Some(Style::default().dim());
|
||||
let length = self.0.phrase.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ impl Plugin {
|
|||
})
|
||||
}
|
||||
}
|
||||
impl Content<Tui> for Plugin {
|
||||
impl Content<TuiOut> for Plugin {
|
||||
fn render (&self, to: &mut TuiOut) {
|
||||
let area = to.area();
|
||||
let [x, y, _, height] = area;
|
||||
|
|
@ -198,7 +198,7 @@ fn draw_header (state: &Plugin, to: &mut TuiOut, x: u16, y: u16, w: u16) {
|
|||
//Ok(Rect { x, y, width: w, height: 1 })
|
||||
}
|
||||
|
||||
handle!(<Tui>|self:Plugin, from|{
|
||||
handle!(TuiIn: |self:Plugin, from|{
|
||||
match from.event() {
|
||||
kpat!(KeyCode::Up) => {
|
||||
self.selected = self.selected.saturating_sub(1);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub struct PoolModel {
|
|||
/// Mode switch
|
||||
pub(crate) mode: Option<PoolMode>,
|
||||
/// Rendered size
|
||||
size: Measure<Tui>,
|
||||
size: Measure<TuiOut>,
|
||||
/// Scroll offset
|
||||
scroll: usize,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ impl PhraseLengthFocus {
|
|||
}
|
||||
}
|
||||
|
||||
render!(Tui: (self: PhraseLength) => {
|
||||
render!(TuiOut: (self: PhraseLength) => {
|
||||
let bars = ||self.bars_string();
|
||||
let beats = ||self.beats_string();
|
||||
let ticks = ||self.ticks_string();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub struct ClipSelected {
|
|||
pub(crate) time: String,
|
||||
}
|
||||
|
||||
render!(Tui: (self: ClipSelected) =>
|
||||
render!(TuiOut: (self: ClipSelected) =>
|
||||
FieldV(self.color, self.title, format!("{} {}", self.time, self.name)));
|
||||
|
||||
impl ClipSelected {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct PoolView<'a>(pub bool, pub &'a PoolModel);
|
||||
render!(Tui: (self: PoolView<'a>) => {
|
||||
render!(TuiOut: (self: PoolView<'a>) => {
|
||||
let Self(compact, model) = self;
|
||||
let PoolModel { phrases, mode, .. } = self.1;
|
||||
let color = self.1.phrase().read().unwrap().color;
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ fn draw_sample (
|
|||
Ok(label1.len() + label2.len() + 4)
|
||||
}
|
||||
|
||||
impl Content<Tui> for AddSampleModal {
|
||||
impl Content<TuiOut> for AddSampleModal {
|
||||
fn render (&self, to: &mut TuiOut) {
|
||||
todo!()
|
||||
//let area = to.area();
|
||||
|
|
@ -207,7 +207,7 @@ impl Content<Tui> for AddSampleModal {
|
|||
}
|
||||
}
|
||||
|
||||
//impl Handle<Tui> for AddSampleModal {
|
||||
//impl Handle<TuiIn> for AddSampleModal {
|
||||
//fn handle (&mut self, from: &TuiIn) -> Perhaps<bool> {
|
||||
//if from.handle_keymap(self, KEYMAP_ADD_SAMPLE)? {
|
||||
//return Ok(Some(true))
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl<'a> SampleList<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
render!(Tui: (self: SampleList<'a>) => {
|
||||
render!(TuiOut: (self: SampleList<'a>) => {
|
||||
let Self { compact, sampler, editor } = self;
|
||||
let note_lo = editor.note_lo().load(Relaxed);
|
||||
let note_pt = editor.note_point();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl SampleViewer {
|
|||
}
|
||||
}
|
||||
|
||||
render!(Tui: |self: SampleViewer, to|{
|
||||
render!(TuiOut: |self: SampleViewer, to|{
|
||||
|
||||
let [x, y, width, height] = to.area();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
|
||||
handle!(<Tui>|self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input.event()));
|
||||
handle!(TuiIn: |self: SamplerTui, input|SamplerTuiCommand::execute_with_state(self, input.event()));
|
||||
|
||||
pub enum SamplerTuiCommand {
|
||||
Import(FileBrowserCommand),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
|
||||
pub struct SamplerStatus<'a>(pub &'a Sampler, pub usize);
|
||||
|
||||
render!(Tui: (self: SamplerStatus<'a>) => Tui::bold(true, Tui::fg(TuiTheme::g(224), self.0.mapped[self.1].as_ref().map(|sample|format!(
|
||||
render!(TuiOut: (self: SamplerStatus<'a>) => Tui::bold(true, Tui::fg(TuiTheme::g(224), self.0.mapped[self.1].as_ref().map(|sample|format!(
|
||||
"Sample {}-{}",
|
||||
sample.read().unwrap().start,
|
||||
sample.read().unwrap().end,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub struct SamplerTui {
|
|||
pub editing: Option<Arc<RwLock<Sample>>>,
|
||||
pub mode: Option<SamplerMode>,
|
||||
/// Size of actual notes area
|
||||
pub size: Measure<Tui>,
|
||||
pub size: Measure<TuiOut>,
|
||||
/// Lowest note displayed
|
||||
pub note_lo: AtomicUsize,
|
||||
pub note_pt: AtomicUsize,
|
||||
|
|
@ -31,7 +31,7 @@ impl SamplerTui {
|
|||
}
|
||||
}
|
||||
|
||||
render!(Tui: (self: SamplerTui) => {
|
||||
render!(TuiOut: (self: SamplerTui) => {
|
||||
let keys_width = 5;
|
||||
let keys = move||"";//SamplerKeys(self);
|
||||
let fg = self.color.base.rgb;
|
||||
|
|
@ -59,7 +59,7 @@ struct SamplesTui {
|
|||
note_pt: usize,
|
||||
height: usize,
|
||||
}
|
||||
render!(Tui: |self: SamplesTui, render|{
|
||||
render!(TuiOut: |self: SamplesTui, render|{
|
||||
let x = render.area.x();
|
||||
let bg_base = self.color.darkest.rgb;
|
||||
let bg_selected = self.color.darker.rgb;
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ pub struct SequencerTui {
|
|||
pub editor: MidiEditor,
|
||||
pub player: MidiPlayer,
|
||||
|
||||
pub transport: bool,
|
||||
pub selectors: bool,
|
||||
pub transport: bool,
|
||||
pub selectors: bool,
|
||||
pub compact: bool,
|
||||
|
||||
pub clock: Clock,
|
||||
pub size: Measure<Tui>,
|
||||
pub size: Measure<TuiOut>,
|
||||
pub status: bool,
|
||||
pub note_buf: Vec<u8>,
|
||||
pub midi_buf: Vec<Vec<Vec<u8>>>,
|
||||
|
|
@ -47,20 +47,20 @@ from_jack!(|jack|SequencerTui {
|
|||
clock,
|
||||
}
|
||||
});
|
||||
render!(Tui: (self: SequencerTui) => self.size.of(
|
||||
render!(TuiOut: (self: SequencerTui) => self.size.of(
|
||||
Bsp::s(self.toolbar_view(),
|
||||
Bsp::n(self.status_view(),
|
||||
Bsp::w(self.pool_view(), Fill::xy(&self.editor))))));
|
||||
impl SequencerTui {
|
||||
fn toolbar_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn toolbar_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
self.transport.then(||TransportView::new(true, &self.clock))
|
||||
}
|
||||
fn status_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn status_view (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
let edit_clip = MidiEditClip(&self.editor);
|
||||
let selectors = When(self.selectors, Bsp::e(ClipSelected::play_phrase(&self.player), ClipSelected::next_phrase(&self.player)));
|
||||
row!(selectors, edit_clip, MidiEditStatus(&self.editor))
|
||||
}
|
||||
fn pool_view (&self) -> impl Content<Tui> + use<'_> {
|
||||
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 };
|
||||
|
|
@ -85,11 +85,11 @@ audio!(|self:SequencerTui, client, scope|{
|
|||
self.perf.update(t0, scope);
|
||||
Control::Continue
|
||||
});
|
||||
has_size!(<Tui>|self:SequencerTui|&self.size);
|
||||
has_size!(<TuiOut>|self:SequencerTui|&self.size);
|
||||
has_clock!(|self:SequencerTui|&self.clock);
|
||||
has_phrases!(|self:SequencerTui|self.pool.phrases);
|
||||
has_editor!(|self:SequencerTui|self.editor);
|
||||
handle!(<Tui>|self:SequencerTui,input|SequencerCommand::execute_with_state(self, input.event()));
|
||||
handle!(TuiIn: |self:SequencerTui,input|SequencerCommand::execute_with_state(self, input.event()));
|
||||
#[derive(Clone, Debug)] pub enum SequencerCommand {
|
||||
Compact(bool),
|
||||
History(isize),
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ from!(|state:&SequencerTui|SequencerStatus = {
|
|||
size: format!("{}x{}│", width, state.size.h()),
|
||||
}
|
||||
});
|
||||
render!(Tui: (self: SequencerStatus) => Fixed::y(2, lay!(
|
||||
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<Tui> {
|
||||
fn help () -> impl Content<TuiOut> {
|
||||
let single = |binding, command|row!(" ", col!(
|
||||
Tui::fg(TuiTheme::yellow(), binding),
|
||||
command
|
||||
|
|
@ -44,7 +44,7 @@ impl SequencerStatus {
|
|||
double(("c", "color"), ("", ""),),
|
||||
))
|
||||
}
|
||||
fn stats (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn stats (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
row!(&self.cpu, &self.size)
|
||||
}
|
||||
}
|
||||
|
|
@ -69,12 +69,12 @@ from!(|state:&ArrangerTui|ArrangerStatus = {
|
|||
size: format!("{}x{}│", width, state.size.h()),
|
||||
}
|
||||
});
|
||||
render!(Tui: (self: ArrangerStatus) => Fixed::y(2, lay!(
|
||||
render!(TuiOut: (self: ArrangerStatus) => Fixed::y(2, lay!(
|
||||
Self::help(),
|
||||
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
|
||||
)));
|
||||
impl ArrangerStatus {
|
||||
fn help () -> impl Content<Tui> {
|
||||
fn help () -> impl Content<TuiOut> {
|
||||
let single = |binding, command|row!(" ", col!(
|
||||
Tui::fg(TuiTheme::yellow(), binding),
|
||||
command
|
||||
|
|
@ -95,7 +95,7 @@ impl ArrangerStatus {
|
|||
double(("[]", "phrase"), ("{}", "order"),),
|
||||
))
|
||||
}
|
||||
fn stats (&self) -> impl Content<Tui> + use<'_> {
|
||||
fn stats (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
row!(&self.cpu, &self.size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue