mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: ArrangerStandalone
This commit is contained in:
parent
1104093395
commit
3cbb2d2e0b
19 changed files with 165 additions and 231 deletions
|
|
@ -1,37 +0,0 @@
|
|||
use tek_core::clap::{self, Parser};
|
||||
use crate::*;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct ArrangerCli {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)] name: Option<String>,
|
||||
/// Pulses per quarter note (arruencer resolution; default: 96)
|
||||
#[arg(short, long)] ppq: Option<usize>,
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long)] transport: Option<bool>,
|
||||
/// Number of tracks
|
||||
#[arg(short = 'x', long, default_value_t = 8)] tracks: usize,
|
||||
/// Number of scenes
|
||||
#[arg(short, long, default_value_t = 8)] scenes: usize,
|
||||
}
|
||||
|
||||
impl Arranger {
|
||||
pub fn from_args () -> Usually<Self> {
|
||||
let args = ArrangerCli::parse();
|
||||
let mut arr = Self::new("");
|
||||
if let Some(name) = args.name {
|
||||
arr.name = name.clone();
|
||||
}
|
||||
if args.transport == Some(true) {
|
||||
arr.transport = Some(Arc::new(RwLock::new(TransportToolbar::new(None))));
|
||||
}
|
||||
for _ in 0..args.tracks {
|
||||
arr.track_add(None)?;
|
||||
}
|
||||
for _ in 0..args.scenes {
|
||||
arr.scene_add(None)?;
|
||||
}
|
||||
Ok(arr)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,15 @@
|
|||
use crate::*;
|
||||
|
||||
handle!(Arranger |self, e| {
|
||||
if let Some(modal) = self.modal.as_mut() {
|
||||
let result = modal.handle(e)?;
|
||||
if modal.exited() {
|
||||
self.modal = None;
|
||||
}
|
||||
Ok(result)
|
||||
} else {
|
||||
match e {
|
||||
AppEvent::Input(Event::Key(k)) => {
|
||||
if k.code == KeyCode::Tab {
|
||||
self.focus_sequencer = !self.focus_sequencer;
|
||||
Ok(true)
|
||||
} else if self.focus_sequencer {
|
||||
if let Some(sequencer) = self.sequencer_mut() {
|
||||
handle_keymap(sequencer, e, KEYMAP_SEQUENCER)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
} else {
|
||||
handle_keymap(self, e, KEYMAP_ARRANGER)
|
||||
}
|
||||
},
|
||||
_ => Ok(false),
|
||||
}
|
||||
match self.modal.as_mut() {
|
||||
Some(modal) => {
|
||||
let result = modal.handle(e)?;
|
||||
if modal.exited() {
|
||||
self.modal = None;
|
||||
}
|
||||
Ok(result)
|
||||
},
|
||||
None => handle_keymap(self, e, KEYMAP_ARRANGER)
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,97 @@
|
|||
include!("lib.rs");
|
||||
|
||||
use tek_core::clap::{self, Parser};
|
||||
|
||||
pub fn main () -> Usually<()> {
|
||||
tek_core::run(Arc::new(RwLock::new(crate::Arranger::from_args()?)))?;
|
||||
tek_core::run(Arc::new(RwLock::new(crate::ArrangerStandalone::from_args()?)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct ArrangerStandalone {
|
||||
arranger: Arranger,
|
||||
transport: Option<Arc<RwLock<TransportToolbar>>>,
|
||||
show_sequencer: Option<tek_core::Direction>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct ArrangerCli {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)] name: Option<String>,
|
||||
/// Pulses per quarter note (arruencer resolution; default: 96)
|
||||
#[arg(short, long)] ppq: Option<usize>,
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long)] transport: Option<bool>,
|
||||
/// Number of tracks
|
||||
#[arg(short = 'x', long, default_value_t = 8)] tracks: usize,
|
||||
/// Number of scenes
|
||||
#[arg(short, long, default_value_t = 8)] scenes: usize,
|
||||
}
|
||||
|
||||
impl ArrangerStandalone {
|
||||
pub fn from_args () -> Usually<Self> {
|
||||
let args = ArrangerCli::parse();
|
||||
let mut app = ArrangerStandalone {
|
||||
arranger: Arranger::new(""),
|
||||
transport: match args.transport {
|
||||
Some(true) => Some(Arc::new(RwLock::new(TransportToolbar::new(None)))),
|
||||
_ => None
|
||||
},
|
||||
show_sequencer: Some(tek_core::Direction::Down),
|
||||
};
|
||||
if let Some(name) = args.name {
|
||||
app.arranger.name = name.clone();
|
||||
}
|
||||
for _ in 0..args.tracks {
|
||||
app.arranger.track_add(None)?;
|
||||
}
|
||||
for _ in 0..args.scenes {
|
||||
app.arranger.scene_add(None)?;
|
||||
}
|
||||
Ok(app)
|
||||
}
|
||||
}
|
||||
|
||||
render!(ArrangerStandalone |self, buf, area| {
|
||||
let mut layout = Split::down();
|
||||
if let Some(transport) = &self.transport {
|
||||
layout = layout.add_ref(transport);
|
||||
}
|
||||
let sequencer = self.arranger.sequencer();
|
||||
if let Some(direction) = self.show_sequencer {
|
||||
layout = layout.add(Split::new(direction)
|
||||
.add_ref(&self.arranger)
|
||||
.add(sequencer))
|
||||
} else {
|
||||
layout = layout.add_ref(&self.arranger)
|
||||
}
|
||||
layout.render(buf, area)
|
||||
});
|
||||
|
||||
handle!(ArrangerStandalone |self, e| {
|
||||
if let Some(modal) = self.arranger.modal.as_mut() {
|
||||
let result = modal.handle(e)?;
|
||||
if modal.exited() {
|
||||
self.arranger.modal = None;
|
||||
}
|
||||
Ok(result)
|
||||
} else {
|
||||
match e {
|
||||
AppEvent::Input(Event::Key(k)) => {
|
||||
if k.code == KeyCode::Tab {
|
||||
self.arranger.focus_sequencer = !self.arranger.focus_sequencer;
|
||||
Ok(true)
|
||||
} else if self.arranger.focus_sequencer {
|
||||
if let Some(sequencer) = self.arranger.sequencer_mut() {
|
||||
handle_keymap(sequencer, e, KEYMAP_SEQUENCER)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
} else {
|
||||
handle_keymap(&mut self.arranger, e, KEYMAP_ARRANGER)
|
||||
}
|
||||
},
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::*;
|
||||
use tek_core::Direction;
|
||||
|
||||
/// Display mode of arranger
|
||||
pub enum ArrangerViewMode {
|
||||
|
|
@ -21,109 +20,24 @@ impl ArrangerViewMode {
|
|||
}
|
||||
|
||||
render!(Arranger |self, buf, area| {
|
||||
|
||||
let arrangement = Box::new(|buf: &mut Buffer, area: Rect| {
|
||||
let area = Rect {
|
||||
x: area.x + 1, width: area.width - 2, y: area.y + 1, height: area.height - 2
|
||||
};
|
||||
let area = match self.mode {
|
||||
ArrangerViewMode::Horizontal =>
|
||||
super::arranger_view_h::draw(self, buf, area),
|
||||
ArrangerViewMode::VerticalCompact1 =>
|
||||
super::arranger_view_v::draw_compact_1(self, buf, area),
|
||||
ArrangerViewMode::VerticalCompact2 =>
|
||||
super::arranger_view_v::draw_compact_2(self, buf, area),
|
||||
ArrangerViewMode::VerticalExpanded =>
|
||||
super::arranger_view_v::draw_expanded(self, buf, area),
|
||||
}?;
|
||||
let area = Rect {
|
||||
x: area.x - 1,
|
||||
width: area.width + 2,
|
||||
y: area.y - 1,
|
||||
height: area.height + 2,
|
||||
};
|
||||
Lozenge(Style::default().fg(Nord::BG2)).draw(buf, area)
|
||||
});
|
||||
|
||||
let mut layout = Split::new(Direction::Down)
|
||||
.add_ref(match &self.transport {
|
||||
Some(transport) => transport as &dyn Render,
|
||||
None => &() as &dyn Render
|
||||
});
|
||||
|
||||
if let Some(direction) = self.show_sequencer {
|
||||
let sequencer = Box::new(Split::new(direction).add_box(arrangement));
|
||||
layout = layout.add_box(sequencer);
|
||||
} else {
|
||||
layout = layout.add_box(arrangement);
|
||||
}
|
||||
|
||||
layout.render(buf, area)
|
||||
|
||||
//.add(if let Some(direction) = self.show_sequencer {
|
||||
//Box::new(Split::new(direction)
|
||||
//.add(arrangement))
|
||||
////.add_ref(&self.sequencer())) as Box<dyn Render>
|
||||
//} else {
|
||||
//Box::new(arrangement) as Box<dyn Render>
|
||||
//})
|
||||
//.render(buf, area)
|
||||
|
||||
|
||||
//Column([
|
||||
//self.transport,
|
||||
//match self.mode {
|
||||
//ArrangerViewMode::Horizontal =>
|
||||
//super::arranger_view_h::draw(self, buf, area),
|
||||
//ArrangerViewMode::VerticalCompact1 =>
|
||||
//super::arranger_view_v::draw_compact_1(self, buf, area),
|
||||
//ArrangerViewMode::VerticalCompact2 =>
|
||||
//super::arranger_view_v::draw_compact_2(self, buf, area),
|
||||
//ArrangerViewMode::VerticalExpanded =>
|
||||
//super::arranger_view_v::draw_expanded(self, buf, area),
|
||||
//},
|
||||
|
||||
|
||||
//let area = if let Some(direction) = self.show_sequencer {
|
||||
//let arrangement = arrangement(buf, area)?;
|
||||
//match direction {
|
||||
//Direction::Down => {
|
||||
//let sequencer = if let Some(sequencer) = self.sequencer() {
|
||||
//sequencer.render(buf, Rect {
|
||||
//y: area.y + arrangement.height,
|
||||
//height: area.height - arrangement.height,
|
||||
//..area
|
||||
//})?
|
||||
//} else {
|
||||
//Rect::default()
|
||||
//};
|
||||
//match self.focus_sequencer {
|
||||
//true => {
|
||||
//"[Arrows] Move, [A]dd, [D]elete, [R]ecord, [P]lay".blit(
|
||||
//buf, area.x + 1, area.height - 1, Some(Style::default().dim())
|
||||
//)?;
|
||||
//},
|
||||
//false => {
|
||||
//"[Arrows] Move, [P]lay, [R]ecord, [N]ame, [E]dit, [C-T]rack add, [C-A]dd scene".blit(
|
||||
//buf, area.x + 1, area.y + arrangement.height, Some(Style::default().dim())
|
||||
//)?;
|
||||
//},
|
||||
//}
|
||||
//Corners(Style::default().green().not_dim()).draw(buf, match self.focus_sequencer {
|
||||
//true => sequencer,
|
||||
//false => arrangement,
|
||||
//})?;
|
||||
//},
|
||||
//_ => unimplemented!()
|
||||
//}
|
||||
//Ok(area)
|
||||
//} else {
|
||||
//arrangement(buf, area)
|
||||
//}?;
|
||||
//if let Some(ref modal) = self.modal {
|
||||
//fill_bg(buf, area, Nord::bg_lo(false, false));
|
||||
//fill_fg(buf, area, Nord::bg_hi(false, false));
|
||||
//modal.render(buf, area)?;
|
||||
//}
|
||||
//Ok(area)
|
||||
let area = Rect {
|
||||
x: area.x + 1, width: area.width - 2, y: area.y + 1, height: area.height - 2
|
||||
};
|
||||
let area = match self.mode {
|
||||
ArrangerViewMode::Horizontal =>
|
||||
super::arranger_view_h::draw(self, buf, area),
|
||||
ArrangerViewMode::VerticalCompact1 =>
|
||||
super::arranger_view_v::draw_compact_1(self, buf, area),
|
||||
ArrangerViewMode::VerticalCompact2 =>
|
||||
super::arranger_view_v::draw_compact_2(self, buf, area),
|
||||
ArrangerViewMode::VerticalExpanded =>
|
||||
super::arranger_view_v::draw_expanded(self, buf, area),
|
||||
}?;
|
||||
let area = Rect {
|
||||
x: area.x - 1,
|
||||
width: area.width + 2,
|
||||
y: area.y - 1,
|
||||
height: area.height + 2,
|
||||
};
|
||||
Lozenge(Style::default().fg(Nord::BG2)).draw(buf, area)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ impl<'a> Render for TrackMonitorColumn<'a> {
|
|||
let Self(tracks) = self;
|
||||
let on = Some(Style::default().not_dim().green().bold());
|
||||
let off = Some(DIM);
|
||||
area.x = area.x + 1;
|
||||
area.x += 1;
|
||||
for y in 0..area.height {
|
||||
if y == 0 {
|
||||
//" MON ".blit(buf, area.x, area.y + y, style2)?;
|
||||
|
|
@ -76,7 +76,7 @@ impl<'a> Render for TrackRecordColumn<'a> {
|
|||
let Self(tracks) = self;
|
||||
let on = Some(Style::default().not_dim().red().bold());
|
||||
let off = Some(Style::default().dim());
|
||||
area.x = area.x + 1;
|
||||
area.x += 1;
|
||||
for y in 0..area.height {
|
||||
if y == 0 {
|
||||
//" REC ".blit(buf, area.x, area.y + y, style2)?;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ pub(crate) use std::sync::{Arc, RwLock};
|
|||
|
||||
submod! {
|
||||
arranger
|
||||
arranger_cli
|
||||
arranger_focus
|
||||
arranger_handle
|
||||
arranger_track
|
||||
|
|
|
|||
|
|
@ -4,25 +4,16 @@ const CORNERS: Corners = Corners(NOT_DIM_GREEN);
|
|||
|
||||
render!(TransportToolbar |self, buf, area| {
|
||||
let mut area = area;
|
||||
area.height = 2;
|
||||
let ppq = self.ppq();
|
||||
let bpm = self.bpm();
|
||||
let pulse = self.pulse();
|
||||
let usecs = self.usecs();
|
||||
area.height = 2;
|
||||
let Self { quant, sync, focused, entered, .. } = self;
|
||||
fill_bg(buf, area, Nord::bg_lo(*focused, *entered));
|
||||
let active = self.focused && self.entered;
|
||||
let playing = TransportPlayPauseButton(self.playing);
|
||||
let bpm = TransportBPM(bpm, active && self.selected == TransportFocus::BPM);
|
||||
let quant = TransportQuantize(*quant, active && self.selected == TransportFocus::Quant);
|
||||
let sync = TransportSync(*sync, active && self.selected == TransportFocus::Sync);
|
||||
let clock = TransportClock(pulse, ppq, usecs);
|
||||
Split::right()
|
||||
.add_ref(&playing)
|
||||
.add_ref(&bpm)
|
||||
.add_ref(&quant)
|
||||
.add_ref(&sync)
|
||||
.add_ref(&clock)
|
||||
.add(TransportPlayPauseButton(self.playing))
|
||||
.add(TransportBPM(self.bpm(), active && self.selected == TransportFocus::BPM))
|
||||
.add(TransportQuantize(*quant, active && self.selected == TransportFocus::Quant))
|
||||
.add(TransportSync(*sync, active && self.selected == TransportFocus::Sync))
|
||||
.add(TransportClock(self.pulse(), self.ppq(), self.usecs()))
|
||||
.render(buf, area)
|
||||
});
|
||||
|
||||
|
|
@ -31,7 +22,6 @@ struct TransportPlayPauseButton(Option<TransportState>);
|
|||
|
||||
render!(TransportPlayPauseButton |self, buf, area| {
|
||||
let Rect { x, y, .. } = area;
|
||||
let gray = Style::default().gray();
|
||||
let style = Some(match self.0 {
|
||||
Some(TransportState::Stopped) => GRAY_DIM.bold(),
|
||||
Some(TransportState::Starting) => GRAY_NOT_DIM_BOLD,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue