~ft/zuke

d074aa0d3c51d95dc943a50cf82623f680c99c16 — Sigrid Haflínudóttir 7 months ago d24b93d
add livestreams support
3 files changed, 49 insertions(+), 14 deletions(-)

M README.md
M mkplist.c
M zuke.c
M README.md => README.md +2 -1
@@ 10,6 10,7 @@ With some stuff one expects from a music player:
 * seeking
 * playlists
 * good metadata support
 * basic livestreams support

## Installing



@@ 22,7 23,7 @@ itself.  The other one is `audio/mkplist`, it's used to make playlists
that are then fed to `audio/zuke`'s stdin:

```
% audio/mkplist /n/somefs/mymusic > $home/somefs.plist
% audio/mkplist /n/somefs/mymusic /n/otherfs/moremusic http://83.137.145.141:14280 > $home/somefs.plist
% audio/zuke < $home/somefs.plist
```


M mkplist.c => mkplist.c +10 -2
@@ 295,8 295,16 @@ main(int argc, char **argv)
	}

	for(i = 1; i < argc; i++){
		dir = strdup(argv[i]);
		scan(&dir, 0);
		if(strncmp(argv[i], "http://", 7) == 0 || strncmp(argv[i], "https://", 8) == 0){
			if((curr = newmeta()) == nil)
				sysfatal("no memory");
			curr->title = argv[i];
			curr->path = argv[i];
			curr->filefmt = "";
		}else{
			dir = strdup(argv[i]);
			scan(&dir, 0);
		}
	}
	qsort(all, numall, sizeof(Meta), cmpmeta);
	print("# %d\n", numall);

M zuke.c => zuke.c +37 -11
@@ 243,9 243,20 @@ redraw(int full)
		}
	}

	if(pcurplaying >= 0)
		snprint(tmp, sizeof(tmp), "%s%P/%P %d%%", shuffle != nil ? "∫ " : "", (int)(byteswritten/Bps), getmeta(pcurplaying)->duration/1000, volume);
	else
	if(pcurplaying >= 0){
		if(getmeta(pcurplaying)->duration != 0){
			snprint(tmp, sizeof(tmp), "%s%P/%P %d%%",
				shuffle != nil ? "∫ " : "",
				(int)(byteswritten/Bps),
				getmeta(pcurplaying)->duration/1000,
				volume);
		}else{
			snprint(tmp, sizeof(tmp), "%s%P %d%%",
				shuffle != nil ? "∫ " : "",
				(int)(byteswritten/Bps),
				volume);
		}
	}else
		snprint(tmp, sizeof(tmp), "%s%d%%", shuffle != nil ? "∫ " : "", volume);
	r = screen->r;
	r.min.x = r.max.x - stringwidth(f, tmp) - 4;


@@ 413,8 424,10 @@ start(Player *player)
static int
openaudio(int audio)
{
	while(audio < 0 && (audio = open("/dev/audio", OWRITE)) < 0)
	while(audio < 0 && (audio = open("/dev/audio", OWRITE)) < 0){
		fprint(2, "audio busy\n");
		sleep(1000);
	}

	return audio;
}


@@ 422,7 435,7 @@ openaudio(int audio)
static void
playerthread(void *player_)
{
	char *buf, cmd[32];
	char *buf, cmd[256], *fmt;
	Player *player;
	Ioproc *io;
	Image *thiscover;


@@ 430,6 443,7 @@ playerthread(void *player_)
	int p[2], fd, pid, n, got, noinit, trycoverload;
	u64int bytesfrom, bf;
	int audio;
	Meta *cur;

	threadsetname("player");
	player = player_;


@@ 443,7 457,10 @@ playerthread(void *player_)
	audio = -1;

restart:
	if((fd = open(getmeta(player->pcur)->path, OREAD)) < 0){
	cur = getmeta(player->pcur);
	fmt = cur->filefmt;
	fd = -1;
	if(*fmt && (fd = open(cur->path, OREAD)) < 0){
		fprint(2, "%r\n");
		sendul(player->ev, Everror);
		goto freeplayer;


@@ 451,17 468,24 @@ restart:

	pipe(p);
	if((pid = rfork(RFPROC|RFFDG|RFREND|RFNOTEG)) == 0){
		dup(p[0], 1); close(p[0]);
		if(fd < 0)
			fd = open("/dev/null", OREAD);
		dup(fd, 0); close(fd);
		dup(open("/dev/null", OWRITE), 2);
		dup(p[0], 1); close(p[0]);
		dup(fd = open("/dev/null", OWRITE), 2); close(fd);
		close(p[1]);
		snprint(cmd, sizeof(cmd), "/bin/audio/%sdec", getmeta(player->pcur)->filefmt);
		execl(cmd, cmd, nil);
		if(*fmt){
			snprint(cmd, sizeof(cmd), "/bin/audio/%sdec", fmt);
			execl(cmd, cmd, nil);
		}else{
			execl("/bin/play", "play", "-o", "/fd/1", cur->path, nil);
		}
		sysfatal("execl: %r");
	}
	if(pid < 0)
		sysfatal("rfork: %r");
	close(fd);
	if(fd >= 0)
		close(fd);
	close(p[0]);

	byteswritten = 0;


@@ 560,6 584,8 @@ restart:
			start(playercurr);
			goto stop;
		}
		close(audio);
		audio = -1;
		goto restart;
	}