ref: 951d3705a090855e9b8bd3278d1fa5ba2ac3771e
parent: 57ce0c691e141db6493ec4c683b55955e64d159b
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Aug 12 10:44:50 EDT 2020
add seek bar
--- a/zuke.c
+++ b/zuke.c
@@ -20,13 +20,13 @@
Everror = 1,
Evready,
- Bps = 44100*2*2, /* 44100KHz, stereo, s16 for a sample */
- Seekbytes = Bps*10, /* 10 seconds */
- Seekbytesfast = Bps*60, /* 1 minute */
+ Seek = 10, /* 10 seconds */
+ Seekfast = 60, /* a minute */
Scrollwidth = 14,
Scrollheight = 16,
+ Bps = 44100*2*2, /* 44100KHz, stereo, s16 for a sample */
Relbufsz = Bps/5, /* 0.2 second */
};
@@ -35,7 +35,7 @@
Channel *ctl;
Channel *ev;
Channel *img;
- vlong seekbytes;
+ double seek;
int pcur;
};
@@ -49,7 +49,7 @@
static int volume;
static Player *playernext;
static Player *playercurr;
-static u64int byteswritten;
+static vlong byteswritten;
static int pcur, pcurplaying;
static int scroll, scrollsz;
static Font *f;
@@ -61,6 +61,7 @@
static int mincolwidth[7];
static char *cols = "AatD";
static int *shuffle;
+static Rectangle seekbar;
static char *covers[] = {"folder", "cover", "Cover", "scans/CD", "Scans/Front", "Covers/Front"};
static char *menu3i[] = {
@@ -159,17 +160,20 @@
Image *col;
Point p, sp;
Rectangle sel, r;
- int i, j, left, scrollcenter;
+ int i, j, left, right, scrollcenter;
char tmp[32];
lockdisplay(display);
+ scrollsz = (Dy(screen->r) - f->height - 4) / f->height - 1;
+ left = screen->r.min.x;
+ if(scrollsz < plnum) /* adjust for scrollbar */
+ left += Scrollwidth + 1;
+
if(full){
draw(screen, screen->r, colors[Dback].im, nil, ZP);
- scrollsz = Dy(screen->r) / f->height - 1;
adjustcolumns();
- left = screen->r.min.x;
- if(scrollsz < plnum){ /* add a scrollbar */
+ if(scrollsz < plnum){ /* scrollbar */
p.x = sp.x = screen->r.min.x + Scrollwidth;
p.y = screen->r.min.y;
sp.y = screen->r.max.y;
@@ -185,8 +189,6 @@
r.min.y += scrollcenter + Scrollheight/4;
r.max.y = r.min.y + Scrollheight;
draw(screen, r, colors[Dfmed].im, nil, ZP);
-
- left += Scrollwidth + 1;
}
p.x = sp.x = left;
@@ -259,10 +261,16 @@
}else
snprint(tmp, sizeof(tmp), "%s%d%%", shuffle != nil ? "∫ " : "", volume);
r = screen->r;
- r.min.x = r.max.x - stringwidth(f, tmp) - 4;
+ right = r.max.x - stringwidth(f, tmp) - 4;
+ r.min.x = left;
r.min.y = r.max.y - f->height - 4;
+ if(pcurplaying < 0 || getmeta(pcurplaying)->duration == 0)
+ r.min.x = right;
draw(screen, r, colors[Dblow].im, nil, ZP);
- string(screen, addpt(r.min, Pt(2, 2)), colors[Dfhigh].im, sp, f, tmp);
+ r.max.x = right;
+ p = addpt(Pt(right, r.min.y), Pt(2, 2));
+ string(screen, p, colors[Dfhigh].im, sp, f, tmp);
+ sel = r;
if(cover != nil && full){
r.max.x = r.min.x;
@@ -276,6 +284,17 @@
draw(screen, insetrect(r, 4), cover, nil, ZP);
}
+ /* seek bar */
+ seekbar = ZR;
+ if(pcurplaying >= 0 && getmeta(pcurplaying)->duration != 0){
+ r = insetrect(sel, 4);
+ draw(screen, r, colors[Dfmed].im, nil, ZP);
+ r = insetrect(r, 1);
+ seekbar = r;
+ r.max.x = r.min.x + Dx(r) * 1000.0*(double)byteswritten/Bps / (double)getmeta(pcurplaying)->duration;
+ draw(screen, r, colors[Dbinv].im, nil, ZP);
+ }
+
flushimage(display, 1);
unlockdisplay(display);
}
@@ -424,7 +443,7 @@
static void
playerthread(void *player_)
{
- char *buf, cmd[256], *fmt;
+ char *buf, cmd[64], seekpos[12], *fmt;
Player *player;
Ioproc *io;
Image *thiscover;
@@ -431,13 +450,13 @@
ulong c;
int p[2], fd, pid, noinit, trycoverload;
long n, r;
- vlong bytesfrom, bf;
+ vlong boffset, boffsetlast;
Meta *cur;
threadsetname("player");
player = player_;
noinit = 0;
- bytesfrom = 0;
+ boffset = 0;
buf = nil;
trycoverload = 1;
io = nil;
@@ -463,7 +482,8 @@
close(p[1]);
if(*fmt){
snprint(cmd, sizeof(cmd), "/bin/audio/%sdec", fmt);
- execl(cmd, cmd, nil);
+ snprint(seekpos, sizeof(seekpos), "%g", (double)boffset/Bps);
+ execl(cmd, cmd, "-s", seekpos, nil);
}else{
execl("/bin/play", "play", "-o", "/fd/1", cur->path, nil);
}
@@ -475,7 +495,6 @@
close(fd);
close(p[0]);
- byteswritten = 0;
c = 0;
if(!noinit){
sendul(player->ev, Evready);
@@ -488,20 +507,17 @@
goto freeplayer;
if(n < 1)
goto next;
- byteswritten = iowrite(io, audio, buf, n);
- bytesfrom = 0;
+ boffset = iowrite(io, audio, buf, n);
noinit = 1;
}
+ byteswritten = boffsetlast = boffset;
pcurplaying = player->pcur;
- if(c != Cseekrel || player->seekbytes >= 0)
+ if(c != Cseekrel)
redraw(1);
while(1){
- n = Relbufsz;
- if(bytesfrom > byteswritten && n > bytesfrom-byteswritten)
- n = bytesfrom-byteswritten;
- n = ioreadn(io, p[1], buf, n);
+ n = ioreadn(io, p[1], buf, Relbufsz);
if(n <= 0)
break;
@@ -512,7 +528,6 @@
redraw(1);
player->img = nil;
}
- bf = bytesfrom != 0 ? bytesfrom : byteswritten;
r = nbrecv(player->ctl, &c);
if(r < 0){
goto stop;
@@ -521,36 +536,33 @@
if(recv(player->ctl, &c) < 0 || c == Cstop)
goto stop;
}else if(c == Cseekrel){
- bytesfrom = MAX(0, bf + player->seekbytes);
- if(player->seekbytes < 0){
- n = 0; /* not an error */
- break;
- }
- }else{ /* Cstop */
+ boffset = MAX(0, boffset + player->seek*Bps);
+ n = 0;
+ break;
+ }else if(c == Cstop){
goto stop;
}
}
- if(bytesfrom <= byteswritten){
- if(bytesfrom == byteswritten)
- bytesfrom = 0;
- if(iowrite(io, audio, buf, n) != n)
- fprint(2, "player: %r\n");
- if(trycoverload && byteswritten >= Bps){
- player->img = chancreate(sizeof(Image*), 0);
- proccreate(coverload, player, 4096);
- trycoverload = 0;
- }
+ boffset += n;
+ byteswritten = boffset;
+ if(iowrite(io, audio, buf, n) != n)
+ fprint(2, "player: %r\n");
+ if(trycoverload){
+ trycoverload = 0;
+ player->img = chancreate(sizeof(Image*), 0);
+ proccreate(coverload, player, 4096);
}
- byteswritten += n;
- if(bytesfrom == byteswritten || (byteswritten/Bps > (byteswritten-n)/Bps))
+ if(labs(boffset/Relbufsz - boffsetlast/Relbufsz) > 0){
+ boffsetlast = boffset;
redraw(0);
+ }
}
if(n < 1){ /* seeking backwards or end of the song */
close(p[1]);
p[1] = -1;
- if(c != Cseekrel || player->seekbytes >= 0){
+ if(c != Cseekrel || boffset >= getmeta(pcurplaying)->duration/1000*Bps){
next:
playercurr = nil;
playercurr = newplayer((player->pcur+1) % plnum, 1);
@@ -588,10 +600,10 @@
}
static void
-seekrel(Player *player, vlong off)
+seekrel(Player *player, double off)
{
if(player != nil){
- player->seekbytes = off;
+ player->seek = off;
sendul(player->ctl, Cseekrel);
}
}
@@ -924,6 +936,12 @@
n = (m.xy.y - screen->r.min.y)/f->height;
+ if(oldbuttons == 0 && !scrolling && ptinrect(m.xy, seekbar)){
+ m.xy.x--;
+ double off = getmeta(pcurplaying)->duration * (double)(m.xy.x-seekbar.min.x) / (double)Dx(seekbar);
+ seekrel(playercurr, off/1000.0 - byteswritten/Bps);
+ break;
+ }
if(oldbuttons == 0 && m.xy.x <= screen->r.min.x+Scrollwidth){
if(m.buttons == 1){
scroll = MAX(0, scroll-n-1);
@@ -970,16 +988,16 @@
case 2:
switch(key){
case Kleft:
- seekrel(playercurr, -(vlong)Seekbytes);
+ seekrel(playercurr, -(double)Seek);
break;
case Kright:
- seekrel(playercurr, Seekbytes);
+ seekrel(playercurr, Seek);
break;
case ',':
- seekrel(playercurr, -(vlong)Seekbytesfast);
+ seekrel(playercurr, -(double)Seekfast);
break;
case '.':
- seekrel(playercurr, Seekbytesfast);
+ seekrel(playercurr, Seekfast);
break;
case Kup:
pcur--;