use crate::core::*; use crate::layout::*; pub struct Transport<'a> { pub timebase: &'a Arc, pub playing: TransportState, pub record: bool, pub overdub: bool, pub monitor: bool, pub frame: usize, } impl<'a> Render for Transport<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Rect { x, y, width, .. } = area; draw_play_stop(buf, x + 1, y, &self.playing); draw_rec(buf, x + 12, y, self.record); draw_dub(buf, x + 19, y, self.overdub); draw_mon(buf, x + 26, y, self.monitor); draw_bpm(buf, x + 33, y, self.timebase.bpm() as usize); draw_timer(buf, x + width - 1, y, &self.timebase, self.frame); Ok(Rect { x, y, width, height: 1 }) } } pub fn draw_timer (buf: &mut Buffer, x: u16, y: u16, timebase: &Arc, frame: usize) { let ppq = timebase.ppq() as usize; let pulse = timebase.frames_pulses(frame as f64) as usize; let (beats, pulses) = (pulse / ppq, pulse % ppq); let (bars, beats) = (beats / 4, beats % 4); let usecs = timebase.frames_usecs(frame as f64) as usize; let (seconds, msecs) = (usecs / 1000000, usecs / 1000 % 1000); let (minutes, seconds) = (seconds / 60, seconds % 60); let timer = format!("{minutes}:{seconds:02}:{msecs:03} {}.{}.{pulses:02}", bars as usize + 1, beats as usize + 1 ); timer.blit(buf, x - timer.len() as u16, y, Some(Style::default().not_dim())); } pub fn draw_play_stop (buf: &mut Buffer, x: u16, y: u16, state: &TransportState) { let style = Style::default().gray(); match state { TransportState::Rolling => "▶ PLAYING", TransportState::Starting => "READY ...", TransportState::Stopped => "⏹ STOPPED", }.blit(buf, x, y, Some(match state { TransportState::Stopped => style.dim().bold(), TransportState::Starting => style.not_dim().bold(), TransportState::Rolling => style.not_dim().white().bold() })); } pub fn draw_rec (buf: &mut Buffer, x: u16, y: u16, on: bool) { "⏺ REC".blit(buf, x, y, Some(if on { Style::default().bold().red() } else { Style::default().bold().dim() })) } pub fn draw_dub (buf: &mut Buffer, x: u16, y: u16, on: bool) { "⏺ DUB".blit(buf, x, y, Some(if on { Style::default().bold().yellow() } else { Style::default().bold().dim() })) } pub fn draw_mon (buf: &mut Buffer, x: u16, y: u16, on: bool) { "⏺ MON".blit(buf, x, y, Some(if on { Style::default().bold().green() } else { Style::default().bold().dim() })) } pub fn draw_bpm (buf: &mut Buffer, x: u16, y: u16, bpm: usize) { let style = Style::default().not_dim(); "BPM" .blit(buf, x, y, Some(style)); format!("{}.{:03}", bpm as usize, bpm % 1) .blit(buf, x + 4, y, Some(style.bold())); "SYNC" .blit(buf, x + 13, y, Some(style)); "4/4" .blit(buf, x + 18, y, Some(style.bold())); "QUANT" .blit(buf, x + 23, y, Some(style)); "1/16" .blit(buf, x + 29, y, Some(style.bold())); }