Plan 9 from Bell Labs’s /usr/web/sources/contrib/fhs/icy.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * ICY (I Can Yell) aka SHOUTcast client
 *
 * Metadata goes to standard error. MP3 data to standard output.
 * Pipe to a MP3 decoder:
 *	icy http://... | games/mp3dec
 */
 
#include <u.h>
#include <libc.h>
#include <bio.h>

typedef struct Icy Icy;
struct Icy {
	Biobuf *bi, *bo;
	//int status;
	//char *name;
	//char *genre;
	//char *url;
	//int pub;
	//int br;
	int metaint;
};

Biobuf icybin, icybout;
Icy icymeta;

void*
emalloc(ulong size)
{
	void *p;
	
	p = malloc(size);
	if(p == nil)
		sysfatal("malloc failed: %r");
	return p;
}

Icy*
icyinit(int fd, char *path)
{
	char *line;
	Icy *icy;
	Biobuf *bi, *bo;
	
	icy = &icymeta;
	icy->bi = bi = &icybin;
	icy->bo = bo = &icybout;
	Binit(bi, fd, OREAD);
	Binit(bo, fd, OWRITE);
	
	Bprint(bo, "GET /%s\r\n"
		"User-Agent: icy/0.1\r\n"
		"Icy-MetaData:1\r\n"
		"\r\n", path);
	Bflush(bo);
	
	icy->metaint = 0;
	while((line = Brdstr(bi, '\n', 1)) != nil){
		if(Blinelen(bi) > 0 && line[Blinelen(bi)-1] == '\r')
			line[Blinelen(bi)-1] = 0;
		if(line[0] == 0)
			break;
		fprint(2, "%s\n", line);
		
		if(strncmp(line, "icy-metaint:", 12)==0)
			icy->metaint = atoi(line+12);
		
		free(line);
	}
	return icy;
}

void
printtitle(Icy *icy)
{
	int len, n;
	char *title;
	
	len = Bgetc(icy->bi);
	if(len <= 0)
		return;
	len *= 16;
	title = emalloc(len+1);
	n = Bread(icy->bi, title, len);
	if(n <= 0){
		free(title);
		return;
	}
	title[n] = 0;
	fprint(2, "%s\n", title);
	free(title);
}

void
parseurl(char *url, char **host, char **port, char **path)
{
	char *h, *s, *p;
	
	if(strncmp(url, "http://", 7) != 0)
		sysfatal("bad url");
	h = url+7;
	s = strchr(h, ':');
	p = strchr(h, '/');
	if(s == nil || s > p)
		s = "80";
	else
		*s++ = 0;
	if(p == nil)
		p = "";
	else
		*p++ = 0;
	if(h[0] == 0 || h[0] == 0)
		sysfatal("bad host/port");
	
	*host = h;
	*port = s;
	*path = p;
}

void
main(int argc, char *argv[])
{
	int fd, n, title;
	Icy *icy;
	uchar *data;
	char *host, *port, *path;
	
	ARGBEGIN{
	}ARGEND
	
	if(argc < 1){
		fprint(2, "usage: ice url\n");
		exits("usage");
	}
	
	parseurl(argv[0], &host, &port, &path);
	fd = dial(netmkaddr(host, "tcp", port), 0, 0, 0);
	if(fd < 0)
		sysfatal("dial: %r");
	icy = icyinit(fd, path);
	
	title = 1;
	if(icy->metaint <= 0)
		title = 0;
	
	data = emalloc(icy->metaint);
	for(;;){
		n = Bread(icy->bi, data, icy->metaint);
		if(n <= 0)
			break;
		write(1, data, n);
		if(title)
			printtitle(icy);
	}
	if(n < 0)
		sysfatal("read: %r");
	
	free(data);
	close(fd);
	exits(nil);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.