如何使用 pygtk 连接到 MediaPlayer2.Player PlaybackStatus 信号?

How to connect to MediaPlayer2.Player PlaybackStatus signal using pygtk?

我实际上想用 window 显示有关当前正在播放的媒体或歌曲的信息作为包含艺术作品和歌曲名称等的弹出窗口。我读到过

PlaybackStatus

每当媒体正在播放或停止时都会发出信号。我将如何连接到该信号,我阅读了有关 dbus 的信息,并了解到可以使用 org.freedesktop.DBus.Properties 接口访问它。我最近开始使用 PyGtk 进行开发,所以我不知道该怎么做?

谢谢。

在使用 Python 执行此操作之前,我发现在命令行上进行试验以查看预期值是什么很有用。这可以使用 busctl 工具来完成。

媒体播放器在会话(或用户)总线上。

$ busctl --user list | grep -i MediaPlayer2
org.mpris.MediaPlayer2.firefox.instance62995  62995 GeckoMain       usera :1.99         user@1000.service -       -          

我可以使用服务的名称来查找 D-Bus 树中的对象:

$ busctl --user tree org.mpris.MediaPlayer2.firefox.instance62995
└─/org
  └─/org/mpris
    └─/org/mpris/MediaPlayer2

使用 nameobject path 可以自省对象

$ 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         -                         >

因为您想使用 Gtk,所以使用来自 https://pygobject.readthedocs.io/en/latest/

的 D-Bus 绑定似乎是明智的

主要是需要的DBusProxy

带有几个播放状态和艺术家信息标签的 window 示例可能如下所示:

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()