1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
=head1 NAME
libttyrec - a library for handling ttyrec files
=head1 SYNOPSIS
B<#include E<lt>ttyrec.hE<gt>>
Link with I<-ltty>.
=head1 DESCRIPTION
=head2 Helper stream function:
=over
=item B<int open_stream(int >I<fd>B<, const char* >I<url>B<, int >I<mode>B<, const char **>I<error>B<);>
This function opens a stream designated by the I<url>. If the given url
ends in ".gz", ".xz", ".bz2" or ".zst"), the stream is assumed to be
compressed and gets passed through the appropriate [un]packer. If the I<fd>
is not -1, it is the descriptor you already opened; if it is -1, the file is
opened. The I<mode> can be:
=over
=item SM_READ
=item SM_WRITE
=item SM_REPREAD
=item SM_APPEND
=back
On error, -1 is returned. If you want the message, pass a non-null pointer I<error>, it will
be filled in.
=back
=head2 Format encoders:
=over
=item B<const char* ttyrec_w_find_format(const char *>I<format>B<, const char *>I<filename>B<, const char *>I<fallback>B<);>
This function searches for a format that would fit the I<filename> provided -- that is, abc.ttyrec.gz
returns "ttyrec". If no known extension is found, the function returns whatever you gave as
I<fallback>. You can force a I<format> yourself, in this case, it is only validated and if invalid, 0
is returned regardless of the other two arguments.
=item B<recorder ttyrec_w_open(int >I<fd>B<, const char *>I<format>B<, const char *>I<filename>B<, const struct timeval *>I<ts>B<);>
A recorder is opened, writing to the file I<fd>; if it's not given (=-1), the function calls B<open_stream()>.
Recording is done in the given I<format>, if not provided, the format is guessed based on the I<filename>.
If you provide a timestamp I<ts>, it becomes date of the recording.
=item B<int ttyrec_w_write(recorder >I<r>B<, const struct timeval *tm, const char *>I<data>B<, int >I<len>B<);>
A chunk of data of length I<len> is written to recorder I<r>, with timestamp I<tm>.
Returns 1 if some sort of write error happened.
=item B<int ttyrec_w_close(recorder >I<r>B<);>
All pending data is flushed, recorder closed and its memory freed.
Returns 1 if there's some kind of failure.
=item B<const char* ttyrec_w_get_format_name(int >I<i>B<);>
You can use this function to enumerate known write formats by calling it with I<i> being subsequent
numbers starting at 0. An invalid I<i> will return a null pointer.
=item B<const char* ttyrec_w_get_format_ext(const char *>I<format>B<);>
If the given write I<format> is associated with a file extension, it is returned.
=back
=head2 Format decoders:
=over
=item B<const char* ttyrec_r_find_format(const char *>I<format>B<, const char *>I<filename>B<, const char *>I<fallback>B<);>
See the _w_ function, except that read formats are searched instead.
=item B<const char* ttyrec_r_get_format_name(int >I<i>B<);>
ditto
=item B<const char* ttyrec_r_get_format_ext(const char *>I<format>B<);>
ditto
=item B<int ttyrec_r_play(int >I<fd>B<, const char *>I<format>B<, const char *>I<filename>B<, void (*>I<synch_init_wait>B<)(const struct timeval *ts, void *>I<arg>B<), void (*>I<synch_wait>B<)(const struct timeval *>I<delay>B<, void *>I<arg>B<), void (*>I<synch_print>B<)(const char *>I<data>B<, int >I<len>B<, void *>I<arg>B<), void *>I<arg>B<);>
This function decodes the file I<fd> (opening I<filename> if I<fd>=-1). If its contents contain
the date of the recording, you'll receive it through the callback I<synch_init_wait>. Between
frames, the delay is passed through I<synch_wait>. The actual frame data goes through
I<synch_print>. Note that in some formats, two or more consecutive delays or two consecutive
frames can happen one after another. If you provide an arbitrary I<arg>, it will be passed to
all callbacks.
The function doesn't return until the end of input data. Returns 1 on success, 0 on failure.
=back
=head2 The following functions deal with in-memory ttyrecs:
=over
=item B<ttyrec ttyrec_init(tty >I<vt>B<);>
An empty one is allocated. If a I<vt> is provided, it becomes the screen that the ttyrec is
internally played on; otherwise, a blank 80x25 one is allocated. The I<vt> is consumed.
=item B<ttyrec ttyrec_load(int >I<fd>B<, const char *>I<format>B<, const char *>I<filename>B<, tty >I<vt>B<);>
This function will load a ttyrec from the file designated with I<fd>. If it's not open yet
(I<fd>=-1), it will be opened with B<open_stream>. The ttyrec is played on the I<vt> you provide
-- or on a new 80x25 one.
=item B<void ttyrec_free(ttyrec >I<tr>B<);>
Destroys the in-memory ttyrec, freeing its memory.
=back
You can read the ttyrec's data while it's being read; all functions are thread-safe
with regard to reading. The frames are stored in structures like this:
typedef struct
{
struct timeval t;
int len;
char *data;
} *ttyrec_frame;
=over
=item B<ttyrec_frame ttyrec_seek(ttyrec >I<tr>B<, const struct timeval *>I<t>B<, tty *>I<vt>B<);>
Finds the frame that should be shown at time I<*t>, or the first frame if I<t> is null.
If I<vt> is not-null, it will receive a terminal containing the screen at that frame.
=item B<ttyrec_frame ttyrec_next_frame(ttyrec >I<tr>B<, ttyrec_frame >I<tfv>B<);>
Returns the next frame after frame I<tfv>, or null if I<tfv> was the last.
=item B<void ttyrec_add_frame(ttyrec >I<tr>B<, const struct timeval *>I<delay>B<, const char *>I<data>B<, int >I<len>B<);>
Creates a new frame and appends it to ttyrec I<tr>.
=item B<int ttyrec_save(ttyrec >I<tr>B<, int >I<fd>B<, const char *>I<format>B<, const char *>I<filename>B<, const struct timeval *>I<selstart>B<, const struct timeval *>I<selend>B<);>
Exports the ttyrec to a new file. If I<selstart> and/or I<selend> are given, they designate
the part that should be exported -- if not, the whole is.
=back
=head2 B<struct timeval> arithmetics:
A handful of macros for operating on timeval values:
=over
=item B<tadd(t, d)>
t+=d;
=item B<tsub(t, d)>
t-=d;
=item B<tmul1000(t, m)>
t*=m/1000;
=item B<tdiv1000(t, m)>
t/=m/1000;
=item B<tcmp(t1, t2)>
If t1E<lt>t2, -1. If t1E<gt>t2, +1. 0 otherwise.
=back
=head1 SEE ALSO
L<libtty(3)>
=cut
|