mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
81 lines
3.5 KiB
Rust
81 lines
3.5 KiB
Rust
use crate::{core::*,view::*,model::*};
|
|
|
|
render!(TransportToolbar |self, buf, area| {
|
|
let mut area = area;
|
|
area.height = 2;
|
|
let gray = Style::default().gray();
|
|
let not_dim = Style::default().not_dim();
|
|
let not_dim_bold = not_dim.bold();
|
|
let corners = Corners(Style::default().green().not_dim());
|
|
let ppq = self.ppq();
|
|
let bpm = self.bpm();
|
|
let pulse = self.pulse();
|
|
let usecs = self.usecs();
|
|
let Self { quant, sync, focused, entered, .. } = self;
|
|
fill_bg(buf, area, Nord::bg_lo(*focused, *entered));
|
|
Split::right([
|
|
|
|
// Play/Pause button
|
|
&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{
|
|
let style = Some(match self.playing {
|
|
Some(TransportState::Stopped) => gray.dim().bold(),
|
|
Some(TransportState::Starting) => gray.not_dim().bold(),
|
|
Some(TransportState::Rolling) => gray.not_dim().white().bold(),
|
|
_ => unreachable!(),
|
|
});
|
|
let label = match self.playing {
|
|
Some(TransportState::Rolling) => "▶ PLAYING",
|
|
Some(TransportState::Starting) => "READY ...",
|
|
Some(TransportState::Stopped) => "⏹ STOPPED",
|
|
_ => unreachable!(),
|
|
};
|
|
let mut result = label.blit(buf, x + 1, y, style)?;
|
|
result.width = result.width + 1;
|
|
Ok(result)
|
|
},
|
|
|
|
// Beats per minute
|
|
&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{
|
|
"BPM".blit(buf, x, y, Some(not_dim))?;
|
|
let width = format!("{}.{:03}", bpm, bpm % 1).blit(buf, x, y + 1, Some(not_dim_bold))?.width;
|
|
let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
|
|
if self.focused && self.entered && self.selected == TransportFocus::BPM {
|
|
corners.draw(buf, Rect { x: area.x - 1, ..area })?;
|
|
}
|
|
Ok(area)
|
|
},
|
|
|
|
// Quantization
|
|
&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{
|
|
"QUANT".blit(buf, x, y, Some(not_dim))?;
|
|
let width = ppq_to_name(*quant).blit(buf, x, y + 1, Some(not_dim_bold))?.width;
|
|
let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
|
|
if self.focused && self.entered && self.selected == TransportFocus::Quant {
|
|
corners.draw(buf, Rect { x: area.x - 1, ..area })?;
|
|
}
|
|
Ok(area)
|
|
},
|
|
|
|
// Clip launch sync
|
|
&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{
|
|
"SYNC".blit(buf, x, y, Some(not_dim))?;
|
|
let width = ppq_to_name(*sync).blit(buf, x, y + 1, Some(not_dim_bold))?.width;
|
|
let area = Rect { x, y, width: (width + 2).max(10), height: 2 };
|
|
if self.focused && self.entered && self.selected == TransportFocus::Sync {
|
|
corners.draw(buf, Rect { x: area.x - 1, ..area })?;
|
|
}
|
|
Ok(area)
|
|
},
|
|
|
|
// Clock
|
|
&|buf: &mut Buffer, Rect { x, y, width, .. }: Rect|{
|
|
let (beats, pulses) = (pulse / ppq, pulse % ppq);
|
|
let (bars, beats) = ((beats / 4) + 1, (beats % 4) + 1);
|
|
let (seconds, msecs) = (usecs / 1000000, usecs / 1000 % 1000);
|
|
let (minutes, seconds) = (seconds / 60, seconds % 60);
|
|
let timer = format!("{minutes}:{seconds:02}:{msecs:03} {bars}.{beats}.{pulses:02}");
|
|
timer.blit(buf, x + width - timer.len() as u16 - 1, y, Some(not_dim))
|
|
}
|
|
|
|
]).render(buf, area)
|
|
});
|