File: timeline.c

package info (click to toggle)
termrec 0.19-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,148 kB
  • sloc: ansic: 8,430; makefile: 181; perl: 16; sh: 15
file content (215 lines) | stat: -rw-r--r-- 4,493 bytes parent folder | download | duplicates (4)
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "error.h"
#include "tty.h"

typedef struct {} *recorder;

struct ttyrec_frame
{
    struct timeval t;
    int len;
    char *data;
    tty snapshot;
    struct ttyrec_frame *next;
};
typedef struct ttyrec_frame *ttyrec_frame;

typedef struct ttyrec
{
    struct ttyrec_frame *tev_head, *tev_tail;
    tty tev_vt;
    int nchunk;
    struct timeval ndelay;
} *ttyrec;
#define _TTYREC_H_NO_TYPES
#include "ttyrec.h"
#include "export.h"

#define SNAPSHOT_CHUNK 65536

#define tr ((ttyrec)arg)
static void synch_init_wait(const struct timeval *ts, void *arg)
{
    tr->tev_head->t=*ts;
}

static const struct timeval maxd = {5,0};

static void synch_wait(const struct timeval *tv, void *arg)
{
    if (tv->tv_sec>=maxd.tv_sec || tv->tv_sec<0)
        tadd(tr->ndelay, maxd);
    else
        tadd(tr->ndelay, *tv);
}

static void synch_print(const char *buf, int len, void *arg)
{
    struct ttyrec_frame *nf;

    if (!(nf=malloc(sizeof(struct ttyrec_frame))))
        return;
    if (!(nf->data=malloc(len)))
    {
        free(nf);
        return;
    }
    nf->len=len;
    memcpy(nf->data, buf, len);
    nf->t=tr->tev_tail->t;
    tadd(nf->t, tr->ndelay);
    tr->ndelay.tv_sec=tr->ndelay.tv_usec=0;
    nf->snapshot=0;
    nf->next=0;
    tr->tev_tail->next=nf;
    tr->tev_tail=nf;
    tty_write(tr->tev_vt, buf, len);
    if ((tr->nchunk+=len)>=SNAPSHOT_CHUNK) // do a snapshot every 64KB of data
    {
        nf->snapshot=tty_copy(tr->tev_vt);
        tr->nchunk=0;
    }
}
#undef tr


export ttyrec ttyrec_init(tty vt)
{
    ttyrec tr = malloc(sizeof(struct ttyrec));
    if (!tr)
        return NULL;
    memset(tr, 0, sizeof(struct ttyrec));
    tr->tev_head = malloc(sizeof(struct ttyrec_frame));
    memset(tr->tev_head, 0, sizeof(struct ttyrec_frame));
    tr->tev_tail=tr->tev_head;
    tr->nchunk=SNAPSHOT_CHUNK;

    tr->tev_vt = vt? vt : tty_init(80, 25, 1);
    tr->tev_head->snapshot = tty_copy(tr->tev_vt);

    return tr;
}


export void ttyrec_free(ttyrec tr)
{
    struct ttyrec_frame *tev_tail, *tc;

    if (!tr)
        return;

    tev_tail=tr->tev_head;
    while (tev_tail)
    {
        tc=tev_tail;
        tev_tail=tev_tail->next;
        free(tc->data);
        if (tc->snapshot)
            tty_free(tc->snapshot);
        free(tc);
    }
    tty_free(tr->tev_vt);
    free(tr);
}


export ttyrec ttyrec_load(int fd, const char *format, const char *filename, tty vt)
{
    ttyrec tr;

    if (!(tr=ttyrec_init(vt)))
        return 0;
    if (!ttyrec_r_play(fd, format, filename, synch_init_wait, synch_wait, synch_print, tr))
    {
        ttyrec_free(tr);
        return 0;
    }
    return tr;
}


export struct ttyrec_frame* ttyrec_seek(const ttyrec tr, const struct timeval *t, tty *vt)
{
    struct ttyrec_frame *tfv, *tfs;

    if (!tr)
        return 0;

    tfv = tr->tev_head;
    tfs = 0;

    if (t)
        while (tfv->next && tcmp(tfv->next->t, *t)<=0)
        {
            tfv=tfv->next;
            if (tfv->snapshot)
                tfs=tfv;
        }
    else
        if (tfv->next)
            tfv=tfv->next;

    if (tfv->snapshot)
        tfs=tfv;

    if (vt)
    {
        tty_free(*vt);
        if (tfs)
            *vt=tty_copy(tfs->snapshot);
        else
        {
            tfs=tr->tev_head;
            *vt=tty_init(80, 25, 1);
        }
        if (!*vt)
            return 0;
        while (tfs!=tfv)
        {
            tfs = tfs->next;
            if (tfs->data)
                tty_write(*vt, tfs->data, tfs->len);
        };
    }

    return tfv;
}


export struct ttyrec_frame* ttyrec_next_frame(ttyrec tr, struct ttyrec_frame *tfv)
{
    if (!tfv)
        return 0;
    return tfv->next;
}


export void ttyrec_add_frame(ttyrec tr, const struct timeval *delay, const char *data, int len)
{
    if (delay)
        synch_wait(delay, tr);
    synch_print(data, len, tr);
}


export int ttyrec_save(ttyrec tr, int fd, const char *format, const char *filename,
                       const struct timeval *selstart, const struct timeval *selend)
{
    struct ttyrec_frame *fr;
    recorder rec;

    fr=ttyrec_seek(tr, selstart, 0);
    if (!(rec=ttyrec_w_open(fd, format, filename, &fr->t)))
        return 0;
    while (fr)
    {
        if (selend && tcmp(fr->t, *selend)>0)
            break;
        ttyrec_w_write(rec, &fr->t, fr->data, fr->len);
        fr=ttyrec_next_frame(tr, fr);
    }
    return ttyrec_w_close(rec);
}