wip: refactor pt.4, reduce number of files

This commit is contained in:
🪞👃🪞 2024-11-10 01:03:47 +01:00
parent adf5b3f0f8
commit 8c37c95cc6
60 changed files with 2185 additions and 2187 deletions

View file

@ -0,0 +1,151 @@
use crate::*;
/// Stores and displays time-related state.
#[derive(Debug)]
pub struct TransportView<E: Engine> {
_engine: PhantomData<E>,
state: TransportToolbar,
focused: bool,
focus: TransportFocus,
}
/// Which item of the transport toolbar is focused
#[derive(Clone, Copy, PartialEq)]
pub enum TransportFocus {
Bpm,
Sync,
PlayPause,
Clock,
Quant,
}
impl<E: Engine> TransportView<E> {
pub fn new (jack: &Arc<RwLock<JackClient>>, clock: Option<&Arc<TransportTime>>) -> Self {
Self {
_engine: Default::default(),
focused: false,
focus: TransportFocus::PlayPause,
state: TransportToolbar {
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
clock: match clock {
Some(clock) => clock.clone(),
None => {
let timebase = Arc::new(Timebase::default());
Arc::new(TransportTime {
playing: Some(TransportState::Stopped).into(),
quant: 24.into(),
sync: (timebase.ppq.get() * 4.).into(),
current: Instant::default(),
started: None.into(),
})
}
},
}
}
}
pub fn toggle_play (&mut self) -> Usually<()> {
let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet");
let playing = match playing {
TransportState::Stopped => {
self.transport.start()?;
Some(TransportState::Starting)
},
_ => {
self.transport.stop()?;
self.transport.locate(0)?;
Some(TransportState::Stopped)
},
};
*self.clock.playing.write().unwrap() = playing;
Ok(())
}
}
impl TransportFocus {
pub fn next (&mut self) {
*self = match self {
Self::PlayPause => Self::Bpm,
Self::Bpm => Self::Quant,
Self::Quant => Self::Sync,
Self::Sync => Self::Clock,
Self::Clock => Self::PlayPause,
}
}
pub fn prev (&mut self) {
*self = match self {
Self::PlayPause => Self::Clock,
Self::Bpm => Self::PlayPause,
Self::Quant => Self::Bpm,
Self::Sync => Self::Quant,
Self::Clock => Self::Sync,
}
}
}
impl Content for TransportToolbar<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
lay!(
self.focus.wrap(self.focused, TransportToolbarFocus::PlayPause, &Styled(
None,
match *self.clock.playing.read().unwrap() {
Some(TransportState::Rolling) => "▶ PLAYING",
Some(TransportState::Starting) => "READY ...",
Some(TransportState::Stopped) => "⏹ STOPPED",
_ => unreachable!(),
}
).min_xy(11, 2).push_x(1)).align_x().fill_x(),
row!(
self.focus.wrap(self.focused, TransportToolbarFocus::Bpm, &Outset::X(1u16, {
let bpm = self.clock.timebase().bpm.get();
row! { "BPM ", format!("{}.{:03}", bpm as usize, (bpm * 1000.0) % 1000.0) }
})),
//let quant = self.focus.wrap(self.focused, TransportToolbarFocus::Quant, &Outset::X(1u16, row! {
//"QUANT ", ppq_to_name(self.quant as usize)
//})),
self.focus.wrap(self.focused, TransportToolbarFocus::Sync, &Outset::X(1u16, row! {
"SYNC ", pulses_to_name(self.clock.sync.get() as usize)
}))
).align_w().fill_x(),
self.focus.wrap(self.focused, TransportToolbarFocus::Clock, &{
let time1 = self.clock.current.format_beat();
let time2 = self.clock.current.usec.format_msu();
row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1)
}).align_e().fill_x(),
).fill_x().bg(Color::Rgb(40, 50, 30))
}
}
impl TransportToolbarFocus {
pub fn wrap <'a, W: Widget<Engine = Tui>> (
self, parent_focus: bool, focus: Self, widget: &'a W
) -> impl Widget<Engine = Tui> + 'a {
let focused = parent_focus && focus == self;
let corners = focused.then_some(CORNERS);
let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50)));
lay!(corners, highlight, *widget)
}
}
impl Handle<Tui> for TransportToolbar<Tui> {
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
if let Some(command) = TransportCommand::input_to_command(self, from) {
let _undo = command.execute(self)?;
return Ok(Some(true))
}
Ok(None)
}
}
impl InputToCommand<Tui, TransportToolbar<Tui>> for TransportCommand {
fn input_to_command (_: &TransportToolbar<Tui>, input: &TuiInput) -> Option<Self> {
match input.event() {
key!(KeyCode::Char(' ')) => Some(Self::FocusPrev),
key!(Shift-KeyCode::Char(' ')) => Some(Self::FocusPrev),
key!(KeyCode::Left) => Some(Self::FocusPrev),
key!(KeyCode::Right) => Some(Self::FocusNext),
key!(KeyCode::Char('.')) => Some(Self::Increment),
key!(KeyCode::Char(',')) => Some(Self::Decrement),
key!(KeyCode::Char('>')) => Some(Self::FineIncrement),
key!(KeyCode::Char('<')) => Some(Self::FineDecrement),
_ => None
}
}
}