aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-04 22:10:54 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-04 22:24:05 -0500
commitc574a3b530aea38c14d8299cbe46d8ffab30d07b (patch)
treed1993545957fcad75697214ecfd59369c2e90570
parent2e2f730c80538e4a0577f6cc1563f29309bb715a (diff)
downloadttyrec-bin-c574a3b530aea38c14d8299cbe46d8ffab30d07b.tar.gz
ttyrec-bin-c574a3b530aea38c14d8299cbe46d8ffab30d07b.zip
filter unnecessary events
-rw-r--r--src/bin/ttyplay/event.rs156
-rw-r--r--src/bin/ttyplay/main.rs28
2 files changed, 172 insertions, 12 deletions
diff --git a/src/bin/ttyplay/event.rs b/src/bin/ttyplay/event.rs
index 55f4da1..618478c 100644
--- a/src/bin/ttyplay/event.rs
+++ b/src/bin/ttyplay/event.rs
@@ -11,3 +11,159 @@ pub enum Event {
ToggleUi,
Quit,
}
+
+enum MoveFrame {
+ First,
+ Last,
+ Next,
+ Previous,
+}
+
+pub struct Reader {
+ pending: async_std::sync::Mutex<Pending>,
+ cvar: async_std::sync::Condvar,
+}
+
+impl Reader {
+ pub fn new(
+ input: async_std::channel::Receiver<Event>,
+ ) -> async_std::sync::Arc<Self> {
+ let this = Self {
+ pending: async_std::sync::Mutex::new(Pending::new()),
+ cvar: async_std::sync::Condvar::new(),
+ };
+ let this = async_std::sync::Arc::new(this);
+ {
+ let this = this.clone();
+ async_std::task::spawn(async move {
+ while let Ok(event) = input.recv().await {
+ this.event(event).await;
+ }
+ this.event(Event::Quit).await;
+ });
+ }
+ this
+ }
+
+ pub async fn read(&self) -> Option<Event> {
+ let mut pending = self
+ .cvar
+ .wait_until(self.pending.lock().await, |pending| {
+ pending.has_event()
+ })
+ .await;
+ pending.get_event()
+ }
+
+ async fn event(&self, event: Event) {
+ let mut pending = self.pending.lock().await;
+ pending.event(event);
+ self.cvar.notify_one();
+ }
+}
+
+#[derive(Default)]
+struct Pending {
+ render: Option<(usize, vt100::Screen)>,
+ key: std::collections::VecDeque<textmode::Key>,
+ frame_loaded: Option<usize>,
+ done_loading: bool,
+ pause: bool,
+ paused: Option<bool>,
+ frame_controls: std::collections::VecDeque<MoveFrame>,
+ toggle_ui: bool,
+ quit: bool,
+}
+
+impl Pending {
+ fn new() -> Self {
+ Self::default()
+ }
+
+ fn event(&mut self, event: Event) {
+ match event {
+ Event::Render((idx, screen)) => {
+ self.render = Some((idx, screen));
+ }
+ Event::Key(key) => {
+ self.key.push_back(key);
+ }
+ Event::FrameLoaded(idx) => {
+ if let Some(idx) = idx {
+ self.frame_loaded = Some(idx);
+ } else {
+ self.done_loading = true;
+ }
+ }
+ Event::Pause => {
+ self.pause = !self.pause;
+ }
+ Event::Paused(paused) => {
+ self.paused = Some(paused);
+ }
+ Event::FirstFrame => {
+ self.frame_controls.push_back(MoveFrame::First);
+ }
+ Event::LastFrame => {
+ self.frame_controls.push_back(MoveFrame::Last);
+ }
+ Event::NextFrame => {
+ self.frame_controls.push_back(MoveFrame::Next);
+ }
+ Event::PreviousFrame => {
+ self.frame_controls.push_back(MoveFrame::Previous);
+ }
+ Event::ToggleUi => {
+ self.toggle_ui = !self.toggle_ui;
+ }
+ Event::Quit => {
+ self.quit = true;
+ }
+ }
+ }
+
+ fn has_event(&self) -> bool {
+ self.render.is_some()
+ || !self.key.is_empty()
+ || self.frame_loaded.is_some()
+ || self.done_loading
+ || self.pause
+ || self.paused.is_some()
+ || !self.frame_controls.is_empty()
+ || self.toggle_ui
+ || self.quit
+ }
+
+ fn get_event(&mut self) -> Option<Event> {
+ if self.quit {
+ self.quit = false;
+ Some(Event::Quit)
+ } else if let Some(key) = self.key.pop_front() {
+ Some(Event::Key(key))
+ } else if self.pause {
+ self.pause = false;
+ Some(Event::Pause)
+ } else if let Some(dir) = self.frame_controls.pop_front() {
+ match dir {
+ MoveFrame::First => Some(Event::FirstFrame),
+ MoveFrame::Last => Some(Event::LastFrame),
+ MoveFrame::Next => Some(Event::NextFrame),
+ MoveFrame::Previous => Some(Event::PreviousFrame),
+ }
+ } else if self.toggle_ui {
+ self.toggle_ui = false;
+ Some(Event::ToggleUi)
+ } else if let Some(paused) = self.paused.take() {
+ Some(Event::Paused(paused))
+ } else if let Some(frame) = self.frame_loaded.take() {
+ Some(Event::FrameLoaded(Some(frame)))
+ } else if self.done_loading {
+ self.done_loading = false;
+ Some(Event::FrameLoaded(None))
+ } else if let Some((idx, screen)) = self.render.take() {
+ Some(Event::Render((idx, screen)))
+ } else {
+ None
+ }
+ }
+}
diff --git a/src/bin/ttyplay/main.rs b/src/bin/ttyplay/main.rs
index 01eecbc..a51435c 100644
--- a/src/bin/ttyplay/main.rs
+++ b/src/bin/ttyplay/main.rs
@@ -1,6 +1,7 @@
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![allow(clippy::missing_const_for_fn)]
+#![allow(clippy::struct_excessive_bools)]
use async_std::prelude::FutureExt as _;
@@ -170,18 +171,19 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
let mut display = display::Display::new();
let mut current_screen = vt100::Parser::default().screen().clone();
+ let events = event::Reader::new(event_r);
loop {
- let event = event_r.recv().await?;
+ let event = events.read().await;
match event {
- event::Event::Render((idx, screen)) => {
+ Some(event::Event::Render((idx, screen))) => {
current_screen = screen.clone();
display.current_frame(idx);
display.render(&screen, &mut output).await?;
}
- event::Event::Key(key) => {
+ Some(event::Event::Key(key)) => {
input::handle(key, event_w.clone()).await?;
}
- event::Event::FrameLoaded(n) => {
+ Some(event::Event::FrameLoaded(n)) => {
if let Some(n) = n {
display.total_frames(n);
} else {
@@ -189,40 +191,42 @@ async fn async_main(opt: Opt) -> anyhow::Result<()> {
}
display.render(&current_screen, &mut output).await?;
}
- event::Event::Pause => timer_w.send(TimerAction::Pause).await?,
- event::Event::Paused(paused) => {
+ Some(event::Event::Pause) => {
+ timer_w.send(TimerAction::Pause).await?;
+ }
+ Some(event::Event::Paused(paused)) => {
display.paused(paused);
display.render(&current_screen, &mut output).await?;
}
- event::Event::FirstFrame => {
+ Some(event::Event::FirstFrame) => {
timer_w.send(TimerAction::GotoFrame(0)).await?;
}
- event::Event::LastFrame => {
+ Some(event::Event::LastFrame) => {
timer_w
.send(TimerAction::GotoFrame(
display.get_total_frames() - 1,
))
.await?;
}
- event::Event::NextFrame => {
+ Some(event::Event::NextFrame) => {
timer_w
.send(TimerAction::GotoFrame(
display.get_current_frame() + 1,
))
.await?;
}
- event::Event::PreviousFrame => {
+ Some(event::Event::PreviousFrame) => {
timer_w
.send(TimerAction::GotoFrame(
display.get_current_frame() - 1,
))
.await?;
}
- event::Event::ToggleUi => {
+ Some(event::Event::ToggleUi) => {
display.toggle_ui();
display.render(&current_screen, &mut output).await?;
}
- event::Event::Quit => {
+ Some(event::Event::Quit) | None => {
timer_w.send(TimerAction::Quit).await?;
break;
}