shithub: pplay

Download patch

ref: 79cda97b806baf2adfc0045537675684d1edfe75
parent: 20868574345b23c2212bfb7c0234436cf481a882
author: qwx <qwx@sciops.net>
date: Mon Aug 26 07:38:41 EDT 2024

rework zoom: try to center on current position

--- a/draw.c
+++ b/draw.c
@@ -342,11 +342,10 @@
 	bgscalf = 32767. / bgscalyl;
 }
 
-void
-redraw(int all)
+static void
+resetview(int all)
 {
 	usize span;
-	Dot d;
 
 	lockdisplay(display);
 	T = (vlong)(dot.totalsz / zoom / Dx(screen->r)) & ~3;
@@ -360,6 +359,14 @@
 	if(all)
 		resetdraw();
 	unlockdisplay(display);
+}
+
+void
+redraw(int all)
+{
+	Dot d;
+
+	resetview(all);
 	if(paused)
 		refresh(Drawall);
 	d = dot;
@@ -369,20 +376,28 @@
 }
 
 void
-setzoom(int Δz, int mul)
+setzoom(int Δz, int x)
 {
-	double z;
+	double z, span, Δx;
 
-	if(!mul)
-		z = zoom + Δz;
-	else if(Δz < 0)
-		z = zoom / pow(2, -Δz);
+	if(Δz < 0)
+		z = zoom / pow(1.025, -Δz);
 	else
-		z = zoom * pow(2, Δz);
-	if(z < 1.0 || z > (dot.totalsz / Sampsz) / Dx(screen->r))
+		z = zoom * pow(1.025, Δz);
+	if(z < 1.0)
+		z = 1.0;
+	else if(z > (dot.totalsz / Sampsz) / Dx(screen->r))
+		z = (dot.totalsz / Sampsz) / Dx(screen->r);
+	if(z == zoom)
 		return;
 	zoom = z;
-	redraw(0);
+	span = T;
+	resetview(0);
+	span -= T;
+	span *= Dx(screen->r);
+	Δx = ((double)x / Dx(screen->r)) * span / T;
+	if(!setpan(Δx))
+		redraw(0);
 }
 
 int
@@ -405,14 +420,14 @@
 	return 0;
 }
 
-void
+int
 setpan(int Δx)
 {
 	usize new;
 
 	Δx *= T;
-	if(zoom == 1)
-		return;
+	if(zoom == 1.0)
+		return 0;
 	if(Δx < 0 && -Δx > views)
 		new = 0;
 	else if(views + Δx >= viewmax)
@@ -420,9 +435,10 @@
 	else
 		new = views + Δx;
 	if(new == views)
-		return;
+		return 0;
 	views = new;
 	redraw(0);
+	return 1;
 }
 
 void
--- a/fns.h
+++ b/fns.h
@@ -11,11 +11,12 @@
 int	cmd(char*);
 void	appendfile(char*);
 void	refresh(int);
+void	setcenter(int);
 void	setzoom(int, int);
 int	zoominto(vlong, vlong);
 void	setrange(usize, usize);
 int	setloop(vlong);
-void	setpan(int);
+int	setpan(int);
 void	setpage(int);
 int	setjump(vlong);
 vlong	ss2view(int);
--- a/pplay.c
+++ b/pplay.c
@@ -106,7 +106,7 @@
 threadmain(int argc, char **argv)
 {
 	char *p;
-	Mouse mo;
+	Mouse m, mo;
 	Rune r;
 
 	notriob = 0;
@@ -146,24 +146,26 @@
 	for(;;){
 		switch(alt(a)){
 		case 0:
+			mo = mc->Mouse;
 			lockdisplay(display);
 			if(getwindow(display, Refnone) < 0)
 				sysfatal("resize failed: %r");
 			unlockdisplay(display);
 			redraw(1);
-			mo = mc->Mouse;
 			break;
 		case 1:
-			if(eqpt(mo.xy, ZP))
-				mo = mc->Mouse;
+			m = mc->Mouse;
+			if(mo.msec == 0)
+				mo = m;
 			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;
-			case 4: setpan(mo.xy.x - mc->xy.x); break;
-			case 8: setzoom(1, 1); break;
-			case 16: setzoom(-1, 1); break;
+			case 1: setjump(view2ss(m.xy.x - screen->r.min.x)); break;
+			case 2: setloop(view2ss(m.xy.x - screen->r.min.x)); break;
+			case 4: setpan(mo.xy.x - m.xy.x); break;
+			case 5: setzoom(m.xy.y - mo.xy.y, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+			case 8: setzoom(1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+			case 16: setzoom(-1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
 			}
-			mo = mc->Mouse;
+			mo = m;
 			break;
 		case 2:
 			switch(r){
@@ -171,10 +173,10 @@
 			case Kesc: setrange(0, dot.totalsz); break;
 			case '\n': zoominto(dot.from, dot.to); break;
 			case '\t': chan = chan + 1 & 1; break;
-			case '-': setzoom(-1, 0); break;
-			case '=': setzoom(1, 0); break;
-			case '_': setzoom(-1, 1); break;
-			case '+': setzoom(1, 1); break;
+			case '-': setzoom(-20.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+			case '=': setzoom(20.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+			case '_': setzoom(-1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
+			case '+': setzoom(1.0, mo.xy.x - screen->r.min.x); m.xy.x = mo.xy.x; break;
 			case '1': bound = 0; break;
 			case '2': bound = 1; break;
 			case 'S': stereo ^= 1; redraw(1); break;
--- a/pplay.man
+++ b/pplay.man
@@ -49,13 +49,11 @@
 .IR tmdate (2)),
 or the number of stereo samples so far if toggled.
 .PP
-When the selected range is the entire data and only the
-.I @
-timestamp is displayed.
-The
-.I ‡
-timestamp is displayed if a cursor has been set
-see section "Loop points and selection" below).
+The view can be moved horizontally with the cursor keys,
+or by holding the right mouse button.
+Zooming in decreases the sample period (and vice-versa)
+via keyboard shortcuts, the mouse scroll buttons,
+or by holding the left mouse button while panning.
 .SS "Loop points and selection"
 Playback is constrained to a range defined by two positional markers,
 the start and end loop points, initially the entire data.