From ac2e413ec03c68b39819292a3ecf28dadd61d470 Mon Sep 17 00:00:00 2001 From: David Eisner Date: Fri, 1 Nov 2013 09:27:31 +0000 Subject: [PATCH 01/15] Advertise MPD with Avahi A rudimentary implementation to resolve #39, ignoring dbus errors (just restart), name collisions (choose a fresh name), etc. --- mopidy/frontends/mpd/__init__.py | 2 ++ mopidy/frontends/mpd/actor.py | 26 ++++++++++++++++++++ mopidy/frontends/mpd/ext.conf | 2 ++ mopidy/frontends/mpd/zeroconf.py | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 mopidy/frontends/mpd/zeroconf.py diff --git a/mopidy/frontends/mpd/__init__.py b/mopidy/frontends/mpd/__init__.py index 276be450..28f9c951 100644 --- a/mopidy/frontends/mpd/__init__.py +++ b/mopidy/frontends/mpd/__init__.py @@ -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): diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 4d983b73..b48b2b65 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -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('(? Date: Tue, 5 Nov 2013 10:33:04 +0000 Subject: [PATCH 02/15] Avahi python compatibility fix --- mopidy/frontends/mpd/actor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index b48b2b65..f2e203c6 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -47,7 +47,7 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): lo = re.search('(? Date: Tue, 5 Nov 2013 10:37:54 +0000 Subject: [PATCH 03/15] Avahi wrapper moved to utils --- mopidy/frontends/mpd/actor.py | 2 +- mopidy/{frontends/mpd => utils}/zeroconf.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename mopidy/{frontends/mpd => utils}/zeroconf.py (100%) diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index f2e203c6..ab5bd35d 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -47,7 +47,7 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): lo = re.search('(? Date: Tue, 5 Nov 2013 11:06:51 +0000 Subject: [PATCH 04/15] Avahi constants named --- mopidy/utils/zeroconf.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index db92877a..750f6731 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -2,6 +2,10 @@ import dbus __all__ = ["Zeroconf"] +avahi_IF_UNSPEC = -1 +avahi_PROTO_UNSPEC = -1 +avahi_PublishFlags_None = 0 + class Zeroconf: """A simple class to publish a network service with zeroconf using @@ -31,7 +35,8 @@ class Zeroconf: server.EntryGroupNew()), "org.freedesktop.Avahi.EntryGroup") - g.AddService(-1, -1, dbus.UInt32(0), + g.AddService(avahi_IF_UNSPEC, avahi_PROTO_UNSPEC, + dbus.UInt32(avahi_PublishFlags_None), self.name, self.stype, self.domain, self.host, dbus.UInt16(self.port), self.text) From c4281339b6401d5c83f6231b4b5ade3e8a2334cd Mon Sep 17 00:00:00 2001 From: David Eisner Date: Tue, 5 Nov 2013 11:07:35 +0000 Subject: [PATCH 05/15] Avahi hostname choice extracted for reuse --- mopidy/frontends/mpd/actor.py | 5 +---- mopidy/utils/zeroconf.py | 6 +++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index ab5bd35d..66218593 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -43,14 +43,11 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): try: if self.config['mpd']['zeroconf_enabled']: name = self.config['mpd']['zeroconf_name'] - import re - lo = re.search('(? Date: Tue, 5 Nov 2013 16:23:58 +0000 Subject: [PATCH 06/15] Advertise HTTP with Avahi --- mopidy/frontends/http/__init__.py | 2 ++ mopidy/frontends/http/actor.py | 26 ++++++++++++++++++++++++-- mopidy/frontends/http/ext.conf | 2 ++ mopidy/frontends/mpd/actor.py | 6 +++--- mopidy/frontends/mpd/ext.conf | 2 +- mopidy/utils/zeroconf.py | 5 ++++- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/mopidy/frontends/http/__init__.py b/mopidy/frontends/http/__init__.py index 6d84b25b..d5f8f1bc 100644 --- a/mopidy/frontends/http/__init__.py +++ b/mopidy/frontends/http/__init__.py @@ -21,6 +21,8 @@ class Extension(ext.Extension): schema['hostname'] = config.Hostname() schema['port'] = config.Port() schema['static_dir'] = config.Path(optional=True) + schema['zeroconf_enabled'] = config.Boolean() + schema['zeroconf_name'] = config.String() return schema def validate_environment(self): diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index 5e49d2cd..47602b33 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -28,10 +28,13 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): self._setup_logging(app) def _setup_server(self): + self.config_section = self.config['http'] + self.hostname = self.config_section['hostname'] + self.port = self.config_section['port'] cherrypy.config.update({ 'engine.autoreload_on': False, - 'server.socket_host': self.config['http']['hostname'], - 'server.socket_port': self.config['http']['port'], + 'server.socket_host': self.hostname, + 'server.socket_port': self.port, }) def _setup_websocket_plugin(self): @@ -87,11 +90,30 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): logger.debug('Starting HTTP server') cherrypy.engine.start() logger.info('HTTP server running at %s', cherrypy.server.base()) + try: + if self.config_section['zeroconf_enabled']: + name = self.config_section['zeroconf_name'] + + from mopidy.utils.zeroconf import Zeroconf + self.service = Zeroconf( + stype="_http._tcp", + name=name, port=self.port, host=self.hostname, + text=["path=/"]) + 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): logger.debug('Stopping HTTP server') cherrypy.engine.exit() logger.info('Stopped HTTP server') + try: + if self.service: + self.service.unpublish() + except Exception as e: + logger.warning('Avahi unregistration failed (%s)', e) def on_event(self, name, **data): event = data diff --git a/mopidy/frontends/http/ext.conf b/mopidy/frontends/http/ext.conf index 04fb1aae..f3df5f1a 100644 --- a/mopidy/frontends/http/ext.conf +++ b/mopidy/frontends/http/ext.conf @@ -3,6 +3,8 @@ enabled = true hostname = 127.0.0.1 port = 6680 static_dir = +zeroconf_enabled = true +zeroconf_name = Mopidy [loglevels] cherrypy = warning diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 66218593..b252ee2d 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -17,7 +17,7 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): super(MpdFrontend, self).__init__() hostname = network.format_hostname(config['mpd']['hostname']) port = config['mpd']['port'] - self.config = config + self.config_section = config['mpd'] self.hostname = hostname self.port = port @@ -41,8 +41,8 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): def on_start(self): try: - if self.config['mpd']['zeroconf_enabled']: - name = self.config['mpd']['zeroconf_name'] + if self.config_section['zeroconf_enabled']: + name = self.config_section['zeroconf_name'] from mopidy.utils.zeroconf import Zeroconf self.service = Zeroconf( diff --git a/mopidy/frontends/mpd/ext.conf b/mopidy/frontends/mpd/ext.conf index 667aff24..d51c04f6 100644 --- a/mopidy/frontends/mpd/ext.conf +++ b/mopidy/frontends/mpd/ext.conf @@ -6,4 +6,4 @@ password = max_connections = 20 connection_timeout = 60 zeroconf_enabled = true -zeroconf_name = Mopidy +zeroconf_name = Mopidy (MPD) diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index d77738b4..4e802f7c 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -14,7 +14,7 @@ class Zeroconf: """ def __init__(self, name, port, stype="_http._tcp", - domain="", host="", text=""): + domain="", host="", text=[]): self.name = name self.stype = stype self.domain = domain @@ -39,6 +39,9 @@ class Zeroconf: server.EntryGroupNew()), "org.freedesktop.Avahi.EntryGroup") + if self.text: + self.text = [[dbus.Byte(ord(c)) for c in s] for s in self.text] + g.AddService(avahi_IF_UNSPEC, avahi_PROTO_UNSPEC, dbus.UInt32(avahi_PublishFlags_None), self.name, self.stype, self.domain, self.host, From cf5589b4eba1315ce1931cd3b4bcb7930f25dfd5 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sat, 9 Nov 2013 13:56:05 +0100 Subject: [PATCH 07/15] avahi: Style and code cleanups in zeroconf module. - Prepare for handling missing dbus directly in module. - Constants should always be all caps. - Extracted helpers from class to convey intent via their naming. - Moved imports out of class, imports should always be on the top. - Made sure calling publish mutiple times does not re-convert text. - Made sure calling unpublish without publish does not break. --- mopidy/utils/zeroconf.py | 69 +++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index 4e802f7c..c69fb950 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -1,17 +1,30 @@ -import dbus +from __future__ import unicode_literals -__all__ = ["Zeroconf"] +try: + import dbus +except ImportError: + dbus = None -avahi_IF_UNSPEC = -1 -avahi_PROTO_UNSPEC = -1 -avahi_PublishFlags_None = 0 +import re + +_AVAHI_IF_UNSPEC = -1 +_AVAHI_PROTO_UNSPEC = -1 +_AVAHI_PUBLISHFLAGS_NONE = 0 + + +def _filter_loopback_and_meta_addresses(host): + # TODO: see if we can find a cleaner way of handling this. + if re.search(r'(? Date: Sat, 9 Nov 2013 14:04:38 +0100 Subject: [PATCH 08/15] avahi: Improve error handling for dbus errors. - Handle dbus not being installed. - Handle not finding the system bus. - Handle not finding the avahi service. - Return if publish succeeded. --- mopidy/utils/zeroconf.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index c69fb950..62545e27 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -1,17 +1,21 @@ from __future__ import unicode_literals +import logging +import re + +logger = logging.getLogger('mopidy.utils.zerconf') + try: import dbus except ImportError: dbus = None -import re - _AVAHI_IF_UNSPEC = -1 _AVAHI_PROTO_UNSPEC = -1 _AVAHI_PUBLISHFLAGS_NONE = 0 + def _filter_loopback_and_meta_addresses(host): # TODO: see if we can find a cleaner way of handling this. if re.search(r'(? Date: Sat, 9 Nov 2013 14:21:41 +0100 Subject: [PATCH 09/15] avahi: Convert MPD and HTTP to use cleaned up versions - Move imports to top as they should be. - Report state based on publish return value. - Remove overly broad except clauses. - Unpublish before stopping servers. --- mopidy/frontends/http/actor.py | 31 ++++++++++++++----------------- mopidy/frontends/mpd/actor.py | 32 ++++++++++++++------------------ 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index 47602b33..d5c37f09 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -11,6 +11,7 @@ from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool from mopidy import models from mopidy.core import CoreListener +from mopidy.utils import zeroconf from . import ws @@ -22,6 +23,7 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): super(HttpFrontend, self).__init__() self.config = config self.core = core + self.zeroconf_service = None self._setup_server() self._setup_websocket_plugin() app = self._create_app() @@ -90,30 +92,25 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): logger.debug('Starting HTTP server') cherrypy.engine.start() logger.info('HTTP server running at %s', cherrypy.server.base()) - try: - if self.config_section['zeroconf_enabled']: - name = self.config_section['zeroconf_name'] - from mopidy.utils.zeroconf import Zeroconf - self.service = Zeroconf( - stype="_http._tcp", - name=name, port=self.port, host=self.hostname, - text=["path=/"]) - self.service.publish() + if self.config_section['zeroconf_enabled']: + name = self.config_section['zeroconf_name'] + self.zeroconf_service = zeroconf.Zeroconf( + stype="_http._tcp", name=name, port=self.port, + host=self.hostname) - logger.info('Registered with Avahi as %s', name) - except Exception as e: - logger.warning('Avahi registration failed (%s)', e) + if self.zeroconf_service.publish(): + logger.info('Registered HTTP with zeroconf as %s', name) + else: + logger.warning('Registering HTTP with zeroconf failed.') def on_stop(self): + if self.zeroconf_service: + self.zeroconf_service.unpublish() + logger.debug('Stopping HTTP server') cherrypy.engine.exit() logger.info('Stopped HTTP server') - try: - if self.service: - self.service.unpublish() - except Exception as e: - logger.warning('Avahi unregistration failed (%s)', e) def on_event(self, name, **data): event = data diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index b252ee2d..51735837 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -7,7 +7,7 @@ import pykka from mopidy.core import CoreListener from mopidy.frontends.mpd import session -from mopidy.utils import encoding, network, process +from mopidy.utils import encoding, network, process, zeroconf logger = logging.getLogger('mopidy.frontends.mpd') @@ -20,6 +20,7 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): self.config_section = config['mpd'] self.hostname = hostname self.port = port + self.zeroconf_service = None try: network.Server( @@ -40,27 +41,22 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): logger.info('MPD server running at [%s]:%s', hostname, port) def on_start(self): - try: - if self.config_section['zeroconf_enabled']: - name = self.config_section['zeroconf_name'] + if self.config_section['zeroconf_enabled']: + name = self.config_section['zeroconf_name'] + self.zeroconf_service = zeroconf.Zeroconf( + stype="_mpd._tcp", name=name, port=self.port, + host=self.hostname) - from mopidy.utils.zeroconf import Zeroconf - self.service = Zeroconf( - stype="_mpd._tcp", - name=name, port=self.port, host=self.hostname) - self.service.publish() - - logger.info('Registered with Avahi as %s', name) - except Exception as e: - logger.warning('Avahi registration failed (%s)', e) + if self.zeroconf_service.publish(): + logger.info('Registered MPD with zeroconf as %s', name) + else: + logger.warning('Registering MPD with zeroconf failed.') def on_stop(self): + if self.zeroconf_service: + self.zeroconf_service.unpublish() + 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) From 6c6932c374d5be7de6b69d50ae40a09f423218b0 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sat, 9 Nov 2013 17:22:37 +0100 Subject: [PATCH 10/15] avahi: Only convert single string at a time in helper --- mopidy/utils/zeroconf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index 62545e27..8af63777 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -24,7 +24,7 @@ def _filter_loopback_and_meta_addresses(host): def _convert_text_to_dbus_bytes(text): - return [[dbus.Byte(ord(c)) for c in s] for s in text] + return [dbus.Byte(ord(c)) for c in text] class Zeroconf: @@ -62,7 +62,7 @@ class Zeroconf: bus.get_object("org.freedesktop.Avahi", server.EntryGroupNew()), "org.freedesktop.Avahi.EntryGroup") - text = _convert_text_to_dbus_bytes(self.text) + text = [_convert_text_to_dbus_bytes(t) for t in self.text] self.group.AddService(_AVAHI_IF_UNSPEC, _AVAHI_PROTO_UNSPEC, dbus.UInt32(_AVAHI_PUBLISHFLAGS_NONE), self.name, self.stype, self.domain, self.host, From fb31193ed057ea87d5477ab302e0cd61c9b79dcf Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Mon, 11 Nov 2013 21:26:11 +0100 Subject: [PATCH 11/15] avahi: Fixes from review comments --- mopidy/frontends/http/actor.py | 8 ++++---- mopidy/frontends/mpd/actor.py | 8 ++++---- mopidy/utils/zeroconf.py | 5 ++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index d5c37f09..ad5441c3 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -96,13 +96,13 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): if self.config_section['zeroconf_enabled']: name = self.config_section['zeroconf_name'] self.zeroconf_service = zeroconf.Zeroconf( - stype="_http._tcp", name=name, port=self.port, - host=self.hostname) + stype='_http._tcp', name=name, + host=self.hostname, port=self.port) if self.zeroconf_service.publish(): - logger.info('Registered HTTP with zeroconf as %s', name) + logger.info('Registered HTTP with Zeroconf as %s', name) else: - logger.warning('Registering HTTP with zeroconf failed.') + logger.warning('Registering HTTP with Zeroconf failed.') def on_stop(self): if self.zeroconf_service: diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 51735837..575f4159 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -44,13 +44,13 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): if self.config_section['zeroconf_enabled']: name = self.config_section['zeroconf_name'] self.zeroconf_service = zeroconf.Zeroconf( - stype="_mpd._tcp", name=name, port=self.port, - host=self.hostname) + stype="_mpd._tcp", name=name, + port=self.port, host=self.hostname) if self.zeroconf_service.publish(): - logger.info('Registered MPD with zeroconf as %s', name) + logger.info('Registered MPD with Zeroconf as %s', name) else: - logger.warning('Registering MPD with zeroconf failed.') + logger.warning('Registering MPD with Zeroconf failed.') def on_stop(self): if self.zeroconf_service: diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index 8af63777..34e9a182 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -15,7 +15,6 @@ _AVAHI_PROTO_UNSPEC = -1 _AVAHI_PUBLISHFLAGS_NONE = 0 - def _filter_loopback_and_meta_addresses(host): # TODO: see if we can find a cleaner way of handling this. if re.search(r'(? Date: Mon, 11 Nov 2013 21:39:14 +0100 Subject: [PATCH 12/15] avahi: Add hostname and port template values to names --- mopidy/frontends/http/actor.py | 3 ++- mopidy/frontends/http/ext.conf | 2 +- mopidy/frontends/mpd/actor.py | 3 ++- mopidy/frontends/mpd/ext.conf | 2 +- mopidy/utils/zeroconf.py | 9 +++++++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index ad5441c3..1cd0c5f4 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -100,7 +100,8 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): host=self.hostname, port=self.port) if self.zeroconf_service.publish(): - logger.info('Registered HTTP with Zeroconf as %s', name) + logger.info('Registered HTTP with Zeroconf as "%s"', + self.zeroconf_service.name) else: logger.warning('Registering HTTP with Zeroconf failed.') diff --git a/mopidy/frontends/http/ext.conf b/mopidy/frontends/http/ext.conf index f3df5f1a..891aeb5b 100644 --- a/mopidy/frontends/http/ext.conf +++ b/mopidy/frontends/http/ext.conf @@ -4,7 +4,7 @@ hostname = 127.0.0.1 port = 6680 static_dir = zeroconf_enabled = true -zeroconf_name = Mopidy +zeroconf_name = Mopidy HTTP server on $hostname [loglevels] cherrypy = warning diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 575f4159..a40834b2 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -48,7 +48,8 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): port=self.port, host=self.hostname) if self.zeroconf_service.publish(): - logger.info('Registered MPD with Zeroconf as %s', name) + logger.info('Registered MPD with Zeroconf as "%s"', + self.zeroconf_service.name) else: logger.warning('Registering MPD with Zeroconf failed.') diff --git a/mopidy/frontends/mpd/ext.conf b/mopidy/frontends/mpd/ext.conf index d51c04f6..ad3b333a 100644 --- a/mopidy/frontends/mpd/ext.conf +++ b/mopidy/frontends/mpd/ext.conf @@ -6,4 +6,4 @@ password = max_connections = 20 connection_timeout = 60 zeroconf_enabled = true -zeroconf_name = Mopidy (MPD) +zeroconf_name = Mopidy MPD server on $hostname diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index 34e9a182..ba4e327d 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals import logging import re +import socket +import string logger = logging.getLogger('mopidy.utils.zerconf') @@ -31,13 +33,16 @@ class Zeroconf: def __init__(self, name, port, stype="_http._tcp", domain="", host="", text=[]): - self.name = name + self.group = None self.stype = stype self.domain = domain self.port = port self.text = text self.host = _filter_loopback_and_meta_addresses(host) - self.group = None + + template = string.Template(name) + self.name = template.safe_substitute( + hostname=self.host or socket.getfqdn(), port=self.port) def publish(self): if not dbus: From c964d15ac46adc1994aeab93629d07bf39d245fb Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Mon, 11 Nov 2013 21:42:23 +0100 Subject: [PATCH 13/15] avahi: Simplify config to single value --- mopidy/frontends/http/__init__.py | 3 +-- mopidy/frontends/http/actor.py | 5 ++--- mopidy/frontends/http/ext.conf | 3 +-- mopidy/frontends/mpd/__init__.py | 3 +-- mopidy/frontends/mpd/actor.py | 5 ++--- mopidy/frontends/mpd/ext.conf | 3 +-- 6 files changed, 8 insertions(+), 14 deletions(-) diff --git a/mopidy/frontends/http/__init__.py b/mopidy/frontends/http/__init__.py index d5f8f1bc..64cb88f9 100644 --- a/mopidy/frontends/http/__init__.py +++ b/mopidy/frontends/http/__init__.py @@ -21,8 +21,7 @@ class Extension(ext.Extension): schema['hostname'] = config.Hostname() schema['port'] = config.Port() schema['static_dir'] = config.Path(optional=True) - schema['zeroconf_enabled'] = config.Boolean() - schema['zeroconf_name'] = config.String() + schema['zeroconf'] = config.String(optional=True) return schema def validate_environment(self): diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index 1cd0c5f4..3e46dc63 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -93,10 +93,9 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): cherrypy.engine.start() logger.info('HTTP server running at %s', cherrypy.server.base()) - if self.config_section['zeroconf_enabled']: - name = self.config_section['zeroconf_name'] + if self.config_section['zeroconf']: self.zeroconf_service = zeroconf.Zeroconf( - stype='_http._tcp', name=name, + stype='_http._tcp', name=self.config_section['zeroconf'], host=self.hostname, port=self.port) if self.zeroconf_service.publish(): diff --git a/mopidy/frontends/http/ext.conf b/mopidy/frontends/http/ext.conf index 891aeb5b..fc239230 100644 --- a/mopidy/frontends/http/ext.conf +++ b/mopidy/frontends/http/ext.conf @@ -3,8 +3,7 @@ enabled = true hostname = 127.0.0.1 port = 6680 static_dir = -zeroconf_enabled = true -zeroconf_name = Mopidy HTTP server on $hostname +zeroconf = Mopidy HTTP server on $hostname [loglevels] cherrypy = warning diff --git a/mopidy/frontends/mpd/__init__.py b/mopidy/frontends/mpd/__init__.py index 28f9c951..571d6455 100644 --- a/mopidy/frontends/mpd/__init__.py +++ b/mopidy/frontends/mpd/__init__.py @@ -23,8 +23,7 @@ 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() + schema['zeroconf'] = config.String(optional=True) return schema def validate_environment(self): diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index a40834b2..6e277078 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -41,10 +41,9 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): logger.info('MPD server running at [%s]:%s', hostname, port) def on_start(self): - if self.config_section['zeroconf_enabled']: - name = self.config_section['zeroconf_name'] + if self.config_section['zeroconf']: self.zeroconf_service = zeroconf.Zeroconf( - stype="_mpd._tcp", name=name, + stype="_mpd._tcp", name=self.config_section['zeroconf'], port=self.port, host=self.hostname) if self.zeroconf_service.publish(): diff --git a/mopidy/frontends/mpd/ext.conf b/mopidy/frontends/mpd/ext.conf index ad3b333a..c62c37ef 100644 --- a/mopidy/frontends/mpd/ext.conf +++ b/mopidy/frontends/mpd/ext.conf @@ -5,5 +5,4 @@ port = 6600 password = max_connections = 20 connection_timeout = 60 -zeroconf_enabled = true -zeroconf_name = Mopidy MPD server on $hostname +zeroconf = Mopidy MPD server on $hostname From f03c049485a22d0df63c88a455e3ff78c3f05618 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Mon, 11 Nov 2013 22:04:13 +0100 Subject: [PATCH 14/15] avahi: More review comments and some other fixes. - Switched to newstyle class - Switched to safe values in kwargs --- mopidy/frontends/mpd/actor.py | 4 ++-- mopidy/utils/zeroconf.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 6e277078..87c1a571 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -43,8 +43,8 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): def on_start(self): if self.config_section['zeroconf']: self.zeroconf_service = zeroconf.Zeroconf( - stype="_mpd._tcp", name=self.config_section['zeroconf'], - port=self.port, host=self.hostname) + stype='_mpd._tcp', name=self.config_section['zeroconf'], + host=self.hostname, port=self.port) if self.zeroconf_service.publish(): logger.info('Registered MPD with Zeroconf as "%s"', diff --git a/mopidy/utils/zeroconf.py b/mopidy/utils/zeroconf.py index ba4e327d..c1781867 100644 --- a/mopidy/utils/zeroconf.py +++ b/mopidy/utils/zeroconf.py @@ -28,17 +28,17 @@ def _convert_text_to_dbus_bytes(text): return [dbus.Byte(ord(c)) for c in text] -class Zeroconf: - """Publish a network service with zeroconf using Avahi.""" +class Zeroconf(object): + """Publish a network service with Zeroconf using Avahi.""" - def __init__(self, name, port, stype="_http._tcp", - domain="", host="", text=[]): + def __init__(self, name, port, stype=None, domain=None, + host=None, text=None): self.group = None - self.stype = stype - self.domain = domain + self.stype = stype or '_http._tcp' + self.domain = domain or '' self.port = port - self.text = text - self.host = _filter_loopback_and_meta_addresses(host) + self.text = text or [] + self.host = _filter_loopback_and_meta_addresses(host or '') template = string.Template(name) self.name = template.safe_substitute( @@ -59,12 +59,12 @@ class Zeroconf: logger.debug('Zeroconf publish failed: Avahi service not running.') return False - server = dbus.Interface(bus.get_object("org.freedesktop.Avahi", "/"), - "org.freedesktop.Avahi.Server") + server = dbus.Interface(bus.get_object('org.freedesktop.Avahi', '/'), + 'org.freedesktop.Avahi.Server') self.group = dbus.Interface( - bus.get_object("org.freedesktop.Avahi", server.EntryGroupNew()), - "org.freedesktop.Avahi.EntryGroup") + bus.get_object('org.freedesktop.Avahi', server.EntryGroupNew()), + 'org.freedesktop.Avahi.EntryGroup') text = [_convert_text_to_dbus_bytes(t) for t in self.text] self.group.AddService(_AVAHI_IF_UNSPEC, _AVAHI_PROTO_UNSPEC, From 660a1b738290afa45d9c2f0fbcabf0b171e34b9d Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Mon, 11 Nov 2013 22:32:46 +0100 Subject: [PATCH 15/15] avahi: Remove use of config_section --- mopidy/frontends/http/actor.py | 12 +++++++----- mopidy/frontends/mpd/actor.py | 14 +++++++------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/mopidy/frontends/http/actor.py b/mopidy/frontends/http/actor.py index 3e46dc63..4e3493d4 100644 --- a/mopidy/frontends/http/actor.py +++ b/mopidy/frontends/http/actor.py @@ -23,16 +23,18 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): super(HttpFrontend, self).__init__() self.config = config self.core = core + + self.hostname = config['http']['hostname'] + self.port = config['http']['port'] + self.zeroconf_name = config['http']['zeroconf'] self.zeroconf_service = None + self._setup_server() self._setup_websocket_plugin() app = self._create_app() self._setup_logging(app) def _setup_server(self): - self.config_section = self.config['http'] - self.hostname = self.config_section['hostname'] - self.port = self.config_section['port'] cherrypy.config.update({ 'engine.autoreload_on': False, 'server.socket_host': self.hostname, @@ -93,9 +95,9 @@ class HttpFrontend(pykka.ThreadingActor, CoreListener): cherrypy.engine.start() logger.info('HTTP server running at %s', cherrypy.server.base()) - if self.config_section['zeroconf']: + if self.zeroconf_name: self.zeroconf_service = zeroconf.Zeroconf( - stype='_http._tcp', name=self.config_section['zeroconf'], + stype='_http._tcp', name=self.zeroconf_name, host=self.hostname, port=self.port) if self.zeroconf_service.publish(): diff --git a/mopidy/frontends/mpd/actor.py b/mopidy/frontends/mpd/actor.py index 87c1a571..9df7ba07 100644 --- a/mopidy/frontends/mpd/actor.py +++ b/mopidy/frontends/mpd/actor.py @@ -15,16 +15,16 @@ logger = logging.getLogger('mopidy.frontends.mpd') class MpdFrontend(pykka.ThreadingActor, CoreListener): def __init__(self, config, core): super(MpdFrontend, self).__init__() + hostname = network.format_hostname(config['mpd']['hostname']) - port = config['mpd']['port'] - self.config_section = config['mpd'] self.hostname = hostname - self.port = port + self.port = config['mpd']['port'] + self.zeroconf_name = config['mpd']['zeroconf'] self.zeroconf_service = None try: network.Server( - hostname, port, + self.hostname, self.port, protocol=session.MpdSession, protocol_kwargs={ 'config': config, @@ -38,12 +38,12 @@ class MpdFrontend(pykka.ThreadingActor, CoreListener): encoding.locale_decode(error)) sys.exit(1) - logger.info('MPD server running at [%s]:%s', hostname, port) + logger.info('MPD server running at [%s]:%s', self.hostname, self.port) def on_start(self): - if self.config_section['zeroconf']: + if self.zeroconf_name: self.zeroconf_service = zeroconf.Zeroconf( - stype='_mpd._tcp', name=self.config_section['zeroconf'], + stype='_mpd._tcp', name=self.zeroconf_name, host=self.hostname, port=self.port) if self.zeroconf_service.publish():