Streaming KEXP with Ruby
Jul 23, 2007 @ 9:23 amA while back, I ported JustePort from C# to Ruby so that I could play music on my AirportExpress. The result was a library called raop-client. Unfortunately, after writing that, I found that there were no libraries in Ruby to decode MP3s. So I wrote a wrapper around Lame called icanhasaudio. Right now, it only lets you decode MP3s, but I plan on adding new features soon.
So, I decided to write a little program that will stream music from KEXP to my Airport Express.
require 'rubygems'
require 'raop'
require 'icanhasaudio'
require 'socket'
rd, wr = IO.pipe
decoder = Thread.new(rd, wr) { |read, write|
reader = Audio::MPEG::Decoder.new
socket = TCPSocket.new('kexp-mp3-128k.cac.washington.edu', '8000')
socket.puts("GET / HTTP/1.0\r\n\r\n")
until(socket.readline == "\r\n"); end
reader.decode(socket, write);
write.close
}
sleep 2
raop = Net::RAOP::Client.new('192.168.1.173')
raop.connect
raop.play rd
raop.disconnect
rd.close
decoder.join
I’ll try to explain a little how this works. First I open a pipe which will be used to buffer my decoded mp3. The pipe is passed in to a new thread where my poor mans shoutcast client hooks up to KEXP and starts decoding the mp3 into the pipe.
Meanwhile the main thread waits a couple seconds to make sure there is data in the buffer, connects to the Airport Express, then starts streaming the data from the pipe.