gtk + vlc,MediaPlayerEndReached事件不播放下一个视频

时间:2018-06-01 11:53:19

标签: python events gtk vlc

所以,我正在使用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()

1 个答案:

答案 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()