mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
transport -> clock
This commit is contained in:
parent
7f57465b3a
commit
7a4fa1692b
15 changed files with 37 additions and 36 deletions
149
src/transport.rs
149
src/transport.rs
|
|
@ -1,149 +0,0 @@
|
|||
use crate::*;
|
||||
use ClockCommand::{Play, Pause, SetBpm, SetQuant, SetSync};
|
||||
use FocusCommand::{Next, Prev};
|
||||
use KeyCode::{Enter, Left, Right, Char};
|
||||
|
||||
/// Transport clock app.
|
||||
pub struct TransportTui {
|
||||
pub jack: Arc<RwLock<JackConnection>>,
|
||||
pub clock: ClockModel,
|
||||
pub size: Measure<Tui>,
|
||||
pub cursor: (usize, usize),
|
||||
pub color: ItemPalette,
|
||||
}
|
||||
from_jack!(|jack|TransportTui Self {
|
||||
jack: jack.clone(),
|
||||
clock: ClockModel::from(jack),
|
||||
size: Measure::new(),
|
||||
cursor: (0, 0),
|
||||
color: ItemPalette::random(),
|
||||
});
|
||||
has_clock!(|self: TransportTui|&self.clock);
|
||||
audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope));
|
||||
handle!(<Tui>|self: TransportTui, from|TransportCommand::execute_with_state(self, from));
|
||||
render!(Tui: (self: TransportTui) => TransportView(&self.clock));
|
||||
|
||||
pub struct TransportView<'a>(pub &'a ClockModel);
|
||||
render!(Tui: (self: TransportView<'a>) => row!(
|
||||
BeatStats::new(self.0), " ",
|
||||
PlayPause(self.0.is_rolling()), " ",
|
||||
OutputStats::new(self.0),
|
||||
));
|
||||
|
||||
pub struct PlayPause(pub bool);
|
||||
render!(Tui: (self: PlayPause) => Tui::bg(
|
||||
if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
|
||||
Fixed::x(5, Tui::either(self.0,
|
||||
Tui::fg(Color::Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||
Tui::fg(Color::Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))));
|
||||
impl std::fmt::Debug for TransportTui {
|
||||
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||
f.debug_struct("TransportTui")
|
||||
.field("jack", &self.jack)
|
||||
.field("size", &self.size)
|
||||
.field("cursor", &self.cursor)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BeatStats { bpm: String, beat: String, time: String, }
|
||||
impl BeatStats {
|
||||
fn new (clock: &ClockModel) -> Self {
|
||||
let (beat, time) = clock.started.read().unwrap().as_ref().map(|started|{
|
||||
let current_usec = clock.global.usec.get() - started.usec.get();
|
||||
(
|
||||
clock.timebase.format_beats_1(clock.timebase.usecs_to_pulse(current_usec)),
|
||||
format!("{:.3}s", current_usec/1000000.)
|
||||
)
|
||||
}).unwrap_or_else(||("-.-.--".to_string(), "-.---s".to_string()));
|
||||
Self { bpm: format!("{:.3}", clock.timebase.bpm.get()), beat, time }
|
||||
}
|
||||
}
|
||||
render!(Tui: (self: BeatStats) => col!(
|
||||
Bsp::e(&self.bpm, " BPM"), Bsp::e("Beat ", &self.beat), Bsp::e("Time ", &self.time),
|
||||
));
|
||||
|
||||
pub struct OutputStats { sample_rate: String, buffer_size: String, latency: String, }
|
||||
impl OutputStats {
|
||||
fn new (clock: &ClockModel) -> Self {
|
||||
let rate = clock.timebase.sr.get();
|
||||
let chunk = clock.chunk.load(Relaxed);
|
||||
Self {
|
||||
sample_rate: format!("{:.1}Hz", rate),
|
||||
buffer_size: format!("{chunk}"),
|
||||
latency: format!("{}", chunk as f64 / rate * 1000.),
|
||||
}
|
||||
}
|
||||
}
|
||||
render!(Tui: (self: OutputStats) => col!(
|
||||
Bsp::e(format!("{}", self.sample_rate), " sample rate"),
|
||||
Bsp::e(format!("{}", self.buffer_size), " sample buffer"),
|
||||
Bsp::e(format!("{:.3}ms", self.latency), " latency"),
|
||||
));
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum TransportCommand {
|
||||
Clock(ClockCommand),
|
||||
}
|
||||
command!(|self:TransportCommand,state:TransportTui|match self {
|
||||
//Self::Focus(cmd) => cmd.execute(state)?.map(Self::Focus),
|
||||
Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock),
|
||||
_ => unreachable!(),
|
||||
});
|
||||
impl InputToCommand<Tui, TransportTui> for TransportCommand {
|
||||
fn input_to_command (state: &TransportTui, input: &TuiIn) -> Option<Self> {
|
||||
use TransportCommand::*;
|
||||
Some(match input.event() {
|
||||
key_pat!(Char(' ')) => Clock(if state.clock().is_stopped() {
|
||||
Play(None)
|
||||
} else {
|
||||
Pause(None)
|
||||
}),
|
||||
key_pat!(Shift-Char(' ')) => Clock(if state.clock().is_stopped() {
|
||||
Play(Some(0))
|
||||
} else {
|
||||
Pause(Some(0))
|
||||
}),
|
||||
_ => return None
|
||||
})
|
||||
}
|
||||
}
|
||||
fn to_bpm_command (input: &TuiIn, bpm: f64) -> Option<TransportCommand> {
|
||||
use TransportCommand::*;
|
||||
Some(match input.event() {
|
||||
key_pat!(Char(',')) => Clock(SetBpm(bpm - 1.0)),
|
||||
key_pat!(Char('.')) => Clock(SetBpm(bpm + 1.0)),
|
||||
key_pat!(Char('<')) => Clock(SetBpm(bpm - 0.001)),
|
||||
key_pat!(Char('>')) => Clock(SetBpm(bpm + 0.001)),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
fn to_quant_command (input: &TuiIn, quant: &Quantize) -> Option<TransportCommand> {
|
||||
use TransportCommand::*;
|
||||
Some(match input.event() {
|
||||
key_pat!(Char(',')) => Clock(SetQuant(quant.prev())),
|
||||
key_pat!(Char('.')) => Clock(SetQuant(quant.next())),
|
||||
key_pat!(Char('<')) => Clock(SetQuant(quant.prev())),
|
||||
key_pat!(Char('>')) => Clock(SetQuant(quant.next())),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
fn to_sync_command (input: &TuiIn, sync: &LaunchSync) -> Option<TransportCommand> {
|
||||
use TransportCommand::*;
|
||||
Some(match input.event() {
|
||||
key_pat!(Char(',')) => Clock(SetSync(sync.prev())),
|
||||
key_pat!(Char('.')) => Clock(SetSync(sync.next())),
|
||||
key_pat!(Char('<')) => Clock(SetSync(sync.prev())),
|
||||
key_pat!(Char('>')) => Clock(SetSync(sync.next())),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
fn to_seek_command (input: &TuiIn) -> Option<TransportCommand> {
|
||||
use TransportCommand::*;
|
||||
Some(match input.event() {
|
||||
key_pat!(Char(',')) => todo!("transport seek bar"),
|
||||
key_pat!(Char('.')) => todo!("transport seek bar"),
|
||||
key_pat!(Char('<')) => todo!("transport seek beat"),
|
||||
key_pat!(Char('>')) => todo!("transport seek beat"),
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue