shithub: aplay

Download patch

ref: 0d129e1d3b2c49cea3bfe06faa70e34888a262d8
parent: 3c4ce564149ff198790b2ceb41d353e24994b5ac
author: Benjamin Scher Purcell <ben@spew.club>
date: Tue Jan 12 16:48:31 EST 2016

get the right files

--- a/aplay.c
+++ b/aplay.c
@@ -1,4 +1,385 @@
-<html><body>
-Browser did not accept redirect.
-<a href="/aplay/aplay.c/">Click here</a>
-</body></html>
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+enum
+{
+	DEBUG = 0,
+	STACK = 8192
+};
+
+typedef struct Codecargs Codecargs;
+typedef struct Kbdargs Kbdargs;
+
+struct Codecargs
+{
+	Channel *pidchan;
+	char *codec;
+	int infd[2];
+	int outfd[2];
+};
+
+struct Kbdargs
+{
+	Channel *exit;
+	Codecargs *codecargs;
+};
+
+char *devaudio = "/dev/audio";
+Channel *waitchan;
+vlong maxoff, curoff;
+int codecpid, pause;
+Image *back;
+
+void resized(int new);
+void mousethread(void*);
+void kbdthread(void*);
+void inproc(void*);
+void outproc(void*);
+void timerproc(void*);
+void codecproc(void*);
+void usage(void);
+void shutdown(char*);
+void startstop(Codecargs*);
+void start(Codecargs*);
+void threadsfatal(void);
+
+void
+threadmain(int argc, char **argv)
+{
+	static Codecargs codecargs;
+	Kbdargs kbdargs;
+	int timer;
+
+	threadsetname("mainproc");
+	codecargs.codec = "/bin/audio/mp3dec";
+	ARGBEGIN{
+	case 'C':
+		codecargs.codec = ARGF();
+		if(codecargs.codec == nil)
+			usage();
+		break;
+	case 'a':
+		devaudio = ARGF();
+		if(devaudio == nil)
+			usage();
+		break;
+	default:
+		usage();
+		break;
+	}ARGEND;
+
+	if(argc > 1)
+		usage();
+	if(argc == 1){
+		close(0);
+		if(open(argv[0], OREAD) != 0)
+			threadsfatal();
+	}
+	close(1);
+	if(open(devaudio, OWRITE) != 1)
+		threadsfatal();
+	maxoff = seek(0, 0, 2);
+	codecargs.pidchan = chancreate(sizeof(ulong), 0);
+	waitchan = threadwaitchan();
+	initdraw(nil, nil, argv0);
+	back = allocimagemix(display, DPalebluegreen, DWhite);
+	threadcreate(mousethread, &codecargs, STACK);
+	kbdargs.exit = chancreate(sizeof(char*), 0);
+	kbdargs.codecargs = &codecargs;
+	threadcreate(kbdthread, &kbdargs, STACK);
+	timer = 500;
+	proccreate(timerproc, &timer, STACK);
+	pause = 1;
+	startstop(&codecargs);
+	resized(0);
+	shutdown(recvp(kbdargs.exit));
+}
+
+void
+kbdthread(void *a)
+{
+	Kbdargs *args;
+	Codecargs *cargs;
+	Channel *exit;
+	Keyboardctl *kc;
+	Rune r;
+
+	threadsetname("kbdthread");
+	args = a;
+	exit = args->exit;
+	cargs = args->codecargs;
+	kc = initkeyboard(nil);
+	for(;;){
+		recv(kc->c, &r);
+		switch(r){
+		default:
+			break;
+		case 'q':
+		case Kdel:
+			sendp(exit, nil);
+			break;
+		case ' ':
+			startstop(cargs);
+//			if(pause)
+//				curoff -= 16384;
+//			resized(0);
+			break;
+		}
+	}
+}
+
+void
+mousethread(void *a)
+{
+	Codecargs *cargs;
+	Mousectl *mc = initmouse(nil, screen);
+	vlong o;
+	enum
+	{
+		MOUSE,
+		RESIZE,
+		NALT
+	};
+	Alt alts[] = {
+		[MOUSE] {mc->c, &mc->Mouse, CHANRCV},
+		[RESIZE] {mc->resizec, nil, CHANRCV},
+		[NALT] {nil, nil, CHANEND}
+	};
+
+	threadsetname("mousethread");
+	cargs = a;
+	for(;;) switch(alt(alts)){
+	default:
+		break;
+	case MOUSE: 
+		if(mc->buttons == 0)
+			break;
+		do{
+			if(pause == 0)
+				startstop(cargs);
+			o = mc->xy.x - screen->r.min.x;
+			if(o < 0) o = 0LL;
+			o *= maxoff;
+			o /= Dx(screen->r);
+			o &= ~0xFLL;
+			curoff = o;
+			resized(0);
+			recv(mc->c, &mc->Mouse);
+		}while(mc->buttons != 0);
+		startstop(cargs);
+		break;
+	case RESIZE:
+		resized(1);
+		break;
+	}
+}
+
+void
+startstop(Codecargs *codecargs)
+{
+	static int inpid, outpid;
+	Channel *c;
+
+	if(pause == 0){
+		assert(codecpid != 0 && inpid != 0 && outpid != 0);
+		postnote(PNPROC, codecpid, "die yankee pig dog");
+		threadkill(inpid);
+		threadkill(outpid);
+		codecpid = inpid = outpid = 0;
+	}else{
+		assert(codecpid == 0 && inpid == 0 && outpid == 0);
+
+		if(pipe(codecargs->infd) < 0)
+			threadsfatal();
+		if(pipe(codecargs->outfd) < 0)
+			threadsfatal();
+
+/*
+ *		I'm leaking fd's here.
+ */
+if(DEBUG){
+		fprint(2, "inpipes: %d %d\n", codecargs->infd[0], codecargs->infd[1]);
+		fprint(2, "outpipes: %d %d\n", codecargs->outfd[0], codecargs->outfd[1]);
+}
+		proccreate(codecproc, codecargs, STACK);
+		codecpid = recvul(codecargs->pidchan);
+
+		c = chancreate(sizeof(int), 0);
+
+		inpid = proccreate(inproc, c, STACK);
+		send(c, &codecargs->infd[1]);
+
+		outpid = proccreate(outproc, c, STACK);
+		send(c, &codecargs->outfd[0]);
+
+		chanfree(c);
+
+		close(codecargs->infd[0]);
+		close(codecargs->infd[1]);
+		close(codecargs->outfd[0]);
+		close(codecargs->outfd[1]);
+	}
+	pause ^= 1;
+}
+
+void
+inproc(void *a)
+{
+	Channel *c;
+	int fd, i;
+	char buf[1024];
+	long n;
+
+	threadsetname("inproc");
+	rfork(RFFDG);
+	c = a;
+	recv(c, &fd);
+	dup(fd, 1);
+	close(fd);
+	for(i = 2; i < 20; i++)
+		close(i);
+	for(;;){
+		n = sizeof(buf);
+		if(curoff < 0)
+			curoff = 0;
+		if(curoff >= maxoff)
+			threadexits(0);
+		else if(n > maxoff - curoff){
+			n = maxoff - curoff;
+		}
+		n = pread(0, buf, n, curoff);
+		if(n <= 0)
+			threadexits(0);
+		if(write(1, buf, n) != n)
+			threadexits(0);
+		curoff += n;
+	}
+}
+
+void
+outproc(void *a)
+{
+	Channel *c;
+	int fd, i;
+	char buf[1024];
+	long n;
+
+	threadsetname("outproc");
+	rfork(RFFDG);
+	c = a;
+	recv(c, &fd);
+	dup(fd, 0);
+	close(fd);
+	for(i = 2; i < 20; i++)
+		close(i);
+	for(;;){
+		n = read(0, buf, sizeof(buf));
+		if(n <= 0)
+			threadexits(0);
+		if(write(1, buf, n) != n)
+			threadexits(0);
+	}
+}
+
+void
+codecproc(void *a)
+{
+	Codecargs *codecargs;
+	char *args[2];
+	int i;
+
+	threadsetname("codecproc");
+	rfork(RFFDG);
+	codecargs = a;
+
+	close(codecargs->infd[1]);
+	if(dup(codecargs->infd[0], 0) < 0){
+		threadsfatal();
+	}
+	close(codecargs->infd[0]);
+
+	close(codecargs->outfd[0]);
+	if(dup(codecargs->outfd[1], 1) < 0){
+		threadsfatal();
+	}
+	close(codecargs->outfd[1]);
+
+	for(i = 3; i < 20; i++)
+		close(i);
+	args[0] = codecargs->codec;
+	args[1] = nil;
+	procexec(codecargs->pidchan, codecargs->codec, args);
+	threadsfatal();
+}
+	
+void
+timerproc(void *a)
+{
+	int t;
+
+	threadsetname("timerproc");
+	t = *(int*)a;
+	for(;;){
+		sleep(t);
+		resized(0);
+	}
+}
+
+void
+resized(int new)
+{
+	Rectangle r1, r2;
+	char buf[32];
+	
+	if(new && getwindow(display, Refnone) < 0)
+		threadsfatal();
+	r1 = screen->r;
+	r2 = r1;
+	if(maxoff<= 0)
+		r1.max.x = r1.min.x + Dx(r2);
+	else
+		r1.max.x = r1.min.x + ((vlong)Dx(r2) * curoff) / maxoff;
+	r2.min.x = r1.max.x;
+	draw(screen, r1, back, nil, ZP);
+	draw(screen, r2, display->white, nil, ZP);
+	if(pause)
+		strcpy(buf, "pause");
+	else
+		strcpy(buf, "play");
+	r2.min = ZP;
+	r2.max = stringsize(display->defaultfont, buf);
+	r1 = rectsubpt(screen->r, screen->r.min);
+	r2 = rectaddpt(r2, subpt(divpt(r1.max, 2), divpt(r2.max, 2)));
+	r2 = rectaddpt(r2, screen->r.min);
+	r1 = insetrect(r2, -4);
+	draw(screen, r1, display->white, nil, ZP);
+	border(screen, insetrect(r1, 1), 2, display->black, ZP);
+	string(screen, r2.min, display->black, ZP, display->defaultfont, buf);
+	flushimage(display, 1);
+}
+
+void
+usage(void)
+{
+	fprint(2, "%s: aplay [-C codec] [-a audiodevice] [file]\n", argv0);
+	threadexitsall(0);
+}
+
+void
+shutdown(char *s)
+{
+	if(codecpid != 0)
+		postnote(PNPROC, codecpid, "die yankee pig dog");
+	threadexitsall(s);
+}
+
+void
+threadsfatal(void)
+{
+	fprint(2, "%r\n");
+	shutdown("error");
+}
--- a/mkfile
+++ b/mkfile
@@ -1,4 +1,7 @@
-<html><body>
-Browser did not accept redirect.
-<a href="/aplay/mkfile/">Click here</a>
-</body></html>
+</$objtype/mkfile
+
+TARG=aplay
+OFILES=$TARG.$O
+BIN=$home/bin/$objtype
+
+</sys/src/cmd/mkone