如何使用 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
使用 name
和 object 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()
我实际上想用 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
使用 name
和 object 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()