shithub: zuke

Download patch

ref: b1dc12bf2d11aa0ab8becc35d185cd586bb4b279
parent: 56d78c5f36adc9dd6dd6f5fa9063f795888e5de6
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Wed Feb 24 20:32:31 EST 2016

more stuff

--- a/zuke.c
+++ b/zuke.c
@@ -17,12 +17,17 @@
 	Cforward,
 	Cbackward,
 
-	Relbufsz = 32768,
+	Everror = 1,
+	Evready,
 
 	Bps = 44100*2*2, /* 44100KHz, stereo, u16 for a sample */
 	Seekbytes = Bps*10, /* 10 seconds */
 
 	Scrollwidth = 12,
+
+	Maxfailures = 16,
+
+	Relbufsz = Bps/5, /* 0.2 second */
 };
 
 static Meta *pl;
@@ -33,6 +38,8 @@
 struct Player
 {
 	Channel *ctl;
+	Channel *ev;
+	Channel *img;
 	int pcur;
 };
 
@@ -175,7 +182,7 @@
 	if(cover != nil){
 		r = screen->r;
 		r.min.x = r.max.x - cover->r.max.x - 8;
-		r.min.y = r.max.y - cover->r.max.y - 8;
+		r.min.y = r.max.y - cover->r.max.y - 8 - f->height - 4;
 		draw(screen, r, display->black, nil, ZP);
 		r.min.x += 4;
 		r.min.y += 4;
@@ -199,68 +206,54 @@
 }
 
 static void
