From ec6772bfd75aa2be226fe8763ab31a91b941cfc9 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 4 Dec 2021 19:48:28 -0500 Subject: add a bit of ui --- src/bin/ttyplay/display.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++-- src/bin/ttyplay/event.rs | 4 +++- src/bin/ttyplay/frames.rs | 4 ++++ src/bin/ttyplay/main.rs | 43 ++++++++++++++++++++++++++------- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/bin/ttyplay/display.rs b/src/bin/ttyplay/display.rs index 4868154..32226e1 100644 --- a/src/bin/ttyplay/display.rs +++ b/src/bin/ttyplay/display.rs @@ -1,10 +1,36 @@ use textmode::Textmode as _; -pub struct Display {} +pub struct Display { + current_frame: usize, + total_frames: usize, + done_loading: bool, + paused: bool, +} impl Display { pub fn new() -> Self { - Self {} + Self { + current_frame: 0, + total_frames: 0, + done_loading: false, + paused: false, + } + } + + pub fn current_frame(&mut self, idx: usize) { + self.current_frame = idx; + } + + pub fn total_frames(&mut self, n: usize) { + self.total_frames = n; + } + + pub fn done_loading(&mut self) { + self.done_loading = true; + } + + pub fn paused(&mut self, paused: bool) { + self.paused = paused; } pub async fn render( @@ -14,8 +40,38 @@ impl Display { ) -> anyhow::Result<()> { output.clear(); output.move_to(0, 0); + output.reset_attributes(); output.write(&screen.contents_formatted()); + let pos = output.screen().cursor_position(); + + output.move_to(0, 0); + output.reset_attributes(); + output.set_fgcolor(textmode::color::BLACK); + if self.done_loading { + output.set_bgcolor(textmode::color::CYAN); + } else { + output.set_bgcolor(textmode::color::RED); + } + output.write_str(&format!( + " {}/{} ", + self.current_frame + 1, + self.total_frames + )); + + if self.paused { + let size = output.screen().size(); + output.move_to(0, size.1 - 1); + output.reset_attributes(); + output.set_fgcolor(textmode::color::BLACK); + output.set_bgcolor(textmode::color::RED); + output.write_str("⏸") + } + + output.reset_attributes(); + output.move_to(pos.0, pos.1); + output.refresh().await?; + Ok(()) } } diff --git a/src/bin/ttyplay/event.rs b/src/bin/ttyplay/event.rs index 82a200e..1c653c9 100644 --- a/src/bin/ttyplay/event.rs +++ b/src/bin/ttyplay/event.rs @@ -1,6 +1,8 @@ pub enum Event { - Render(vt100::Screen), + Render((usize, vt100::Screen)), Key(textmode::Key), + FrameLoaded(Option), Pause, + Paused(bool), Quit, } diff --git a/src/bin/ttyplay/frames.rs b/src/bin/ttyplay/frames.rs index 231f84a..2f0b1a7 100644 --- a/src/bin/ttyplay/frames.rs +++ b/src/bin/ttyplay/frames.rs @@ -40,6 +40,10 @@ impl FrameData { self.frames.get(i) } + pub fn count(&self) -> usize { + self.frames.len() + } + pub async fn add_frame(&mut self, frame: Frame) { self.frames.push(frame); self.new_frame_w diff --git a/src/bin/ttyplay/main.rs b/src/bin/ttyplay/main.rs index 8446bd6..10e3d3e 100644 --- a/src/bin/ttyplay/main.rs +++ b/src/bin/ttyplay/main.rs @@ -18,6 +18,7 @@ enum TimerAction { } fn spawn_frame_reader_task( + event_w: async_std::channel::Sender, frames: async_std::sync::Arc>, fh: async_std::fs::File, ) { @@ -35,13 +36,17 @@ fn spawn_frame_reader_task( std::time::Duration::from_secs(0) }; parser.process(&frame.data); + let mut frames = frames.lock_arc().await; frames - .lock_arc() - .await .add_frame(frames::Frame::new(parser.screen().clone(), delay)) .await; + event_w + .send(event::Event::FrameLoaded(Some(frames.count()))) + .await + .unwrap(); } frames.lock_arc().await.done_reading().await; + event_w.send(event::Event::FrameLoaded(None)).await.unwrap(); }); } @@ -86,13 +91,14 @@ fn spawn_timer_task( let action = async { Res::TimerAction(timer_r.recv().await) }; match wait.race(action).await { Res::Wait(Some(screen)) => { - event_w.send(event::Event::Render(screen)).await.unwrap(); + event_w + .send(event::Event::Render((idx, screen))) + .await + .unwrap(); idx += 1; } Res::Wait(None) => { - if paused_time.is_none() { - paused_time = Some(std::time::Instant::now()); - } + event_w.send(event::Event::Pause).await.unwrap(); } Res::TimerAction(Ok(action)) => match action { TimerAction::Pause => { @@ -102,6 +108,10 @@ fn spawn_timer_task( } else { paused_time = Some(now); } + event_w + .send(event::Event::Paused(paused_time.is_some())) + .await + .unwrap(); } TimerAction::Quit => break, }, @@ -138,22 +148,37 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> { let (event_w, event_r) = async_std::channel::unbounded(); let (timer_w, timer_r) = async_std::channel::unbounded(); - spawn_frame_reader_task(frames.clone(), fh); + spawn_frame_reader_task(event_w.clone(), frames.clone(), fh); spawn_input_task(event_w.clone(), input); let timer_task = spawn_timer_task(event_w.clone(), frames.clone(), timer_r); - let display = display::Display::new(); + let mut display = display::Display::new(); + let mut current_screen = vt100::Parser::default().screen().clone(); loop { let event = event_r.recv().await?; match event { - event::Event::Render(screen) => { + event::Event::Render((idx, screen)) => { + current_screen = screen.clone(); + display.current_frame(idx); display.render(&screen, &mut output).await?; } event::Event::Key(key) => { input::handle_input(key, event_w.clone()).await? } + event::Event::FrameLoaded(n) => { + if let Some(n) = n { + display.total_frames(n); + } else { + display.done_loading(); + } + display.render(¤t_screen, &mut output).await?; + } event::Event::Pause => timer_w.send(TimerAction::Pause).await?, + event::Event::Paused(paused) => { + display.paused(paused); + display.render(¤t_screen, &mut output).await?; + } event::Event::Quit => { timer_w.send(TimerAction::Quit).await?; break; -- cgit v1.2.3-54-g00ecf