如何快速获取所有VLC实例的dbus?

3 投票
1 回答
1282 浏览
提问于 2025-04-16 04:34

基本上,问题是,要获取所有的VLC实例,唯一的方法就是搜索所有没有名字的实例,找到它们的org.freedesktop.MediaPlayer身份函数并调用它。

(另外,我可以使用反射API,但这似乎并不能解决我的问题)不幸的是,很多程序在发送dbus调用后,根本不响应,这会导致很长的超时等待。

当这种情况发生多次时,时间就会累积起来。总的来说,内置的超时时间太长了。

如果我能以某种方式减少dbus的超时时间,那就能解决我的问题,但理想的解决方案是找到一种方法。

我想到可以把每次调用“Identify”放在一个线程里,这样如果某个线程耗时太长就可以结束它,但这似乎并不是推荐的做法。而且,增加多线程会大幅提高CPU的负担,但并没有显著提高程序的速度。

这是我正在尝试让它快速运行的代码(或多或少),目前运行得非常慢。

import dbus
bus = dbus.SessionBus()
dbus_proxy = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
names = dbus_proxy.ListNames()
for name in names:
    if name.startswith(':'):
        try:
            proxy = bus.get_object(name, '/')
            ident_method = proxy.get_dbus_method("Identity",     
                dbus_interface="org.freedesktop.MediaPlayer")

            print ident_method()

        except dbus.exceptions.DBusException:
            pass

1 个回答

1

比起创建很多线程,更简单的方法是让不同的服务异步调用,也就是在请求服务时提供一个回调处理程序,这样当结果返回或者出现错误时就能处理。所有的调用实际上是同时进行的,你的程序可以在收到一些有效结果后就继续运行。

下面是一个简单的程序,它会打印出找到的所有服务的列表。你会注意到,它能很快得到所有有效的结果,而不需要等待任何超时。在一个真正的程序中,你可能会给错误处理程序分配一个什么都不做的函数,因为你的目标是忽略那些没有响应的服务,但这个例子会等到所有服务都回应后才结束。

#! /usr/bin/env python

import dbus
import dbus.mainloop.glib
import functools
import glib

class VlcFinder (object):
    def __init__ (self, mainloop):
        self.outstanding = 0
        self.mainloop = mainloop

        bus = dbus.SessionBus ()
        dbus_proxy = bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
        names = dbus_proxy.ListNames ()
        for name in dbus_proxy.ListNames ():
            if name.startswith (":"):
                proxy = bus.get_object (name, "/")
                iface = dbus.Interface (proxy, "org.freedesktop.MediaPlayer")
                iface.Identity (reply_handler = functools.partial (self.reply_cb, name),
                                error_handler = functools.partial (self.error_cb, name))
                self.outstanding += 1

    def reply_cb (self, name, ver):
        print "Found {0}: {1}".format (name, ver)
        self.received_result ()

    def error_cb (self, name, msg):
        self.received_result ()

    def received_result (self):
        self.outstanding -= 1
        if self.outstanding == 0:
            self.mainloop.quit ()

if __name__ == "__main__":
    dbus.mainloop.glib.DBusGMainLoop (set_as_default = True)
    mainloop = glib.MainLoop ()
    finder = VlcFinder (mainloop)
    mainloop.run ()

撰写回答