/*
* Copy me if you can.
* by 20h
*
* I can.
* capso
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#define SHOUTSZ 512
int debug = 1;
char *
read_line(int s)
{
char *ret;
int l;
ret = nil;
l = 0;
while((ret = realloc(ret, ++l)) != nil
&& read(s, &ret[l - 1], 1) > 0 && l < 1024)
{
if(l > 1)
{
if(ret[l - 1] == '\n')
{
ret[l - 1] = '\0';
if(ret[l - 2] == '\r')
ret[l - 2] = '\0';
return ret;
}
}
}
if(ret != nil)
free(ret);
return nil;
}
int
read_httphdr(int s)
{
int blksz = 0;
char *ret, *n;
while((ret = read_line(s)) != nil && ret[0] != '\0'){
if(debug)
fprint(2, "dbg: %s\n", ret);
if(!strncmp(ret, "icy-metaint", 11)) /* match */
{
n = strchr(ret, ':') + 1; /* atoi handles space */
blksz = atoi(n);
}
free(ret);
}
return blksz;
}
int
read_pls(int fd, char **host, char **port, char **path)
{
char *ret, *h, *a;
while((ret = read_line(fd)) != nil && ret[0] != '\0')
{
if(!strncmp(ret, "File", 4))
{
h = strchr(ret + 13, ':');
if(h == nil)
{
*port = strdup("8000");
h = ret + 13;
} else {
*h++ = '\0';
}
a = strchr(h, '/');
if(a != nil)
{
*a++ = '\0';
} else {
*path = strdup("");
}
*host = strdup(ret + 13);
if(*port == nil)
*port = strdup(h);
if(*path == nil)
*path = strdup(a);
free(ret);
return 0;
}
free(ret);
}
return 1;
}
char*
read_title(Biobuf *in)
{
char buf[4096];
int size;
Bread(in, buf, 1);
if(*buf == 0)
return "";
size = (*buf&0xff) * 16;
Bread(in, buf, size);
buf[size+1] = '\0';
return buf; /* parse it with awk(1) */
}
void
shoutcast(int fd, char *path)
{
Biobuf in;
int l, osz, sz, data, blksz;
char buf[SHOUTSZ], *s;
data = 0;
fprint(fd, "GET /%s HTTP/1.0\r\n", path);
fprint(fd, "User-Agent: streamget/1st\r\n");
fprint(fd, "Icy-MetaData:1\r\n");
fprint(fd, "\r\n");
blksz = read_httphdr(fd);
osz = sz = (blksz < SHOUTSZ) ? blksz : SHOUTSZ;
Binit(&in, fd, OREAD);
while((l = Bread(&in, buf, sz)) > 0){
data += l;
if((blksz - data) < osz)
sz = blksz - data;
if(data == blksz)
{
data = 0;
sz = osz;
s = read_title(&in);
if(strlen(s) > 0)
fprint(2, "%s\n", s);
}
write(1, buf, l);
}
}
void
main(void)
{
int fd;
char *path, *host, *port;
host = port = path = nil;
if(read_pls(0, &host, &port, &path))
{
print("Wrong pls format.\n");
exits(0);
}
fd = dial(netmkaddr(host, "tcp", port), 0, 0, 0);
if(fd < 0)
{
perror("dial: %r");
exits(0);
}
free(host);
free(port);
shoutcast(fd, path);
exits(0);
}
|