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 = ˙
}
--- 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 = ˙
- 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;