mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
134 lines
5 KiB
Rust
134 lines
5 KiB
Rust
use crate::*;
|
|
|
|
impl Handle<Tui> for TransportTui {
|
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
|
TransportCommand::execute_with_state(self, from)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
pub enum TransportCommand {
|
|
Focus(FocusCommand),
|
|
Clock(ClockCommand),
|
|
}
|
|
|
|
impl<T: TransportControl> Command<T> for TransportCommand {
|
|
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
|
use TransportCommand::{Focus, Clock};
|
|
use FocusCommand::{Next, Prev};
|
|
use ClockCommand::{SetBpm, SetQuant, SetSync};
|
|
Ok(match self {
|
|
Focus(cmd) => cmd.execute(state)?.map(Focus),
|
|
Clock(cmd) => cmd.execute(state)?.map(Clock),
|
|
//Clock(SetBpm(bpm)) => Some(Clock(SetBpm(state.bpm().set(bpm)))),
|
|
//Clock(SetQuant(quant)) => Some(Clock(SetQuant(state.quant().set(quant)))),
|
|
//Clock(SetSync(sync)) => Some(Clock(SetSync(state.sync().set(sync)))),
|
|
_ => return Ok(None)
|
|
})
|
|
}
|
|
}
|
|
|
|
pub trait TransportControl: HasClock + FocusGrid + HasEnter {
|
|
fn transport_focused (&self) -> Option<TransportFocus>;
|
|
}
|
|
|
|
impl TransportControl for TransportTui {
|
|
fn transport_focused (&self) -> Option<TransportFocus> {
|
|
Some(self.focus.inner())
|
|
}
|
|
}
|
|
|
|
impl TransportControl for SequencerTui {
|
|
fn transport_focused (&self) -> Option<TransportFocus> {
|
|
match self.focus.inner() {
|
|
SequencerFocus::Transport(focus) => Some(focus),
|
|
_ => None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TransportControl for ArrangerTui {
|
|
fn transport_focused (&self) -> Option<TransportFocus> {
|
|
match self.focus.inner() {
|
|
ArrangerFocus::Transport(focus) => Some(focus),
|
|
_ => None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
|
|
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
|
|
to_transport_command(state, input)
|
|
.or_else(||to_focus_command(input).map(TransportCommand::Focus))
|
|
}
|
|
}
|
|
|
|
pub fn to_transport_command <T> (state: &T, input: &TuiInput) -> Option<TransportCommand>
|
|
where
|
|
T: TransportControl
|
|
{
|
|
use ClockCommand::{SetBpm, SetQuant, SetSync};
|
|
use TransportCommand::{Focus, Clock};
|
|
use KeyCode::{Enter, Left, Right, Char};
|
|
Some(match input.event() {
|
|
key!(Left) => Focus(FocusCommand::Prev),
|
|
key!(Right) => Focus(FocusCommand::Next),
|
|
key!(Char(' ')) => Clock(if state.clock().is_stopped() {
|
|
ClockCommand::Play(None)
|
|
} else {
|
|
ClockCommand::Pause(None)
|
|
}),
|
|
key!(Shift-Char(' ')) => Clock(if state.clock().is_stopped() {
|
|
ClockCommand::Play(Some(0))
|
|
} else {
|
|
ClockCommand::Pause(Some(0))
|
|
}),
|
|
_ => match state.transport_focused().unwrap() {
|
|
TransportFocus::Bpm => match input.event() {
|
|
key!(Char(',')) => Clock(SetBpm(state.clock().bpm().get() - 1.0)),
|
|
key!(Char('.')) => Clock(SetBpm(state.clock().bpm().get() + 1.0)),
|
|
key!(Char('<')) => Clock(SetBpm(state.clock().bpm().get() - 0.001)),
|
|
key!(Char('>')) => Clock(SetBpm(state.clock().bpm().get() + 0.001)),
|
|
_ => return None,
|
|
},
|
|
TransportFocus::Quant => match input.event() {
|
|
key!(Char(',')) => Clock(SetQuant(state.clock().quant.prev())),
|
|
key!(Char('.')) => Clock(SetQuant(state.clock().quant.next())),
|
|
key!(Char('<')) => Clock(SetQuant(state.clock().quant.prev())),
|
|
key!(Char('>')) => Clock(SetQuant(state.clock().quant.next())),
|
|
_ => return None,
|
|
},
|
|
TransportFocus::Sync => match input.event() {
|
|
key!(Char(',')) => Clock(SetSync(state.clock().sync.prev())),
|
|
key!(Char('.')) => Clock(SetSync(state.clock().sync.next())),
|
|
key!(Char('<')) => Clock(SetSync(state.clock().sync.prev())),
|
|
key!(Char('>')) => Clock(SetSync(state.clock().sync.next())),
|
|
_ => return None,
|
|
},
|
|
TransportFocus::Clock => match input.event() {
|
|
key!(Char(',')) => todo!("transport seek bar"),
|
|
key!(Char('.')) => todo!("transport seek bar"),
|
|
key!(Char('<')) => todo!("transport seek beat"),
|
|
key!(Char('>')) => todo!("transport seek beat"),
|
|
_ => return None,
|
|
},
|
|
TransportFocus::PlayPause => match input.event() {
|
|
key!(Enter) => Clock(
|
|
if state.clock().is_stopped() {
|
|
ClockCommand::Play(None)
|
|
} else {
|
|
ClockCommand::Pause(None)
|
|
}
|
|
),
|
|
key!(Shift-Enter) => Clock(
|
|
if state.clock().is_stopped() {
|
|
ClockCommand::Play(Some(0))
|
|
} else {
|
|
ClockCommand::Pause(Some(0))
|
|
}
|
|
),
|
|
_ => return None,
|
|
},
|
|
}
|
|
})
|
|
}
|