Provided by: libterm-ttyrec-plus-perl_0.09-1_all bug

NAME

       Term::TtyRec::Plus - read a ttyrec

SYNOPSIS

       "Term::TtyRec::Plus" is a module that lets you read ttyrec files. The related module,
       Term::TtyRec is designed more for simple interactions. "Term::TtyRec::Plus" gives you more
       information and, using a callback, lets you munge the data block and timestamp. It will do
       all the subtle work of making sure timing is kept consistent, and of rebuilding each frame
       header.

           use Term::TtyRec::Plus;
           # complete (but simple) ttyrec playback script

           foreach my $file (@ARGV) {
             my $ttyrec = Term::TtyRec::Plus->new(infile => $file, time_threshold => 10);
             while (my $frame_ref = $ttyrec->next_frame()) {
               select undef, undef, undef, $frame_ref->{diff};
               print $frame_ref->{data};
             }
           }

CONSTRUCTOR AND STARTUP

   new()
       Creates and returns a new "Term::TtyRec::Plus" object.

           my $ttyrec = Term::TtyRec::Plus->new();

       Parameters

       Here are the parameters that "Term::TtyRec::Plus->new()" recognizes.

       infile
           The input filename. A value of "-", which is the default, or "undef", means "STDIN".

       filehandle
           The input filehandle. By default this is "undef"; if you have already opened the
           ttyrec then you can pass its filehandle to the constructor. If both filehandle and
           infile are defined, filehandle is used.

       bzip2
           Perform bzip2 decompression. By default this is "undef", which signals that bzip2
           decompression should occur if and only if the filename is available and it ends in
           ".bz2". Otherwise, you can force or forbid decompression by setting bzip2 to a true or
           false value, respectively. After the call to new, this field will be set to either 1
           if decompression is enabled or 0 if it is not.

       time_threshold
           The maximum difference between two frames, in seconds. If "undef", which is the
           default, there is no enforced maximum. The second most common value would be 10, which
           some ttyrec utilities (such as timettyrec) use.

       frame_filter
           A callback, run for each frame before returning the frame to the user of
           "Term::TtyRec::Plus". This callback receives three arguments: the frame text, the
           timestamp, and the timestamp of the previous frame. All three arguments are passed as
           scalar references. The previous frame's timestamp is "undef" for the first frame. The
           return value is not currently looked at. If you modify the timestamp, the module will
           make sure that change is noted and respected in further frame timestamps.
           Modifications to the previous frame's timestamp are currently ignored.

               sub halve_frame_time_and_stumblify {
                   my ($data_ref, $time_ref, $prev_ref) = @_;
                   $$time_ref = $$prev_ref + ($$time_ref - $$prev_ref) / 2
                       if defined $$prev_ref;
                   $$data_ref =~ s/Eidolos/Stumbly/g;
               }

       State

       In addition to passing arguments, you can modify "Term::TtyRec::Plus"'s initial state, if
       you want to. This could be useful if you are chaining multiple ttyrecs together; you could
       pass a different initial frame. Support for such chaining might be added in a future
       version.

       frame
           The initial frame number. Default 0.

       prev_timestamp
           The previous frame's timestamp. Default "undef".

       accum_diff
           The accumulated difference of all frames seen so far; see the section on
           "diffed_timestamp" in "next_frame()"'s return value. Default 0.

       relative_time
           The time passed since the first frame. Default 0.

