~ft/zuke

951d3705a090855e9b8bd3278d1fa5ba2ac3771e — Sigrid Haflínudóttir 5 months ago 57ce0c6
add seek bar
1 files changed, 69 insertions(+), 51 deletions(-)

M zuke.c
M zuke.c => zuke.c +69 -51
@@ 20,13 20,13 @@ enum
	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 @@ struct Player
	Channel *ctl;
	Channel *ev;
	Channel *img;
	vlong seekbytes;
	double seek;
	int pcur;
};



@@ 49,7 49,7 @@ static int plrawsize;
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 colwidth[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 @@ redraw(int full)
	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 @@ redraw(int full)
			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 @@ redraw(int full)
	}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 @@ redraw(int full)
		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,20 443,20 @@ start(Player *player)
static void
playerthread(void *player_)
{
	char *buf, cmd[256], *fmt;
	char *buf, cmd[64], seekpos[12], *fmt;
	Player *player;
	Ioproc *io;
	Image *thiscover;
	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 @@ restart:
		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 @@ restart:
		close(fd);
	close(p[0]);

	byteswritten = 0;
	c = 0;
	if(!noinit){
		sendul(player->ev, Evready);


@@ 488,20 507,17 @@ restart:
			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 @@ restart:
			redraw(1);
			player->img = nil;
		}
		bf = bytesfrom != 0 ? bytesfrom : byteswritten;
		r = nbrecv(player->ctl, &c);
		if(r < 0){
			goto stop;


@@ 521,36 536,33 @@ restart:
				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 @@ toggle(Player *player)
}

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 @@ ev:

			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 @@ ev:
		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--;