7

dbus を介して制御される libvlc を使用して、基本的なメディア プレーヤーを作成しようとしています。Python には gtk および libvlc バインディングを使用しています。コードは、 vlc Web サイトの公式の例に基づいてい ます。

私が変更した唯一のことは、dbus インターフェイスを vlc インスタンスに追加することです

# Create a single vlc.Instance() to be shared by (possible) multiple players.
instance = vlc.Instance()
print vlc.libvlc_add_intf(instance, "dbus"); // this is what i added. // returns 0 which is ok

すべて順調です。デモは動作し、ビデオ ファイルを再生します。しかし、何らかの理由で dbus 制御モジュールが機能しません (恐ろしい「機能しない」という言葉を言っただけだとは信じられません)。

MPRIS 2 インターフェイスにバインドするクライアント dbus コードは既に動作しています。VLC メディア プレーヤーの通常のインスタンスを制御できます。これは問題なく動作しますが、上記の例では何も起こりません。libvlc_add_intfエラーを返さず、D-Feet (org.mpris.MediaPlayer2.vlc) で MPRIS 2 サービスを確認できるため、dbus 制御モジュールは適切にロードされています。D-Feet でも、dbus vlc オブジェクトのメソッドを呼び出そうとしてもエラーは返されませんが、何も起こりません。

dbus モジュールで libvlc プレーヤーを制御するには、何か他の設定が必要ですか?

ありがとう

アップデート

vlc インスタンスを作成し、より高い冗長性を設定すると、DBus 呼び出しは受信されますが、プレーヤー自体にはまったく影響がないことが示されているようです。また、DBus の代わりに RC インターフェイスをインスタンスに追加すると、いくつかの問題もあります。コマンド ラインから例を実行すると、制御コマンドを入力できる RC インターフェイス コンソールに移動しますが、動作は次のようになります。 DBus - 何も起こらず、エラーもありません。なだ、まったく何もありません。コマンドを完全に無視します。

何かご意見は?

更新 2

libvlc を使用して基本的なプレーヤーを作成するコードは次のとおりです。

    from    dbus.mainloop.glib import DBusGMainLoop
    import gtk
    import  gobject


    import sys
    import vlc

    from gettext import gettext as _


    # Create a single vlc.Instance() to be shared by (possible) multiple players.
    instance = vlc.Instance("--one-instance --verbose 2")

    class VLCWidget(gtk.DrawingArea):
        """Simple VLC widget.

        Its player can be controlled through the 'player' attribute, which
        is a vlc.MediaPlayer() instance.
        """
        def __init__(self, *p):
            gtk.DrawingArea.__init__(self)
            self.player = instance.media_player_new()
            def handle_embed(*args):
                if sys.platform == 'win32':
                    self.player.set_hwnd(self.window.handle)
                else:
                    self.player.set_xwindow(self.window.xid)
                return True
            self.connect("map", handle_embed)
            self.set_size_request(640, 480)

    class VideoPlayer:
        """Example simple video player.
        """
        def __init__(self):
            self.vlc = VLCWidget()

        def main(self, fname):
            self.vlc.player.set_media(instance.media_new(fname))
            w = gtk.Window()
            w.add(self.vlc)
            w.show_all()
            w.connect("destroy", gtk.main_quit)
            self.vlc.player.play()
            DBusGMainLoop(set_as_default = True)
            gtk.gdk.threads_init()
            gobject.MainLoop().run()


    if __name__ == '__main__':
        if not sys.argv[1:]:
           print "You must provide at least 1 movie filename"
           sys.exit(1)
        if len(sys.argv[1:]) == 1:
            # Only 1 file. Simple interface
            p=VideoPlayer()
            p.main(sys.argv[1])

スクリプトは、次のようにコマンド ラインから実行できます。

python example_vlc.py file.avi

vlc dbus オブジェクトに接続するクライアント コードは長すぎて投稿できないため、代わりにD-Feetを使用してバス接続を取得し、メッセージを投稿するふりをします。サンプルが実行されると、プレーヤーの dbus インターフェイスが d-feet に表示されますが、制御できません。上記のコードを機能させるために追加する必要があるものは他にありますか?

4

2 に答える 2

0

イベント ループの実装が見えないため、コマンドが認識されない、または削除される原因を特定するのは困難です。スレッドがスタックトレース情報を失い、実際に例外をスローしている可能性はありますか?

イベント ループと DBus コマンド解析の疑似コード バージョン、または簡略化されたバージョンのいずれかを追加すると、より多くの応答が得られる可能性があります。

