It’s Alive — MPD + UPnP

December 22nd, 2009 Comments Off

I’ve put together a (working) quick and dirty script to wrap MPD in a UPnP Media Renderer. This is far from a complete solution, but it allows playing/pausing via UPnP Control Points. (Python-GUPnP CP works just dandy for it!)


from gi.repository import GUPnP, GObject, GLib
import mpd

CON_ID = None
MPDCLIENT = None

GObject.threads_init()

def setup_server():

ctx = GUPnP.Context(interface="eth0")

ctx.host_path("device.xml", "/device.xml")
ctx.host_path("AVTransport2.xml", "/AVTransport2.xml")

desc = "device.xml"
desc_loc = "./"

rd = GUPnP.RootDevice.new(ctx, desc, desc_loc)
rd.set_available(True)

return rd

def setup_mpd():
global CON_ID, MPDCLIENT
HOST = 'localhost'
PORT = '6600'
CON_ID = {'host':HOST, 'port':PORT}

MPDCLIENT = mpd.MPDClient()


def on_play_action(service, action):
print "Play"
MPDCLIENT.connect(**CON_ID)
MPDCLIENT.play()
MPDCLIENT.disconnect()

def on_pause_action(service, action):
print "Pause"
MPDCLIENT.connect(**CON_ID)
MPDCLIENT.pause()
MPDCLIENT.disconnect()

rd = setup_server()
print "UPnP MediaRenderer Service Exported"

setup_mpd()
print "MPD Client Setup"

service = rd.get_service("urn:schemas-upnp-org:service:AVTransport:1")
service.connect("action-invoked::Play", on_play_action)
service.connect("action-invoked::Pause", on_pause_action)

print "Awaiting commands..."
GObject.MainLoop().run()

Update: This is an updated version of the script that supports more commands and properly ends each UPnP action. Unfortunately it doesn’t entirely work because of either 1) A bug in g-i or 2) a problem with the gupnp api that will require a break to fix. Spent a lot of time today to understand the problem, hopefully we’ll have either a gupnp or a g-i fix in a few days.

Update 2: Now available on github. Zhaan (formerly known as “GUPnP-Python UPnP Control Point” has also been pushed)