diff --git a/docs/api/frontends.rst b/docs/api/frontends.rst index af0cc991..36626fa0 100644 --- a/docs/api/frontends.rst +++ b/docs/api/frontends.rst @@ -6,22 +6,36 @@ The following requirements applies to any frontend implementation: - A frontend MAY do mostly whatever it wants to, including creating threads, opening TCP ports and exposing Mopidy for a group of clients. + - A frontend MUST implement at least one `Pykka `_ actor, called the "main actor" from here on. + +- The main actor MUST accept a constructor argument ``core``, which will be an + :class:`ActorProxy ` for the core actor. This object + gives access to the full :ref:`core-api`. + - It MAY use additional actors to implement whatever it does, and using actors in frontend implementations is encouraged. + - The frontend is activated by including its main actor in the :attr:`mopidy.settings.FRONTENDS` setting. + - The main actor MUST be able to start and stop the frontend when the main actor is started and stopped. + - The frontend MAY require additional settings to be set for it to work. + - Such settings MUST be documented. + - The main actor MUST stop itself if the defined settings are not adequate for the frontend to work properly. -- Any actor which is part of the frontend MAY implement any listener interface - from :mod:`mopidy.listeners` to receive notification of the specified events. + +- Any actor which is part of the frontend MAY implement the + :class:`mopidy.core.CoreListener` interface to receive notification of the + specified events. + Frontend implementations ======================== diff --git a/mopidy/__main__.py b/mopidy/__main__.py index ee2e21b6..dbdb193b 100644 --- a/mopidy/__main__.py +++ b/mopidy/__main__.py @@ -54,8 +54,8 @@ def main(): setup_settings(options.interactive) audio = setup_audio() backend = setup_backend(audio) - setup_core(audio, backend) - setup_frontends() + core = setup_core(audio, backend) + setup_frontends(core) loop.run() except SettingsError as e: logger.error(e.message) @@ -137,17 +137,17 @@ def stop_backend(): def setup_core(audio, backend): - return Core.start(audio, backend).proxy() + return Core.start(audio=audio, backend=backend).proxy() def stop_core(): stop_actors_by_class(Core) -def setup_frontends(): +def setup_frontends(core): for frontend_class_name in settings.FRONTENDS: try: - get_class(frontend_class_name).start() + get_class(frontend_class_name).start(core=core) except OptionalDependencyError as e: logger.info(u'Disabled: %s (%s)', frontend_class_name, e) diff --git a/mopidy/frontends/lastfm.py b/mopidy/frontends/lastfm.py index f2bc44d2..37fbafe2 100644 --- a/mopidy/frontends/lastfm.py +++ b/mopidy/frontends/lastfm.py @@ -37,7 +37,7 @@ class LastfmFrontend(ThreadingActor, core.CoreListener): - :attr:`mopidy.settings.LASTFM_PASSWORD` """ - def __init__(self): + def __init__(self, core): super(LastfmFrontend, self).__init__() self.lastfm = None self.last_start_time = None diff --git a/mopidy/frontends/mpd/__init__.py b/mopidy/frontends/mpd/__init__.py index 9dcf4c34..f8c7a9ef 100644 --- a/mopidy/frontends/mpd/__init__.py +++ b/mopidy/frontends/mpd/__init__.py @@ -26,7 +26,7 @@ class MpdFrontend(actor.ThreadingActor, core.CoreListener): - :attr:`mopidy.settings.MPD_SERVER_PASSWORD` """ - def __init__(self): + def __init__(self, core): super(MpdFrontend, self).__init__() hostname = network.format_hostname(settings.MPD_SERVER_HOSTNAME) port = settings.MPD_SERVER_PORT diff --git a/mopidy/frontends/mpris/__init__.py b/mopidy/frontends/mpris/__init__.py index 2815c551..769f2e84 100644 --- a/mopidy/frontends/mpris/__init__.py +++ b/mopidy/frontends/mpris/__init__.py @@ -55,7 +55,7 @@ class MprisFrontend(ThreadingActor, core.CoreListener): player.Quit(dbus_interface='org.mpris.MediaPlayer2') """ - def __init__(self): + def __init__(self, core): super(MprisFrontend, self).__init__() self.indicate_server = None self.mpris_object = None diff --git a/tests/frontends/mpris/events_test.py b/tests/frontends/mpris/events_test.py index 3db03ccf..f466e207 100644 --- a/tests/frontends/mpris/events_test.py +++ b/tests/frontends/mpris/events_test.py @@ -16,7 +16,7 @@ from tests import unittest @unittest.skipUnless(sys.platform.startswith('linux'), 'requires Linux') class BackendEventsTest(unittest.TestCase): def setUp(self): - self.mpris_frontend = MprisFrontend() # As a plain class, not an actor + self.mpris_frontend = MprisFrontend(core=None) # As a plain class, not an actor self.mpris_object = mock.Mock(spec=objects.MprisObject) self.mpris_frontend.mpris_object = self.mpris_object