于 2012-11-29T12:00:25.213 に答える
0

nullege.com で見つかった作業プログラムは、ctypes を使用しています。サーバーとして機能するものは、rpyc を使用しました。それを無視します。

dbus に対する ctypes の利点は、速度が大幅に向上すること (Python を使用して対話するのではなく、C ライブラリ コードを呼び出すこと) と、ライブラリが dbus インターフェイスを実装する必要がないことです。

gtk または dbus を使用した例が見つかりませんでした;-(

注目すべき例

PyNuvo vlc.py

ミロンガタンゴDJプログラム

dbus/gtk の使用

dbus は、gtk メインループではなく、gobject メインループを使用します。全く違う獣。小川を渡るな!いくつかの修正:

これはいらない。スレッドは悪です。

gtk.gdk.threads_init()

gobject Mainloop を使用している場合、gtk.main_quit() は機能しないはずです。gobject mainloop は ur クラス内に存在できません。

if __name__ == '__main__':
loop = gobject.MainLoop()
loop.run()

ループを ur クラスに渡します。次に、呼び出してアプリを終了します

loop.quit()

dbus (通知) / gtk の動作例

あなたのためにあなたのvlcアプリを書くつもりはありません。しかし、これは dbus / gtk を使用した実際の例です。vlcに適応するだけです。上記のgtkに関する私のアドバイスを受けたと仮定します。gobject.Mainloop を使用している間は、 DesktopNotify のインスタンスを呼び出す必要があります。しかし、メインクラス内のどこにでも配置できます。

desktop_notify.py

from __future__ import print_function
import gobject
import time, dbus
from dbus.exceptions import DBusException
from dbus.mainloop.glib import DBusGMainLoop

class DesktopNotify(object):
    """ Notify-OSD ubuntu's implementation has a 20 message limit. U've been warned. When queue is full, delete old message before adding new messages."""
    #Static variables
    dbus_loop = None
    dbus_proxy = None
    dbus_interface = None
    loop = None

    @property
    def dbus_name(self):
        return ("org.freedesktop.Notifications")

    @property
    def dbus_path(self):
        return ("/org/freedesktop/Notifications")

    @property
    def dbus_interface(self):
        return self.dbus_name

    def __init__(self, strInit="initializing passive notification messaging")
        strProxyInterface = "<class 'dbus.proxies.Interface'>"
        """ Reinitializing dbus when making a 2nd class instance would be bad"""
        if str(type(DesktopNotify.dbus_interface)) != strProxyInterface:
            DesktopNotify.dbus_loop = DBusGMainLoop(set_as_default=True)
            bus = dbus.SessionBus(mainloop=DesktopNotify.dbus_loop)
            DesktopNotify.dbus_proxy = bus.get_object(self.dbus_name, self.dbus_path)
            DesktopNotify.dbus_interface = dbus.Interface(DesktopNotify.dbus_proxy, self.dbus_interface )
            DesktopNotify.dbus_proxy.connect_to_signal("NotificationClosed", self.handle_closed)

    def handle_closed(self, *arg, **kwargs):
        """ Notification closed by user or by code. Print message or not"""
        lngNotificationId = int(arg[0])
        lngReason = int(arg[1])

    def pop(self, lngID):
        """ ID stored in database, but i'm going to skip this and keep it simple"""
        try:
            DesktopNotify.dbus_interface.CloseNotification(lngID)
        except DBusException as why:
            print(self.__class__.__name__ + ".pop probably no message with id, lngID, why)
        finally:
            pass

    def push(self, strMsgTitle, strMsg, dictField):
        """ Create a new passive notification (took out retrying and handling full queues)"""
        now = time.localtime( time.time() )
        strMsgTime = strMsg + " " + time.asctime(now)
        del now
        strMsgTime = strMsgTime % dictField

        app_name="[your app name]"
        app_icon = ''
        actions = ''
        hint = ''
        expire_timeout = 10000 #Use seconds * 1000
        summary = strMsgTitle
        body = strMsgTime
        lngNotificationID = None
        try:
            lngNotificationID = DesktopNotify.dbus_interfacec.Notify(app_name, 0, app_icon, summary, body, actions, hint, expire_timeout)
        except DBusException as why:
            #Excellent spot to delete oldest notification and then retry
            print(self.__class__.__name__ + ".push Being lazy. Posting passive notification was unsuccessful.", why)
        finally:
            #Excellent spot to add to database upon success
            pass
于 2013-04-08T15:16:10.137 に答える