pub struct FrameRecorder<B> { /* private fields */ }Expand description
Wraps a backend and records every frame it draws.
Taps Output::draw_layers – the same DrawCell diff stream
Terminal::present and every backend already
consume – and buffers each call’s changed cells as an owned CapturedFrame, timestamped
against when recording started. Works over a Backend,
or any subset of Output/Input/Cursor: only Output is tapped, everything else is
delegated unchanged, the same shape as
InputRecorder.
DrawCell borrows from the source grid, so capture converts to OwnedCell immediately on
each draw_layers call rather than deferring to export time, when the borrow would already be
gone.
§Known limitation
Buffers the whole session in memory (every frame captured, and every cell in it, lives in the
shared FrameRecorderHandle until write_cast exports and
take_frames drops it) rather than streaming to disk as
frames arrive. Fine for docs/demo-length captures – the ones this crate exists for – but not
a fit for an unbounded, long-running recording.
§Examples
use retroglyph_core::backend::{Headless, Output};
use retroglyph_core::color::Style;
use retroglyph_core::grid::Pos;
use retroglyph_core::tile::Tile;
use retroglyph_recorder::FrameRecorder;
let mut recorder = FrameRecorder::new(Headless::new(10, 3));
let tile = Tile::new('x', Style::default());
let cell = retroglyph_core::backend::DrawCell::new(Pos::new(0, 0), &tile);
recorder.draw_layers(std::iter::once(cell)).unwrap();
assert_eq!(recorder.frames().len(), 1);Implementations§
Source§impl<B: Output> FrameRecorder<B>
impl<B: Output> FrameRecorder<B>
Sourcepub fn new(inner: B) -> Self
pub fn new(inner: B) -> Self
Wraps inner. Recording starts immediately: the clock CapturedFrame::at is measured
against begins ticking here, not on the first draw_layers call.
Source§impl<B> FrameRecorder<B>
impl<B> FrameRecorder<B>
Sourcepub fn handle(&self) -> FrameRecorderHandle
pub fn handle(&self) -> FrameRecorderHandle
A cloneable FrameRecorderHandle onto this recorder’s shared state, for reading
captured frames after a driver (e.g. retroglyph_core::app::run_on) has taken this
recorder’s Terminal by value and won’t hand it back.
Sourcepub fn frames(&self) -> Vec<CapturedFrame>
pub fn frames(&self) -> Vec<CapturedFrame>
FrameRecorderHandle::frames on this recorder’s own handle.
Sourcepub fn take_frames(&mut self) -> Vec<CapturedFrame>
pub fn take_frames(&mut self) -> Vec<CapturedFrame>
FrameRecorderHandle::take_frames on this recorder’s own handle.
Trait Implementations§
Source§impl<B: Cursor> Cursor for FrameRecorder<B>
impl<B: Cursor> Cursor for FrameRecorder<B>
Source§fn set_cursor_visible(&mut self, visible: bool)
fn set_cursor_visible(&mut self, visible: bool)
Source§fn set_cursor_position(&mut self, position: Pos)
fn set_cursor_position(&mut self, position: Pos)
Source§fn set_cursor_style(&mut self, style: CursorStyle)
fn set_cursor_style(&mut self, style: CursorStyle)
Source§impl<B: Input> Input for FrameRecorder<B>
impl<B: Input> Input for FrameRecorder<B>
Source§impl<B: Output> Output for FrameRecorder<B>
impl<B: Output> Output for FrameRecorder<B>
Source§fn draw_layers<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
fn draw_layers<'a, I>(&mut self, content: I) -> Result<(), Self::Error>
Source§fn compositing(&self) -> Compositing
fn compositing(&self) -> Compositing
draw_layers. Read moreSource§fn flush(&mut self) -> Result<(), Self::Error>
fn flush(&mut self) -> Result<(), Self::Error>
Auto Trait Implementations§
impl<B> Freeze for FrameRecorder<B>where
B: Freeze,
impl<B> RefUnwindSafe for FrameRecorder<B>where
B: RefUnwindSafe,
impl<B> Send for FrameRecorder<B>where
B: Send,
impl<B> Sync for FrameRecorder<B>where
B: Sync,
impl<B> Unpin for FrameRecorder<B>where
B: Unpin,
impl<B> UnsafeUnpin for FrameRecorder<B>where
B: UnsafeUnpin,
impl<B> UnwindSafe for FrameRecorder<B>where
B: UnwindSafe,
Blanket Implementations§
impl<T> Backend for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.