我正在尝试创建一个系统来通过 mpris 跟踪当前正在播放的媒体。改编自这个问题的PyQt6答案,我尝试了以下代码:
from PyQt6 import QtCore, QtWidgets, QtDBus
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__ (self):
super().__init__()
service = 'org.mpris.MediaPlayer2.vlc'
path = '/org/mpris/MediaPlayer2'
iface = 'org.mpris.MediaPlayer2'
conn = QtDBus.QDBusConnection.systemBus()
conn.registerObject('/', self)
conn.connect(service, path, iface, 'PropertiesChanged', self.nochangeslot)
@QtCore.pyqtSlot(QtDBus.QDBusMessage)
def nochangeslot(self, msg):
print(f'signature: {msg.signature()!r}, '
f'arguments: {msg.arguments()!r}')
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
这应该连接任何 VLC Media Player 实例(替换为您选择的服务或以编程方式查找它),将 PropertiesChanged 发送到打印消息的简单函数。
在执行更改当前歌曲等操作时,应发出PropertiesChanged。但是,这样做时不会打印任何内容。我也尝试将
iface
更改为'org.mrpis.MediaPlayer2.Player'
,但并没有改善问题。
知道为什么这不起作用吗?
有两个问题:
您不会在系统总线上找到 MPRIS 播放器(或任何桌面其他应用程序)。它们都连接到用户的个人session总线,即
.sessionBus()
。
通常,您在系统总线上找到的唯一服务是系统全局的服务(例如 NetworkManager),而同一系统上的多个用户可以运行相同播放器或应用程序的自己的副本,因此每个用户也有一个单独的“会话总线”(现在通常是真正的“用户总线”)。
使用
d-spy
或 d-feet
、qdbusviewer6
或 busctl --acquired
(使用会话总线的 --user
选项)查看哪些 D-Bus 服务在何处处于活动状态。
$ busctl --user --acquired
NAME
org.mpris.MediaPlayer2.quodlibet
¹(此类应用程序仍可能作为 客户端 连接到系统总线 – 只是不作为 服务。)
由于属性是通用 D-Bus 概念,因此它们的信号和方法是作为通用
org.freedesktop.DBus.Properties
接口的一部分实现的,而不是作为对象自定义接口的一部分。 (每个属性所属的“真实”接口实际上是作为这些信号和方法的参数提供的。)
使用 D-Spy/D-Feet/QDBusViewer 或
gdbus introspect
或 busctl introspect
查看哪些接口下存在哪些信号。
$ busctl --user introspect \
org.mpris.MediaPlayer2.quodlibet /org/mpris/MediaPlayer2
NAME TYPE SIGNATURE RESULT/VALUE
org.freedesktop.DBus.Properties interface - -
.PropertiesChanged signal sa{sv}as -
$ gdbus introspect -e \
-d org.mpris.MediaPlayer2.quodlibet \
-o /org/mpris/MediaPlayer2
node /org/mpris/MediaPlayer2 {
interface org.freedesktop.DBus.Properties {
signals:
PropertiesChanged(s interface_name,
a{sv} changed_properties,
as invalidated_properties);
};
};
如果有疑问,请运行
dbus-monitor
或 busctl monitor
(或使用 Bustle,甚至 Wireshark)来查看每条总线上传输的内容。
dbus-monitor --session "type=signal,member=PropertiesChanged"
注意:对于使用“旧版”libdbus 的服务,有时 服务通过 .Introspect() 声明的内容与实际发送的内容之间可能不匹配,就像不提供任何功能的非常低级的库一样用于管理对象或生成正确的内省数据。 (它要求服务有自己的 Introspect() 实现,它通常返回手写的 XML 字符串 – 例如这个示例 – 它可能或可能不是 100% 准确于代码的其他部分实际发送或接受。)这始终是服务中的一个错误,但这意味着您应该始终使用总线监控工具进行仔细检查。