Как быстро получить все экземпляры VLC на dbus? - PullRequest
3 голосов
/ 25 сентября 2010

По сути, проблема в том, что единственный способ получить все экземпляры VLC - это найти во всех неименованных экземплярах функцию идентификации org.freedesktop.MediaPlayer и вызвать ее.

(в качестве альтернативы я мог бы использовать API интроспекции, но это, похоже, не решило бы мою проблему) К сожалению, многие программы после отправки вызова по протоколу dbus просто не отвечают, что приводит к длительному и дорогостоящему таймауту.

Когда это происходит несколько раз, оно может сложиться. По сути, встроенный тайм-аут слишком длинный.

Если я смогу каким-то образом уменьшить время ожидания dbus, это решит мою проблему, но идеальным решением будет способ.

Мне пришла в голову мысль, что я могу помещать каждый вызов «Identify» внутри потока и что я могу уничтожать потоки, которые занимают слишком много времени, но, похоже, это не рекомендуется. Кроме того, добавление многопоточности значительно увеличивает нагрузку на процессор, не сильно увеличивая скорость работы программы.

Вот код, который я пытаюсь запустить быстро (более или менее), который в настоящее время мучительно медленный.

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 голос
/ 25 сентября 2010

Проще, чем порождать кучу потоков, было бы делать вызовы к различным сервисам асинхронно, предоставляя обработчик обратного вызова, когда возвращается результат или возникает ошибка 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 ()
...