shithub: cuefs

Download patch

ref: 448e84898530e6f597db845c72ea66e372374558
parent: 5bcb2fe1d68844ca15df83fb205b94fb3873e227
author: Tevo <estevan.cps@gmail.com>
date: Tue Dec 22 22:30:33 EST 2020

Use a decoder instance per Fid

--- a/cue.y
+++ b/cue.y
@@ -6,12 +6,7 @@
 
 Cuesheet *cursheet;
 
-/*
- * FIXME find a way to "fix" the grammar so that it
- * doesn't do right-hand recursion (and overflow the
- * stack) instead of just growing it and pretending
- * it's not a problem
- */
+/* maybe it doesn't matter */
 #define YYMAXDEPTH 8192
 %}
 
--- a/fs.c
+++ b/fs.c
@@ -12,6 +12,12 @@
 	int outfmt;
 } Fsprops;
 
+typedef struct
+{
+	int fd, pid;
+	vlong curoff;
+} Decoder;
+
 void pcmserve(Entry*, Req*);
 
 void (*servefmt[])(Entry*, Req*) =
@@ -29,9 +35,10 @@
 	[WAVE]	= "audio/wavdec"
 };
 
-int
-pipedec(AFile *f, double sec)
+Decoder*
+pipedec(AFile *f, double sec, vlong off)
 {
+	Decoder *ret;
 	int fd[2], afd;
 	char *dec;
 
@@ -42,7 +49,11 @@
 	if(pipe(fd) < 0)
 		sysfatal("pipedec: can't decode: pipe: %r");
 
-	switch(rfork(RFPROC|RFFDG|RFREND|RFNOTEG))
+	ret = emalloc(sizeof(*ret));
+	ret->fd = fd[0];
+	ret->curoff = off;
+
+	switch(ret->pid = rfork(RFPROC|RFFDG|RFREND|RFNOTEG))
 	{
 	case 0:
 		if((afd = open(f->name, OREAD)) < 0)
@@ -72,21 +83,56 @@
 		sysfatal("pipedec: can't decode: rfork: %r");
 	}
 	close(fd[1]);
-	return fd[0];
+	return ret;
 }
 
 void
+closedec(Decoder *dec)
+{
+	char *path;
+	int fd;
+
+	if(dec == nil)
+		return;
+
+	close(dec->fd);
+
+	if((path = smprint("/proc/%d/notepg", dec->pid)) == nil)
+		sysfatal("smprint: %r");
+	if((fd = open(path, OWRITE)) < 0)
+		sysfatal("open: %r");
+	write(fd, "kill", strlen("kill"));
+	close(fd);
+
+	free(dec);
+}
+
+long
+readdec(Decoder *dec, void *buf, long count)
+{
+	long ret;
+
+	ret = read(dec->fd, buf, count);
+	dec->curoff += ret;
+
+	return ret;
+}
+
+void
 pcmserve(Entry *e, Req *r)
 {
+	Decoder *dec;
 	double sec;
-	int dec;
 
-	sec  = t2sec(e->starts[0]);
-	sec += of2sec(44100, 16, 2, r->ifcall.offset);
+	sec = t2sec(e->starts[0]) + of2sec(44100, 16, 2, r->ifcall.offset);
 
-	dec = pipedec(e->file, sec);
-	r->ofcall.count = read(dec, r->ofcall.data, r->ifcall.count);
-	close(dec);
+	if((dec = r->fid->aux) == nil || dec->curoff != r->ifcall.offset)
+	{
+		closedec(dec);
+		dec = r->fid->aux = pipedec(e->file, sec, r->ifcall.offset);
+	}
+
+	r->ofcall.count = readdec(dec, r->ofcall.data, r->ifcall.count);
 	respond(r, nil);
 }
 
@@ -97,6 +143,13 @@
 }
 
 void
+fsclose(Fid *fid)
+{
+	if(fid->aux != nil)
+		closedec(fid->aux);
+}
+
+void
 fsread(Req *r)
 {
 	void (*func)(Entry*, Req*);
@@ -125,10 +178,11 @@
 
 Srv fs =
 {
-	.open	= fsopen,
-	.read	= fsread,
+	.open		= fsopen,
+	.read		= fsread,
+	.destroyfid	= fsclose,
 
-	.end	= fsend
+	.end		= fsend
 };
 
 void
@@ -147,6 +201,7 @@
 	for(Entry *e = sheet->entries; e != nil; e = e->next)
 	{
 		debug("%d: %d\n",  e->index, e->starts[0].frames);
+		/* TODO make the format customizable */
 		s = smprint("%02d - %s.%s", e->index, e->title, formatext(p->outfmt));
 		strreplace(s, '/', '-');
 		createfile(fs.tree->root, s, nil, 0444, e);