shithub: pplay

Download patch

ref: 2ab2e801072d772e3e9370a6c0f17de80cf974fb
parent: 9e1e20f6b9552189fef5111638f84d944fd6451b
author: qwx <qwx@sciops.net>
date: Sat Aug 10 04:37:42 EDT 2024

there's only one global dot; fix draw performance and timing issues

--- a/cmd.c
+++ b/cmd.c
@@ -5,7 +5,6 @@
 #include "fns.h"
 
 Dot dot;
-Dot *current;
 
 static int epfd[2];
 
@@ -15,7 +14,7 @@
 	vlong off, m;
 
 	off = atoll(s) * Sampsz;
-	if(current->cur > off){
+	if(dot.cur > off){
 		m = Rate * Sampsz;
 		setjump(off - m >= 0 ? off - m : 0);
 	}
@@ -28,7 +27,7 @@
 	vlong off;
 
 	off = atoll(s) * Sampsz;
-	if(current->cur < off)
+	if(dot.cur < off)
 		setjump(off + Sampsz);
 	return setloop(off);
 }
@@ -45,7 +44,7 @@
 	int r;
 
 	qlock(&lsync);
-	r = cpaste(current) == 0 ? 1 : -1;
+	r = cpaste(&dot) == 0 ? 1 : -1;
 	qunlock(&lsync);
 	return r;
 }
@@ -53,7 +52,7 @@
 static int
 copy(char *)
 {
-	ccopy(current);
+	ccopy(&dot);
 	return 0;
 }
 
@@ -60,13 +59,13 @@
 static vlong
 cut(char *)
 {
-	dprint(nil, "cmd/cut %Δ\n", current);
-	if(current->from == 0 && current->to == current->totalsz){
+	dprint(nil, "cmd/cut %Δ\n", &dot);
+	if(dot.from == 0 && dot.to == dot.totalsz){
 		werrstr("cut: can't cut entire buffer");
 		return -1;
 	}
 	qlock(&lsync);
-	ccut(current);
+	ccut(&dot);
 	qunlock(&lsync);
 	return 1;
 }
@@ -74,9 +73,9 @@
 static int
 crop(char *)
 {
-	dprint(nil, "cmd/crop %Δ\n", current);
+	dprint(nil, "cmd/crop %Δ\n", &dot);
 	qlock(&lsync);
-	ccrop(current);
+	ccrop(&dot);
 	qunlock(&lsync);
 	return 1;
 }
@@ -89,7 +88,7 @@
 	usize n, m, k;
 	Dot d;
 
-	d = *current;
+	d = dot;
 	d.cur = d.from;
 	if((nio = iounit(fd)) == 0)
 		nio = 8192;
@@ -138,7 +137,7 @@
 	Dot d, cd;
 	Chunk *c;
 
-	d = *current;
+	d = dot;
 	if(d.from != 0 && d.to != d.totalsz)
 		d.off = -1;
 	fd = (intptr)efd;
@@ -149,7 +148,7 @@
 	close(fd);
 	qlock(&lsync);
 	chold(c, &d);
-	*current = d;
+	dot = d;
 	qunlock(&lsync);
 	if(paste(nil) < 0)
 		fprint(2, "paste: %r\n");
@@ -256,7 +255,7 @@
 			break;
 		s += n;
 	}
-	dprint(current->norris, "current dot=%Δ\n", current);
+	dprint(dot.norris, "current dot=%Δ\n", &dot);
 	switch(r){
 	case '<': x = pipefrom(s); break;
 	case '^': x = pipethrough(s); break;
@@ -277,7 +276,7 @@
 	case 'x': x = crop(s); break;
 	default: werrstr("unknown command %C", r); x = -1; break;
 	}
-	dprint(current->norris, "final dot=%Δ\n", current);
+	dprint(dot.norris, "final dot=%Δ\n", &dot);
 	return x;
 }
 
@@ -320,5 +319,4 @@
 	if(loadfile(fd, &dot) == nil)
 		sysfatal("initcmd: %r");
 	close(fd);
-	current = &dot;
 }
--- a/dat.h
+++ b/dat.h
@@ -30,14 +30,13 @@
 	Chunk *norris;
 };
 extern Dot dot;
-extern Dot *current;
 
 extern QLock lsync;
 
 enum{
-	Drawcur,
-	Drawrender,
-	Drawall,
+	Drawcur = 1<<0,
+	Drawrender = 1<<1,
+	Drawall = 1<<2,
 };
 
 extern int stereo;
