coderholic

Extending VLC with Lua

When I'm programming I like to listen to music, as I find it blocks out distractions and keeps my mind focused. I usually listen to a variety of streaming chillout radio stations using my command line application PyRadio. I was recently reading through the Lua wikipedia page and noticed that VLC media player has support for Lua plugins, and thought that creating a streaming radio plugin would be a great way to learn some Lua, as well as giving me a new way of listening to my music.

Getting up and running

Support for Lua extensions was added to VLC in version 1.1, which is still in beta. You can get the beta version from the VLC nightlies site, or follow this helpful guide on upgrading for Ubuntu users. I followed the guide, and after getting VLC 1.1.5 installed I was keen to try some of the sample extensions, but none of them worked! Running vlc -vvv from the command line allowed me to see the debug output and track down the problems. I fixed the majority of the issues by simply removing quotes around function references (eg. add_button("OK", "button_clicked") -> add_button("OK", button_clicked)).

Documentation

The documentation for writing Lua extensions is definitely lacking. It seems to consist of a single README file and the broken sample extensions. Fortunately it's a fairly simple API, and the Lua documentation itself is fantastic (there's a reference manual, an active community wiki, and even a free book).

The streaming radio extension

After going through the README and sample extensions, and some trial and error, I was able to put together the streaming radio extension shown at the top of this post. I'm really pleased with the results, and I'm actually using it right now as I write this post! The full code listing for the extension is below:

--[[
 Streaming Radio Player extension for VLC >= 1.1.0
 Authors: Ben Dowling (http://www.coderholic.com)
--]]

stations = {
    { name = "SomaFM: Groove Salad", url = "http://somafm.com/startstream=groovesalad.pls" },
    { name = "Digitally Imported: Chillout", url = "http://listen.di.fm/public3/chillout.pls" },
    { name = "Digitally Imported: Chillout Dreams", url = "http://listen.di.fm/public3/chilloutdreams.pls" },
    { name = "Digitally Imported: Soulful House", url = "http://listen.di.fm/public3/soulfulhouse.pls" },
    { name = "Digitally Imported: Lounge", url = "http://listen.di.fm/public3/lounge.pls" },
    { name = "Monkey Radio Groove", url = "http://groove.monkeyradio.org/"},
    { name = "SKY.FM Jazz", url = "http://www.sky.fm/mp3/jazz.pls"},
    { name = "SKY.FM Smooth Jazz", url = "http://www.sky.fm/mp3/smoothjazz.pls"},
    { name = "SKY.FM Uptempo Smooth Jazz", url = "http://www.sky.fm/mp3/uptemposmoothjazz.pls"},
}

function descriptor()
    return { title = "Streaming Radio Player" ;
             version = "0.1" ;
             author = "Ben Dowling" ;
             capabilities = {} }
end

function activate()
    dlg = vlc.dialog("Streaming Radio Player")
    list = dlg:add_list(1, 3, 4, 1)
    button_play = dlg:add_button("Play", click_play, 1, 4, 4, 1)
    -- Add the radio stations
    for idx, details in ipairs(stations) do
        list:add_value(details.name, idx)
    end
    dlg:show()
end

function click_play()
    selection = list:get_selection()
    if (not selection) then return 1 end
    local sel = nil
    for idx, selectedItem in pairs(selection) do
        sel = idx
        break
    end
    details = stations[sel]

    -- Play the selected radio station
    vlc.playlist.clear()
    vlc.playlist.add()
    vlc.playlist.play()
end

function deactivate()
end

function close()
    vlc.deactivate()
end

It's a testament to the power of the VLC extension API how little code is required. Hopefully by the time 1.1 comes out of beta the documentation will have improved, and we'll start to see lots of really useful extensions.

Thoughts on Lua

One of the aims of writing the VLC extension was to learn Lua. It seems very similar to JavaScript, but with fewer bad parts, and some really nice additions. When writing the extension I got some exposure to Lua's table data structure. It initially struck me as similar to PHP's array structure, but I ran into trouble when specifying keys:

-- What I thought would work but didn't
{ "key" = "value" }
-- What does work (if the key doesn't contain spaces)
{ key = "value" }
-- Key with spaces
{ ["a key"] = "value" }

It still seems strange to me, but I'm sure there's a good reason.

If you've had experience with Lua (or you've got some good ideas for another VLC extension!) please let me know your thoughts in the comments.

Posted on 13 Jan 2011
If you enjoyed reading this post you might want to follow @coderholic on twitter or browse though the full blog archive.