commit fc70639523ebd14acd776a5bb14cedc198de81cc
parent 184d2e480ecd07edc897e77c42b6028eb7b26c6d
Author: Kris Maglione <jg@suckless.org>
Date: Mon, 24 Aug 2009 13:56:37 -0400
Minor changes, what I don't know.
Diffstat:
http.c | | | 9 | ++++++--- |
last.c | | | 76 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
pass | | | 16 | ++++++++++++++++ |
player.c | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
posix.c | | | 7 | +++++-- |
util.c | | | 7 | ++++--- |
6 files changed, 143 insertions(+), 45 deletions(-)
diff --git a/http.c b/http.c
@@ -66,10 +66,11 @@ hconv(Fmt *f) {
for(p=s; (c = *p); p++) {
if(c & 0x80 || !isprint(c) || isspace(c))
break;
+ if(c == '%' && !(f->flags & FmtComma))
+ break;
switch(c) {
default:
continue;
- case '%':
case '<':
case '>':
case '{':
@@ -85,6 +86,7 @@ hconv(Fmt *f) {
case '+':
break;
}
+ break;
}
if(p != s)
ret += fmtprint(f, "%.*s", p-s, s);
@@ -92,7 +94,7 @@ hconv(Fmt *f) {
if(c == ' ')
ret += fmtstrcpy(f, "+");
else
- ret += fmtprint(f, "%%%02X", c);
+ ret += fmtprint(f, "%%%02uX", (uchar)c);
p++;
}
}
@@ -122,11 +124,12 @@ Hconv(Fmt *f) {
case '\\':
break;
}
+ break;
}
if(p != s)
ret += fmtprint(f, "%.*s", p-s, s);
if(c) {
- ret += fmtprint(f, "%%%02X", c);
+ ret += fmtprint(f, "%%%02uX", (uchar)c);
p++;
}
}
diff --git a/last.c b/last.c
@@ -1,10 +1,13 @@
#define EXTERN
+#define _GNU_SOURCE
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <bio.h>
#include <mp.h>
#include <libsec.h>
+#include <signal.h>
+#include <string.h>
#include <thread.h>
#include "last.h"
@@ -52,8 +55,9 @@ struct Assoc {
Rartist, "Conlon Nancarrow",
Rartist, "Iannis Xenakis",
Rartist, "Olivier Messiaen",
+ Rartist, "Mauricio Kagel",
Ralbum, "Music Box",
- 0, 0,
+ 0,
};
char*
@@ -66,9 +70,15 @@ erespval(int i) {
}
void
-exitsall(char *err) {
- if(err)
+exitsall(char *err, ...) {
+ va_list ap;
+
+ if(err) {
+ va_start(ap, err);
+ err = vsmprint(err, ap);
+ va_end(ap);
print("threadexitsall(%s)\n", err);
+ }
threadexitsall(err);
}
@@ -125,7 +135,10 @@ get(char *path, char *fmt, ...) {
if(debug['a'] && !debug['h'])
print("GET %q %s\n", host, uri);
- b = httpget(host, uri);
+ do {
+ b = httpget(host, uri);
+ rerrstr(buf, sizeof buf);
+ }while(b == nil && strcasestr(buf, "interrupted"));
free(uri);
if(b == nil) {
resp[Rresponse] = smprint("get fails: %r");
@@ -177,6 +190,24 @@ rpc(const char *cmd, const char *fmt, ...) {
return i;
}
+void
+erpc(const char *cmd, const char *fmt, ...) {
+ VFmt v;
+
+ v.fmt = query(nil, fmt);
+ va_start(v.args, fmt);
+ if(get("%s/%s.php", "session=%h %V", basepath, cmd, session, &v))
+ sysfatal("rpc %s: %r\n", cmd);
+ va_end(v.args);
+ free(v.fmt);
+}
+
+int
+skip(char *cmd) {
+ skipping = 1;
+ return rpc("control", "command=%h", cmd);
+}
+
static void
printresp(void) {
char *s;
@@ -203,8 +234,7 @@ getmeta(void) {
do {
if(n > 50)
exitsall("meta");
- if(rpc("np", ""))
- exitsall("rpc np");
+ erpc("np", "");
}while(resp[Rstreaming] == nil || strcmp(resp[Rstreaming], "true"));
s = resp[Rtrackduration];
@@ -215,7 +245,7 @@ getmeta(void) {
print("\n");
print("Station: %R\n", Rstation);
- print("Atrist: %R <%R>\n", Rartist, Rartist_url);
+ print("Artist: %R <%R>\n", Rartist, Rartist_url);
print("Album: %R\n", Ralbum);
print("Track: %R\n", Rtrack);
print("Duration: %d:%02d\n", sec/60, sec%60);
@@ -223,14 +253,13 @@ getmeta(void) {
print("\n");
print("> ");
- label("Playing \"%R\" by %R", Rtrack, Rartist);
+ label("Playing “%R” by %R", Rtrack, Rartist);
for(a=junk; a->str; a++)
if(resp[a->field] && cistrstr(resp[a->field], a->str)) {
print("Junk %s; banning.\n", respnam[a->field]);
- rpc("control", "command=ban");
+ skip("ban");
printresp();
- skipping = 1;
break;
}
}
@@ -246,7 +275,7 @@ userinfo(char **user, char **pass) {
if(up == nil)
sysfatal("no username/password: %r");
- md5(up->passwd, strlen(up->passwd), digest, nil);
+ md5((uchar*)up->passwd, strlen(up->passwd), digest, nil);
for(i=0; i < MD5dlen; i++)
sprint(buf+2*i, "%02x", digest[i]);;
@@ -274,6 +303,9 @@ threadmain(int argc, char *argv[]) {
fmtinstall('R', Rconv);
quotefmtinstall();
+ signal(SIGCHLD, SIG_IGN);
+ notifyoff("sys: child");
+
label("Wait...");
httpinit();
@@ -297,7 +329,11 @@ threadmain(int argc, char *argv[]) {
label("Stopped.");
Binit(&in, 0, OREAD);
- while(print("> "), s = Brdline(&in, '\n')) {
+ while(print("> "), Bgetc(&in) != Beof) {
+ Bungetc(&in);
+ s = Brdline(&in, '\n');
+ if(s == nil)
+ continue;
s[BLINELEN(&in)-1] = '\0';
q = tok(&s);
if(!strcmp(q, "start")) {
@@ -306,18 +342,28 @@ threadmain(int argc, char *argv[]) {
if(!strcmp(q, "stop")) {
endstream();
}else
+ if(!strcmp(q, "info")) {
+ getmeta();
+ }else
if(!strcmp(q, "skip") || !strcmp(q, "ban")) {
- skipping = 1;
label("Skipping...");
- rpc("control", "command=%h", q);
+ skip(q);
printresp();
}else
if(!strcmp(q, "love")) {
rpc("control", "command=love");
printresp();
}else
+ if(!strcmp(q, "artist")) {
+ rpc("adjust", "url=%h%h", "lastfm://artist/", s);
+ printresp();
+ }else
+ if(!strcmp(q, "tag")) {
+ rpc("adjust", "url=%h%h", "lastfm://globaltags/", s);
+ printresp();
+ }else
if(!strcmp(q, "station")) {
- rpc("adjust", "url=%h", s);
+ rpc("adjust", "url=%,h", s);
printresp();
}else
if(!strcmp(q, "time")) {
diff --git a/pass b/pass
@@ -0,0 +1,16 @@
+#!/bin/rc
+. 9.rc
+
+echo Enter your last.fm login credentials.
+echo -n Username: ''
+username=`{read}
+echo -n Password: ''
+stty -echo
+pass=`{read}
+stty echo
+
+9p read factotum/ctl >/dev/null >[2=1] || 9 factotum &
+
+echo 'delkey dom=last.fm' | 9p write factotum/ctl >[2]/dev/null
+echo 'key user='$"username' !password='$"pass' dom=last.fm proto=pass' | 9p write factotum/ctl >/dev/null >[2=1]
+
diff --git a/player.c b/player.c
@@ -25,7 +25,9 @@ playerproc(void *v) {
fd[0] = dup(fdin, -1);
fd[1] = open("/dev/null", OWRITE);
fd[2] = open("/dev/null", OWRITE);
+ notedisable("alarm");
cpid = threadspawn(fd, player[0], player);
+ noteenable("alarm");
do{
m = recvp(cwait);
i = 0;
@@ -65,12 +67,29 @@ tgetc(Biobuf *b) {
#define GETC(bp) \
((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:tgetc((bp)))
+static int
+scan(int c, char *str) {
+ char *s;
+
+ s=str;
+ do {
+ if(*s++ != c)
+ break;
+ if(*s == '\0')
+ return 1;
+ }while((c = GETC(stream)) != Beof);
+ while(--s > str)
+ Bungetc(stream);
+ return 0;
+}
+
static void
proxyproc(void *v) {
char errbuf[16];
- int c, i;
+ int c, i, j, bytes;
qlock(&lk);
+ j = 0;
while(playing) {
label("Starting stream.");
if(debug['p'])
@@ -82,34 +101,37 @@ proxyproc(void *v) {
if(stream)
break;
if(i++ > 5) {
- fprint(2, "can't get stream: %r\n");
+ msg("Can't get stream: %r\n");
playing = 0;
}
rerrstr(errbuf, sizeof errbuf);
- }while(playing && !strcmp(errbuf, "interrupted"));
+ }while(playing && !strcasestr(errbuf, "interrupted"));
c = 0;
+ bytes = 0;
while(playing && (c = GETC(stream)) != Beof) {
- if(c == 'S') {
- i = 0;
- if(i++, 'Y' == GETC(stream))
- if(i++, 'N' == GETC(stream))
- if(i++, 'C' == GETC(stream)) {
- if(debug['v'])
- msg("SYNC\n");
- skipping = 0;
- getmeta();
- continue;
+ if(scan(c, "SYNC")) {
+ if(debug['v'])
+ msg("SYNC\n");
+ skipping = 0;
+ getmeta();
+ }else
+ if(scan(c, "HTTP/1.0 ")) {
+ msg("Stream died: %.*s\n", Blinelen(stream)-1, Brdline(stream, '\n'));
+ playing = 0;
+ }else {
+ bytes++;
+ if(!skipping)
+ BPUTC(&playerin, c);
+ else {
+ playerin.ocount = -playerin.bsize;
+ /* Waited too long, probably won't actually skip.
+ * Just start a new stream.
+ */
+ /* 8192 is arbitrary. */
+ if(skipping++ > 8192)
+ break;
}
- while(i--)
- Bungetc(stream);
- }
- if(!skipping)
- BPUTC(&playerin, c);
- else {
- playerin.ocount = -playerin.bsize;
- if(skipping++ > 8192)
- break;
}
}
if(debug['p'] && !playing)
@@ -117,6 +139,12 @@ proxyproc(void *v) {
if(c == Beof)
msg("Stream died\n");
Bterm(stream);
+ if(bytes > 2048)
+ j = 0;
+ else if(j++ > 15) {
+ msg("Stream won't stay open\n");
+ playing = 0;
+ }
}
qunlock(&lk);
}
@@ -139,6 +167,7 @@ endstream(void) {
return;
playing = 0;
+ postnote(PNGROUP, getpid(), "alarm");
qlock(&lk);
qunlock(&lk);
diff --git a/posix.c b/posix.c
@@ -6,7 +6,10 @@
void
noblock(int fd) {
- if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ int old;
+
+ old = fcntl(fd, F_GETFL, 0);
+ if(fcntl(fd, F_SETFL, old | O_NONBLOCK) == -1)
sysfatal("Can't set O_NONBLOCK for %d: %r", fd);
}
@@ -24,7 +27,7 @@ label(const char *fmt, ...) {
print("\033];LastFM: %V\007", &v);
va_end(v.args);
- return;
+ /* return; */
if(status == nil) {
home = getenv("HOME");
diff --git a/util.c b/util.c
@@ -7,7 +7,7 @@ static void
eat(char **s, int (*p)(int), int r) {
char *q;
- for(q=*s; p(*q) == r; q++)
+ for(q=*s; *q && p(*q) == r; q++)
;
*s = q;
}
@@ -19,6 +19,8 @@ tok(char **s) {
eat(s, isspace, 1);
p = *s;
eat(s, isspace, 0);
+ if(**s)
+ *(*s)++ = '\0';
eat(s, isspace, 1);
return p;
}
@@ -28,10 +30,9 @@ printfile(char *file, const char *fmt, ...) {
va_list ap;
int fd;
- fd = open(file, OWRITE);
+ fd = open(file, OWRITE|ONONBLOCK);
if(fd < 0)
return;
- noblock(fd);
va_start(ap, fmt);
vfprint(fd, (char*)fmt, ap);