shithub: cuefs

ref: 3f6f039bf673f3ecaba6aa26abd3b89d363facfb
dir: cuefs/fs.c

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>

#include "cuefs.h"

typedef struct {
	Cuesheet* sheet;
	int outfmt;
} Fsprops;

void wavserve(Entry*, Req*);

void (*servefmt[])(Entry*, Req*) =
{
	[WAVE]	= wavserve,

	[UNKNOWN] = nil
};

char *decoder[] =
{
	[MP3]	= "audio/mp3dec",
	[FLAC]	= "audio/flacdec",
	[WAVE]	= "audio/wavedec"
};

int
pipedec(AFile *f, Timestamp t)
{
	int fd[2];
	double sec;
	char *dec;

	dec = decoder[f->actual];
	sec = t2sec(t);

	if(pipe(fd) < 0)
		sysfatal("pipedec: can't decode: pipe: %r");

	switch(rfork(RFFDG|RFPROC|RFMEM|RFNAMEG|RFNOTEG|RFREND))
	{
	case 0:
		close(0);
		close(1);
		dup(f->fd, 0);
		dup(fd[1], 1);
		close(f->fd);
		close(fd[1]);
		dec = strdup(dec);
		{
			char *argv[] = { dec };
			if(argv[2] == nil)
				sysfatal("pipedec: can't decode: smprint: %r");
			exec(dec, argv);
			dec = smprint("/bin/%s", dec);
			if(dec == nil)
				sysfatal("pipedec: can't decode: smprint: %r");
			exec(dec, argv);
			sysfatal("pipedec: can't decode: exec: %r");
		}
		break;
	case -1:
		sysfatal("pipedec: can't decode: rfork: %r");
	}
	return fd[0];
}

void
wavserve(Entry *e, Req *r)
{
	int dec;

	dec = pipedec(e->file, e->starts[0]);
	r->ofcall.count = readn(dec, r->ofcall.data, r->ifcall.count);
	respond(r, Estub);
}

void
fsopen(Req *r)
{
	respond(r, nil);
}

void
fsread(Req *r)
{
	void (*func)(Entry*, Req*);
	extern Srv fs;
	Fsprops *p;

	p = fs.aux;

	func = servefmt[p->outfmt];

	if(func != nil)
		func(r->fid->file->aux, r);
	else
		respond(r, Eunsupported);
}

void
fsend(Srv *s)
{
	Fsprops *p;

	p = s->aux;
	freesheet(p->sheet);
	free(p);
}

Srv fs =
{
	.open	= fsopen,
	.read	= fsread,

	.end	= fsend
};

void
cuefsinit(Cuesheet *sheet, char *mtpt)
{
	Fsprops *p;
	char *s;

	p = emalloc(sizeof(*p));
	p->sheet  = sheet;
	p->outfmt = WAVE;	/* STUB */

	fs.aux	= p;
	fs.tree	= alloctree(nil, nil, DMDIR | 0444, nil);

	for(AFile *f = sheet->files; f != nil; f = f->next)
		if(f->fd = open(f->name, OREAD) < 0)
			sysfatal("open: %r");

	for(Entry *e = sheet->entries; e != nil; e = e->next)
	{
		s = smprint("%02d - %s.%s", e->index, e->title, formatext(e->file));
		strreplace(s, '/', '-');
		createfile(fs.tree->root, s, nil, 0444, e);
		free(s);
	}

	postmountsrv(&fs, nil, mtpt, MREPL);
}