-coverload(void *m_)
+coverload(void *player_)
 {
-	int p[2], p2[2], fd, pid, pid2;
+	int p[2], pid, fd;
 	char *prog;
 	Meta *m;
-	Ioproc *io;
+	Channel *ch;
+	Player *player;
+	Image *newcover;
 
 	threadsetname("cover");
-	m = m_;
-	freeimage(cover);
-	cover = nil;
-	redraw(screen, 1);
+	player = player_;
+	m = &pl[player->pcur];
+	pid = -1;
+	ch = player->img;
+
 	if(m->imagefmt == nil || m->imagereader != 0)
-		return;
+		goto done;
 	if(strcmp(m->imagefmt, "image/png") == 0)
-		prog = "/bin/png";
+		prog = "png -9t | resize -x128";
 	else if(strcmp(m->imagefmt, "image/jpeg") == 0)
-		prog = "/bin/jpg";
+		prog = "jpg -9t | resize -x128";
 	else
-		return;
+		goto done;
 
-	io = ioproc();
-	if((fd = ioopen(io, m->path, OREAD)) < 0){
-		closeioproc(io);
-		return;
-	}
-	if(seek(fd, m->imageoffset, 0) != m->imageoffset){
-		ioclose(io, fd);
-		closeioproc(io);
-		return;
-	}
-
 	pipe(p);
 	if((pid = rfork(RFPROC|RFFDG|RFREND|RFNOTEG)) == 0){
+		fd = open(m->path, OREAD);
+		seek(fd, m->imageoffset, 0);
 		dup(fd, 0); close(fd);
-		dup(p[0], 1); close(p[0]);
-		close(p[1]);
-		execl(prog, prog, "-9t", nil);
+		dup(p[1], 1); close(p[1]);
+		close(2);
+		execl("/bin/rc", "rc", "-c", prog, nil);
 		sysfatal("execl: %r");
 	}
-	ioclose(io, fd);
-	close(p[0]);
-
-	pipe(p2);
-	if((pid2 = rfork(RFPROC|RFFDG|RFREND|RFNOTEG)) == 0){
-		dup(p[1], 0); close(p[1]);
-		dup(p2[0], 1); close(p2[0]);
-		close(p2[1]);
-		execl("/bin/resize", "/bin/resize", "-x128", nil);
-		sysfatal("execl: %r");
-	}
 	close(p[1]);
-	close(p2[0]);
 
-	if(pid > 0 && pid2 > 0){
-		cover = readimage(display, p2[1], 0);
-		redraw(screen, 1);
+	if(pid > 0){
+		newcover = readimage(display, p[0], 0);
+		sendp(ch, newcover);
 	}
-	postnote(PNGROUP, pid, "interrupt");
-	postnote(PNGROUP, pid2, "interrupt");
-	close(p2[1]);
-	closeioproc(io);
+	close(p[0]);
+done:
+	if(pid < 0)
+		sendp(ch, nil);
+	chanfree(ch);
+	if(pid >= 0)
+		postnote(PNGROUP, pid, "interrupt");
+	threadexits(nil);
 }
 
 static void
@@ -269,54 +262,69 @@
 	char *buf;
 	Player *player;
 	Ioproc *io;
+	Image *thiscover;
 	ulong c;
-	int p[2], fd, pid, n, noinit;
+	int p[2], fd, pid, n, got, noinit, trycoverload;
 	u64int bytesfrom;
 
+	threadsetname("player");
 	player = player_;
 	noinit = 0;
 	bytesfrom = 0;
 	c = 0;
 	buf = nil;
+	trycoverload = 1;
+	io = nil;
+	pid = -1;
 
 restart:
+	if((fd = open(pl[player->pcur].path, OREAD)) < 0){
+		fprint(2, "%r\n");
+		nbsendul(player->ev, Everror);
+		goto freeplayer;
+	}
+
 	pipe(p);
 	if((pid = rfork(RFPROC|RFFDG|RFREND|RFNOTEG)) == 0){
-		dup(p[0], 1);
-		if((fd = open(pl[player->pcur].path, OREAD)) < 0){
-			fprint(2, "%r\n");
-			exits(nil);
-		}
-		dup(fd, 0);
-		close(fd);
-		close(p[0]);
+		dup(p[0], 1); close(p[0]);
+		dup(fd, 0); close(fd);
 		close(p[1]);
 		close(2);
-		execl("/bin/play", "/bin/play", "-o", "/fd/1", nil);
+		execl("/bin/rc", "rc", "-c", "play -o /fd/1", nil);
 		sysfatal("execl: %r");
 	}
 	if(pid < 0)
 		sysfatal("rfork: %r");
+	close(fd);
 	close(p[0]);
 
+	byteswritten = 0;
 	if(!noinit){
-		threadsetname("player");
-		c = recvul(player->ctl);
-		if(c != Cstart)
-			return;
+		nbsendul(player->ev, Evready);
 		buf = malloc(Relbufsz);
+		io = ioproc();
+		for(c = 0, got = 0; got < Relbufsz; got += n){
+			if((c = nbrecvul(player->ctl)) != 0)
+				break;
+			n = ioread(io, p[1], buf+got, Relbufsz-got);
+			if(n < 1)
+				break;
+		}
+		if(c == 0)
+			c = recvul(player->ctl);
+		if(c != Cstart)
+			goto freeplayer;
+		write(audio, buf, got);
+		byteswritten = got;
 		bytesfrom = 0;
 		c = 0;
 		noinit = 1;
 	}
 
-	byteswritten = 0;
 	pcurplaying = player->pcur;
 	if(c != Cbackward)
-		redraw(screen, 1);
-	/*proccreate(coverload, &pl[pcurplaying], 4096);*/
+		redraw(screen, 0);
 
-	io = ioproc();
 	while(1){
 		n = Relbufsz;
 		if(bytesfrom > byteswritten && n > bytesfrom-byteswritten)
@@ -325,6 +333,12 @@
 		if(n < 1)
 			break;
 
+		if(player->img != nil && nbrecv(player->img, &thiscover) > 0){
+			freeimage(cover);
+			cover = thiscover;
+			redraw(screen, 0);
+			player->img = nil;
+		}
 		c = nbrecvul(player->ctl);
 		if(c == Cstop)
 			goto stop;
@@ -342,22 +356,26 @@
 
 		c = 0;
 		if(bytesfrom <= byteswritten){
-			if(iowrite(io, audio, buf, n) != n){
+			if(write(audio, buf, n) != n){
 				fprint(2, "failed to write %d bytes: %r\n", n);
 				break;
 			}
+			if(trycoverload && byteswritten >= Bps){
+				freeimage(cover);
+				cover = nil;
+				player->img = chancreate(sizeof(Image*), 0);
+				proccreate(coverload, player, 4096);
+				trycoverload = 0;
+				redraw(screen, 0);
+			}
 		}
 		byteswritten += n;
-		if(bytesfrom == byteswritten || (bytesfrom < byteswritten && byteswritten/Bps > (byteswritten-n)/Bps))
+		if(bytesfrom == byteswritten || (byteswritten/Bps > (byteswritten-n)/Bps))
 			redraw(screen, 0);
 	}
-	closeioproc(io);
-	io = nil;
 
 	if(n == 0){ /* seeking backwards or end of the song */
 		close(p[1]);
-		postnote(PNGROUP, pid, "interrupt");
-		waitpid();
 		if(c != Cbackward){
 			bytesfrom = 0;
 			player->pcur++;
@@ -366,27 +384,28 @@
 	}
 
 stop:
-	closeioproc(io);
+	if(player->img != nil)
+		freeimage(recvp(player->img));
+freeplayer:
 	close(p[1]);
-	postnote(PNGROUP, pid, "interrupt");
-	waitpid();
+	closeioproc(io);
 	free(buf);
+	chanfree(player->ctl);
+	chanfree(player->ev);
+	free(player);
+	if(pid >= 0)
+		postnote(PNGROUP, pid, "interrupt");
+	threadexits(nil);
 }
 
-static Player *
-newplayer(int pcur)
+static int
+playerret(Player *player)
 {
-	Player *player;
-
-	player = malloc(sizeof(*player));
-	player->ctl = chancreate(sizeof(ulong), 0);
-	player->pcur = pcur;
-
-	threadcreate(playerthread, player, mainstacksize);
-
-	return player;
+	return recvul(player->ev) == Everror ? -1 : 0;
 }
 
+static Player *playernext;
+
 static void
 stop(Player *player)
 {
@@ -393,16 +412,48 @@
 	if(player == nil)
 		return;
 
+	if(player == playernext)
+		playernext = nil;
 	sendul(player->ctl, Cstop);
-	chanfree(player->ctl);
-	free(player);
 }
 
-static void
+static Player *
+newplayer(int pcur, int loadnext)
+{
+	Player *player;
+
+	if(playernext != nil && loadnext){
+		if(pcur == playernext->pcur){
+			player = playernext;
+			playernext = nil;
+			goto done;
+		}
+		stop(playernext);
+		playernext = nil;
+	}
+
+	player = mallocz(sizeof(*player), 1);
+	player->ctl = chancreate(sizeof(ulong), 0);
+	player->ev = chancreate(sizeof(ulong), 0);
+	player->pcur = pcur;
+
+	threadcreate(playerthread, player, mainstacksize);
+	if(playerret(player) < 0)
+		return nil;
+
+done:
+	if(pcur < plnum-1 && playernext == nil && loadnext)
+		playernext = newplayer(pcur+1, 0);
+
+	return player;
+}
+
+static int
 start(Player *player)
 {
 	if(player != nil)
 		sendul(player->ctl, Cstart);
+	return -1;
 }
 
 static void
@@ -559,9 +610,9 @@
 void
 threadmain(int argc, char **argv)
 {
-	int inv, fd, scrolling, oldscroll, oldpcur, oldscrolling, usingscrollbar;
-	Point lastclick;
+	char tmp[256];
 	Player *player;
+	Point lastclick;
 	Rune key;
 	Mouse m;
 	Alt a[] =
@@ -571,7 +622,7 @@
 		{ nil, &key, CHANRCV },
 		{ nil, nil, CHANEND },
 	};
-	char tmp[256];
+	int inv, fd, scrolling, oldscroll, oldpcur, oldscrolling, usingscrollbar;
 
 	inv = 0;
 	ARGBEGIN{
@@ -652,12 +703,12 @@
 				pcur = scroll + (m.xy.y - screen->r.min.y)/f->height;
 				if(m.buttons == 4){
 					stop(player);
-					player = newplayer(pcur);
+					player = newplayer(pcur, 1);
 					start(player);
 				}
 			}
 			break;
-		case 1:
+		case 1: /* resize */
 			redraw(screen, 1);
 			break;
 		case 2:
@@ -688,7 +739,7 @@
 				break;
 			case 10:
 				stop(player);
-				player = newplayer(pcur);
+				player = newplayer(pcur, 1);
 				start(player);
 				break;
 			case 'q': case Kdel:
@@ -704,7 +755,7 @@
 				if(++pcur >= plnum)
 					pcur = 0;
 				stop(player);
-				player = newplayer(pcur);
+				player = newplayer(pcur, 1);
 				start(player);
 				break;
 			case '<':
@@ -714,7 +765,7 @@
 				if(--pcur < 0)
 					pcur = plnum-1;
 				stop(player);
-				player = newplayer(pcur);
+				player = newplayer(pcur, 1);
 				start(player);
 				break;
 			case 's':