It run it correctly you would have to use pyglet.app.run()
at the end of code. It will run event loop
which will run code which play next music. It will also run code assigned to on_eos
, etc.
import pyglet
files = [
'somemusic1.wav',
'somemusic2.wav',
'somemusic3.wav',
]
player = pyglet.media.Player()
@player.event
def on_eos():
print("[event] on_eos: end of file")
@player.event
def on_player_eos():
print("[event] on_player_eos: end of queue")
musics = []
for filename in files:
item = pyglet.media.load(filename)
musics.append( item )
print('load:', filename)
player.queue(item)
print('queue:', item)
player.play()
pyglet.app.run() # need it to run `event loop`
If you want to run it with tkinter
then it can be problem because pyglet
runs event loop pyglet.app.run()
which blocks code and tkinter
has to run own event loop root.mainloop()
which also blocks code. One of this loop would have to run in separated thread - something similar to answer in Playing music with Pyglet and Tkinter in Python
I tried use thread for this code but I played only first music when I press button in tkinter
. So I resigned.
I tried also build own loop in piglet
(see and add root.update()
instead of root.mainloop()
but it would need something more to work correctly. So I resigned.
while True:
pyglet.clock.tick()
for window in pyglet.app.windows:
window.switch_to()
window.dispatch_events()
window.dispatch_event('on_draw')
window.flip()
root.update()
As for me the best solution is to use PyQt
. It is used to create GUI
and it has many wigdets and many classes for other task.
I used some example code with QMediaPlayer
and QMediaPlaylist
to run all music one by one after clicking button. It has also function to change volume
but I didn't test it.
It can load not only sound but also video which it can display in QVideoWidget
. And it can load files directly from internet (URLs).
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QPushButton
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer, QMediaPlaylist
import sys
files = [
'somemusic1.wav',
'somemusic2.wav',
'somemusic3.wav',
]
class VideoPlayer:
def __init__(self):
#self.video = QVideoWidget()
#self.video.resize(300, 300)
#self.video.move(0, 0)
self.playlist = QMediaPlaylist()
for item in files:
self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(item)))
self.playlist.setCurrentIndex(1)
self.player = QMediaPlayer()
#self.player.setVideoOutput(self.video)
self.player.setPlaylist(self.playlist)
def callback(self):
self.player.setPosition(0) # to start at the beginning of the video every time
#self.video.show()
self.player.play()
if __name__ == '__main__':
app = QApplication(sys.argv)
v = VideoPlayer()
b = QPushButton('start')
b.clicked.connect(v.callback)
b.show()
sys.exit(app.exec_())
EDIT:
I created working code with Pyglet
and tkinter
using pyglet.clock.schedule()
to runs root.update()
periodically.
import pyglet
from pyglet import clock
import tkinter as tk
files = [
'somemusic1.wav',
'somemusic2.wav',
'somemusic3.wav',
]
player = pyglet.media.Player()
@player.event
def on_eos():
print("[event] on_eos: end of file")
@player.event
def on_player_eos():
print("[event] on_player_eos: end of queue")
media = []
# load files
for filename in files:
print('load:', filename)
item = pyglet.media.load(filename)
media.append( item )
def create_queue():
# create queue
for item in media:
print('queue:', item)
player.queue(item)
# --- tkitner ---
def play():
create_queue()
player.play()
def update(event): # `schedule` sends `event` but `root.update` doesn't get any arguments
root.update()
def on_close():
clock.unschedule(update)
root.destroy()
pyglet.app.exit()
is_paused = False
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", on_close)
tk.Button(root, text="Play", command=play).pack()
tk.Button(root, text="Exit", command=on_close).pack()
clock.schedule(update)
pyglet.app.run() # need it to run `event loop`