3

基本的に問題は、VLCのすべてのインスタンスを取得する唯一の方法は、名前のないすべてのインスタンスでorg.freedesktop.MediaPlayer ID関数を検索し、それを呼び出すことです。

(または、イントロスペクション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
4

1 に答える 1

1

多数のスレッドを生成するよりも簡単なのは、さまざまなサービスを非同期で呼び出し、結果が戻ったときやD-Busエラーが発生したときのコールバックハンドラーを提供することです。すべての呼び出しは事実上並行して行われ、プログラムはいくつかの肯定的な結果が得られるとすぐに続行できます。

これは、見つかったすべてのサービスのリストを印刷する手っ取り早いプログラムです。何かからのタイムアウトを待たずに、どれだけ早くすべての肯定的な結果が得られるかに注意してください。実際のプログラムでは、おそらく何もしない関数をエラーハンドラーに割り当てます。これは、ここでの目標は応答しないサービスを無視することであるためですが、この例では、すべてから通知されるまで待機してから終了します。

#! /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 ()
于 2010-09-25T00:16:29.230 に答える