--- a/draw.c
+++ b/draw.c
@@ -24,20 +24,17 @@
 static usize views, viewe, viewmax, linepos;
 static int bgscalyl, bgscalyr;
 static double bgscalf;
-static Channel *drawc;
+static Channel *drawc, *sampc;
 static usize T;
 static int sampwidth = 1;	/* pixels per sample */
 static double zoom = 1.0;
 static int stalerender, tworking;
-// FIXME
-static int nbuf = 1;
-static Channel *trkc[1];
-static Rectangle tr;
-
 static int working;
 static vlong slen;
 static s16int *graph[2];
 
+#define Rrate	(1000.0 / 60.0)
+
 static Image *
 eallocimage(Rectangle r, int repl, ulong col)
 {
@@ -81,7 +78,7 @@
 	usize p;
 
 	p = va_arg(fmt->args, usize);
-	if(p > current->totalsz)
+	if(p > dot.totalsz)
 		return fmtstrcpy(fmt, "-∞");
 	b2t(p, &th, &tm, &ts, &tμ);
 	return fmtprint(fmt, "%02d:%02d:%02d.%03d (%zd)",
@@ -112,7 +109,7 @@
 	usize p, off;
 	Chunk *c;
 
-	c = p2c(views, &off, current);
+	c = p2c(views, &off, &dot);
 	for(p=views-off; p<viewe; p+=c->len, c=c->right){
 		if(p == 0)
 			continue;
@@ -125,10 +122,10 @@
 {
 	if(debugdraw)
 		renderchunks();
-	renderpos(current->from, col[Cloop], 0);
-	renderpos(current->to, col[Cloop], 0);
-	if(current->off != current->from)
-		renderpos(current->off, col[Cins], 0);
+	renderpos(dot.from, col[Cloop], 0);
+	renderpos(dot.to, col[Cloop], 0);
+	if(dot.off != dot.from)
+		renderpos(dot.off, col[Cins], 0);
 }
 
 static void
@@ -139,7 +136,7 @@
 
 	if(slen == 0)
 		return;
-	rr = tr;
+	rr = view->r;
 	draw(view, rr, col[Cbg], nil, ZP);
 	if(Dx(rr) > slen / 2)
 		rr.max.x = rr.min.x + slen / 2;
@@ -195,14 +192,14 @@
 	Point p;
 
 	draw(screen, statr, col[Cbg], nil, ZP);
-	seprint(s, s+sizeof s, "T %zd @ %τ", T / Sampsz, current->cur);
+	seprint(s, s+sizeof s, "T %zd @ %τ", T / Sampsz, dot.cur);
 	p = string(screen, statr.min, col[Ctext], ZP, font, s);
-	if(current->from > 0 || current->to < current->totalsz){
-		seprint(s, s+sizeof s, " ↺ %τ - %τ", current->from, current->to);
+	if(dot.from > 0 || dot.to < dot.totalsz){
+		seprint(s, s+sizeof s, " ↺ %τ - %τ", dot.from, dot.to);
 		p = string(screen, p, col[Cloop], ZP, font, s);
 	}
-	if(current->off != current->from){
-		seprint(s, s+sizeof s, " ‡ %τ", current->off);
+	if(dot.off != dot.from){
+		seprint(s, s+sizeof s, " ‡ %τ", dot.off);
 		p = string(screen, p, col[Cins], ZP, font, s);
 	}
 	statr.max.x = p.x;
@@ -212,13 +209,14 @@
 drawproc(void*)
 {
 	int what;
+	long Δt;
+	double t0, t;
 
 	threadsetname("drawer");
+	t0 = nsec() / 1000000.0 + Rrate;
 	for(;;){
 		what = Drawrender;
-		// FIXME
-		if(recv(drawc, &what) < 0){
-//		if(nbrecv(drawc, &what) < 0){
+		if(nbrecv(drawc, &what) < 0){
 			fprint(2, "drawproc: %r\n");
 			break;
 		}
@@ -230,23 +228,37 @@
 			draw(screen, rectaddpt(view->r, screen->r.min), view, nil, ZP);
 		}else
 			erasemark(linepos);
-		renderpos(current->cur, col[Cline], 1);
-		linepos = current->cur;
+		renderpos(dot.cur, col[Cline], 1);
+		linepos = dot.cur;
 		drawstat();
 		flushimage(display, 1);
 		unlockdisplay(display);
-		sleep(100);
+		//sleep(100);
+		t = nsec() / 1000000.0;
+		Δt = t0 - t;
+		if(Δt > 0)
+			sleep(Δt);
+		else{
+			Δt = -Δt;
+			t0 += Δt - Δt % (long)Rrate;
+		}
+		t0 += Rrate;
 	}
 }
-
+ 
+/* throttling of draw requests happens here */
 void
 refresh(int what)
 {
-	nbsend(drawc, &what);
+	static int f;
+
+	f |= what;
+	if(nbsend(drawc, &f) != 0)
+		f = 0;
 }
 
 static void
-sampler(void *cp)
+sampler(void *)
 {
 	int n, lmin, lmax, rmin, rmax;
 	usize k;
@@ -254,11 +266,9 @@
 	s16int s, *l, *r, *le;
 	vlong N;
 	Dot d;
-	Channel *c;
 
-	c = cp;
 again:
-	if(recv(c, &d) < 0)
+	if(recv(sampc, &d) < 0)
 		threadexits("recv: %r");
 	tworking = ++working;
 	stalerender++;
@@ -276,7 +286,7 @@
 	r = graph[1];
 	le = l + slen;
 	while(l < le){
-		if(c->n > 0)
+		if(sampc->n > 0)	/* start over */
 			break;
 		n = T * sampwidth;
 		lmin = lmax = rmin = rmax = 0;
@@ -316,21 +326,6 @@
 	goto again;
 }
 
-void
-setcurrent(Point o)
-{
-	int dy;
-	Rectangle r;
-
-	dy = screen->r.max.y / 1;
-	r = Rpt(screen->r.min, Pt(screen->r.max.x, dy));
-	if(ptinrect(o, r)){
-		current = &dot;
-		return;
-	}
-	sysfatal("setcurrent: phase error");
-}
-
 static void
 resetdraw(void)
 {
@@ -348,13 +343,6 @@
 	bgscalyl = (viewr.max.y - font->height) / (1 * (stereo ? 4 : 2));
 	bgscalyr = viewr.max.y - bgscalyl;
 	bgscalf = 32767. / bgscalyl;
-	if(trkc[0] == nil){
-		if((trkc[0] = chancreate(sizeof(Dot), 2)) == nil)
-			sysfatal("chancreate: %r");
-		if(proccreate(sampler, trkc[0], mainstacksize) < 0)
-			sysfatal("00reate: %r");
-	}
-	tr = Rpt(view->r.min, Pt(view->r.max.x, Dy(view->r)));
 }
 
 void
@@ -364,11 +352,11 @@
 	Dot d;
 
 	lockdisplay(display);
-	T = (vlong)(current->totalsz / zoom / Dx(screen->r)) & ~3;
+	T = (vlong)(dot.totalsz / zoom / Dx(screen->r)) & ~3;
 	if(T < Sampsz)
 		T = Sampsz;
 	span = Dx(screen->r) * T;
-	viewmax = current->totalsz - span;
+	viewmax = dot.totalsz - span;
 	if(views > viewmax)
 		views = viewmax;
 	viewe = views + span;
@@ -380,7 +368,7 @@
 	d = dot;
 	d.from = d.cur = views;
 	d.to = viewe;
-	nbsend(trkc[0], &d);
+	nbsend(sampc, &d);
 }
 
 void
@@ -394,7 +382,7 @@
 		z = zoom / pow(2, -Δz);
 	else
 		z = zoom * pow(2, Δz);
-	if(z < 1.0 || z > (current->totalsz / Sampsz) / Dx(screen->r))
+	if(z < 1.0 || z > (dot.totalsz / Sampsz) / Dx(screen->r))
 		return;
 	zoom = z;
 	redraw(0);
@@ -406,8 +394,8 @@
 	if(from < 0)
 		from = 0;
 	from &= ~3;
-	if(to >= current->totalsz)
-		to = current->totalsz;
+	if(to >= dot.totalsz)
+		to = dot.totalsz;
 	to &= ~3;
 	if((to - from) / Sampsz < Dx(screen->r)){
 		werrstr("range too small");
@@ -415,7 +403,7 @@
 	}
 	views = from;
 	viewe = to;
-	zoom = (double)current->totalsz / (to - from);
+	zoom = (double)dot.totalsz / (to - from);
 	redraw(0);
 	return 0;
 }
@@ -451,11 +439,11 @@
 {
 	from &= ~3;
 	to &= ~3;
-	current->from = from;
-	current->to = to;
-	if(current->cur < from || current->cur >= to)
-		current->cur = from;
-	current->off = -1;
+	dot.from = from;
+	dot.to = to;
+	if(dot.cur < from || dot.cur >= to)
+		dot.cur = from;
+	dot.off = -1;
 	stalerender = 1;
 	refresh(Drawrender);
 }
@@ -464,11 +452,11 @@
 setjump(vlong off)
 {
 	off &= ~3;
-	if(off < current->from || off > current->to - Sampsz){
+	if(off < dot.from || off > dot.to - Sampsz){
 		werrstr("cannot jump outside of loop bounds");
 		return -1;
 	}
-	current->off = current->cur = off;
+	dot.off = dot.cur = off;
 	stalerender = 1;
 	refresh(Drawrender);
 	return 0;
@@ -478,14 +466,14 @@
 setloop(vlong off)
 {
 	off &= ~3;
-	if(off < 0 || off > current->totalsz){
+	if(off < 0 || off > dot.totalsz){
 		werrstr("invalid range");
 		return -1;
 	}
-	if(off < current->cur)
-		setrange(off, current->to);
+	if(off < dot.cur)
+		setrange(off, dot.to);
 	else
-		setrange(current->from, off);
+		setrange(dot.from, off);
 	return 0;
 }
 
@@ -513,9 +501,11 @@
 		col[Cloop] = eallocimage(Rect(0,0,1,1), 1, 0x8888CCFF);
 		col[Cchunk] = eallocimage(Rect(0,0,1,1), 1, 0xEE0000FF);
 	}
-	if((drawc = chancreate(sizeof(int), 1)) == nil)
+	if((drawc = chancreate(sizeof(int), 0)) == nil
+	|| (sampc = chancreate(sizeof(Dot), 2)) == nil)
 		sysfatal("chancreate: %r");
 	redraw(1);
-	if(proccreate(drawproc, nil, mainstacksize) < 0)
+	if(proccreate(sampler, nil, mainstacksize) < 0
+	|| proccreate(drawproc, nil, mainstacksize) < 0)
 		sysfatal("proccreate: %r");
 }
--- a/fns.h
+++ b/fns.h
@@ -23,7 +23,6 @@
 void	redraw(int);
 void	initdrw(int);
 void	advance(usize);
-void	setcurrent(Punkt);
 Chunk*	p2c(usize, usize*, Dot*);
 int	setpos(usize);
 uchar*	getslice(Dot*, usize, usize*);
--- a/pplay.c
+++ b/pplay.c
@@ -55,9 +55,8 @@
 			fprint(2, "alt: %r\n");
 			break;
 		}
-		// FIXME: multitrack mixing
 		for(bp=buf, m=sizeof buf; bp<buf+sizeof buf; bp+=n, m-=n){
-			if((b = getslice(current, m, &n)) == nil || n <= 0){
+			if((b = getslice(&dot, m, &n)) == nil || n <= 0){
 				fprint(2, "aproc: %r\n");
 				nerr++;
 				goto again;
@@ -157,9 +156,6 @@
 		case 1:
 			if(eqpt(mo.xy, ZP))
 				mo = mc->Mouse;
-			// FIXME: multitrack drawing first
-			//if(mc->buttons != 0)
-			//	setcurrent(mc->xy);
 			switch(mc->buttons){
 			case 1: setjump(view2ss(mc->xy.x - screen->r.min.x)); break;
 			case 2: setloop(view2ss(mc->xy.x - screen->r.min.x)); break;
@@ -176,10 +172,10 @@
 			case 'D': debugdraw ^= 1; refresh(Drawrender); break;
 			case 'S': stereo ^= 1; refresh(Drawall); break;
 			case ' ': toggleplay(); break;
-			case 'b': setjump(current->from); break;
-			case Kesc: setrange(0, current->totalsz); break;
-			case '\n': zoominto(current->from, current->to); break;
-			case 'z': zoominto(0, current->totalsz); break;
+			case 'b': setjump(dot.from); break;
+			case Kesc: setrange(0, dot.totalsz); break;
+			case '\n': zoominto(dot.from, dot.to); break;
+			case 'z': zoominto(0, dot.totalsz); break;
 			case '-': setzoom(-1, 0); break;
 			case '=': setzoom(1, 0); break;
 			case '_': setzoom(-1, 1); break;