Python libvlc与dbus接口

Python libvlc与dbus接口,python,linux,gtk,dbus,libvlc,Python,Linux,Gtk,Dbus,Libvlc,我正在尝试使用libvlc创建一个基本的媒体播放器,它将通过dbus进行控制。我正在使用python的gtk和libvlc绑定。该代码基于 我唯一修改的是将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

我正在尝试使用libvlc创建一个基本的媒体播放器,它将通过dbus进行控制。我正在使用python的gtk和libvlc绑定。该代码基于

我唯一修改的是将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控制模块不工作(我不敢相信我刚才说了可怕的“不工作”字):

我已经有了绑定到MPRIS2接口的工作客户端dbus代码。我可以控制一个VLC媒体播放器的普通实例——它工作得很好,但在上面的例子中什么都没有发生。dbus控制模块加载正确,因为
libvlc\u add\u intf
不会返回错误,我可以在D-Feet(org.MPRIS.MediaPlayer2.vlc)中看到MPRIS 2服务。 即使在D-Feet中,尝试调用dbusvlc对象的任何方法都不会返回错误,但不会发生任何事情

为了使dbus模块控制libvlc播放器,是否需要配置其他内容

谢谢

更新

看起来,创建vlc实例并设置更高的详细度,表明收到了DBus调用,但它们对播放器本身没有任何影响。 另外,将RC接口而不是DBus添加到实例中也有一些问题:当我从命令行运行示例时,它会将我放到RC接口控制台,在那里我可以键入控制命令,但它与DBus具有相同的行为-没有发生任何事,没有错误,nada,绝对没有。它完全忽略命令

有什么想法吗

更新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
连接到VLCDBUS对象的客户机代码太长,无法发布,因此请假装我正在使用它获取总线连接并向其发布消息。
一旦这个例子运行起来,我可以看到d-feet中的播放器dbus接口,但我无法控制它还有什么需要我添加到上面的代码中才能使其正常工作的吗?

我看不到您的事件循环的实现,因此很难判断是什么原因导致命令无法识别或被删除。您的线程是否可能正在丢失stacktrace信息并实际抛出异常


如果添加事件循环和DBus命令解析的psuedo代码版本或简化版本,您可能会得到更多响应。

在nullege.com上找到的工作程序使用ctypes。充当服务器的服务器使用rpyc。忽略那个

ctypes相对于dbus的优点是速度上的巨大优势(调用C库代码,不使用python进行交互),并且不需要库实现dbus接口

没有发现任何使用gtk或dbus的示例-(

显著的例子

使用dbus/gtk dbus使用gobject mainloop,而不是gtk mainloop。完全不同的野兽。不要穿越河流!一些修复:

不需要这个,线是邪恶的

gtk.gdk.threads_init()
当使用gobject Mainloop时,gtk.main_quit()不应该工作。gobject Mainloop不能存在于您的类中

if __name__ == '__main__':
loop = gobject.MainLoop()
loop.run()
将循环传递到你的类中。然后调用退出应用程序

loop.quit()
dbus(通知)/gtk工作示例 不打算为你编写你的vlc应用程序。但这里有一个使用dbus/gtk的工作示例。只需适应vlc。假设你接受了我在上面gtk上的建议。正如你所知,在使用gobject.Mainloop时必须调用DesktopNotify的任何实例。但你可以将它放在你的主类中的任何地方

桌面通知.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
from\uuuuu future\uuuuu导入打印功能
导入gobject
导入时间,dbus
从dbus.exceptions导入DBusException
从dbus.mainloop.glib导入DBusGMainLoop
类DesktopNotify(对象):
“”“Notify OSD ubuntu的实现有20条消息的限制。您已收到警告。当队列已满时,请在添加新消息之前删除旧消息。”“”
#静态变量
dbus_循环=无
dbus_proxy=None
dbus_接口=无
循环=无
@财产
def dbus_名称(自身):
返回(“org.freedesktop.Notifications”)
@财产
def dbus_路径(自身):
返回(“/org/freedesktop/Notifications”)
@财产
def dbus_接口(自身):
返回self.dbus_名称
def _uinit _;(self,strInit=“初始化被动通知消息”)
strProxy接口=“”
“”“在生成第二类实例时重新初始化DBU是不好的”“”
如果str(类型(DesktopNotify.dbus_接口))!=strproxy接口:
DesktopNotify.dbus_loop=DBusGMainLoop(将_设置为默认值=True)
总线=dbus.SessionBus(mainloop=DesktopNotify.dbus\u循环)
DesktopNotify.dbus_proxy=bus.get_对象(self.dbus_名称,self.dbus_路径)
DesktopNotify.dbus_接口=dbus.interface(DesktopNotify.dbus_代理,self.dbus_接口)
DesktopNotify.dbus\u proxy.connect\u to\u信号(“NotificationClosed”,self.handle\u closed)
def手柄_关闭(自身、*arg、**kwargs):
“”“通知已由用户或代码关闭。是否打印邮件”“”
LnNotificationId=int(参数[0])
Lnglison=int(参数[1])
def pop(自我,lngID):
“”“ID存储在数据库中,但我将跳过此操作并保持简单”“”
尝试:
DesktopNotify.dbus_接口.CloseNotification(lngID)
除了DbUseException,原因如下:
打印(self.\uuuuuu class.\uuuuuu.\uuuuuu name.\uuuuuuuuu+”。可能没有id为lngID的消息,为什么)
最后:
通过
def推送(自身、STRMSGTILE、strMsg、dictField):
“”“创建新的被动通知(执行重试和处理已满队列)”
now=time.localtime(time.time())
strMsgTime=strMsg+“”+time.asctime(现在)
德尔诺
strMsgTime=strMsgTime%dictField
app_name=“[your app name]”