Building a Shoutcast Server

I visited a friend of mine who had copied all his CDs to hard disk, using the Itunes system, and buying a dedicated player that hooked into his hifi. I began to wonder if I could do the same, but for free (or, more accurately, for no money).

First, I copied all my CDs to mp3 files using ripit, although I installed the standard package available under Debian etch.

Next challenge was how to get these mp3's playing on the hifi. Some sort of internet radio broadcasting thing, I guessed. I poked around the Shoutcast site and discovered I could pretty easily do what I wanted using the Shoutcast server (agreeing to a licence required) and broadcasting utilities (now no longer available) from http://www.shoutcast.com/downloads/sc_trans_posix_040.tgz. The server handles the delivery of content to clients, while sc_trans defines what the content is. Both of these come as Linux binaries, so if you are leary of binaries, you might want to look at other sources of supply.

I installed both of these packages on my main Debian box and configured them. The server is fairly easy, and the config file is well commented. I configured sc_trans to deliver random content from a playlist file (just a list of mp3 files).

In order to ease the creation of playlist files for my collection of mp3 files, I wrote a small python program playlist.py, which created playlists based on a simple database of categorised mp3 directories. All the ripped music lives is the /rep/music/mp3 directory, each subdirectory holding a CD's tracks. E.g:

  johnny_lytle_-_the_loop_-_new_and_groovy/
  josh_rouse_-_nashville/
  stacey_kent_-_dreamsville/
  kevin_ayers_-_the_confessions_of_dr_dream/

The database is a text file, each line consisting of a directory name (i.e. CD) and category, separated by a colon ":". More than one category may be assigned; multiple categories are comma "," separated. So, the above album directories could be represented as:

  johnny_lytle_-_the_loop_-_new_and_groovy:jazz
  josh_rouse_-_nashville:rock
  stacey_kent_-_dreamsville:jazz
  kevin_ayers_-_the_confessions_of_dr_dream:rock,prog

playlist.py allows the creation of playlists, based on categories one specifies on the command line. For full details, you'll need to look at the source code.

To control the server and broadcast playlists, I generated a GNU make file. The targets provided are:

Once this thing was broadcasting on the LAN, I could use yet another knackered laptop from work, now running Debian, to act as the client. It had a wireless card, so all I had to do was fire up xmms and plug the headphone outlet into the hifi. How easy was that?

Here's the Makefile:


# Make file to control shoutcast server

.SILENT:

.PHONY: start stop clean skip reload playlists use

MR=/rep/music

PID-TRANS=${MR}/pid.sc_trans
PID-SERV=${MR}/pid.sc_serv

start:
	if [ -r ${PID-TRANS} -o -r ${PID-SERV} ]; then \
		echo "Server already running" ; \
		exit 1 ; \
	fi
	cd ${MR}/sc/sc_trans_040 ;\
	./sc_trans_linux  </dev/null >/dev/null 2>&1  & echo $$! >${PID-TRANS}
	cd ${MR}/sc/server ;\
	./sc_serv  </dev/null >/dev/null 2>&1  & echo $$! >${PID-SERV}
	echo "Shoutcast server and transcoder started."

stop:
	if [ -r ${PID-TRANS} ]; then \
		/bin/kill -TERM `cat ${PID-TRANS}` ; \
	fi
	if [ -r ${PID-SERV} ]; then \
		/bin/kill -TERM `cat ${PID-SERV}` ; \
	fi
	rm -f pid.*

playlists:
	find `tools/playlist.py -a` -type f -name "*.mp3" >playlists/all
	for genre in `tools/playlist.py -l`; do \
		find `tools/playlist.py $$genre` -type f -name "*.mp3" \
				>playlists/$$genre  ;\
	done

use:
ifndef cat
	${error Must specifiy category with cat=}
endif
	if [ -r ${MR}/playlists/${cat} ]; then \
		cp ${MR}/playlists/${cat} ${MR}/sc/sc_trans_040/playlist ; \
	else \
		echo "No such playlist: ${cat}" ; \
	fi

skip:
	kill -WINCH `cat ${PID-TRANS}`

reload:
	kill -USR1 `cat ${PID-TRANS}`

clean:
	find ${MR} -type f -name "*.log" -delete