diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-12-04 03:15:50 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-12-04 03:15:50 -0500 |
commit | 9a4caa186dd38bb2fd0e84c87fadef41050f3ad8 (patch) | |
tree | 5cfded3d8721a29b34ca411c44b4c54b583a7eeb | |
parent | 46d1b6266062fa85267532613d181c51ea884e01 (diff) | |
download | ttyrec-bin-9a4caa186dd38bb2fd0e84c87fadef41050f3ad8.tar.gz ttyrec-bin-9a4caa186dd38bb2fd0e84c87fadef41050f3ad8.zip |
parse the frames into terminal screens and draw those
-rw-r--r-- | Cargo.lock | 13 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/bin/ttyplay/main.rs | 61 |
3 files changed, 68 insertions, 7 deletions
@@ -747,7 +747,7 @@ dependencies = [ "nix", "terminal_size", "thiserror", - "vt100", + "vt100 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -802,6 +802,7 @@ dependencies = [ "terminal_size", "textmode", "ttyrec", + "vt100 0.13.0", ] [[package]] @@ -853,6 +854,16 @@ checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "vt100" version = "0.13.0" +dependencies = [ + "itoa", + "log", + "unicode-width", + "vte", +] + +[[package]] +name = "vt100" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831a634b9ec18a269b230e687b9dbfe240e49808198dc84b7ed4bdcfe6f85910" dependencies = [ @@ -17,3 +17,4 @@ structopt = { version = "0.3.25", features = ["paw", "wrap_help"] } terminal_size = "0.1.17" textmode = { version = "0.2.0", features = ["async"] } ttyrec = { path = "../ttyrec", version = "0.2.0", features = ["async"] } +vt100 = { path = "../vt100-rust", version = "0.13.0" } diff --git a/src/bin/ttyplay/main.rs b/src/bin/ttyplay/main.rs index f30cda4..296fdc0 100644 --- a/src/bin/ttyplay/main.rs +++ b/src/bin/ttyplay/main.rs @@ -7,25 +7,74 @@ struct Opt { file: std::ffi::OsString, } +#[derive(Debug, Clone)] +struct Frame { + screen: vt100::Screen, + delay: std::time::Duration, +} + async fn async_main(opt: Opt) -> anyhow::Result<()> { let Opt { file } = opt; let fh = async_std::fs::File::open(file).await?; let mut reader = ttyrec::Reader::new(fh); + let size = terminal_size::terminal_size().map_or( + (24, 80), + |(terminal_size::Width(w), terminal_size::Height(h))| (h, w), + ); let mut input = textmode::Input::new().await?; let mut output = textmode::Output::new().await?; let _input_guard = input.take_raw_guard(); let _output_guard = output.take_screen_guard(); - let mut last_frame_time = None; - while let Ok(frame) = reader.read_frame().await { - if let Some(time) = last_frame_time { - async_std::task::sleep(frame.time - time).await; + let frames = + async_std::sync::Arc::new(async_std::sync::Mutex::new(vec![])); + let (frame_count_w, frame_count_r) = async_std::channel::unbounded(); + + { + let frames = frames.clone(); + async_std::task::spawn(async move { + let mut parser = vt100::Parser::new(size.0, size.1, 0); + while let Ok(frame) = reader.read_frame().await { + let delay = if let Some(time) = reader.offset() { + frame.time - time + } else { + std::time::Duration::from_secs(0) + }; + parser.process(&frame.data); + let mut frames = frames.lock_arc().await; + frames.push(Frame { + screen: parser.screen().clone(), + delay, + }); + frame_count_w.send(Some(frames.len())).await.unwrap(); + } + frame_count_w.send(None).await.unwrap(); + }); + } + + let start_time = std::time::Instant::now(); + let mut idx = 0; + let mut prev_frame: Option<Frame> = None; + loop { + frame_count_r.recv().await?; + let frame = if let Some(frame) = frames.lock_arc().await.get(idx) { + frame.clone() + } else { + break; + }; + if let Some(prev_frame) = prev_frame { + let dur = (start_time + frame.delay) + .saturating_duration_since(std::time::Instant::now()); + async_std::task::sleep(dur).await; + output.write(&frame.screen.contents_diff(&prev_frame.screen)); + } else { + output.write(&frame.screen.contents_formatted()); } - output.write(&frame.data); output.refresh().await?; - last_frame_time = Some(frame.time); + idx += 1; + prev_frame = Some(frame); } Ok(()) |