For a project I'm building a PyQt5 media player. I want to be able to play new video's in my media player by enqueueing a new url to a shared queue between my main thread and my media player. The code I'm using for now is the following:
from PyQt5.QtWidgets import QWidget, QVBoxLayout
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import QUrl
import threading
import time
class MediaPlayer(QWidget, threading.Thread):
def __init__(self, queue, url_first_media):
super().__init__()
# Instantiate queue
self.queue = queue
# Create URL
self.url = QUrl.fromLocalFile(url_first_media)
# Set window title
self.setWindowTitle("Media Player")
# Init UI
self.__init_ui()
# Play initial video
self.media_player.setMedia(QMediaContent(self.url))
self.media_player.play()
# Show maximized
self.showMaximized()
def __init_ui(self):
INITIALIZE UI, left out to not make this code block too bulky.
def run(self):
self.__process_data()
def __process_data(self):
terminate = False
while not terminate:
if not self.queue.empty():
url, terminate = self.queue.get()
self.__change_video(url)
time.sleep(1)
def __change_video(self, video_url):
# Create URL object
self.url = QUrl.fromLocalFile(video_url)
# Change playing video
self.media_player.setMedia(QMediaContent(self.url))
# Play new video
self.media_player.play()
My main thread is from another class called Environment, the code for that one is the following.
from media_player import MediaPlayer
import queue
class Environment:
def __init__(self):
self.queue = queue.Queue(5)
self.media_player = MediaPlayer(self.queue, "path")
self.__start_media_player()
def __start_media_player(self):
self.media_player.start()
So for now, what I think is working correctly is just starting the thread. Obviously the media player isn't showing since I'm not showing it like the PyQt5 documentation suggests. The code they suggest adapted to my class is the following.
import sys
from PyQt5.QtWidgets import QApplication
from media_player import MediaPlayer
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MediaPlayer(queue, "path_to_video")
window.show()
sys.exit(app.exec())
I am not sure where to put this code into my current structure to make this work. I wanted to put it after self.__process_data() in run() but I'm afraid this won't work since there is a while loop in front of it. Something else I wanted to try is to put it after starting my thread in Environment. I'm also afraid this won't work since I guess the loop from showing the media player will lock up my main thread. Is there any solution to this or am I looking at it wrong?
The main thing what I want to achieve is changing the playing video in my media_player by calling for example __change_video(). I also looked into working threads from PyQt5 but I don't want my environment thread to be destroyed since I need it for other things to interact with (so I cannot keep deleting / initializing an Environment object). I'm quite new to multithreading and PyQt5 so any help / advice is greatly appreciated!