diff --git a/mopidy/frontends/mpris.py b/mopidy/frontends/mpris.py index d3ce8f44..9a1194c7 100644 --- a/mopidy/frontends/mpris.py +++ b/mopidy/frontends/mpris.py @@ -13,6 +13,7 @@ from pykka.actor import ThreadingActor from pykka.registry import ActorRegistry from mopidy.backends.base import Backend +from mopidy.backends.base.playback import PlaybackController from mopidy.frontends.base import BaseFrontend logger = logging.getLogger('mopidy.frontends.mpris') @@ -85,8 +86,19 @@ class MprisFrontend(ThreadingActor, BaseFrontend): class MprisObject(dbus.service.Object): """Implements http://www.mpris.org/2.0/spec/""" - properties = { - ROOT_IFACE: { + properties = None + + def __init__(self): + self._backend = None + self.properties = { + ROOT_IFACE: self._get_root_iface_properties(), + PLAYER_IFACE: self._get_player_iface_properties(), + } + bus_name = self._connect_to_dbus() + super(MprisObject, self).__init__(bus_name, OBJECT_PATH) + + def _get_root_iface_properties(self): + return { 'CanQuit': (True, None), 'CanRaise': (False, None), # TODO Add track list support @@ -97,10 +109,11 @@ class MprisObject(dbus.service.Object): 'SupportedUriSchemes': (dbus.Array([], signature='s'), None), # TODO Return MIME types supported by local backend if active 'SupportedMimeTypes': (dbus.Array([], signature='s'), None), - }, - PLAYER_IFACE: { - # TODO Get backend.playback.state - 'PlaybackStatus': ('Stopped', None), + } + + def _get_player_iface_properties(self): + return { + 'PlaybackStatus': (self.get_PlaybackStatus, None), # TODO Get/set loop status 'LoopStatus': ('None', None), 'Rate': (1.0, None), @@ -128,13 +141,7 @@ class MprisObject(dbus.service.Object): 'CanSeek': (False, None), # TODO Set to True when the rest is implemented 'CanControl': (False, None), - }, - } - - def __init__(self): - self._backend = None - bus_name = self._connect_to_dbus() - super(MprisObject, self).__init__(bus_name, OBJECT_PATH) + } def _connect_to_dbus(self): logger.debug(u'Connecting to D-Bus...') @@ -156,8 +163,9 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') def Get(self, interface, prop): - logger.debug(u'%s.Get called', dbus.PROPERTIES_IFACE) - getter, setter = self.properties[interface][prop] + logger.debug(u'%s.Get(%s, %s) called', + dbus.PROPERTIES_IFACE, repr(interface), repr(prop)) + (getter, setter) = self.properties[interface][prop] return getter() if callable(getter) else getter @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, @@ -173,7 +181,8 @@ class MprisObject(dbus.service.Object): props = player.GetAll('org.mpris.MediaPlayer2', dbus_interface='org.freedesktop.DBus.Properties') """ - logger.debug(u'%s.GetAll called', dbus.PROPERTIES_IFACE) + logger.debug(u'%s.GetAll(%s) called', + dbus.PROPERTIES_IFACE, repr(interface)) getters = {} for key, (getter, setter) in self.properties[interface].iteritems(): getters[key] = getter() if callable(getter) else getter @@ -182,7 +191,8 @@ class MprisObject(dbus.service.Object): @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ssv', out_signature='') def Set(self, interface, prop, value): - logger.debug(u'%s.Set called', dbus.PROPERTIES_IFACE) + logger.debug(u'%s.Set(%s, %s, %s) called', + dbus.PROPERTIES_IFACE, repr(interface), repr(prop), repr(value)) getter, setter = self.properties[interface][prop] if setter is not None: setter(value) @@ -221,6 +231,15 @@ class MprisObject(dbus.service.Object): ### Player interface + def get_PlaybackStatus(self): + state = self.backend.playback.state.get() + if state == PlaybackController.PLAYING: + return 'Playing' + elif state == PlaybackController.PAUSED: + return 'Paused' + elif state == PlaybackController.STOPPED: + return 'Stopped' + @dbus.service.method(dbus_interface=PLAYER_IFACE) def Next(self): logger.debug(u'%s.Next called', PLAYER_IFACE) diff --git a/tests/frontends/mpris/player_interface_test.py b/tests/frontends/mpris/player_interface_test.py index d44196a0..d3a671b0 100644 --- a/tests/frontends/mpris/player_interface_test.py +++ b/tests/frontends/mpris/player_interface_test.py @@ -4,6 +4,7 @@ import unittest from pykka.registry import ActorRegistry from mopidy.backends.base import Backend +from mopidy.backends.base.playback import PlaybackController from mopidy.frontends import mpris class PlayerInterfaceTest(unittest.TestCase): @@ -14,6 +15,21 @@ class PlayerInterfaceTest(unittest.TestCase): self.mpris_object = mpris.MprisObject() self.mpris_object._backend = self.backend + def test_playback_status_is_playing_when_playing(self): + self.backend.playback.state.get.return_value = PlaybackController.PLAYING + result = self.mpris_object.Get(mpris.PLAYER_IFACE, 'PlaybackStatus') + self.assertEqual('Playing', result) + + def test_playback_status_is_paused_when_paused(self): + self.backend.playback.state.get.return_value = PlaybackController.PAUSED + result = self.mpris_object.Get(mpris.PLAYER_IFACE, 'PlaybackStatus') + self.assertEqual('Paused', result) + + def test_playback_status_is_stopped_when_stopped(self): + self.backend.playback.state.get.return_value = PlaybackController.STOPPED + result = self.mpris_object.Get(mpris.PLAYER_IFACE, 'PlaybackStatus') + self.assertEqual('Stopped', result) + def test_next_should_call_next_on_backend(self): self.mpris_object.Next() self.assert_(self.backend.playback.next.called)