I'm trying to play a video with QMediaPlayer in response to a drag and drop event, and I find that it works or doesn't work depending on where the player is instantiated. Am I doing something obviously wrong here?
Details: Qt 6.4.2, Python 3.11.2, Apple M2 Pro, macOS 13.2.1
(Background: My app allows (a variable number of) videos to be loaded simultaneously when the user drops videos, and I want each to have its own QMediaPlayer. Hence the need to instantiate the player in response to a drop event.)
Here is a minimal example highlighting the issue. This works fine when EARLY = True, and gives a segfault when EARLY = False.
#!/usr/bin/env python3
# encoding: utf-8
import os
import sys
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QUrl, qVersion
from PySide6.QtWidgets import QMainWindow
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget
# Drag and drop a video file into the window to play it
# e.g., http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4
#
# Crashes on macOS when EARLY = False; works when EARLY = True
# (Qt 6.4.2, Python 3.11.2, Apple M2 Pro, macOS 13.2.1)
EARLY = True # segfault when `False`
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(800, 600)
self.setWindowTitle('Qt6 Video Player')
self.setAcceptDrops(True)
if EARLY:
self.player = QMediaPlayer()
def dragEnterEvent(self, e):
if e.mimeData().hasUrls():
e.acceptProposedAction()
def dropEvent(self, e):
paths = [os.path.abspath(url.toLocalFile())
for url in e.mimeData().urls()]
if not EARLY:
self.player = QMediaPlayer()
videoWidget = QVideoWidget()
self.setCentralWidget(videoWidget)
self.player.errorOccurred.connect(self.mediaErrorOccured)
self.player.setVideoOutput(videoWidget)
self.player.setSource(QUrl.fromLocalFile(paths[0]))
self.player.play()
def mediaErrorOccured(self, error, message):
print('error:', error, message)
if __name__ == '__main__':
print(f'Qt version {qVersion()}')
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()