diff -Nru python-vlc-3.0.6109/debian/changelog python-vlc-3.0.7110/debian/changelog --- python-vlc-3.0.6109/debian/changelog 2019-05-13 20:06:38.000000000 +0000 +++ python-vlc-3.0.7110/debian/changelog 2019-08-22 19:17:16.000000000 +0000 @@ -1,3 +1,13 @@ +python-vlc (3.0.7110-1) unstable; urgency=medium + + [ Ondřej Nový ] + * Bump Standards-Version to 4.4.0. + + [ Bastian Germann ] + * New upstream version 3.0.7110 + + -- Bastian Germann Thu, 22 Aug 2019 21:17:16 +0200 + python-vlc (3.0.6109-1) unstable; urgency=low * New upstream version 3.0.6109 diff -Nru python-vlc-3.0.6109/debian/control python-vlc-3.0.7110/debian/control --- python-vlc-3.0.6109/debian/control 2019-05-13 20:06:38.000000000 +0000 +++ python-vlc-3.0.7110/debian/control 2019-08-22 18:56:56.000000000 +0000 @@ -4,7 +4,7 @@ Maintainer: Bastian Germann Uploaders: Debian Python Modules Team Build-Depends: dh-python, python3-setuptools, python3-all, debhelper-compat (= 12) -Standards-Version: 4.3.0 +Standards-Version: 4.4.0 Homepage: http://wiki.videolan.org/PythonBinding Vcs-Git: https://salsa.debian.org/python-team/modules/python-vlc.git Vcs-Browser: https://salsa.debian.org/python-team/modules/python-vlc diff -Nru python-vlc-3.0.6109/examples/tkvlc.py python-vlc-3.0.7110/examples/tkvlc.py --- python-vlc-3.0.6109/examples/tkvlc.py 2015-11-24 10:02:15.000000000 +0000 +++ python-vlc-3.0.7110/examples/tkvlc.py 2019-08-03 17:03:50.000000000 +0000 @@ -1,7 +1,6 @@ #! /usr/bin/python # -*- coding: utf-8 -*- -# # tkinter example for VLC Python bindings # Copyright (C) 2015 the VideoLAN team # @@ -19,294 +18,496 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. # -"""A simple example for VLC python bindings using tkinter. Uses python 3.4 +"""A simple example for VLC python bindings using tkinter. + +Requires Python 3.4 or later. Author: Patrick Fay Date: 23-09-2015 """ +# Tested with Python 3.7.4, tkinter/Tk 8.6.9 on macOS 10.13.6 only. +__version__ = '19.07.29' # mrJean1 at Gmail dot com + # import external libraries import vlc +# import standard libraries import sys - if sys.version_info[0] < 3: import Tkinter as Tk from Tkinter import ttk from Tkinter.filedialog import askopenfilename + from Tkinter.tkMessageBox import showerror else: import tkinter as Tk from tkinter import ttk from tkinter.filedialog import askopenfilename - -# import standard libraries -import os -import pathlib -from threading import Thread, Event + from tkinter.messagebox import showerror +from os.path import basename, expanduser, isfile, join as joined +from pathlib import Path import time -import platform -class ttkTimer(Thread): - """a class serving same function as wxTimer... but there may be better ways to do this - """ - def __init__(self, callback, tick): - Thread.__init__(self) - self.callback = callback - self.stopFlag = Event() - self.tick = tick - self.iters = 0 - - def run(self): - while not self.stopFlag.wait(self.tick): - self.iters += 1 - self.callback() +_isMacOS = sys.platform.startswith('darwin') +_isWindows = sys.platform.startswith('win') +_isLinux = sys.platform.startswith('linux') + +if _isMacOS: + from ctypes import c_void_p, cdll + # libtk = cdll.LoadLibrary(ctypes.util.find_library('tk')) + # returns the tk library /usr/lib/libtk.dylib from macOS, + # but we need the tkX.Y library bundled with Python 3+, + # to match the version number of tkinter, _tkinter, etc. + try: + libtk = 'libtk%s.dylib' % (Tk.TkVersion,) + libtk = joined(sys.prefix, 'lib', libtk) + dylib = cdll.LoadLibrary(libtk) + # getNSView = dylib.TkMacOSXDrawableView is the + # proper function to call, but that is non-public + # (in Tk source file macosx/TkMacOSXSubwindows.c) + # and dylib.TkMacOSXGetRootControl happens to call + # dylib.TkMacOSXDrawableView and return the NSView + _GetNSView = dylib.TkMacOSXGetRootControl + # C signature: void *_GetNSView(void *drawable) to get + # the Cocoa/Obj-C NSWindow.contentView attribute, the + # drawable NSView object of the (drawable) NSWindow + _GetNSView.restype = c_void_p + _GetNSView.argtypes = c_void_p, + del dylib + + except (NameError, OSError): # image or symbol not found + def _GetNSView(unused): + return None + libtk = "N/A" + + C_Key = "Command-" # shortcut key modifier + +else: # *nix, Xwindows and Windows, UNTESTED + + libtk = "N/A" + C_Key = "Control-" # shortcut key modifier + + +class _Tk_Menu(Tk.Menu): + '''Tk.Menu extended with .add_shortcut method. + + Note, this is a kludge just to get Command-key shortcuts to + work on macOS. Other modifiers like Ctrl-, Shift- and Option- + are not handled in this code. + ''' + _shortcuts_entries = {} + _shortcuts_widget = None + + def add_shortcut(self, label='', key='', command=None, **kwds): + '''Like Tk.menu.add_command extended with shortcut key. + + If needed use modifiers like Shift- and Alt_ or Option- + as before the shortcut key character. Do not include + the Command- or Control- modifier nor the <...> brackets + since those are handled here, depending on platform and + as needed for the binding. + ''' + # + if not key: + self.add_command(label=label, command=command, **kwds) + + elif _isMacOS: + # keys show as upper-case, always + self.add_command(label=label, accelerator='Command-' + key, + command=command, **kwds) + self.bind_shortcut(key, command, label) + + else: # XXX not tested, not tested, not tested + self.add_command(label=label, underline=label.lower().index(key), + command=command, **kwds) + self.bind_shortcut(key, command, label) - def stop(self): - self.stopFlag.set() + def bind_shortcut(self, key, command, label=None): + """Bind shortcut key, default modifier Command/Control. + """ + # The accelerator modifiers on macOS are Command-, + # Ctrl-, Option- and Shift-, but for .bind[_all] use + # , , and , + # + if self._shortcuts_widget: + if C_Key.lower() not in key.lower(): + key = "<%s%s>" % (C_Key, key.lstrip('<').rstrip('>')) + self._shortcuts_widget.bind(key, command) + # remember the shortcut key for this menu item + if label is not None: + item = self.index(label) + self._shortcuts_entries[item] = key + # The Tk modifier for macOS' Command key is called + # Meta, but there is only Meta_L[eft], no Meta_R[ight] + # and both keyboard command keys generate Meta_L events. + # Similarly for macOS' Option key, the modifier name is + # Alt and there's only Alt_L[eft], no Alt_R[ight] and + # both keyboard option keys generate Alt_L events. See: + # + + def bind_shortcuts_to(self, widget): + '''Set the widget for the shortcut keys, usually root. + ''' + self._shortcuts_widget = widget + + def entryconfig(self, item, **kwds): + """Update shortcut key binding if menu entry changed. + """ + Tk.Menu.entryconfig(self, item, **kwds) + # adjust the shortcut key binding also + if self._shortcuts_widget: + key = self._shortcuts_entries.get(item, None) + if key is not None and "command" in kwds: + self._shortcuts_widget.bind(key, kwds["command"]) - def get(self): - return self.iters class Player(Tk.Frame): """The main window has to deal with events. """ - def __init__(self, parent, title=None): - Tk.Frame.__init__(self, parent) + _geometry = '' + _stopped = None - self.parent = parent + def __init__(self, parent, title=None, video=''): + Tk.Frame.__init__(self, parent) - if title == None: - title = "tk_vlc" - self.parent.title(title) + self.parent = parent # == root + self.parent.title(title or "tkVLCplayer") + self.video = expanduser(video) # Menu Bar # File Menu menubar = Tk.Menu(self.parent) self.parent.config(menu=menubar) - fileMenu = Tk.Menu(menubar) - fileMenu.add_command(label="Open", underline=0, command=self.OnOpen) - fileMenu.add_command(label="Exit", underline=1, command=_quit) + fileMenu = _Tk_Menu(menubar) + fileMenu.bind_shortcuts_to(parent) # XXX must be root? + + fileMenu.add_shortcut("Open...", 'o', self.OnOpen) + fileMenu.add_separator() + fileMenu.add_shortcut("Play", 'p', self.OnPlay) # Play/Pause + fileMenu.add_command(label="Stop", command=self.OnStop) + fileMenu.add_separator() + fileMenu.add_shortcut("Mute", 'm', self.OnMute) + fileMenu.add_separator() + fileMenu.add_shortcut("Close", 'w' if _isMacOS else 's', self.OnClose) + if _isMacOS: # intended for and tested on macOS + fileMenu.add_separator() + fileMenu.add_shortcut("Full Screen", 'f', self.OnFullScreen) menubar.add_cascade(label="File", menu=fileMenu) + self.fileMenu = fileMenu + self.playIndex = fileMenu.index("Play") + self.muteIndex = fileMenu.index("Mute") - # The second panel holds controls - self.player = None + # first, top panel shows video self.videopanel = ttk.Frame(self.parent) - self.canvas = Tk.Canvas(self.videopanel).pack(fill=Tk.BOTH,expand=1) - self.videopanel.pack(fill=Tk.BOTH,expand=1) - - ctrlpanel = ttk.Frame(self.parent) - pause = ttk.Button(ctrlpanel, text="Pause", command=self.OnPause) - play = ttk.Button(ctrlpanel, text="Play", command=self.OnPlay) - stop = ttk.Button(ctrlpanel, text="Stop", command=self.OnStop) - volume = ttk.Button(ctrlpanel, text="Volume", command=self.OnSetVolume) - pause.pack(side=Tk.LEFT) - play.pack(side=Tk.LEFT) + self.canvas = Tk.Canvas(self.videopanel) + self.canvas.pack(fill=Tk.BOTH, expand=1) + self.videopanel.pack(fill=Tk.BOTH, expand=1) + + # panel to hold buttons + buttons = ttk.Frame(self.parent) + self.playButton = ttk.Button(buttons, text="Play", command=self.OnPlay) + stop = ttk.Button(buttons, text="Stop", command=self.OnStop) + self.muteButton = ttk.Button(buttons, text="Mute", command=self.OnMute) + self.playButton.pack(side=Tk.LEFT) stop.pack(side=Tk.LEFT) - volume.pack(side=Tk.LEFT) - self.volume_var = Tk.IntVar() - self.volslider = Tk.Scale(ctrlpanel, variable=self.volume_var, command=self.volume_sel, - from_=0, to=100, orient=Tk.HORIZONTAL, length=100) - self.volslider.pack(side=Tk.LEFT) - ctrlpanel.pack(side=Tk.BOTTOM) - - ctrlpanel2 = ttk.Frame(self.parent) - self.scale_var = Tk.DoubleVar() - self.timeslider_last_val = "" - self.timeslider = Tk.Scale(ctrlpanel2, variable=self.scale_var, command=self.scale_sel, - from_=0, to=1000, orient=Tk.HORIZONTAL, length=500) - self.timeslider.pack(side=Tk.BOTTOM, fill=Tk.X,expand=1) - self.timeslider_last_update = time.time() - ctrlpanel2.pack(side=Tk.BOTTOM,fill=Tk.X) + self.muteButton.pack(side=Tk.LEFT) - - # VLC player controls - self.Instance = vlc.Instance() + self.volMuted = False + self.volVar = Tk.IntVar() + self.volSlider = Tk.Scale(buttons, variable=self.volVar, command=self.OnVolume, + from_=0, to=100, orient=Tk.HORIZONTAL, length=200, + showvalue=0, label='Volume') + self.volSlider.pack(side=Tk.LEFT) + buttons.pack(side=Tk.BOTTOM) + + # panel to hold player time slider + timers = ttk.Frame(self.parent) + self.timeVar = Tk.DoubleVar() + self.timeSliderLast = 0 + self.timeSlider = Tk.Scale(timers, variable=self.timeVar, command=self.OnTime, + from_=0, to=1000, orient=Tk.HORIZONTAL, length=500, + showvalue=0) # label='Time', + self.timeSlider.pack(side=Tk.BOTTOM, fill=Tk.X, expand=1) + self.timeSliderUpdate = time.time() + timers.pack(side=Tk.BOTTOM, fill=Tk.X) + + # VLC player + args = [] + if _isLinux: + args.append('--no-xlib') + self.Instance = vlc.Instance(args) self.player = self.Instance.media_player_new() - # below is a test, now use the File->Open file menu - #media = self.Instance.media_new('output.mp4') - #self.player.set_media(media) - #self.player.play() # hit the player button - #self.player.video_set_deinterlace(str_to_bytes('yadif')) - - self.timer = ttkTimer(self.OnTimer, 1.0) - self.timer.start() + self.parent.bind("", self.OnConfigure) # catch window resize, etc. self.parent.update() - #self.player.set_hwnd(self.GetHandle()) # for windows, OnOpen does does this + self.OnTick() # set the timer up + def OnClose(self, *unused): + """Closes the window and quit. + """ + # print("_quit: bye") + self.parent.quit() # stops mainloop + self.parent.destroy() # this is necessary on Windows to avoid + # ... Fatal Python Error: PyEval_RestoreThread: NULL tstate + sys.exit(0) - def OnExit(self, evt): - """Closes the window. + def OnConfigure(self, *unused): + """Some widget configuration changed. """ - self.Close() + # + self._geometry = '' # force .OnResize in .OnTick, recursive? - def OnOpen(self): + def OnFullScreen(self, *unused): + """Toggle full screen, macOS only. + """ + # + f = not self.parent.attributes("-fullscreen") # or .wm_attributes + if f: + self._previouscreen = self.parent.geometry() + self.parent.attributes("-fullscreen", f) # or .wm_attributes + self.parent.bind("", self.OnFullScreen) + else: + self.parent.attributes("-fullscreen", f) # or .wm_attributes + self.parent.geometry(self._previouscreen) + self.parent.unbind("") + + def OnMute(self, *unused): + """Mute/Unmute audio. + """ + # audio un/mute may be unreliable, see vlc.py docs. + self.volMuted = m = not self.volMuted # self.player.audio_get_mute() + self.player.audio_set_mute(m) + u = "Unmute" if m else "Mute" + self.fileMenu.entryconfig(self.muteIndex, label=u) + self.muteButton.config(text=u) + # update the volume slider text + self.OnVolume() + + def OnOpen(self, *unused): """Pop up a new dialow window to choose a file, then play the selected file. """ # if a file is already running, then stop it. self.OnStop() - # Create a file dialog opened in the current home directory, where - # you can display all kind of files, having as title "Choose a file". - p = pathlib.Path(os.path.expanduser("~")) - fullname = askopenfilename(initialdir = p, title = "choose your file",filetypes = (("all files","*.*"),("mp4 files","*.mp4"))) - if os.path.isfile(fullname): - dirname = os.path.dirname(fullname) - filename = os.path.basename(fullname) - # Creation - self.Media = self.Instance.media_new(str(os.path.join(dirname, filename))) - self.player.set_media(self.Media) - # Report the title of the file chosen - #title = self.player.get_title() - # if an error was encountred while retriving the title, then use - # filename - #if title == -1: - # title = filename - #self.SetTitle("%s - tkVLCplayer" % title) + # you can display all kind of files, having as title "Choose a video". + video = askopenfilename(initialdir = Path(expanduser("~")), + title = "Choose a video", + filetypes = (("all files", "*.*"), + ("mp4 files", "*.mp4"), + ("mov files", "*.mov"))) + self._Play(video) + + def _Pause_Play(self, playing): + # re-label menu item and button, adjust callbacks + p = 'Pause' if playing else 'Play' + c = self.OnPlay if playing is None else self.OnPause + self.fileMenu.entryconfig(self.playIndex, label=p, command=c) + # self.fileMenu.bind_shortcut('p', c) # XXX handled + self.playButton.config(text=p, command=c) + self._stopped = False + + def _Play(self, video): + # helper for OnOpen and OnPlay + if isfile(video): # Creation + m = self.Instance.media_new(str(video)) # Path, unicode + self.player.set_media(m) + self.parent.title("tkVLCplayer - %s" % (basename(video),)) # set the window id where to render VLC's video output - if platform.system() == 'Windows': - self.player.set_hwnd(self.GetHandle()) + h = self.videopanel.winfo_id() # .winfo_visualid()? + if _isWindows: + self.player.set_hwnd(h) + elif _isMacOS: + # XXX 1) using the videopanel.winfo_id() handle + # causes the video to play in the entire panel on + # macOS, covering the buttons, sliders, etc. + # XXX 2) .winfo_id() to return NSView on macOS? + v = _GetNSView(h) + if v: + self.player.set_nsobject(v) + else: + self.player.set_xwindow(h) # plays audio, no video else: - self.player.set_xwindow(self.GetHandle()) # this line messes up windows + self.player.set_xwindow(h) # fails on Windows # FIXME: this should be made cross-platform self.OnPlay() - # set the volume slider to the current volume - #self.volslider.SetValue(self.player.audio_get_volume() / 2) - self.volslider.set(self.player.audio_get_volume()) - - def OnPlay(self): - """Toggle the status to Play/Pause. - If no file is loaded, open the dialog window. + def OnPause(self, *unused): + """Toggle between Pause and Play. """ - # check if there is a file to play, otherwise open a - # Tk.FileDialog to select a file + if self.player.get_media(): + self._Pause_Play(not self.player.is_playing()) + self.player.pause() # toggles + + def OnPlay(self, *unused): + """Play video, if none is loaded, open the dialog window. + """ + # if there's no video to play or playing, + # open a Tk.FileDialog to select a file if not self.player.get_media(): - self.OnOpen() + if self.video: + self._Play(expanduser(self.video)) + self.video = '' + else: + self.OnOpen() + # Try to play, if this fails display an error message + elif self.player.play(): # == -1 + self.showError("Unable to play the video.") else: - # Try to launch the media, if this fails display an error message - if self.player.play() == -1: - self.errorDialog("Unable to play.") - - def GetHandle(self): - return self.videopanel.winfo_id() - - #def OnPause(self, evt): - def OnPause(self): - """Pause the player. - """ - self.player.pause() - - def OnStop(self): - """Stop the player. - """ - self.player.stop() - # reset the time slider - self.timeslider.set(0) - - def OnTimer(self): - """Update the time slider according to the current movie time. - """ - if self.player == None: - return - # since the self.player.get_length can change while playing, - # re-set the timeslider to the correct range. - length = self.player.get_length() - dbl = length * 0.001 - self.timeslider.config(to=dbl) - - # update the time on the slider - tyme = self.player.get_time() - if tyme == -1: - tyme = 0 - dbl = tyme * 0.001 - self.timeslider_last_val = ("%.0f" % dbl) + ".0" - # don't want to programatically change slider while user is messing with it. - # wait 2 seconds after user lets go of slider - if time.time() > (self.timeslider_last_update + 2.0): - self.timeslider.set(dbl) - - def scale_sel(self, evt): - if self.player == None: - return - nval = self.scale_var.get() - sval = str(nval) - if self.timeslider_last_val != sval: - # this is a hack. The timer updates the time slider. - # This change causes this rtn (the 'slider has changed' rtn) to be invoked. - # I can't tell the difference between when the user has manually moved the slider and when - # the timer changed the slider. But when the user moves the slider tkinter only notifies - # this rtn about once per second and when the slider has quit moving. - # Also, the tkinter notification value has no fractional seconds. - # The timer update rtn saves off the last update value (rounded to integer seconds) in timeslider_last_val - # if the notification time (sval) is the same as the last saved time timeslider_last_val then - # we know that this notification is due to the timer changing the slider. - # otherwise the notification is due to the user changing the slider. - # if the user is changing the slider then I have the timer routine wait for at least - # 2 seconds before it starts updating the slider again (so the timer doesn't start fighting with the - # user) - self.timeslider_last_update = time.time() - mval = "%.0f" % (nval * 1000) - self.player.set_time(int(mval)) # expects milliseconds - - - def volume_sel(self, evt): - if self.player == None: - return - volume = self.volume_var.get() - if volume > 100: - volume = 100 - if self.player.audio_set_volume(volume) == -1: - self.errorDialog("Failed to set volume") - - - - def OnToggleVolume(self, evt): - """Mute/Unmute according to the audio button. - """ - is_mute = self.player.audio_get_mute() - - self.player.audio_set_mute(not is_mute) - # update the volume slider; - # since vlc volume range is in [0, 200], - # and our volume slider has range [0, 100], just divide by 2. - self.volume_var.set(self.player.audio_get_volume()) - - def OnSetVolume(self): - """Set the volume according to the volume sider. - """ - volume = self.volume_var.get() - # vlc.MediaPlayer.audio_set_volume returns 0 if success, -1 otherwise - if volume > 100: - volume = 100 - if self.player.audio_set_volume(volume) == -1: - self.errorDialog("Failed to set volume") + self._Pause_Play(True) + # set volume slider to audio level + vol = self.player.audio_get_volume() + if vol > 0: + self.volVar.set(vol) + self.volSlider.set(vol) + + def OnResize(self, *unused): + """Adjust the window/frame to the video aspect ratio. + """ + g = self.parent.geometry() + if g != self._geometry and self.player: + u, v = self.player.video_get_size() # often (0, 0) + if v > 0 and u > 0: + # get window size and position + g, x, y = g.split('+') + w, h = g.split('x') + # alternatively, use .winfo_... + # w = self.parent.winfo_width() + # h = self.parent.winfo_height() + # x = self.parent.winfo_x() + # y = self.parent.winfo_y() + # use the video aspect ratio ... + if u > v: # ... for landscape + # adjust the window height + h = round(float(w) * v / u) + else: # ... for portrait + # adjust the window width + w = round(float(h) * u / v) + self.parent.geometry("%sx%s+%s+%s" % (w, h, x, y)) + self._geometry = self.parent.geometry() # actual + + def OnStop(self, *unused): + """Stop the player, resets media. + """ + if self.player: + self.player.stop() + self._Pause_Play(None) + # reset the time slider + self.timeSlider.set(0) + self._stopped = True + # XXX on macOS libVLC prints these error messages: + # [h264 @ 0x7f84fb061200] get_buffer() failed + # [h264 @ 0x7f84fb061200] thread_get_buffer() failed + # [h264 @ 0x7f84fb061200] decode_slice_header error + # [h264 @ 0x7f84fb061200] no frame! + + def OnTick(self): + """Timer tick, update the time slider to the video time. + """ + if self.player: + # since the self.player.get_length may change while + # playing, re-set the timeSlider to the correct range + t = self.player.get_length() * 1e-3 # to seconds + if t > 0: + self.timeSlider.config(to=t) + + t = self.player.get_time() * 1e-3 # to seconds + # don't change slider while user is messing with it + if t > 0 and time.time() > (self.timeSliderUpdate + 2): + self.timeSlider.set(t) + self.timeSliderLast = int(self.timeVar.get()) + # start the 1 second timer again + self.parent.after(1000, self.OnTick) + # adjust window to video aspect ratio, done periodically + # on purpose since the player.video_get_size() only + # returns non-zero sizes after playing for a while + if not self._geometry: + self.OnResize() + + def OnTime(self, *unused): + if self.player: + t = self.timeVar.get() + if self.timeSliderLast != int(t): + # this is a hack. The timer updates the time slider. + # This change causes this rtn (the 'slider has changed' rtn) + # to be invoked. I can't tell the difference between when + # the user has manually moved the slider and when the timer + # changed the slider. But when the user moves the slider + # tkinter only notifies this rtn about once per second and + # when the slider has quit moving. + # Also, the tkinter notification value has no fractional + # seconds. The timer update rtn saves off the last update + # value (rounded to integer seconds) in timeSliderLast if + # the notification time (sval) is the same as the last saved + # time timeSliderLast then we know that this notification is + # due to the timer changing the slider. Otherwise the + # notification is due to the user changing the slider. If + # the user is changing the slider then I have the timer + # routine wait for at least 2 seconds before it starts + # updating the slider again (so the timer doesn't start + # fighting with the user). + self.player.set_time(int(t * 1e3)) # milliseconds + self.timeSliderUpdate = time.time() - def errorDialog(self, errormessage): + def OnVolume(self, *unused): + """Volume slider changed, adjust the audio volume. + """ + vol = min(self.volVar.get(), 100) + v_M = "%d%s" % (vol, " (Muted)" if self.volMuted else '') + self.volSlider.config(label="Volume " + v_M) + if self.player and not self._stopped: + # .audio_set_volume returns 0 if success, -1 otherwise, + # e.g. if the player is stopped or doesn't have media + if self.player.audio_set_volume(vol): # and self.player.get_media(): + self.showError("Failed to set the volume: %s." % (v_M,)) + + def showError(self, message): """Display a simple error dialog. """ - Tk.tkMessageBox.showerror(self, 'Error', errormessage) + self.OnStop() + showerror(self.parent.title(), message) -def Tk_get_root(): - if not hasattr(Tk_get_root, "root"): #(1) - Tk_get_root.root= Tk.Tk() #initialization call is inside the function - return Tk_get_root.root - -def _quit(): - print("_quit: bye") - root = Tk_get_root() - root.quit() # stops mainloop - root.destroy() # this is necessary on Windows to prevent - # Fatal Python Error: PyEval_RestoreThread: NULL tstate - os._exit(1) if __name__ == "__main__": - # Create a Tk.App(), which handles the windowing system event loop - root = Tk_get_root() - root.protocol("WM_DELETE_WINDOW", _quit) - player = Player(root, title="tkinter vlc") - # show the player window centred and run the application + _video = '' + + while len(sys.argv) > 1: + arg = sys.argv.pop(1) + if arg.lower() in ('-v', '--version'): + # show all versions, sample output on macOS: + # % python3 ./tkvlc.py -v + # tkvlc.py: 2019.07.28 (tkinter 8.6 /Library/Frameworks/Python.framework/Versions/3.7/lib/libtk8.6.dylib) + # vlc.py: 3.0.6109 (Sun Mar 31 20:14:16 2019 3.0.6) + # LibVLC version: 3.0.6 Vetinari (0x3000600) + # LibVLC compiler: clang: warning: argument unused during compilation: '-mmacosx-version-min=10.7' [-Wunused-command-line-argument] + # Plugin path: /Applications/VLC3.0.6.app/Contents/MacOS/plugins + # Python: 3.7.4 (64bit) macOS 10.13.6 + + # Print version of this vlc.py and of the libvlc + print('%s: %s (%s %s %s)' % (basename(__file__), __version__, + Tk.__name__, Tk.TkVersion, libtk)) + try: + vlc.print_version() + vlc.print_python() + except AttributeError: + pass + sys.exit(0) + + elif arg.startswith('-'): + print('usage: %s [-v | --version] []' % (sys.argv[0],)) + sys.exit(1) + + elif arg: # video file + _video = expanduser(arg) + if not isfile(_video): + print('%s error: no such file: %r' % (sys.argv[0], arg)) + sys.exit(1) + + # Create a Tk.App() to handle the windowing event loop + root = Tk.Tk() + player = Player(root, video=_video) + root.protocol("WM_DELETE_WINDOW", player.OnClose) # XXX unnecessary (on macOS) root.mainloop() diff -Nru python-vlc-3.0.6109/examples/wxvlc.py python-vlc-3.0.7110/examples/wxvlc.py --- python-vlc-3.0.6109/examples/wxvlc.py 2018-07-13 08:56:14.000000000 +0000 +++ python-vlc-3.0.7110/examples/wxvlc.py 2019-08-03 17:08:16.000000000 +0000 @@ -1,6 +1,7 @@ #! /usr/bin/python # -*- coding: utf-8 -*- +# # # WX example for VLC Python bindings # Copyright (C) 2009-2010 the VideoLAN team @@ -26,12 +27,15 @@ Date: 23-11-2010 """ +# Tested with Python 3.7.4, wxPython 4.0.6 on macOS 10.13.6 only. +__version__ = '19.07.28' # mrJean1 at Gmail dot com + # import external libraries -import wx # 2.8 +import wx # 2.8 ... 4.0.6 import vlc # import standard libraries -import os +from os.path import basename, expanduser, isfile, join as joined import sys try: @@ -43,15 +47,17 @@ class Player(wx.Frame): """The main window has to deal with events. """ - def __init__(self, title): - wx.Frame.__init__(self, None, -1, title, + def __init__(self, title='', video=''): + wx.Frame.__init__(self, None, -1, title=title or 'wxVLC', pos=wx.DefaultPosition, size=(550, 500)) + self.video = video + # Menu Bar # File Menu self.frame_menubar = wx.MenuBar() self.file_menu = wx.Menu() - self.file_menu.Append(1, "&Open", "Open from file..") + self.file_menu.Append(1, "&Open...", "Open from file...") self.file_menu.AppendSeparator() self.file_menu.Append(2, "&Close", "Quit") self.Bind(wx.EVT_MENU, self.OnOpen, id=1) @@ -65,21 +71,23 @@ self.videopanel.SetBackgroundColour(wx.BLACK) # The second panel holds controls - ctrlpanel = wx.Panel(self, -1 ) + ctrlpanel = wx.Panel(self, -1) self.timeslider = wx.Slider(ctrlpanel, -1, 0, 0, 1000) self.timeslider.SetRange(0, 1000) - pause = wx.Button(ctrlpanel, label="Pause") - play = wx.Button(ctrlpanel, label="Play") - stop = wx.Button(ctrlpanel, label="Stop") - volume = wx.Button(ctrlpanel, label="Volume") + self.pause = wx.Button(ctrlpanel, label="Pause") + self.pause.Disable() + self.play = wx.Button(ctrlpanel, label="Play") + self.stop = wx.Button(ctrlpanel, label="Stop") + self.stop.Disable() + self.mute = wx.Button(ctrlpanel, label="Mute") self.volslider = wx.Slider(ctrlpanel, -1, 0, 0, 100, size=(100, -1)) # Bind controls to events - self.Bind(wx.EVT_BUTTON, self.OnPlay, play) - self.Bind(wx.EVT_BUTTON, self.OnPause, pause) - self.Bind(wx.EVT_BUTTON, self.OnStop, stop) - self.Bind(wx.EVT_BUTTON, self.OnToggleVolume, volume) - self.Bind(wx.EVT_SLIDER, self.OnSetVolume, self.volslider) + self.Bind(wx.EVT_BUTTON, self.OnPlay, self.play) + self.Bind(wx.EVT_BUTTON, self.OnPause, self.pause) + self.Bind(wx.EVT_BUTTON, self.OnStop, self.stop) + self.Bind(wx.EVT_BUTTON, self.OnMute, self.mute) + self.Bind(wx.EVT_SLIDER, self.OnVolume, self.volslider) # Give a pretty layout to the controls ctrlbox = wx.BoxSizer(wx.VERTICAL) @@ -88,11 +96,11 @@ # box1 contains the timeslider box1.Add(self.timeslider, 1) # box2 contains some buttons and the volume controls - box2.Add(play, flag=wx.RIGHT, border=5) - box2.Add(pause) - box2.Add(stop) + box2.Add(self.play, flag=wx.RIGHT, border=5) + box2.Add(self.pause) + box2.Add(self.stop) box2.Add((-1, -1), 1) - box2.Add(volume) + box2.Add(self.mute) box2.Add(self.volslider, flag=wx.TOP | wx.LEFT, border=5) # Merge box1 and box2 to the ctrlsizer ctrlbox.Add(box1, flag=wx.EXPAND | wx.BOTTOM, border=10) @@ -124,40 +132,40 @@ # if a file is already running, then stop it. self.OnStop(None) - # Create a file dialog opened in the current home directory, where - # you can display all kind of files, having as title "Choose a file". - dlg = wx.FileDialog(self, "Choose a file", os.path.expanduser('~'), "", - "*.*", wx.OPEN) - if dlg.ShowModal() == wx.ID_OK: - dirname = dlg.GetDirectory() - filename = dlg.GetFilename() - # Creation - self.Media = self.Instance.media_new(unicode(os.path.join(dirname, filename))) + video = self.video + if video: + self.video = '' + else: # Create a file dialog opened in the current home directory, + # to show all kind of files, having as title "Choose a ...". + dlg = wx.FileDialog(self, "Choose a video file", expanduser('~'), + "", "*.*", wx.FD_OPEN) # XXX wx.OPEN + if dlg.ShowModal() == wx.ID_OK: + video = joined(dlg.GetDirectory(), dlg.GetFilename()) + # finally destroy the dialog + dlg.Destroy() + + if isfile(video): # Creation + self.Media = self.Instance.media_new(unicode(video)) self.player.set_media(self.Media) # Report the title of the file chosen title = self.player.get_title() - # if an error was encountred while retriving the title, then use - # filename - if title == -1: - title = filename - self.SetTitle("%s - wxVLCplayer" % title) + # if an error was encountred while retrieving the title, + # otherwise use filename + self.SetTitle("%s - %s" % (title if title != -1 else 'wxVLC', basename(video))) # set the window id where to render VLC's video output handle = self.videopanel.GetHandle() - if sys.platform.startswith('linux'): # for Linux using the X Server + if sys.platform.startswith('linux'): # for Linux using the X Server self.player.set_xwindow(handle) - elif sys.platform == "win32": # for Windows + elif sys.platform == "win32": # for Windows self.player.set_hwnd(handle) - elif sys.platform == "darwin": # for MacOS + elif sys.platform == "darwin": # for MacOS self.player.set_nsobject(handle) self.OnPlay(None) # set the volume slider to the current volume self.volslider.SetValue(self.player.audio_get_volume() / 2) - # finally destroy the dialog - dlg.Destroy() - def OnPlay(self, evt): """Toggle the status to Play/Pause. @@ -167,16 +175,28 @@ # wx.FileDialog to select a file if not self.player.get_media(): self.OnOpen(None) - else: # Try to launch the media, if this fails display an error message - if self.player.play() == -1: - self.errorDialog("Unable to play.") - else: - self.timer.Start() + elif self.player.play(): # == -1: + self.errorDialog("Unable to play.") + else: + # adjust window to video aspect ratio + # w, h = self.player.video_get_size() + # if h > 0 and w > 0: # often (0, 0) + # self.videopanel.... + self.timer.Start(1000) # XXX millisecs + self.play.Disable() + self.pause.Enable() + self.stop.Enable() def OnPause(self, evt): """Pause the player. """ + if self.player.is_playing(): + self.play.Enable() + self.pause.Disable() + else: + self.play.Disable() + self.pause.Enable() self.player.pause() def OnStop(self, evt): @@ -186,6 +206,9 @@ # reset the time slider self.timeslider.SetValue(0) self.timer.Stop() + self.play.Enable() + self.pause.Disable() + self.stop.Disable() def OnTimer(self, evt): """Update the time slider according to the current movie time. @@ -199,18 +222,18 @@ time = self.player.get_time() self.timeslider.SetValue(time) - def OnToggleVolume(self, evt): + def OnMute(self, evt): """Mute/Unmute according to the audio button. """ - is_mute = self.player.audio_get_mute() - - self.player.audio_set_mute(not is_mute) + muted = self.player.audio_get_mute() + self.player.audio_set_mute(not muted) + self.mute.SetLabel("Mute" if muted else "Unmute") # update the volume slider; # since vlc volume range is in [0, 200], # and our volume slider has range [0, 100], just divide by 2. - self.volslider.SetValue(self.player.audio_get_volume() / 2) + # self.volslider.SetValue(self.player.audio_get_volume() / 2) - def OnSetVolume(self, evt): + def OnVolume(self, evt): """Set the volume according to the volume sider. """ volume = self.volslider.GetValue() * 2 @@ -225,12 +248,50 @@ wx.ICON_ERROR) edialog.ShowModal() + if __name__ == "__main__": + + _video = '' + + while len(sys.argv) > 1: + arg = sys.argv.pop(1) + if arg.lower() in ('-v', '--version'): + # show all versions, sample output on macOS: + # % python3 ./wxvlc.py -v + # wxvlc.py: 19.07.28 (wx 4.0.6 osx-cocoa (phoenix) wxWidgets 3.0.5 _core.cpython-37m-darwin.so) + # vlc.py: 3.0.6109 (Sun Mar 31 20:14:16 2019 3.0.6) + # LibVLC version: 3.0.6 Vetinari (0x3000600) + # LibVLC compiler: clang: warning: argument unused during compilation: '-mmacosx-version-min=10.7' [-Wunused-command-line-argument] + # Plugin path: /Applications/VLC3.0.6.app/Contents/MacOS/plugins + # Python: 3.7.4 (64bit) macOS 10.13.6 + + # Print version of this vlc.py and of the libvlc + c = basename(str(wx._core).split()[-1].rstrip('>').strip("'").strip('"')) + print('%s: %s (%s %s %s)' % (basename(__file__), __version__, + wx.__name__, wx.version(), c)) + try: + vlc.print_version() + vlc.print_python() + except AttributeError: + pass + sys.exit(0) + + elif arg.startswith('-'): + print('usage: %s [-v | --version] []' % (sys.argv[0],)) + sys.exit(1) + + elif arg: # video file + _video = expanduser(arg) + if not isfile(_video): + print('%s error: no such file: %r' % (sys.argv[0], arg)) + sys.exit(1) + # Create a wx.App(), which handles the windowing system event loop - app = wx.PySimpleApp() - # Create the window containing our small media player - player = Player("Simple PyVLC Player") - # show the player window centred and run the application + app = wx.App() # XXX wx.PySimpleApp() + # Create the window containing our media player + player = Player(video=_video) + # show the player window centred player.Centre() player.Show() + # run the application app.MainLoop() diff -Nru python-vlc-3.0.6109/PKG-INFO python-vlc-3.0.7110/PKG-INFO --- python-vlc-3.0.6109/PKG-INFO 2019-03-31 18:17:41.000000000 +0000 +++ python-vlc-3.0.7110/PKG-INFO 2019-08-03 18:19:10.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: python-vlc -Version: 3.0.6109 +Version: 3.0.7110 Summary: VLC bindings for python. Home-page: http://wiki.videolan.org/PythonBinding Author: Olivier Aubert @@ -14,7 +14,7 @@ player. Note that it relies on an already present install of VLC. It has been automatically generated from the include files of - vlc 3.0.6, using generator 1.9. + vlc 3.0.7, using generator 1.10. Keywords: vlc,video Platform: UNKNOWN diff -Nru python-vlc-3.0.6109/python_vlc.egg-info/PKG-INFO python-vlc-3.0.7110/python_vlc.egg-info/PKG-INFO --- python-vlc-3.0.6109/python_vlc.egg-info/PKG-INFO 2019-03-31 18:17:40.000000000 +0000 +++ python-vlc-3.0.7110/python_vlc.egg-info/PKG-INFO 2019-08-03 18:19:10.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: python-vlc -Version: 3.0.6109 +Version: 3.0.7110 Summary: VLC bindings for python. Home-page: http://wiki.videolan.org/PythonBinding Author: Olivier Aubert @@ -14,7 +14,7 @@ player. Note that it relies on an already present install of VLC. It has been automatically generated from the include files of - vlc 3.0.6, using generator 1.9. + vlc 3.0.7, using generator 1.10. Keywords: vlc,video Platform: UNKNOWN diff -Nru python-vlc-3.0.6109/setup.py python-vlc-3.0.7110/setup.py --- python-vlc-3.0.6109/setup.py 2019-03-31 18:16:52.000000000 +0000 +++ python-vlc-3.0.7110/setup.py 2019-08-03 18:18:29.000000000 +0000 @@ -4,7 +4,7 @@ from setuptools import setup setup(name='python-vlc', - version = '3.0.6109', + version = '3.0.7110', author='Olivier Aubert', author_email='contact@olivieraubert.net', maintainer='Olivier Aubert', @@ -35,5 +35,5 @@ player. Note that it relies on an already present install of VLC. It has been automatically generated from the include files of - vlc 3.0.6, using generator 1.9. + vlc 3.0.7, using generator 1.10. """) diff -Nru python-vlc-3.0.6109/vlc.py python-vlc-3.0.7110/vlc.py --- python-vlc-3.0.6109/vlc.py 2019-03-31 18:14:16.000000000 +0000 +++ python-vlc-3.0.7110/vlc.py 2019-08-03 18:13:06.000000000 +0000 @@ -52,10 +52,10 @@ import logging logger = logging.getLogger(__name__) -__version__ = "3.0.6109" -__libvlc_version__ = "3.0.6" -__generator_version__ = "1.9" -build_date = "Sun Mar 31 20:14:16 2019 3.0.6" +__version__ = "3.0.7110" +__libvlc_version__ = "3.0.7" +__generator_version__ = "1.10" +build_date = "Sat Aug 3 20:13:06 2019 3.0.7" # The libvlc doc states that filenames are expected to be in UTF8, do # not rely on sys.getfilesystemencoding() which will be confused, @@ -803,19 +803,19 @@ 5: 'Refresh', 6: 'Size', 7: 'Timeout', - 8: 'marquee_X', - 9: 'marquee_Y', + 8: 'X', + 9: 'Y', } -VideoMarqueeOption.Color = VideoMarqueeOption(2) -VideoMarqueeOption.Enable = VideoMarqueeOption(0) -VideoMarqueeOption.Opacity = VideoMarqueeOption(3) -VideoMarqueeOption.Position = VideoMarqueeOption(4) -VideoMarqueeOption.Refresh = VideoMarqueeOption(5) -VideoMarqueeOption.Size = VideoMarqueeOption(6) -VideoMarqueeOption.Text = VideoMarqueeOption(1) -VideoMarqueeOption.Timeout = VideoMarqueeOption(7) -VideoMarqueeOption.marquee_X = VideoMarqueeOption(8) -VideoMarqueeOption.marquee_Y = VideoMarqueeOption(9) +VideoMarqueeOption.Color = VideoMarqueeOption(2) +VideoMarqueeOption.Enable = VideoMarqueeOption(0) +VideoMarqueeOption.Opacity = VideoMarqueeOption(3) +VideoMarqueeOption.Position = VideoMarqueeOption(4) +VideoMarqueeOption.Refresh = VideoMarqueeOption(5) +VideoMarqueeOption.Size = VideoMarqueeOption(6) +VideoMarqueeOption.Text = VideoMarqueeOption(1) +VideoMarqueeOption.Timeout = VideoMarqueeOption(7) +VideoMarqueeOption.X = VideoMarqueeOption(8) +VideoMarqueeOption.Y = VideoMarqueeOption(9) class NavigateMode(_Enum): '''Navigation mode. @@ -1000,328 +1000,6 @@ PlaybackMode.loop = PlaybackMode(1) PlaybackMode.repeat = PlaybackMode(2) -class Callback(ctypes.c_void_p): - """Callback function notification. - @param p_event: the event triggering the callback. - """ - pass -class LogCb(ctypes.c_void_p): - """Callback prototype for LibVLC log message handler. - @param data: data pointer as given to L{libvlc_log_set}(). - @param level: message level (@ref L{LogLevel}). - @param ctx: message context (meta-information about the message). - @param fmt: printf() format string (as defined by ISO C11). - @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns. - """ - pass -class MediaOpenCb(ctypes.c_void_p): - """Callback prototype to open a custom bitstream input media. - The same media item can be opened multiple times. Each time, this callback - is invoked. It should allocate and initialize any instance-specific - resources, then store them in *datap. The instance resources can be freed - in the @ref libvlc_media_close_cb callback. - @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}(). - @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown. - """ - pass -class MediaReadCb(ctypes.c_void_p): - """Callback prototype to read data from a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - @param buf: start address of the buffer to read data into. - @param len: bytes length of the buffer. - @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return. - """ - pass -class MediaSeekCb(ctypes.c_void_p): - """Callback prototype to seek a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - @param offset: absolute byte offset to seek to. - @return: 0 on success, -1 on error. - """ - pass -class MediaCloseCb(ctypes.c_void_p): - """Callback prototype to close a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - """ - pass -class VideoLockCb(ctypes.c_void_p): - """Callback prototype to allocate and lock a picture buffer. - Whenever a new video frame needs to be decoded, the lock callback is - invoked. Depending on the video chroma, one or three pixel planes of - adequate dimensions must be returned via the second parameter. Those - planes must be aligned on 32-bytes boundaries. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT]. - @return: a private pointer for the display and unlock callbacks to identify the picture buffers. - """ - pass -class VideoUnlockCb(ctypes.c_void_p): - """Callback prototype to unlock a picture buffer. - When the video frame decoding is complete, the unlock callback is invoked. - This callback might not be needed at all. It is only an indication that the - application can now read the pixel values if it needs to. - @note: A picture buffer is unlocked after the picture is decoded, - but before the picture is displayed. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. - @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN]. - """ - pass -class VideoDisplayCb(ctypes.c_void_p): - """Callback prototype to display a picture. - When the video frame needs to be shown, as determined by the media playback - clock, the display callback is invoked. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. - """ - pass -class VideoFormatCb(ctypes.c_void_p): - """Callback prototype to configure picture buffers format. - This callback gets the format of the video as output by the video decoder - and the chain of video filters (if any). It can opt to change any parameter - as it needs. In that case, LibVLC will attempt to convert the video format - (rescaling and chroma conversion) but these operations can be CPU intensive. - @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT]. - @param chroma: pointer to the 4 bytes video format identifier [IN/OUT]. - @param width: pointer to the pixel width [IN/OUT]. - @param height: pointer to the pixel height [IN/OUT]. - @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT]. - @return: lines table of scanlines count for each plane. - """ - pass -class VideoCleanupCb(ctypes.c_void_p): - """Callback prototype to configure picture buffers format. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN]. - """ - pass -class AudioPlayCb(ctypes.c_void_p): - """Callback prototype for audio playback. - The LibVLC media player decodes and post-processes the audio signal - asynchronously (in an internal thread). Whenever audio samples are ready - to be queued to the output, this callback is invoked. - The number of samples provided per invocation may depend on the file format, - the audio coding algorithm, the decoder plug-in, the post-processing - filters and timing. Application must not assume a certain number of samples. - The exact format of audio samples is determined by L{libvlc_audio_set_format}() - or L{libvlc_audio_set_format_callbacks}() as is the channels layout. - Note that the number of samples is per channel. For instance, if the audio - track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds - of audio signal - regardless of the number of audio channels. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param samples: pointer to a table of audio samples to play back [IN]. - @param count: number of audio samples to play back. - @param pts: expected play time stamp (see libvlc_delay()). - """ - pass -class AudioPauseCb(ctypes.c_void_p): - """Callback prototype for audio pause. - LibVLC invokes this callback to pause audio playback. - @note: The pause callback is never called if the audio is already paused. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param pts: time stamp of the pause request (should be elapsed already). - """ - pass -class AudioResumeCb(ctypes.c_void_p): - """Callback prototype for audio resumption. - LibVLC invokes this callback to resume audio playback after it was - previously paused. - @note: The resume callback is never called if the audio is not paused. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param pts: time stamp of the resumption request (should be elapsed already). - """ - pass -class AudioFlushCb(ctypes.c_void_p): - """Callback prototype for audio buffer flush. - LibVLC invokes this callback if it needs to discard all pending buffers and - stop playback as soon as possible. This typically occurs when the media is - stopped. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - """ - pass -class AudioDrainCb(ctypes.c_void_p): - """Callback prototype for audio buffer drain. - LibVLC may invoke this callback when the decoded audio track is ending. - There will be no further decoded samples for the track, but playback should - nevertheless continue until all already pending buffers are rendered. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - """ - pass -class AudioSetVolumeCb(ctypes.c_void_p): - """Callback prototype for audio volume change. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param volume: software volume (1. = nominal, 0. = mute). - @param mute: muted flag. - """ - pass -class AudioSetupCb(ctypes.c_void_p): - """Callback prototype to setup the audio playback. - This is called when the media player needs to create a new audio output. - @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT]. - @param format: 4 bytes sample format [IN/OUT]. - @param rate: sample rate [IN/OUT]. - @param channels: channels count [IN/OUT]. - @return: 0 on success, anything else to skip audio playback. - """ - pass -class AudioCleanupCb(ctypes.c_void_p): - """Callback prototype for audio playback cleanup. - This is called when the media player no longer needs an audio output. - @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - """ - pass -class CallbackDecorators(object): - "Class holding various method decorators for callback functions." - Callback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) - Callback.__doc__ = '''Callback function notification. - @param p_event: the event triggering the callback. - ''' - LogCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, Log_ptr, ctypes.c_char_p, ctypes.c_void_p) - LogCb.__doc__ = '''Callback prototype for LibVLC log message handler. - @param data: data pointer as given to L{libvlc_log_set}(). - @param level: message level (@ref L{LogLevel}). - @param ctx: message context (meta-information about the message). - @param fmt: printf() format string (as defined by ISO C11). - @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns. - ''' - MediaOpenCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(ctypes.c_uint64)) - MediaOpenCb.__doc__ = '''Callback prototype to open a custom bitstream input media. - The same media item can be opened multiple times. Each time, this callback - is invoked. It should allocate and initialize any instance-specific - resources, then store them in *datap. The instance resources can be freed - in the @ref libvlc_media_close_cb callback. - @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}(). - @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown. - ''' - MediaReadCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_ssize_t), ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t) - MediaReadCb.__doc__ = '''Callback prototype to read data from a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - @param buf: start address of the buffer to read data into. - @param len: bytes length of the buffer. - @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return. - ''' - MediaSeekCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.c_void_p, ctypes.c_uint64) - MediaSeekCb.__doc__ = '''Callback prototype to seek a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - @param offset: absolute byte offset to seek to. - @return: 0 on success, -1 on error. - ''' - MediaCloseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) - MediaCloseCb.__doc__ = '''Callback prototype to close a custom bitstream input media. - @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. - ''' - VideoLockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) - VideoLockCb.__doc__ = '''Callback prototype to allocate and lock a picture buffer. - Whenever a new video frame needs to be decoded, the lock callback is - invoked. Depending on the video chroma, one or three pixel planes of - adequate dimensions must be returned via the second parameter. Those - planes must be aligned on 32-bytes boundaries. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT]. - @return: a private pointer for the display and unlock callbacks to identify the picture buffers. - ''' - VideoUnlockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) - VideoUnlockCb.__doc__ = '''Callback prototype to unlock a picture buffer. - When the video frame decoding is complete, the unlock callback is invoked. - This callback might not be needed at all. It is only an indication that the - application can now read the pixel values if it needs to. - @note: A picture buffer is unlocked after the picture is decoded, - but before the picture is displayed. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. - @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN]. - ''' - VideoDisplayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) - VideoDisplayCb.__doc__ = '''Callback prototype to display a picture. - When the video frame needs to be shown, as determined by the media playback - clock, the display callback is invoked. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. - @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. - ''' - VideoFormatCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint)) - VideoFormatCb.__doc__ = '''Callback prototype to configure picture buffers format. - This callback gets the format of the video as output by the video decoder - and the chain of video filters (if any). It can opt to change any parameter - as it needs. In that case, LibVLC will attempt to convert the video format - (rescaling and chroma conversion) but these operations can be CPU intensive. - @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT]. - @param chroma: pointer to the 4 bytes video format identifier [IN/OUT]. - @param width: pointer to the pixel width [IN/OUT]. - @param height: pointer to the pixel height [IN/OUT]. - @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT]. - @return: lines table of scanlines count for each plane. - ''' - VideoCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) - VideoCleanupCb.__doc__ = '''Callback prototype to configure picture buffers format. - @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN]. - ''' - AudioPlayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_int64) - AudioPlayCb.__doc__ = '''Callback prototype for audio playback. - The LibVLC media player decodes and post-processes the audio signal - asynchronously (in an internal thread). Whenever audio samples are ready - to be queued to the output, this callback is invoked. - The number of samples provided per invocation may depend on the file format, - the audio coding algorithm, the decoder plug-in, the post-processing - filters and timing. Application must not assume a certain number of samples. - The exact format of audio samples is determined by L{libvlc_audio_set_format}() - or L{libvlc_audio_set_format_callbacks}() as is the channels layout. - Note that the number of samples is per channel. For instance, if the audio - track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds - of audio signal - regardless of the number of audio channels. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param samples: pointer to a table of audio samples to play back [IN]. - @param count: number of audio samples to play back. - @param pts: expected play time stamp (see libvlc_delay()). - ''' - AudioPauseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) - AudioPauseCb.__doc__ = '''Callback prototype for audio pause. - LibVLC invokes this callback to pause audio playback. - @note: The pause callback is never called if the audio is already paused. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param pts: time stamp of the pause request (should be elapsed already). - ''' - AudioResumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) - AudioResumeCb.__doc__ = '''Callback prototype for audio resumption. - LibVLC invokes this callback to resume audio playback after it was - previously paused. - @note: The resume callback is never called if the audio is not paused. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param pts: time stamp of the resumption request (should be elapsed already). - ''' - AudioFlushCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) - AudioFlushCb.__doc__ = '''Callback prototype for audio buffer flush. - LibVLC invokes this callback if it needs to discard all pending buffers and - stop playback as soon as possible. This typically occurs when the media is - stopped. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - ''' - AudioDrainCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) - AudioDrainCb.__doc__ = '''Callback prototype for audio buffer drain. - LibVLC may invoke this callback when the decoded audio track is ending. - There will be no further decoded samples for the track, but playback should - nevertheless continue until all already pending buffers are rendered. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - ''' - AudioSetVolumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_float, ctypes.c_bool) - AudioSetVolumeCb.__doc__ = '''Callback prototype for audio volume change. - @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - @param volume: software volume (1. = nominal, 0. = mute). - @param mute: muted flag. - ''' - AudioSetupCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint)) - AudioSetupCb.__doc__ = '''Callback prototype to setup the audio playback. - This is called when the media player needs to create a new audio output. - @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT]. - @param format: 4 bytes sample format [IN/OUT]. - @param rate: sample rate [IN/OUT]. - @param channels: channels count [IN/OUT]. - @return: 0 on success, anything else to skip audio playback. - ''' - AudioCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) - AudioCleanupCb.__doc__ = '''Callback prototype for audio playback cleanup. - This is called when the media player no longer needs an audio output. - @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. - ''' -cb = CallbackDecorators # End of generated enum types # # From libvlc_structures.h @@ -1549,80 +1227,449 @@ def module_description_list(head): """Convert a ModuleDescription linked list to a Python list (and release the former). """ - r = [] - if head: - item = head - while item: - item = item.contents - r.append((item.name, item.shortname, item.longname, item.help)) - item = item.next - libvlc_module_description_list_release(head) - return r - -class AudioOutputDevice(_Cstruct): - - def __str__(self): - return '%s(%d:%s)' % (self.__class__.__name__, self.id, self.name) - -AudioOutputDevice._fields_ = [ # recursive struct - ('next', ctypes.POINTER(AudioOutputDevice)), - ('device', ctypes.c_char_p ), - ('description', ctypes.c_char_p), - ] - -class TitleDescription(_Cstruct): - _fields_ = [ - ('duration', ctypes.c_longlong), - ('name', ctypes.c_char_p), - ('menu', ctypes.c_bool), - ] - -class ChapterDescription(_Cstruct): - _fields_ = [ - ('time_offset', ctypes.c_longlong), - ('duration', ctypes.c_longlong), - ('name', ctypes.c_char_p), - ] - -class VideoViewpoint(_Cstruct): - _fields_ = [ - ('yaw', ctypes.c_float), - ('pitch', ctypes.c_float), - ('roll', ctypes.c_float), - ('field_of_view', ctypes.c_float), - ] - -class MediaDiscovererDescription(_Cstruct): - _fields_ = [ - ('name', ctypes.c_char_p), - ('longname', ctypes.c_char_p), - ('cat', MediaDiscovererCategory), - ] - - def __str__(self): - return '%s %s (%d) - %s' % (self.__class__.__name__, self.name, self.cat, self.longname) - -# This struct depends on the MediaSlaveType enum that is defined only -# in > 2.2 -if 'MediaSlaveType' in locals(): - class MediaSlave(_Cstruct): - _fields_ = [ - ('psz_uri', ctypes.c_char_p), - ('i_type', MediaSlaveType), - ('i_priority', ctypes.c_uint) - ] - -class RDDescription(_Cstruct): - _fields_ = [ - ('name', ctypes.c_char_p), - ('longname', ctypes.c_char_p) - ] - - -class MediaThumbnailRequest: - def __new__(cls, *args): - if len(args) == 1 and isinstance(args[0], _Ints): - return _Constructor(cls, args[0]) + r = [] + if head: + item = head + while item: + item = item.contents + r.append((item.name, item.shortname, item.longname, item.help)) + item = item.next + libvlc_module_description_list_release(head) + return r + +class AudioOutputDevice(_Cstruct): + + def __str__(self): + return '%s(%d:%s)' % (self.__class__.__name__, self.id, self.name) + +AudioOutputDevice._fields_ = [ # recursive struct + ('next', ctypes.POINTER(AudioOutputDevice)), + ('device', ctypes.c_char_p ), + ('description', ctypes.c_char_p), + ] + +class TitleDescription(_Cstruct): + _fields_ = [ + ('duration', ctypes.c_longlong), + ('name', ctypes.c_char_p), + ('menu', ctypes.c_bool), + ] + +class ChapterDescription(_Cstruct): + _fields_ = [ + ('time_offset', ctypes.c_longlong), + ('duration', ctypes.c_longlong), + ('name', ctypes.c_char_p), + ] + +class VideoViewpoint(_Cstruct): + _fields_ = [ + ('yaw', ctypes.c_float), + ('pitch', ctypes.c_float), + ('roll', ctypes.c_float), + ('field_of_view', ctypes.c_float), + ] + +class MediaDiscovererDescription(_Cstruct): + _fields_ = [ + ('name', ctypes.c_char_p), + ('longname', ctypes.c_char_p), + ('cat', MediaDiscovererCategory), + ] + + def __str__(self): + return '%s %s (%d) - %s' % (self.__class__.__name__, self.name, self.cat, self.longname) + +# This struct depends on the MediaSlaveType enum that is defined only +# in > 2.2 +if 'MediaSlaveType' in locals(): + class MediaSlave(_Cstruct): + _fields_ = [ + ('psz_uri', ctypes.c_char_p), + ('i_type', MediaSlaveType), + ('i_priority', ctypes.c_uint) + ] + +class RDDescription(_Cstruct): + _fields_ = [ + ('name', ctypes.c_char_p), + ('longname', ctypes.c_char_p) + ] + + +class MediaThumbnailRequest: + def __new__(cls, *args): + if len(args) == 1 and isinstance(args[0], _Ints): + return _Constructor(cls, args[0]) + +class Direct3dDeviceSetup(_Cstruct): + _fields_ = [ + ('device_context', ctypes.c_void_p), + ] + +class Direct3dDeviceCfg(_Cstruct): + _fields_ = [ + ('hardware_decoding', ctypes.c_bool), + ] + +class Direct3dCfg(_Cstruct): + _fields_ = [ + ('width', ctypes.c_uint), + ('height', ctypes.c_uint), + ('bitdepth', ctypes.c_uint), + ('full_range', ctypes.c_bool), + # FIXME: should be references to enums + ('colorspace', ctypes.c_uint), + ('primaries', ctypes.c_uint), + ('transfer', ctypes.c_uint), + ] + +class VideoOutputCfg(_Cstruct): + _fields_ = [ + ('surface_format', ctypes.c_int), + ('full_range', ctypes.c_bool), + # FIXME: should be references to enums + ('colorspace', ctypes.c_uint), + ('primaries', ctypes.c_uint), + ('transfer', ctypes.c_uint), + ] + +class Direct3dHdr10Metadata(_Cstruct): + _fields_ = [ + ('RedPrimary ', ctypes.c_uint16 * 2), + ('GreenPrimary', ctypes.c_uint16 * 2), + ('BluePrimary', ctypes.c_uint16 * 2), + ('WhitePoint', ctypes.c_uint16 * 2), + ('MaxMasteringLuminance', ctypes.c_uint), + ('MinMasteringLuminance', ctypes.c_uint), + ('MaxContentLightLevel', ctypes.c_uint16), + ('MaxFrameAverageLightLevel', ctypes.c_uint16), + ] + +# Generated callback definitions # +class Callback(ctypes.c_void_p): + """Callback function notification. + @param p_event: the event triggering the callback. + """ + pass +class LogCb(ctypes.c_void_p): + """Callback prototype for LibVLC log message handler. + @param data: data pointer as given to L{libvlc_log_set}(). + @param level: message level (@ref L{LogLevel}). + @param ctx: message context (meta-information about the message). + @param fmt: printf() format string (as defined by ISO C11). + @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns. + """ + pass +class MediaOpenCb(ctypes.c_void_p): + """Callback prototype to open a custom bitstream input media. + The same media item can be opened multiple times. Each time, this callback + is invoked. It should allocate and initialize any instance-specific + resources, then store them in *datap. The instance resources can be freed + in the @ref libvlc_media_close_cb callback. + @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}(). + @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown. + """ + pass +class MediaReadCb(ctypes.c_void_p): + """Callback prototype to read data from a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + @param buf: start address of the buffer to read data into. + @param len: bytes length of the buffer. + @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return. + """ + pass +class MediaSeekCb(ctypes.c_void_p): + """Callback prototype to seek a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + @param offset: absolute byte offset to seek to. + @return: 0 on success, -1 on error. + """ + pass +class MediaCloseCb(ctypes.c_void_p): + """Callback prototype to close a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + """ + pass +class VideoLockCb(ctypes.c_void_p): + """Callback prototype to allocate and lock a picture buffer. + Whenever a new video frame needs to be decoded, the lock callback is + invoked. Depending on the video chroma, one or three pixel planes of + adequate dimensions must be returned via the second parameter. Those + planes must be aligned on 32-bytes boundaries. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT]. + @return: a private pointer for the display and unlock callbacks to identify the picture buffers. + """ + pass +class VideoUnlockCb(ctypes.c_void_p): + """Callback prototype to unlock a picture buffer. + When the video frame decoding is complete, the unlock callback is invoked. + This callback might not be needed at all. It is only an indication that the + application can now read the pixel values if it needs to. + @note: A picture buffer is unlocked after the picture is decoded, + but before the picture is displayed. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. + @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN]. + """ + pass +class VideoDisplayCb(ctypes.c_void_p): + """Callback prototype to display a picture. + When the video frame needs to be shown, as determined by the media playback + clock, the display callback is invoked. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. + """ + pass +class VideoFormatCb(ctypes.c_void_p): + """Callback prototype to configure picture buffers format. + This callback gets the format of the video as output by the video decoder + and the chain of video filters (if any). It can opt to change any parameter + as it needs. In that case, LibVLC will attempt to convert the video format + (rescaling and chroma conversion) but these operations can be CPU intensive. + @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT]. + @param chroma: pointer to the 4 bytes video format identifier [IN/OUT]. + @param width: pointer to the pixel width [IN/OUT]. + @param height: pointer to the pixel height [IN/OUT]. + @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT]. + @return: lines table of scanlines count for each plane. + """ + pass +class VideoCleanupCb(ctypes.c_void_p): + """Callback prototype to configure picture buffers format. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN]. + """ + pass +class AudioPlayCb(ctypes.c_void_p): + """Callback prototype for audio playback. + The LibVLC media player decodes and post-processes the audio signal + asynchronously (in an internal thread). Whenever audio samples are ready + to be queued to the output, this callback is invoked. + The number of samples provided per invocation may depend on the file format, + the audio coding algorithm, the decoder plug-in, the post-processing + filters and timing. Application must not assume a certain number of samples. + The exact format of audio samples is determined by L{libvlc_audio_set_format}() + or L{libvlc_audio_set_format_callbacks}() as is the channels layout. + Note that the number of samples is per channel. For instance, if the audio + track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds + of audio signal - regardless of the number of audio channels. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param samples: pointer to a table of audio samples to play back [IN]. + @param count: number of audio samples to play back. + @param pts: expected play time stamp (see libvlc_delay()). + """ + pass +class AudioPauseCb(ctypes.c_void_p): + """Callback prototype for audio pause. + LibVLC invokes this callback to pause audio playback. + @note: The pause callback is never called if the audio is already paused. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param pts: time stamp of the pause request (should be elapsed already). + """ + pass +class AudioResumeCb(ctypes.c_void_p): + """Callback prototype for audio resumption. + LibVLC invokes this callback to resume audio playback after it was + previously paused. + @note: The resume callback is never called if the audio is not paused. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param pts: time stamp of the resumption request (should be elapsed already). + """ + pass +class AudioFlushCb(ctypes.c_void_p): + """Callback prototype for audio buffer flush. + LibVLC invokes this callback if it needs to discard all pending buffers and + stop playback as soon as possible. This typically occurs when the media is + stopped. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + """ + pass +class AudioDrainCb(ctypes.c_void_p): + """Callback prototype for audio buffer drain. + LibVLC may invoke this callback when the decoded audio track is ending. + There will be no further decoded samples for the track, but playback should + nevertheless continue until all already pending buffers are rendered. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + """ + pass +class AudioSetVolumeCb(ctypes.c_void_p): + """Callback prototype for audio volume change. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param volume: software volume (1. = nominal, 0. = mute). + @param mute: muted flag. + """ + pass +class AudioSetupCb(ctypes.c_void_p): + """Callback prototype to setup the audio playback. + This is called when the media player needs to create a new audio output. + @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT]. + @param format: 4 bytes sample format [IN/OUT]. + @param rate: sample rate [IN/OUT]. + @param channels: channels count [IN/OUT]. + @return: 0 on success, anything else to skip audio playback. + """ + pass +class AudioCleanupCb(ctypes.c_void_p): + """Callback prototype for audio playback cleanup. + This is called when the media player no longer needs an audio output. + @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + """ + pass +class CallbackDecorators(object): + "Class holding various method decorators for callback functions." + Callback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) + Callback.__doc__ = '''Callback function notification. + @param p_event: the event triggering the callback. + ''' + LogCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, Log_ptr, ctypes.c_char_p, ctypes.c_void_p) + LogCb.__doc__ = '''Callback prototype for LibVLC log message handler. + @param data: data pointer as given to L{libvlc_log_set}(). + @param level: message level (@ref L{LogLevel}). + @param ctx: message context (meta-information about the message). + @param fmt: printf() format string (as defined by ISO C11). + @param args: variable argument list for the format @note Log message handlers B{must} be thread-safe. @warning The message context pointer, the format string parameters and the variable arguments are only valid until the callback returns. + ''' + MediaOpenCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(ctypes.c_uint64)) + MediaOpenCb.__doc__ = '''Callback prototype to open a custom bitstream input media. + The same media item can be opened multiple times. Each time, this callback + is invoked. It should allocate and initialize any instance-specific + resources, then store them in *datap. The instance resources can be freed + in the @ref libvlc_media_close_cb callback. + @param opaque: private pointer as passed to L{libvlc_media_new_callbacks}(). + @return: datap storage space for a private data pointer, sizep byte length of the bitstream or UINT64_MAX if unknown. + ''' + MediaReadCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t) + MediaReadCb.__doc__ = '''Callback prototype to read data from a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + @param buf: start address of the buffer to read data into. + @param len: bytes length of the buffer. + @return: strictly positive number of bytes read, 0 on end-of-stream, or -1 on non-recoverable error @note If no data is immediately available, then the callback should sleep. @warning The application is responsible for avoiding deadlock situations. In particular, the callback should return an error if playback is stopped; if it does not return, then L{libvlc_media_player_stop}() will never return. + ''' + MediaSeekCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64) + MediaSeekCb.__doc__ = '''Callback prototype to seek a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + @param offset: absolute byte offset to seek to. + @return: 0 on success, -1 on error. + ''' + MediaCloseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) + MediaCloseCb.__doc__ = '''Callback prototype to close a custom bitstream input media. + @param opaque: private pointer as set by the @ref libvlc_media_open_cb callback. + ''' + VideoLockCb = ctypes.CFUNCTYPE(ctypes.POINTER(ctypes.c_void_p), ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) + VideoLockCb.__doc__ = '''Callback prototype to allocate and lock a picture buffer. + Whenever a new video frame needs to be decoded, the lock callback is + invoked. Depending on the video chroma, one or three pixel planes of + adequate dimensions must be returned via the second parameter. Those + planes must be aligned on 32-bytes boundaries. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param planes: start address of the pixel planes (LibVLC allocates the array of void pointers, this callback must initialize the array) [OUT]. + @return: a private pointer for the display and unlock callbacks to identify the picture buffers. + ''' + VideoUnlockCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p)) + VideoUnlockCb.__doc__ = '''Callback prototype to unlock a picture buffer. + When the video frame decoding is complete, the unlock callback is invoked. + This callback might not be needed at all. It is only an indication that the + application can now read the pixel values if it needs to. + @note: A picture buffer is unlocked after the picture is decoded, + but before the picture is displayed. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. + @param planes: pixel planes as defined by the @ref libvlc_video_lock_cb callback (this parameter is only for convenience) [IN]. + ''' + VideoDisplayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) + VideoDisplayCb.__doc__ = '''Callback prototype to display a picture. + When the video frame needs to be shown, as determined by the media playback + clock, the display callback is invoked. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() [IN]. + @param picture: private pointer returned from the @ref libvlc_video_lock_cb callback [IN]. + ''' + VideoFormatCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint)) + VideoFormatCb.__doc__ = '''Callback prototype to configure picture buffers format. + This callback gets the format of the video as output by the video decoder + and the chain of video filters (if any). It can opt to change any parameter + as it needs. In that case, LibVLC will attempt to convert the video format + (rescaling and chroma conversion) but these operations can be CPU intensive. + @param opaque: pointer to the private pointer passed to L{libvlc_video_set_callbacks}() [IN/OUT]. + @param chroma: pointer to the 4 bytes video format identifier [IN/OUT]. + @param width: pointer to the pixel width [IN/OUT]. + @param height: pointer to the pixel height [IN/OUT]. + @param pitches: table of scanline pitches in bytes for each pixel plane (the table is allocated by LibVLC) [OUT]. + @return: lines table of scanlines count for each plane. + ''' + VideoCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) + VideoCleanupCb.__doc__ = '''Callback prototype to configure picture buffers format. + @param opaque: private pointer as passed to L{libvlc_video_set_callbacks}() (and possibly modified by @ref libvlc_video_format_cb) [IN]. + ''' + AudioPlayCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_int64) + AudioPlayCb.__doc__ = '''Callback prototype for audio playback. + The LibVLC media player decodes and post-processes the audio signal + asynchronously (in an internal thread). Whenever audio samples are ready + to be queued to the output, this callback is invoked. + The number of samples provided per invocation may depend on the file format, + the audio coding algorithm, the decoder plug-in, the post-processing + filters and timing. Application must not assume a certain number of samples. + The exact format of audio samples is determined by L{libvlc_audio_set_format}() + or L{libvlc_audio_set_format_callbacks}() as is the channels layout. + Note that the number of samples is per channel. For instance, if the audio + track sampling rate is 48000 Hz, then 1200 samples represent 25 milliseconds + of audio signal - regardless of the number of audio channels. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param samples: pointer to a table of audio samples to play back [IN]. + @param count: number of audio samples to play back. + @param pts: expected play time stamp (see libvlc_delay()). + ''' + AudioPauseCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) + AudioPauseCb.__doc__ = '''Callback prototype for audio pause. + LibVLC invokes this callback to pause audio playback. + @note: The pause callback is never called if the audio is already paused. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param pts: time stamp of the pause request (should be elapsed already). + ''' + AudioResumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) + AudioResumeCb.__doc__ = '''Callback prototype for audio resumption. + LibVLC invokes this callback to resume audio playback after it was + previously paused. + @note: The resume callback is never called if the audio is not paused. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param pts: time stamp of the resumption request (should be elapsed already). + ''' + AudioFlushCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int64) + AudioFlushCb.__doc__ = '''Callback prototype for audio buffer flush. + LibVLC invokes this callback if it needs to discard all pending buffers and + stop playback as soon as possible. This typically occurs when the media is + stopped. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + ''' + AudioDrainCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) + AudioDrainCb.__doc__ = '''Callback prototype for audio buffer drain. + LibVLC may invoke this callback when the decoded audio track is ending. + There will be no further decoded samples for the track, but playback should + nevertheless continue until all already pending buffers are rendered. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + ''' + AudioSetVolumeCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_float, ctypes.c_bool) + AudioSetVolumeCb.__doc__ = '''Callback prototype for audio volume change. + @param data: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + @param volume: software volume (1. = nominal, 0. = mute). + @param mute: muted flag. + ''' + AudioSetupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_uint)) + AudioSetupCb.__doc__ = '''Callback prototype to setup the audio playback. + This is called when the media player needs to create a new audio output. + @param opaque: pointer to the data pointer passed to L{libvlc_audio_set_callbacks}() [IN/OUT]. + @param format: 4 bytes sample format [IN/OUT]. + @param rate: sample rate [IN/OUT]. + @param channels: channels count [IN/OUT]. + @return: 0 on success, anything else to skip audio playback. + ''' + AudioCleanupCb = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p) + AudioCleanupCb.__doc__ = '''Callback prototype for audio playback cleanup. + This is called when the media player no longer needs an audio output. + @param opaque: data pointer as passed to L{libvlc_audio_set_callbacks}() [IN]. + ''' +cb = CallbackDecorators +# End of generated enum types # # End of header.py # class AudioEqualizer(_Ctype): @@ -1753,10 +1800,11 @@ """ try: # retrieve Python callback and arguments call, args, kwds = self._callbacks[k] - # deref event.contents to simplify callback code - call(event.contents, *args, **kwds) except KeyError: # detached? pass + else: + # deref event.contents to simplify callback code + call(event.contents, *args, **kwds) self._callback_handler = _callback_handler self._callbacks = {} @@ -3729,7 +3777,7 @@ '''Sets a fixed decoded audio format. This only works in combination with L{audio_set_callbacks}(), and is mutually exclusive with L{audio_set_format_callbacks}(). - @param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32"). + @param format: a four-characters string identifying the sample format (e.g. "S16N" or "f32l"). @param rate: sample rate (expressed in Hz). @param channels: channels count. @version: LibVLC 2.0.0 or later. @@ -4765,7 +4813,7 @@ ''' f = _Cfunctions.get('libvlc_log_get_context', None) or \ _Cfunction('libvlc_log_get_context', ((1,), (2,), (2,), (2,),), None, - None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint)) + None, Log_ptr, ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint)) return f(ctx) def libvlc_log_get_object(ctx, id): @@ -4786,7 +4834,7 @@ ''' f = _Cfunctions.get('libvlc_log_get_object', None) or \ _Cfunction('libvlc_log_get_object', ((1,), (2,), (2,), (1,),), None, - None, Log_ptr, ListPOINTER(ctypes.c_char_p), ListPOINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint)) + None, Log_ptr, ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_uint)) return f(ctx, id) def libvlc_log_unset(p_instance): @@ -6894,7 +6942,7 @@ This only works in combination with L{libvlc_audio_set_callbacks}(), and is mutually exclusive with L{libvlc_audio_set_format_callbacks}(). @param mp: the media player. - @param format: a four-characters string identifying the sample format (e.g. "S16N" or "FL32"). + @param format: a four-characters string identifying the sample format (e.g. "S16N" or "f32l"). @param rate: sample rate (expressed in Hz). @param channels: channels count. @version: LibVLC 2.0.0 or later.