Copyright © 2010 The G String. All Rights Reserved. Snowblind by Themes by bavotasan.com. Powered by WordPress.
Archive for March, 2009
I had just resurrected some old music from my music collection; some good, some very, very bad; but I wanted to be honest and display the information on my music blog. After all, it would show I have good taste in music ;)
I was streaming music using the excellent Icecast streaming server, and I wanted to display the currently playing track on my rails-based music blog as a link, which when clicked would feed the artist and track info into Google in a new window to help others find out about artists they might not have heard of. Fortunately, the current track information is provided by Icecast and is used by iTunes to display the current track information while I’m listening. The information is hosted on the admin section of the icecast server, /admin/stats.xml, so actually the simple solution would be to grab that XML file, parse it, and obtain the track information. The element I was interested in was called ‘Title’, under the source element, which contained the Artist – Track Title information, presumably from the mp3′s ID3 tag.
The first step was to obtain the XML file and read in the value of the Title element. I created a method named currently_playing in the application_helper.rb file, which would enable the method to be available to any view in the application.
Net::HTTP.start(‘hostname.co.uk’ , 8888) {|http|
req = Net::HTTP::Get.new(‘/admin/stats.xml’)
req.basic_auth ‘admin’, ICECAST_ADMIN_PASSWORD
response = http.request(req)
xml = REXML::Document.new response.body
xml.elements.each(‘icestats/source/title’) { |title|
return title.text
}
}
Note that I used a constant value for the Icecast admin password, controlled via the constants.rb file in the config folder. This nice block of code HTTP gets the XML file, takes care of the basic HTTP authentication and turns the result into an XML DOM, using XPath to retrieve the value of the Title element.
I decided that I wanted to display this information in the top-right of my header, so I found that component in rails and added a link:
<% cl = currently_listening
unless cl.empty? %>
<div id=”currentlylistening”>
Currently listening to : <%= link_to cl, { :controller => ‘referrals’, :action => ‘redirect_google’,
:title => CGI.escape(cl)}, :target => ‘_blank’ %>
</div>
<% end %>
Finally, I added a method in my referrals controller, called redirect_google. That way, I don’t lose page rank having a link to Google and instead redirect the user where I want them to go.
def redirect_google
redirect_to ‘http://www.google.co.uk/search?q=’ + params + ‘&ie=utf-8&oe=utf-8&aq=t’
end
Now, whenever the user visits a page, they can see what I’m actually listening to in iTunes. Time to delete my embarrassing Simply Red, Eternal and Cher tracks…
I like to think that I stay ahead of the times. In 2000, I used to think that my Creative Nomad jukebox with 6GB of hard-disk space was the most incredible thing ever, and I took mine to University, proud of its ability to reduce a shelf-load of CDs into an object no larger than one or two discs. It was cool how you could take a bunch of music, let them all get strung together into a continuous stream, and have them played back in a random order, like your own personal radio station without the ‘personalities’. Back then, Creative had to market them as jukeboxes- they were still too bulky to be used like iPod shuffles are now. But that was nearly ten years ago, and times must move on.
I have found that the biggest problem after moving to mp3s is keeping up with my collection. I stopped collecting after around 20GB and began to just have smaller collections here and there: some music on my PC laptop, some on my Mac, some on my PC, some on a mp3 player. Overall, it became difficult to keep it all in one place, and so whenever I’d buy a CD, download an album or mix one of my own tracks my collection would become increasingly fragmented. Its got to the stage now where I haven’t actually listened to parts of my collection for many months, so I decided to do something about it.
I wanted to setup my own jukebox, streaming music over the web, so that I could access it wherever I was, from any platform, at any time. That way, all my music is in one place and I save heaps of disc space on my local computers.
So I decided to setup Icecast, an open-source streaming server. It works by receiving an audio stream from somewhere, and converting it into itty-bitty-bytes that are downloaded to clients over the Internet, such as iTunes. The audio stream can be a live feed from a soundcard, or taken from a playlist running off your hard drive. I used the latter approach, because I have a large directory of mp3 files that I want to listen to. This involves using another piece of software called Ices, which is responsible for building the audio stream sent to Icecast. Its a handy piece of software; working from a playlist, it can randomly choose a track, re-sample it to a lower bitrate (to save your bandwidth costs and keep the music playing smoothly) and even cross-fade between tracks.
While I was busy rsyncing my music collection to my server, I downloaded and installed icecast 2.3.2 and ices 0.4 from source. I chose the older version of ices, because it deals with mp3s, whereas the newer version can only read ogg Vorbis files, and my collection consists mainly of mp3 files. I needed to install a couple of dependencies thrown up by configure, specifically libxslt, which I did using apt-get. So far so good.
The first configuration step was configuring Icecast. By default, icecast creates a configuration file in /usr/local/etc/ called icecast.xml which you can edit. The file is commented with examples, and can be tweaked as needed. Don’t forget as this is an XML file that it should be well-formed with matching opening and closing tags, as well as opening and closing comments (and no nesting comments!). I reduced the number of clients (it is a private stream for me!), set the hostname/port, log directory and the source, relay and admin passwords (they’re ‘hackme’ by default!). Following that, I was able to test the server was working by running icecast and checking the error.log file:
icecast -c /usr/local/etc/icecast.xml
tail /var/log/icecast/error.log
I could also visit the admin pages at the hostname and port I had configured, which show a basic admin interface.
The next step was to provide audio for Icecast by configuring Ices. Similarly, the default install created an example configuration file in /usr/local/etc/ called ices.conf.dist. I moved this to ices.conf and began to edit. I changed:
- <File> – I set this to be the playlist file I wanted for the stream. The playlist file is simply a text file with a path to an mp3 file on each line, so I generated it automatically from the music files I kept in /music.
find /music -name *.mp3 > /usr/local/etc/playlist.txt - <Randomize> – I set this to 1 so that Ices jumped around the list, creating a radio station style mix, rather than playing through sequentially.
- <Crossfade> – I set this to 5 so that each song fades-in/fades-out over the course over five seconds, resulting in nice, continuous play.
- <BaseDirectory> – I set this to be the same as the log directory of Icecast so that the logs were nearby each other.
- <Hostname> – I set this to match the hostname I configured in Icecast.
- <Port> – Ditto…
- <Password> – Same…
- <Name> – I set this to “Dan’s Jukebox”, which is what the stream is listed under in iTunes.
- <Genre> – I set this to “Anything”.
- <Description> – This also appears on the web interface and iTunes so I wrote something in there too.
- <URL> – This URL is a page used to describe the stream, and appears on rotation in the iTunes interface so I used my website URL.
- <Public> – I set this to 0 so that the stream isn’t listed publicly and I get subpoenaed by the RIAA…
- <Bitrate> – Very important! This is the setting that Ices uses to determine what quality to send the audio in, and has implications on the amount of bandwidth you use; which in turn determines the financial cost and smoothness of your stream. If your stream is available to multiple users, you have to consider that this figure would be multiplied by the number of listeners, so be careful not to set it too high. 64kbps is about the quality you get listening to MySpace and is low-quality; but you won’t really notice if listening on a laptop speaker anyway. Bearing in mind that the mp3s were mostly encoded at 128kps originally, I decided to keep my bandwidth use down and started out with 64kbs. It sounds alright to me, maybe I’ll ramp it up to about 80-something later if I feel like it.
Once configured, I tested Ices by running it without any options:
ices
By default, Icecast and Ices run in the foreground, which means that once you start running them they don’t return the console back to you and you have to open another to keep using Linux. I wanted them to run in the background as daemons so that when my server boots up / restarts, or I log-out, the music keeps going. I so put together two init.d scripts, starting from /etc/skeleton, to start/stop Icecast and Ices. Below is the icecast init.d script I’m using, and Ices is similar.
#! /bin/sh
# Author: Dan Garland dan@NOSPAMdangarland.co.uk>
# Do NOT “set -e”
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=”Icecast Server”
NAME=icecast
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS=”-b -c /usr/local/etc/icecast.xml”
ICES=/usr/local/bin/ices
USER=$NAME
GROUP=$NAME
PIDFILE=/var/run/$NAME.pid
ICES_PIDFILE=/var/run/ices.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
|| exit 0
# Read configuration variable file if it is present
&& . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon –start –quiet –chuid $USER:$GROUP –pidfile $PIDFILE –exec $DAEMON –test > /dev/null \
|| return 1
start-stop-daemon –start –quiet –chuid $USER:$GROUP –pidfile $PIDFILE –exec $DAEMON — \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon –stop –quiet –retry=TERM/30/KILL/5 –pidfile $PIDFILE –name $NAME
RETVAL=”$?”
&& return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon –stop –quiet –oknodo –retry=0/30/KILL/5 –exec $DAEMON
&& return 2
# Many daemons don’t delete their pidfiles when they exit.
rm -f $PIDFILE
return “$RETVAL”
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon –stop –signal 1 –quiet –pidfile $PIDFILE –name $NAME
return 0
}
case “$1″ in
start)
&& log_daemon_msg “Starting $DESC” “$NAME”
do_start
case “$?” in
0|1) && log_end_msg 0 ;;
2) && log_end_msg 1 ;;
esac
;;
stop)
&& log_daemon_msg “Stopping $DESC” “$NAME”
do_stop
case “$?” in
0|1) && log_end_msg 0 ;;
2) && log_end_msg 1 ;;
esac
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave ‘force-reload’ as an alias for ‘restart’.
#
#log_daemon_msg “Reloading $DESC” “$NAME”
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the “reload” option is implemented then remove the
# ‘force-reload’ alias
#
log_daemon_msg “Restarting $DESC” “$NAME”
do_stop
case “$?” in
0|1)
do_start
case “$?” in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
#echo “Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}” >&2
echo “Usage: $SCRIPTNAME {start|stop|restart|force-reload}” >&2
exit 3
;;
esac
:
Note the -b option to run in the background and the –chuid option to run the program as the icecast user and group (Icecast doesn’t run as root). If you don’t have a icecast user or group, create them as root with the adduser and addgroup commands:
adduser icecast
addgroup icecast
I could then tell Debian to run these scripts at start-up using update-rc.d:
update-rc.d icecast defaults
update-rc.d ices defaults
Once running, I could point iTunes to the stream by choosing Advanced -> Open Audio Stream, and typing in the full url to the mointpoint. Now I’m listening to some track I swear I haven’t heard since the mid 90′s, and I want to tell the world.
An aside. I’m not much of a photographer; I agree with my namesake Alex Garland’s opinion that rather than photographing momentous events you are better off simply witnessing them. This conviction has resulted in some neglect of my digital camera which I got for Christmas last year, but I did have a few snaps rattling around in its SD card. I decided to publish them on the web; why not after all? But rather than using some corporate ad-based solution like Flickr I wanted to know whether there was some software lying around on the web that would allow me to create a web gallery for my photos instantly and effortlessly.
That software is called JAlbum. One of the more impressive Java desktop applications I’ve seen recently, I had the photos off my camera and onto the web in five minutes, looking good, with a slideshow option and it even handled mov files.
Once you’ve downloaded the software and verified your e-mail, you will have an application called JAlbum. When you fire it up, you’ll see a large window just waiting for photographs. I dragged + dropped all the photographs from the camera, mounted as a USB drive, straight into the JAlbum window.
Once you drag+dropt the photographs, JAlbum asks you to create an album and to name it. This name is used as part of the URL which the album will be hosted later.
Then, your photographs appear as a grid of thumbnails for you to review. This is the point to re-order photographs, strip-out those red-eyes and drop those embarrassing photos of you drunk and trying to smoke the cigarette on a camel advertisement. Use the ‘exclude’ button to drop photographs from the album.
At this point, you can begin to consider how you want the gallery to be presented on the web. The software is going to generate a bunch of static HTML and CSS files, but you can decide what they look like using the range of built-in skins. On the left-hand side, choose a skin, and then an appearance; for each skin comes in a variety of colours. A pop-up instantly demonstrates what the album will look like, so you don’t have to wait to see the results.
Once you have decided on your flavour, its time to upload. For those without a webserver, perhaps the majority, JAlbum provide webspace to host your album on a subdomain matching your username. Luckily for me, I have a webserver, so I decided to use that.
Punch the ‘Make JAlbum’ button, the one marked with a frog. The software then resizes your imagery down ready for uploading and generates all of the webpages used to display them.
Once complete, if you press the ‘publish’ button, I trust the software when it says it will upload the album to your allotted webspace on jalbum.net. I however wanted to use my own server, so I cancelled that and pressed the arrow next to ‘Publish’ to choose ‘manage / delete published albums’. From there I could add the user account on my Linux box and configure it to access my server.
I checked the box ‘secure’ to use scp to copy the files, and provided my username/password. There is also a nifty feature to ‘show full server directory tree’, so that you can rummage around your server’s directories to find the best place to upload your album. I created a sub-folder photos from my web server’s DocumentRoot and placed the album there.
The main thing to remember is that JAlbum doesn’t know how your webserver is configured: where DocumentRoot is. So in order for everything to work properly, you have to select the DocumentRoot folder (normally /var/www) and press the ‘Mark as web root’ button. This allows JAlbum to figure out where URLs should point, relative from the DocumentRoot. Make an album directory for your gallery, and then press ‘Upload’.
And that is really as simple as that. I was very impressed by the slick design, the effortless process and the flexibility to ‘just work’ with my existing setup. And its free!
You can see an example album here: http://www.dangarland.co.uk/photos/France2008
Continue Reading »
One of the projects I’m working on right now is an ambitious attempt to realise a 3D-model of the Conic Bellophone, an experimental musical instrument under developed as part of a PhD project. The requirements were to develop a 3D model that can be viewed from any angle, and when a bell is ‘struck’ to sound a sample captured from the real thing.
I hoped to dust-off my Xj3D knowledge from hacking around at University during my thesis, and despite some wrestling I managed to get as far as a 3D model with sounding bells, and a glissando effect when you run the mouse cusor over the bells (press the red box).
Still to do: I have to figure out how to persuade the time/event model to accept restarting sound. Currently, the spec says that passing the current time to both the startTime and stopTime of an AudioNode should restart the node, but I am finding this not to be the case, and I’m trying workarounds with script nodes. After that’s solved, I will be working with MIDI to allow the instrument to play arrangements made in MIDI; all in 3D.
The instrument uses the applet-launcher Java web start program, to wrap an applet which renders the Xj3D browser and the scene. I’ve found this has issues when used in windows, so there is still some work to do.
But take a sneak preview: http://www.dangarland.co.uk/virtualinstrument . Don’t forget to press ‘trust’ on the security prompts that appear.
Continue Reading »