Advertise MPD with Avahi

A rudimentary implementation to resolve #39, ignoring dbus errors (just restart), name collisions (choose a fresh name), etc.
This commit is contained in:
David Eisner 2013-11-01 09:27:31 +00:00
parent c0bfb5dfd3
commit ac2e413ec0
4 changed files with 72 additions and 0 deletions

View File

@ -23,6 +23,8 @@ class Extension(ext.Extension):
schema['password'] = config.Secret(optional=True)
schema['max_connections'] = config.Integer(minimum=1)
schema['connection_timeout'] = config.Integer(minimum=1)
schema['zeroconf_enabled'] = config.Boolean()
schema['zeroconf_name'] = config.String()
return schema
def validate_environment(self):

View File

@ -17,6 +17,9 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener):
super(MpdFrontend, self).__init__()
hostname = network.format_hostname(config['mpd']['hostname'])
port = config['mpd']['port']
self.config = config
self.hostname = hostname
self.port = port
try:
network.Server(
@ -36,8 +39,31 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener):
logger.info('MPD server running at [%s]:%s', hostname, port)
def on_start(self):
try:
if self.config['mpd']['zeroconf_enabled']:
name = self.config['mpd']['zeroconf_name']
import re
lo = re.search('(?<![.\d])(127|0)[.]', self.hostname)
hostname = "" if lo else self.hostname
from zeroconf import Zeroconf
self.service = Zeroconf(
stype="_mpd._tcp",
name=name, port=self.port, host=hostname)
self.service.publish()
logger.info('Registered with Avahi as %s', name)
except Exception as e:
logger.warning('Avahi registration failed (%s)', e)
def on_stop(self):
process.stop_actors_by_class(session.MpdSession)
try:
if self.service:
self.service.unpublish()
except Exception as e:
logger.warning('Avahi unregistration failed (%s)', e)
def send_idle(self, subsystem):
listeners = pykka.ActorRegistry.get_by_class(session.MpdSession)

View File

@ -5,3 +5,5 @@ port = 6600
password =
max_connections = 20
connection_timeout = 60
zeroconf_enabled = true
zeroconf_name = Mopidy

View File

@ -0,0 +1,42 @@
import dbus
__all__ = ["Zeroconf"]
class Zeroconf:
"""A simple class to publish a network service with zeroconf using
avahi.
"""
def __init__(self, name, port, stype="_http._tcp",
domain="", host="", text=""):
self.name = name
self.stype = stype
self.domain = domain
self.host = host
self.port = port
self.text = text
def publish(self):
bus = dbus.SystemBus()
server = dbus.Interface(
bus.get_object(
"org.freedesktop.Avahi",
"/"),
"org.freedesktop.Avahi.Server")
g = dbus.Interface(
bus.get_object("org.freedesktop.Avahi",
server.EntryGroupNew()),
"org.freedesktop.Avahi.EntryGroup")
g.AddService(-1, -1, dbus.UInt32(0),
self.name, self.stype, self.domain, self.host,
dbus.UInt16(self.port), self.text)
g.Commit()
self.group = g
def unpublish(self):
self.group.Reset()