ref: c2f18c2da2fb32360843df37e0f168c5d558a254
dir: /stream_sub.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include "misc.h"
#include "stream.h"
extern Streamops subops;
int
subopenfd(int fd, Stream *s, int *failed)
{
if(fd < 0)
return -1;
s->type = Ssubtitles;
s->timebase.denum = 1;
s->timebase.num = 1;
s->b = Bfdopen(fd, OREAD);
memmove(&s->ops, &subops, sizeof(subops));
*failed = 0;
return 0;
}
Stream *
subopen(char *path, int *num, int *failed)
{
Stream *s;
if((s = calloc(1, sizeof(*s))) == nil){
*failed = 1;
return nil;
}
*num = 1;
if(subopenfd(open(path, OREAD), s, failed) != 0){
free(s);
s = nil;
}
return s;
}
static int
subts2ns(char *s, char **e, uvlong *ns)
{
if(strlen(s) < 9){
werrstr("timestamp too short");
goto err;
}
*ns = 0;
s--;
do{
s++;
*ns *= 60;
*ns += strtod(s, &s)*1000000000.0;
if(*s == ','){
*ns += strtod(s+1, &s)*1000000.0;
break;
}
}while(*s == ':');
*e = s;
return 0;
err:
werrstr("subts2ns: %r");
return -1;
}
static int
subread(Stream *s, Streamframe *f)
{
uvlong end;
char *x;
int i, n;
Brdline(s->b, '\n'); /* index */
if((x = Brdline(s->b, '\n')) == nil){ /* timestamp */
f->sz = 0;
return 0;
}
if((n = Blinelen(s->b)) < 1){
werrstr("unexpected empty line");
goto err;
}
x[n-1] = 0;
if(subts2ns(x, &x, &f->timestamp) != 0)
goto err;
while(isspace(*x))
x++;
if(strncmp(x, "-->", 3) != 0){
werrstr("no timestamp delimeter: %s", x);
goto err;
}
x += 3;
if(subts2ns(x, &x, &end) != 0)
goto err;
f->dt = end - f->timestamp;
for(i = 0; i < nelem(f->lines); i++){
if((x = Brdstr(s->b, '\n', 1)) == nil || *x == 0){
free(x);
break;
}
f->lines[i] = x;
}
f->nlines = i;
s->timestamp = f->timestamp;
return 0;
err:
werrstr("subread: %r");
return -1;
}
static void
subclose(Stream *s)
{
Bterm(s->b);
free(s->buf);
}
Streamops subops = {
.open = subopen,
.read = subread,
.close = subclose,
};