shithub: treason

ref: febd271a231c83b67d94e6cb2b9942edfe37e363
dir: /stream_sub.c/

View raw version
#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,
};