所以,我正在使用GTK + / VLC创建一个带有视频播放区域和“下一步”按钮的窗口。
首先播放第一个视频文件然后点击下一个按钮将跳转到下一个媒体文件,播放它。到目前为止一切都很好。
我的问题,如果我等待MediaPlayerEndReached
被解雇,button_Next()
会被执行,但视频不会改变。
我错过了什么吗?
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = []
for fldrs in sorted(listdir(startingPath)):
self.Fldrs.append(join(startingPath,fldrs))
print self.Fldrs
self.num_Fldrs = len(self.Fldrs)
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget):
print 'next!'
num_FldrFiles = len(listdir(self.Fldrs[self.currFldrIdx]))
self.currFileIdx = self.currFileIdx+1 if self.currFileIdx+1<num_FldrFiles else 0
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
print 'now showing' + fileToShow
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.vlcPlayer.play()
def _realized(self, widget, data=None):
fileToShow = join(self.Fldrs[self.currFldrIdx], sorted(listdir(self.Fldrs[self.currFldrIdx]))[self.currFileIdx])
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
print "Event reports - finished, playing next"
self.button_Next.clicked()
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()
答案 0 :(得分:1)
此处描述了您的问题:
libvlc API在其回调https://forum.videolan.org/viewtopic.php?f=32&t=80305
中不可重入
在这里:https://forum.videolan.org/viewtopic.php?t=82502
你的应用程序通常应该有一个mainloop(gobject.mainloop()或Qt mainloop),所以你应该注册一个方法从那里重新启动播放器
对于文件名这有点麻烦,但您的代码现在注册了所需的GObject.idle_add()
函数。
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
import time
from os import listdir
from os.path import join
startingPath = './files/'
# ----------------------------------
class MediaWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Media Player")
self.autoPlay = 0
self.set_decorated(False) # removes titlebar
self.move(300,150)
self.connect("destroy", Gtk.main_quit)
self.currFldrIdx = 0
self.currFileIdx = 0
self.Fldrs = ['/home/public/2005.mp3','/home/public/happy.mp3','/home/public/vp.mp3']
#for fldrs in sorted(listdir(startingPath)):
# self.Fldrs.append(join(startingPath,fldrs))
self.num_Fldrs = len(self.Fldrs) - 1
# vlc
self.vlcInstance = vlc.Instance('--no-xlib')
self.vlcPlayer = self.vlcInstance.media_player_new()
def setup_objects_and_events(self):
self.pause_nextImg = Gtk.Image.new_from_icon_name(
"gtk-media-forward",
Gtk.IconSize.MENU
)
# Buttons
self.button_Next = Gtk.Button()
self.button_Next.set_image(self.pause_nextImg)
self.button_Next.connect("clicked", self.on_button_NextImg)
# Area
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(800,480)
self.draw_area.connect("realize",self._realized)
# Grid ------------------------------------
self.hbox1 = Gtk.Box()
self.hbox1.pack_start(self.draw_area, True, True, 0)
self.hbox2 = Gtk.Box()
self.hbox2.pack_start(self.button_Next, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.hbox1, True, True, 0)
self.vbox.pack_start(self.hbox2, False, True, 0)
def on_button_NextImg(self, widget=None):
self.currFileIdx += 1
if self.currFileIdx > self.num_Fldrs:
self.currFileIdx = 0
fileToShow = self.Fldrs[self.currFileIdx]
media = self.vlcInstance.media_new_path(fileToShow)
self.vlcPlayer.set_media(media)
if self.vlcPlayer.play() == -1:
print ("error playing",fileToShow)
else:
print("now playing",fileToShow)
def _realized(self, widget, data=None):
fileToShow = self.Fldrs[self.currFldrIdx]
self.win_id = widget.get_window().get_xid()
self.vlcPlayer.set_xwindow(self.win_id)
self.vlcPlayer.set_mrl(fileToShow)
self.events = self.vlcPlayer.event_manager()
self.events.event_attach(vlc.EventType.MediaPlayerEndReached, self.EventManager)
self.vlcPlayer.play()
def EventManager(self, event):
if event.type == vlc.EventType.MediaPlayerEndReached:
GObject.idle_add(self.on_button_NextImg)
# ----------------------------------
if __name__ == '__main__':
# Create
win = MediaWindow()
# Setup
win.setup_objects_and_events()
win.show_all()
Gtk.main()