Page 1 of 1

simple tkinter GUI for vlc.py (python 3.4)

Posted: 23 Sep 2015 19:26
by pat_3
Hello,
Below is tk_vlc.py, a simple tkinter based GUI wrapper for vlc.py. I'm using python 3.4 and windows 10.
tk_vlc.py is based on vlc-python/wxvlc.py. I haven't tested it on linux, or on python 2.x or anywhere else.

Code: Select all

#! /usr/bin/python # -*- coding: utf-8 -*- # # tkinter example for VLC Python bindings # Copyright (C) 2009-2010 the VideoLAN team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # 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 Author: Patrick Fay Date: 23-09-2015 """ # import external libraries import vlc import sys if sys.version_info[0] < 3: import Tkinter as Tk from Tkinter import ttk from Tkinter.filedialog import askopenfilename else: import tkinter as Tk from tkinter import ttk from tkinter.filedialog import askopenfilename # import standard libraries import os import pathlib from threading import Timer,Thread,Event 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 #print("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() #print("ttkTimer start") def stop(self): self.stopFlag.set() def get(self): return self.iters # def doit(): # print("hey dude") # code to demo ttkTimer #t = ttkTimer(doit, 1.0) #t.start() #time.sleep(5) #print("t.get= ", t.get()) #t.stop() #print("timer should be stopped now") class Player(Tk.Frame): """The main window has to deal with events. """ def __init__(self, parent, title=None): Tk.Frame.__init__(self, parent) self.parent = parent if title == None: title = "tk_vlc" self.parent.title(title) # 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) menubar.add_cascade(label="File", menu=fileMenu) # The second panel holds controls self.player = None 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) 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) # VLC player controls self.Instance = vlc.Instance() 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.update() #self.player.set_hwnd(self.GetHandle()) # for windows, OnOpen does does this def OnExit(self, evt): """Closes the window. """ self.Close() def OnOpen(self): """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): print (fullname) splt = os.path.split(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) # set the window id where to render VLC's video output if platform.system() == 'Windows': self.player.set_hwnd(self.GetHandle()) else: self.player.set_xwindow(self.GetHandle()) # this line messes up 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. """ # check if there is a file to play, otherwise open a # Tk.FileDialog to select a file if not self.player.get_media(): self.OnOpen() 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) #selection = "Value, last = " + sval + " " + str(self.timeslider_last_val) #print("selection= ", selection) 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() print("volume= ", volume) #volume = self.volslider.get() * 2 # 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") def errorDialog(self, errormessage): """Display a simple error dialog. """ edialog = Tk.tkMessageBox.showerror(self, 'Error', errormessage) 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 root.mainloop()

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 08 Oct 2015 16:05
by Jean-Baptiste Kempf
Nice!

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 08 Oct 2015 16:05
by Jean-Baptiste Kempf
What's your name?

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 22 Nov 2015 21:23
by pat_3
Patrick Fay
This script was part of a project to find highlights (meta-data) in my kids soccer game videos.
I extract the audio from the video, graph the loudness over the video, and look for the referee's whistle (break the audio into segments, do FFTs to get the frequency, look for a whistle signature, play the video/audio segment with whistle for verification.
The whistle finder works sort of okay. Some people's voices when they yell have the same frequency. Also I've been in cases where there are multiple fields with a football game on the field next to the soccer game... football blows the whistle every few seconds it seems...

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 25 Nov 2015 17:26
by Jean-Baptiste Kempf

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 16 Dec 2015 17:26
by kodela
Hi @pet_3:

I wanted to try your "tk_vlc.py" example program under Windows. I have the Python version 2.7.11 (32 bit) installed.
With this line: "from Tkinter import TTK" I, however, get the following error:

Code: Select all

from Tkinter import ttk 'ImportError: cannot import name ttk'
What can I do against it?

You have indeed written:
A simple example for VLC python bindings using tkinter. Uses python 3.4
but in the version query you have a takes into account the version 2.

Code: Select all

if sys.version_info[0] < 3: import Tkinter as Tk from Tkinter import ttk from Tkinter.filedialog import askopenfilename else: import tkinter as Tk from tkinter import ttk from tkinter.filedialog import askopenfilename
The code in the first block is still unique for version 2.x.

The same problems are there with the import of
"from Tkinter.filedialog import askopenfilename"
and
"import pathlib"

With version 3.5 everything works fine.

Re: simple tkinter GUI for vlc.py (python 3.4)

Posted: 06 Jan 2017 11:59
by ken38
I was just starting a learning curve using tkinter to play mp3 through vlc.py and you have given me the perfect fast start. A great working example and the best way to support newbies.
Simple but brilliant. Thanks for taking the time.