METHODS

   next_frame()
       "next_frame()" reads and processes the next frame in the ttyrec. It accepts no arguments.
       On EOF, it will return "undef". On malformed ttyrec input, it will die. If it cannot
       reconstruct the header of a frame (which might happen if the callback sets the timestamp
       to -1, for example), it will die. Otherwise, a hash reference is returned with the
       following fields set.

       data
           The frame data, filtered through the callback. The original data block is not made
           available.

       orig_timestamp
           The frame timestamp, straight out of the file.

       diffed_timestamp
           The frame timestamp, with the accumulated difference of all of the previous frames
           applied to it. This is so consistent results are given. For example, if your callback
           adds three seconds to frame 5's timestamp, then frame 6's diffed timestamp will take
           into account those three seconds, so frame 6 happens three seconds later as well. So
           the net effect is frame 5 is extended by three seconds, and no other frames' relatives
           times are affected.

       timestamp
           The diffed timestamp, filtered through the callback.

       prev_timestamp
           The previous frame's timestamp (after diffing and filtering; the originals are not
           made available).

       diff
           The difference between the current frame's timestamp and the previous frame's
           timestamp. Yes, it is equivalent to "timestamp - prev_timestamp", but it is provided
           for convenience. On the first frame it will be 0 (not "undef").

       orig_header
           The 12-byte frame header, straight from the file.

       header
           The 12-byte frame header, reconstructed from "data" and "timestamp" (so, after
           filtering, etc.).

       frame
           The frame number, using 1-based indexing.

       relative_time
           The time between the first frame's timestamp and the current frame's timestamp.

   grep()
       Returns the next frame that meets the specified criteria. "grep()" accepts arguments that
       are subroutines, regex, or strings; anything else is a fatal error. If you pass multiple
       arguments to "grep()", each one must be true. The subroutines receive the frame reference
       that is returned by "next_frame()". You can modify the frame, but do so cautiously.

         my $next_jump_frame_ref = $t->grep("Where do you want to jump?", sub { $_[0]{data} !~ /Message History/});

   rewind()
       Rewinds the ttyrec to the first frame and resets state variables to their initial values.
       Note that if "filehandle" is not seekable (such as STDIN on some systems, or if bzip2
       decompression is used), "rewind()" will die.

   infile()
       Returns the infile passed to the constructor. If a filehandle was passed, this will be
       "undef".

   filehandle()
       Returns the filehandle passed to the constructor, or if "infile" was used, a handle to
       "infile".

   bzip2()
       Returns 1 if bzip2 decompression has taken place, 0 if it has not.

   time_threshold()
       Returns the time threshold passed to the constructor. By default it is "undef".

   frame_filter()
       Returns the frame filter callback passed to the constructor. By default it is "sub { @_
       }".

   frame()
       Returns the frame number of the most recently returned frame.

   prev_timestamp()
       Returns the timestamp of the most recently returned frame.

   relative_time()
       Returns the time so far since the first frame.

   accum_diff()
       Returns the total time difference between timestamps and filtered timestamps. "accum_diff"
       is added to each frame's timestamp before they are passed to the "frame_filter" callback.

AUTHOR

       Shawn M Moore, "sartak@gmail.com"

CAVEATS

       •   Ttyrecs are frame-based. If you are trying to modify a string that is broken across
           multiple frames, it will not work. Say you have a ttyrec that prints "foo" in frame
           one and "bar" in frame two, both with the same timestamp. In a ttyrec player, it might
           look like these are one frame (with data "foobar"), but it's not. There is no easy,
           complete way to add arbitrary substitutions; you would have to write (or reuse) a
           terminal emulator.

       •   If you modify the data block, weird things could happen. This is especially true of
           escape-code-littered ttyrecs (such as those of NetHack). For best results, pretend the
           data block is an executable file; changes are OK as long as you do not change the
           length of the file. It really depends on the ttyrec though.

       •   If you modify the timestamp of a frame so that it is not in sequence with other
           frames, the behavior is undefined (it is up to the client program).
           "Term::TtyRec::Plus" will not reorder the frames for you.

       •   bzip2 support is transparent, mostly. Unfortunately IO::Uncompress::Bunzip2 is rather
           slow. I took a lengthy (~4 hours), bzipped ttyrec and ran a simple script on it,
           depending on the built-in bzip2 decompression. This took nearly four minutes. Using
           bunzip2 then the same script took about four seconds. So when you can, do explicit
           bzip2 decompression. Or better yet, help out the guys working on
           IO::Uncompress::Bunzip2. :)

COPYRIGHT & LICENSE

       Copyright 2006-2009 Shawn M Moore, all rights reserved.

       This program is free software; you can redistribute it and/or modify it under the same
       terms as Perl itself.