[英]libvlc and dbus interface
我正在尝试使用libvlc创建一个基本的媒体播放器,它将通过dbus进行控制。 我正在为python使用gtk和libvlc绑定。 该代码基于vlc网站的官方示例
我修改的唯一方法是将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控制模块不起作用(我不敢相信我只是说可怕的“不起作用”的话):
我已经有了工作客户端dbus代码,它绑定到MPRIS 2接口。 我可以控制一个VLC媒体播放器的正常实例 - 工作正常,但上面的例子没有任何反应。 dbus控制模块正确加载,因为libvlc_add_intf
没有返回错误,我可以在D-Feet(org.mpris.MediaPlayer2.vlc)中看到MPRIS 2服务。 即使在D-Feet中,尝试调用dbus vlc对象的任何方法都不会返回错误,但没有任何反应。
我是否需要配置其他内容才能使dbus模块控制libvlc播放器?
谢谢
UPDATE
似乎创建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
连接到vlc dbus对象的客户端代码太长而无法发布,因此假设我正在使用D-Feet来获取总线连接并向其发布消息。 一旦示例运行,我可以看到d-feet中的播放器dbus接口,但我无法控制它。 还有什么我应该添加到上面的代码,使其工作?
我无法看到您的事件循环的实现,因此很难说出可能导致命令无法被识别或被删除的原因。 您的线程是否可能丢失堆栈跟踪信息并且实际上是在抛出异常?
如果您添加了事件循环的伪代码版本和DBus命令解析或简化版本,您可能会得到更多响应?
在nullege.com上找到的工作程序使用ctypes。 一个充当服务器的人使用了rpyc。 忽略那一个。
ctypes相对于dbus的优势是一个巨大的速度优势(调用C库代码,不使用python进行交互)以及不需要库实现dbus接口。
没有找到任何使用gtk或dbus的例子;-(
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()
不打算为你写你的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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.