ref: 4c5bf2f861bb45cb1c2fbce54217c06948c1c8ab
parent: 81916a6bba65225bf4ed83133ebb2081eb996dc5
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Feb 20 12:59:03 EST 2016
use new playlist format in the player
--- a/tracklist.rc
+++ /dev/null
@@ -1,8 +1,0 @@
-#!/bin/rc
-
-ls -Q $"*/*/*/*.mp3 $"*/*/*/*.ogg $"*/*/*/*.flac >[2]/dev/null | while (track=`{read}) {
- echo -n $track
- echo -n ' '
- tags=`{audio/readtags $"track |[2] audio/printtags}
- echo $"tags
-}
--- a/zuke.c
+++ b/zuke.c
@@ -5,6 +5,8 @@
#include <keyboard.h>
#include <bio.h>
#include <thread.h>
+#include <ctype.h>
+#include "plist.h"
typedef struct Player Player;
@@ -15,12 +17,10 @@
Ctoggle,
};
-static struct
-{
- char *file;
- char *name;
-}*plist;
-static int plen;
+static Meta *pl;
+static int plnum;
+static char *plraw;
+static int plrawsize;
struct Player
{
@@ -40,6 +40,7 @@
static void
redraw(Image *screen, int new)
{
+ char tmp[256];
Point p, sp;
int i;
@@ -51,7 +52,7 @@
p.y = screen->r.min.y + 2;
scrollsz = Dy(screen->r) / f->height - 1;
- for(i = scroll; i < plen; i++){
+ for(i = scroll; i < plnum; i++){
if(p.y > screen->r.max.y)
break;
if(pcurplaying == i){
@@ -63,6 +64,8 @@
left.y = right.y = p.y + f->height;
line(screen, left, right, 0, 0, 0, colb, sp);
}
+
+ snprint(tmp, sizeof(tmp), "%s - %s - %s", pl[i].artist[0], pl[i].album, pl[i].title);
if(pcur == i){
Rectangle sel;
sel = screen->r;
@@ -69,10 +72,10 @@
sel.min.y = p.y;
sel.max.y = p.y + f->height;
draw(screen, sel, colb, nil, ZP);
- string(screen, p, cola, sp, f, plist[i].name);
+ string(screen, p, cola, sp, f, tmp);
}
else
- string(screen, p, colb, sp, f, plist[i].name);
+ string(screen, p, colb, sp, f, tmp);
p.y += f->height;
}
@@ -101,7 +104,7 @@
close(p[1]);
close(0);
close(2);
- execl("/bin/play", "/bin/play", "-o", "/fd/1", plist[player->pcur].file, nil);
+ execl("/bin/play", "/bin/play", "-o", "/fd/1", pl[player->pcur].path, nil);
sysfatal("execl: %r");
}
if(pid < 0)
@@ -195,26 +198,81 @@
static void
readplist(void)
{
- Biobuf b;
+ Meta *m;
+ char *s, *e, *endrec;
+ int i, n, sz, alloc, tagsz, intval;
- Binit(&b, 0, OREAD);
- for(plen = 0;; plen++){
- char *s[2];
- int n;
-
- s[0] = Brdstr(&b, '\n', 1);
- if(s[0] == nil)
+ s = nil;
+ for(alloc = sz = 0;;){
+ alloc += 65536;
+ if((s = realloc(s, alloc)) == nil)
+ sysfatal("no memory");
+ for(n = 0; sz < alloc; sz += n){
+ n = read(0, s+sz, alloc-sz);
+ if(n < 0)
+ sysfatal("%r");
+ if(n == 0)
+ break;
+ }
+ if(n == 0)
break;
- plist = realloc(plist, sizeof(*plist)*(plen+1));
- n = getfields(s[0], s, 2, 1, "\t");
- if(n < 1)
- break;
- plist[plen].file = plist[plen].name = s[0];
- if(n > 1)
- plist[plen].name = s[1];
- else if((plist[plen].name = strrchr(s[0], '/')) != nil)
- plist[plen].name++;
}
+
+ plraw = s;
+ plrawsize = sz;
+ plraw[plrawsize-1] = 0;
+ if(sz < 4 || s[0] != '#' || s[1] != ' ' || !isdigit(s[2]) || (s = memchr(plraw, '\n', sz)) == nil)
+ sysfatal("invalid playlist");
+ s++; /* at the start of the first record */
+
+ plnum = atoi(plraw+2);
+ pl = calloc(plnum, sizeof(Meta));
+ for(i = 0; i < plnum; i++, s = endrec){
+ if(plraw+plrawsize < s+10)
+ sysfatal("truncated playlist");
+ if(s[0] != '#' || s[1] != ' ' || !isdigit(s[2]) || strtol(s+2, &e, 10) != i)
+ sysfatal("invalid record");
+
+ sz = strtol(e, &s, 10);
+ s++; /* skip '\n' */
+ if(s+sz > plraw+plrawsize)
+ sysfatal("truncated playlist");
+ s[sz-1] = 0; /* '\n'→'\0' to mark the end of the record */
+ endrec = s+sz;
+ m = &pl[i];
+
+ for(;;){
+ if(s[0] == Pimage){
+ m->imageoffset = strtol(s+2, &e, 10);
+ m->imagesize = strtol(e+1, &s, 10);
+ m->imagereader = strtol(s+1, &e, 10);
+ s = e + 1;
+ }else if(s[0] == Pchannels || s[0] == Pduration || s[0] == Psamplerate){
+ intval = strtol(s+2, &e, 10);
+ if(s[0] == Pchannels) m->channels = intval;
+ else if(s[0] == Pduration) m->duration = intval;
+ else if(s[0] == Psamplerate) m->samplerate = intval;
+ s = e + 1;
+ }else if(s[0] == Ppath){
+ m->path = s+2;
+ break; /* always the last one */
+ }else{
+ tagsz = strtol(s+1, &e, 10);
+ if(e+tagsz >= plraw+plrawsize)
+ sysfatal("truncated playlist");
+ e++; /* point to tag value */
+ e[tagsz] = 0; /* '\n'→'\0' to mark the end of the tag value */
+ if(s[0] == Palbum) m->album = e;
+ else if(s[0] == Partist && m->numartist < Maxartist) m->artist[m->numartist++] = e;
+ else if(s[0] == Pdate) m->date = e;
+ else if(s[0] == Ptitle) m->title = e;
+ else if(s[0] == Pdate) m->date = e;
+ else if(s[0] == Ptrack) m->track = e;
+ else sysfatal("unknown tag type %c", s[0]);
+ s = e + tagsz+1;
+ }
+ }
+ }
}
static void
@@ -252,7 +310,7 @@
sysfatal("audio: %r");
readplist();
- if(plen < 1){
+ if(plnum < 1){
fprint(2, "empty playlist\n");
sysfatal("empty");
}
@@ -298,7 +356,7 @@
}else if(e.kbdc == Kpgdown){
pcur += scrollsz;
}else if(e.kbdc == Kend){
- pcur = plen-1;
+ pcur = plnum-1;
}else if(e.kbdc == Khome){
pcur = 0;
}else if(e.kbdc == 0x0a){
@@ -312,7 +370,7 @@
pcur = pcurplaying;
}else if(e.kbdc == '>' && pcurplaying >= 0){
pcur = pcurplaying;
- if(++pcur >= plen)
+ if(++pcur >= plnum)
pcur = 0;
stop(player);
player = newplayer(pcur);
@@ -320,12 +378,11 @@
}else if(e.kbdc == '<' && pcurplaying >= 0){
pcur = pcurplaying;
if(--pcur < 0)
- pcur = plen-1;
+ pcur = plnum-1;
stop(player);
player = newplayer(pcur);
start(player);
}else if(e.kbdc == 's' && player != nil){
- pcur = -1;
stop(player);
player = nil;
}else if(e.kbdc == 'p'){
@@ -336,8 +393,8 @@
if(pcur != oldpcur){
if(pcur < 0)
pcur = 0;
- else if(pcur >= plen)
- pcur = plen - 1;
+ else if(pcur >= plnum)
+ pcur = plnum - 1;
if(pcur < scroll)
scroll = pcur;
@@ -344,8 +401,8 @@
else if(pcur > scroll + scrollsz)
scroll = pcur - scrollsz;
- if(scroll > plen - scrollsz)
- scroll = plen - scrollsz;
+ if(scroll > plnum - scrollsz)
+ scroll = plnum - scrollsz;
else if(scroll < 0)
scroll = 0;