diff options
Diffstat (limited to 'examples/multimedia/player/player.py')
-rw-r--r-- | examples/multimedia/player/player.py | 249 |
1 files changed, 155 insertions, 94 deletions
diff --git a/examples/multimedia/player/player.py b/examples/multimedia/player/player.py index 44df8853b..359c4ec3d 100644 --- a/examples/multimedia/player/player.py +++ b/examples/multimedia/player/player.py @@ -1,7 +1,7 @@ ############################################################################# ## -## Copyright (C) 2017 The Qt Company Ltd. +## Copyright (C) 2021 The Qt Company Ltd. ## Contact: http://www.qt.io/licensing/ ## ## This file is part of the Qt for Python examples of the Qt Toolkit. @@ -42,118 +42,179 @@ """PySide6 Multimedia player example""" import sys -from PySide6.QtCore import QStandardPaths, Qt +from PySide6.QtCore import QStandardPaths, Qt, Slot from PySide6.QtGui import QAction, QIcon, QKeySequence, QScreen from PySide6.QtWidgets import (QApplication, QDialog, QFileDialog, QMainWindow, QSlider, QStyle, QToolBar) -from PySide6.QtMultimedia import QMediaPlayer, QMediaPlaylist +from PySide6.QtMultimedia import QMediaFormat, QMediaPlayer, QMediaPlaylist from PySide6.QtMultimediaWidgets import QVideoWidget +AVI = "video/x-msvideo" # AVI + + +MP4 = 'video/mp4' + + +def get_supported_mime_types(): + result = [] + for f in QMediaFormat().supportedFileFormats(QMediaFormat.Decode): + mime_type = QMediaFormat(f).mimeType() + result.append(mime_type.name()) + return result + + class MainWindow(QMainWindow): def __init__(self): super().__init__() - self.playlist = QMediaPlaylist() - self.player = QMediaPlayer() - - toolBar = QToolBar() - self.addToolBar(toolBar) - - fileMenu = self.menuBar().addMenu("&File") - openAction = QAction(QIcon.fromTheme("document-open"), - "&Open...", self, shortcut=QKeySequence.Open, - triggered=self.open) - fileMenu.addAction(openAction) - exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit", - self, shortcut="Ctrl+Q", triggered=self.close) - fileMenu.addAction(exitAction) - - playMenu = self.menuBar().addMenu("&Play") - playIcon = self.style().standardIcon(QStyle.SP_MediaPlay) - self.playAction = toolBar.addAction(playIcon, "Play") - self.playAction.triggered.connect(self.player.play) - playMenu.addAction(self.playAction) - - previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward) - self.previousAction = toolBar.addAction(previousIcon, "Previous") - self.previousAction.triggered.connect(self.previousClicked) - playMenu.addAction(self.previousAction) - - pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause) - self.pauseAction = toolBar.addAction(pauseIcon, "Pause") - self.pauseAction.triggered.connect(self.player.pause) - playMenu.addAction(self.pauseAction) - - nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward) - self.nextAction = toolBar.addAction(nextIcon, "Next") - self.nextAction.triggered.connect(self.playlist.next) - playMenu.addAction(self.nextAction) - - stopIcon = self.style().standardIcon(QStyle.SP_MediaStop) - self.stopAction = toolBar.addAction(stopIcon, "Stop") - self.stopAction.triggered.connect(self.player.stop) - playMenu.addAction(self.stopAction) - - self.volumeSlider = QSlider() - self.volumeSlider.setOrientation(Qt.Horizontal) - self.volumeSlider.setMinimum(0) - self.volumeSlider.setMaximum(100) - self.volumeSlider.setFixedWidth(self.screen().availableGeometry().width() / 10) - self.volumeSlider.setValue(self.player.volume()) - self.volumeSlider.setTickInterval(10) - self.volumeSlider.setTickPosition(QSlider.TicksBelow) - self.volumeSlider.setToolTip("Volume") - self.volumeSlider.valueChanged.connect(self.player.setVolume) - toolBar.addWidget(self.volumeSlider) - - aboutMenu = self.menuBar().addMenu("&About") - aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt) - aboutMenu.addAction(aboutQtAct) - - self.videoWidget = QVideoWidget() - self.setCentralWidget(self.videoWidget) - self.player.setPlaylist(self.playlist) - self.player.stateChanged.connect(self.updateButtons) - self.player.setVideoOutput(self.videoWidget) - - self.updateButtons(self.player.state()) - + self._playlist = QMediaPlaylist() + self._player = QMediaPlayer() + self._player.errorOccurred.connect(self._player_error) + + tool_bar = QToolBar() + self.addToolBar(tool_bar) + + file_menu = self.menuBar().addMenu("&File") + icon = QIcon.fromTheme("document-open") + open_action = QAction(icon, "&Open...", self, + shortcut=QKeySequence.Open, triggered=self.open) + file_menu.addAction(open_action) + icon = QIcon.fromTheme("application-exit") + exit_action = QAction(icon, "E&xit", self, + shortcut="Ctrl+Q", triggered=self.close) + file_menu.addAction(exit_action) + + play_menu = self.menuBar().addMenu("&Play") + style = self.style() + icon = QIcon.fromTheme("media-playback-start.png", + style.standardIcon(QStyle.SP_MediaPlay)) + self._play_action = tool_bar.addAction(icon, "Play") + self._play_action.triggered.connect(self._player.play) + play_menu.addAction(self._play_action) + + icon = QIcon.fromTheme("media-skip-backward-symbolic.svg", + style.standardIcon(QStyle.SP_MediaSkipBackward)) + self._previous_action = tool_bar.addAction(icon, "Previous") + self._previous_action.triggered.connect(self.previous_clicked) + play_menu.addAction(self._previous_action) + + icon = QIcon.fromTheme("media-playback-pause.png", + style.standardIcon(QStyle.SP_MediaPause)) + self._pause_action = tool_bar.addAction(icon, "Pause") + self._pause_action.triggered.connect(self._player.pause) + play_menu.addAction(self._pause_action) + + icon = QIcon.fromTheme("media-skip-forward-symbolic.svg", + style.standardIcon(QStyle.SP_MediaSkipForward)) + self._next_action = tool_bar.addAction(icon, "Next") + self._next_action.triggered.connect(self.next_clicked) + play_menu.addAction(self._next_action) + + icon = QIcon.fromTheme("media-playback-stop.png", + style.standardIcon(QStyle.SP_MediaStop)) + self._stop_action = tool_bar.addAction(icon, "Stop") + self._stop_action.triggered.connect(self._ensure_stopped) + play_menu.addAction(self._stop_action) + + self._volume_slider = QSlider() + self._volume_slider.setOrientation(Qt.Horizontal) + self._volume_slider.setMinimum(0) + self._volume_slider.setMaximum(100) + available_width = self.screen().availableGeometry().width() + self._volume_slider.setFixedWidth(available_width / 10) + self._volume_slider.setValue(self._player.volume()) + self._volume_slider.setTickInterval(10) + self._volume_slider.setTickPosition(QSlider.TicksBelow) + self._volume_slider.setToolTip("Volume") + self._volume_slider.valueChanged.connect(self._player.setVolume) + tool_bar.addWidget(self._volume_slider) + + about_menu = self.menuBar().addMenu("&About") + about_qt_act = QAction("About &Qt", self, triggered=qApp.aboutQt) + about_menu.addAction(about_qt_act) + + self._video_widget = QVideoWidget() + self.setCentralWidget(self._video_widget) + self._player.playbackStateChanged.connect(self.update_buttons) + self._player.setVideoOutput(self._video_widget) + + self.update_buttons(self._player.playbackState()) + self._mime_types = [] + + def closeEvent(self, event): + self._ensure_stopped() + event.accept() + + @Slot() def open(self): - fileDialog = QFileDialog(self) - supportedMimeTypes = QMediaPlayer.supportedMimeTypes() - if not supportedMimeTypes: - supportedMimeTypes.append("video/x-msvideo") # AVI - fileDialog.setMimeTypeFilters(supportedMimeTypes) - moviesLocation = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation) - fileDialog.setDirectory(moviesLocation) - if fileDialog.exec() == QDialog.Accepted: - self.playlist.addMedia(fileDialog.selectedUrls()[0]) - self.player.play() - - def previousClicked(self): + self._ensure_stopped() + file_dialog = QFileDialog(self) + + is_windows = sys.platform == 'win32' + if not self._mime_types: + self._mime_types = get_supported_mime_types() + if (is_windows and AVI not in self._mime_types): + self._mime_types.append(AVI) + + file_dialog.setMimeTypeFilters(self._mime_types) + + default_mimetype = AVI if is_windows else MP4 + if default_mimetype in self._mime_types: + file_dialog.selectMimeTypeFilter(default_mimetype) + + movies_location = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation) + file_dialog.setDirectory(movies_location) + if file_dialog.exec() == QDialog.Accepted: + url = file_dialog.selectedUrls()[0] + self._playlist.addMedia(url) + self._player.setSource(url) + self._player.play() + + @Slot() + def _ensure_stopped(self): + if self._player.playbackState() != QMediaPlayer.StoppedState: + self._player.stop() + + @Slot() + def previous_clicked(self): # Go to previous track if we are within the first 5 seconds of playback # Otherwise, seek to the beginning. - if self.player.position() <= 5000: - self.playlist.previous() + if self._player.position() <= 5000: + self._playlist.previous() + self._player.setSource(self._playlist.currentMedia()) else: - self.player.setPosition(0) + self._player.setPosition(0) + + @Slot() + def next_clicked(self): + self._playlist.next() + self._player.setSource(self._playlist.currentMedia()) - def updateButtons(self, state): - mediaCount = self.playlist.mediaCount() - self.playAction.setEnabled(mediaCount > 0 + def update_buttons(self, state): + media_count = self._playlist.mediaCount() + self._play_action.setEnabled(media_count > 0 and state != QMediaPlayer.PlayingState) - self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState) - self.stopAction.setEnabled(state != QMediaPlayer.StoppedState) - self.previousAction.setEnabled(self.player.position() > 0) - self.nextAction.setEnabled(mediaCount > 1) + self._pause_action.setEnabled(state == QMediaPlayer.PlayingState) + self._stop_action.setEnabled(state != QMediaPlayer.StoppedState) + self._previous_action.setEnabled(self._player.position() > 0) + self._next_action.setEnabled(media_count > 1) + + def show_status_message(self, message): + self.statusBar().showMessage(message, 5000) + + @Slot(QMediaPlayer.Error, str) + def _player_error(self, error, error_string): + print(error_string, file=sys.stderr) + self.show_status_message(error_string) if __name__ == '__main__': app = QApplication(sys.argv) - mainWin = MainWindow() - availableGeometry = mainWin.screen().availableGeometry() - mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2) - mainWin.show() + main_win = MainWindow() + available_geometry = main_win.screen().availableGeometry() + main_win.resize(available_geometry.width() / 3, + available_geometry.height() / 2) + main_win.show() sys.exit(app.exec()) |