I actually want to display the information about the media or song currently being played with a window as a popup containing the artwork and the song name etc. I read about that a
PlaybackStatus
signal is emitted whenever a media is playing or stopped. How would i connect to that signal, well I read about dbus and came to know that it can be accessed using the org.freedesktop.DBus.Properties
interface. I have recently started development with PyGtk so I don`t know how to do it?
Thanks.
Advertisement
Answer
Before doing this with Python I find it useful to experiment on the command line to see what the expected values are. This can be done with the busctl
tool.
The media players are on the Session (or user) bus.
$ busctl --user list | grep -i MediaPlayer2 org.mpris.MediaPlayer2.firefox.instance62995 62995 GeckoMain usera :1.99 user@1000.service - -
I can use the name of the service to find the objects in the D-Bus tree:
$ busctl --user tree org.mpris.MediaPlayer2.firefox.instance62995 └─/org └─/org/mpris └─/org/mpris/MediaPlayer2
With the name
and the object path
the object can be introspected
$ busctl --user introspect org.mpris.MediaPlayer2.firefox.instance62995 /org/mpris/MediaPlayer2 NAME TYPE SIGNATURE RESULT/VALUE > org.freedesktop.DBus.Introspectable interface - - > .Introspect method - s > org.freedesktop.DBus.Peer interface - - > .GetMachineId method - s > .Ping method - - > org.freedesktop.DBus.Properties interface - - > .Get method ss v > .GetAll method s a{sv} > .Set method ssv - > .PropertiesChanged signal sa{sv}as - > org.mpris.MediaPlayer2 interface - - > .Quit method - - > .Raise method - - > .CanQuit property b false > .CanRaise property b true > .DesktopEntry property s "firefox" > .HasTrackList property b false > .Identity property s "Mozilla Firefox" > .SupportedMimeTypes property as 0 > .SupportedUriSchemes property as 0 > org.mpris.MediaPlayer2.Player interface - - > .Next method - - > .OpenUri method s - > .Pause method - - > .Play method - - > .PlayPause method - - > .Previous method - - > .Seek method x - > .SetPosition method ox - > .Stop method - - > .CanControl property b true > .CanGoNext property b false > .CanGoPrevious property b false > .CanPause property b true > .CanPlay property b true > .CanSeek property b false > .MaximumRate property d - > .Metadata property a{sv} 5 "mpris:trackid" o "/org/> .MinimumRate property d - > .PlaybackStatus property s "Paused" > .Position property x - > .Rate property d - > .Volume property d - > .Seeked signal x - >
As you want to use Gtk it would seem sensible to use the D-Bus binding from https://pygobject.readthedocs.io/en/latest/
It will mainly be the DBusProxy that will be required.
An example of a window with a couple of labels for playback status and artist information might look like the following:
import gi gi.require_version("Gtk", "3.0") from gi.repository import Gio, Gtk PLAYER_IFACE = 'org.mpris.MediaPlayer2.Player' class MainApp(Gtk.Window): def __init__(self): super().__init__(title="Player Status") self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.add(self.box) self.lbl_status = Gtk.Label(label='Status Here') self.box.pack_start(self.lbl_status, True, True, 0) self.lbl_artist = Gtk.Label(label='Artist Here') self.box.pack_start(self.lbl_artist, True, True, 0) def update_label(self, proxy, changed_props, invalidated_props): props = changed_props.unpack() print(props) status = props.get('PlaybackStatus') artist = props.get('Metadata', {}).get('xesam:title') if status: self.lbl_status.set_text(status) if artist: self.lbl_artist.set_text(artist) def find_player(): """ Find the first `org.mpris.MediaPlayer2` name in list """ names = Gio.DBusProxy.new_for_bus_sync( bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.NONE, info=None, name='org.freedesktop.DBus', object_path='/org/freedesktop/DBus', interface_name='org.freedesktop.DBus', cancellable=None).ListNames() for name in names: if name.startswith('org.mpris.MediaPlayer2'): return name def player_proxy(media_name): """ Provide proxy for comfortable and pythonic method calls """ return Gio.DBusProxy.new_for_bus_sync( bus_type=Gio.BusType.SESSION, flags=Gio.DBusProxyFlags.NONE, info=None, name=media_name, object_path='/org/mpris/MediaPlayer2', interface_name=PLAYER_IFACE, cancellable=None) if __name__ == "__main__": print("running application") app = MainApp() player_name = find_player() player = player_proxy(player_name) # Connect signal to callback player.connect('g-properties-changed', app.update_label) app.show_all() Gtk.main()