【发布时间】:2022-01-17 06:57:48
【问题描述】:
我实际上想通过一个窗口显示有关当前正在播放的媒体或歌曲的信息,作为包含艺术作品和歌曲名称等的弹出窗口。我读到了一个
PlaybackStatus
只要媒体正在播放或停止,就会发出信号。我将如何连接到该信号,好吧,我阅读了 dbus 并知道可以使用org.freedesktop.DBus.Properties 接口访问它。我最近开始使用 PyGtk 进行开发,所以我不知道该怎么做?
谢谢。
【问题讨论】:
我实际上想通过一个窗口显示有关当前正在播放的媒体或歌曲的信息,作为包含艺术作品和歌曲名称等的弹出窗口。我读到了一个
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。
带有几个标签的窗口示例显示播放状态和艺术家信息可能如下所示:
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()
【讨论】: