class BasicVideoWidget(QVideoWidget): def __init__(self, *args, **kwargs): super(BasicVideoWidget, self).__init__(*args, **kwargs) self.mediaPlayer = QMediaPlayer(parent=self) self.setMediaObject(self.mediaPlayer) self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.mediaPlayer.setPlaylist(self.playlist) self.mediaPlayer.positionChanged.connect(self._positionChanged) self.mediaPlayer.mutedChanged.connect(self.mutedChanged) self.mediaPlayer.durationChanged.connect(self._durationChanged) self.mediaPlayer.stateChanged.connect(self.stateChanged) self.mediaPlayer.seekableChanged.connect(self.seekableChanged) def loadUrl(self, url): mc = QMediaContent(url) self.playlist.clear() self.playlist.addMedia(mc) def load(self, path): self.loadUrl(QUrl.fromLocalFile(os.path.abspath(path))) @Slot() def play(self): self.mediaPlayer.play() @Slot() def pause(self): self.mediaPlayer.pause() @Slot() def stop(self): self.mediaPlayer.stop() @Slot(bool) def setMuted(self, b): self.mediaPlayer.setMuted(b) mutedChanged = Signal(bool) @Slot() def playPause(self): if self.mediaPlayer.state() != QMediaPlayer.PlayingState: self.mediaPlayer.play() else: self.mediaPlayer.pause() def state(self): return self.mediaPlayer.state() stateChanged = Signal(QMediaPlayer.State) def duration(self): return self.mediaPlayer.duration() durationChanged = Signal(int) @Slot(int) def setPosition(self, p): self.mediaPlayer.setPosition(p) def position(self): return self.mediaPlayer.position() @Slot('qint64') def _positionChanged(self, p): self.positionChanged.emit(p) positionChanged = Signal(int) @Slot('qint64') def _durationChanged(self, p): self.durationChanged.emit(p) seekableChanged = Signal(bool) def isSeekable(self): return self.mediaPlayer.isSeekable()
class YtdlMusic(QMainWindow, Ui_MainWindow): def __init__(self, *args, **kwargs): QMainWindow.__init__(self, *args, **kwargs) self.setupUi(self) self.setWindowIcon(QIcon(LOCAL_DIR + '/ytdl_music.svg')) self.player = QMediaPlayer() self.player.isSeekable() self.playList = QMediaPlaylist() self.playListData = [] self.player.setPlaylist(self.playList) self.currentPos = 0 self.currentTrackDuration = '0:00:00' self.player.positionChanged.connect(self.positionChanged) self.player.durationChanged.connect(self.durationChanged) self.playList.currentIndexChanged.connect(self.playlistPosChanged) self.playlistTable.itemDoubleClicked.connect(self.changeTrack) self.playlistTable.itemSelectionChanged.connect(self.selectedTracks) # self.timeSlider.valueChanged.connect(self.setPosition) self.addBtn.clicked.connect(self.addDialog) self.removeBtn.clicked.connect(self.delTracks) self.playBtn.clicked.connect(self.playPause) self.stopBtn.clicked.connect(self.stop) self.prevBtn.clicked.connect(self.playList.previous) self.nextBtn.clicked.connect(self.playList.next) self.playlistTable.setHorizontalHeaderLabels([ '', _translate('MainWindow', 'Channel'), _translate('MainWindow', 'Title') ]) header = self.playlistTable.horizontalHeader() header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.Stretch) def setPosition(self, pos): self.player.setPosition(pos) def durationChanged(self, duration): total_time = '0:00:00' duration = self.player.duration() total_time = ms_to_time(duration) # self.timeSlider.setMaximum(duration) self.currentTrackDuration = duration # self.totalTimeLabel.setText(total_time) self.currentTrackDuration = total_time def mediaStatusChanged(self, status): icon = QIcon.fromTheme("media-playback-pause") if self.player.state() == QMediaPlayer.StoppedState: icon = QIcon.fromTheme("media-playback-start") elif self.player.state() == QMediaPlayer.PausedState: icon = QIcon.fromTheme("media-playback-start") self.playBtn.setIcon(icon) def positionChanged(self, position, senderType=False): self.currentTime = position current_time = '0:00:00' if position != -1: current_time = ms_to_time(position) self.timeLabel.setText('{0} / {1}'.format( current_time, self.currentTrackDuration)) '''self.timeSlider.blockSignals(True) self.timeSlider.setValue(position) self.timeSlider.blockSignals(False)''' def playlistPosChanged(self): pos = self.playList.currentIndex() data = self.playListData[pos] self.setWindowTitle('YouTube-dl Music: ' + data['title']) duration = ms_to_time(data['duration'] * 1000) self.timeLabel.setText('0:00:00 / {0}'.format(duration)) # self.totalTimeLabel.setText(ms_to_time(data['duration'] * 1000)) if self.playList.mediaCount() > 1: if pos < self.playList.mediaCount() - 1: self.nextBtn.setEnabled(True) else: self.nextBtn.setEnabled(False) if pos > 0: self.prevBtn.setEnabled(True) else: self.prevBtn.setEnabled(False) prevPos = 0 if pos < self.playList.mediaCount(): if self.currentPos < pos: prevPos = pos - 1 else: prevPos = pos + 1 statusItem = QLabel() icon = QIcon.fromTheme("media-playback-start") statusItem.setPixmap(icon.pixmap(16, 16)) statusItem.setAlignment(Qt.AlignCenter) self.playlistTable.setCellWidget(pos, 0, statusItem) if prevPos > -1: self.playlistTable.setCellWidget(prevPos, 0, QLabel()) else: self.playlistTable.setItem(pos, 0, QTableWidgetItem('')) self.currentPos = pos else: statusItem = QLabel() icon = QIcon.fromTheme("media-playback-start") statusItem.setPixmap(icon.pixmap(16, 16)) statusItem.setAlignment(Qt.AlignCenter) self.playlistTable.setCellWidget(pos, 0, statusItem) def playPause(self): icon = QIcon.fromTheme("media-playback-pause") if self.player.state() == QMediaPlayer.StoppedState: if self.player.mediaStatus() == QMediaPlayer.NoMedia: if self.playList.mediaCount() != 0: self.player.play() elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia: self.playList.setCurrentIndex(self.currentPos) self.player.play() elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia: self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: icon = QIcon.fromTheme("media-playback-start") self.player.pause() elif self.player.state() == QMediaPlayer.PausedState: self.player.play() self.playBtn.setIcon(icon) def stop(self): self.player.stop() icon = QIcon.fromTheme("media-playback-start") self.playBtn.setIcon(icon) def insertTrack(self, data): if data: self.playListData.append(data) totalTracks = self.playList.mediaCount() pos = totalTracks self.playlistTable.insertRow(totalTracks) self.playlistTable.setRowCount(totalTracks + 1) self.playlistTable.setItem(pos, 0, QTableWidgetItem('')) self.playlistTable.setItem(pos, 1, QTableWidgetItem(data['channel'])) self.playlistTable.setItem(pos, 2, QTableWidgetItem(data['title'])) media = QMediaContent(QUrl(data['url'])) self.playList.addMedia(media) if totalTracks > 1: self.nextBtn.setEnabled(True) else: self.statusBar().showMessage('Total pistas: {0}'.format( self.playList.mediaCount())) def addDialog(self): url, ok = QInputDialog.getText( self, _translate('MainWindow', 'Add video/playlist'), 'URL:') if ok and url != '': self.addPCThread = addVideos(self, url) self.addPCThread.video.connect(self.insertTrack) self.addPCThread.start() def changeTrack(self, item): pos = item.row() self.playlistTable.setCellWidget(self.currentPos, 0, QLabel()) self.playList.setCurrentIndex(pos) if self.player.state() == QMediaPlayer.StoppedState: icon = QIcon.fromTheme("media-playback-pause") self.playBtn.setIcon(icon) self.player.play() def delTracks(self): indexes = self.playlistTable.selectionModel().selectedRows() del_first = True for index in sorted(indexes): pos = index.row() if not del_first: pos -= 1 else: del_first = False self.playlistTable.removeRow(pos) self.playListData.pop(pos) self.playList.removeMedia(pos) self.playlistPosChanged() def selectedTracks(self): totalSelected = len(self.playlistTable.selectedItems()) if totalSelected > 0: self.removeBtn.setEnabled(True) else: self.removeBtn.setEnabled(False)
class MainWindowMusicPlayer(QMainWindow): stopState: bool def __init__(self): super().__init__() self.currentPlaylist = QMediaPlaylist() self.player = QMediaPlayer() self.userAction = -1 # 0 - stopped, 1 - playing 2 - paused self.player.mediaStatusChanged.connect(self.qmp_media_status_changed) self.player.stateChanged.connect(self.qmp_state_changed) self.player.positionChanged.connect(self.qmp_position_changed) self.player.volumeChanged.connect(self.qmp_volume_changed) self.player.setVolume(60) # Status bar self.statusBar().showMessage('No Media' ' :: %d' % self.player.volume()) self.home_screen() def home_screen(self): self.setWindowTitle('Music Player') self.create_menubar() self.create_toolbar() controlBar = self.add_controls() # need to add both information screen # and control bar to the central widget. centralWidget = QWidget() centralWidget.setLayout(controlBar) self.setCentralWidget(centralWidget) # Set size of the MainWindow self.resize(200, 100) self.show() def create_menubar(self): menubar = self.menuBar() file_menu = menubar.addMenu('File') file_menu.addAction(self.file_open()) file_menu.addAction(self.song_info()) file_menu.addAction(self.folder_open()) file_menu.addAction(self.exit_action()) def create_toolbar(self): pass def add_controls(self): controlArea = QVBoxLayout() seekSliderLayout = QHBoxLayout() controls = QHBoxLayout() playlistCtrlLayout = QHBoxLayout() # creating buttons playBtn = QPushButton('Play') # play button pauseBtn = QPushButton('Pause') # pause button stopBtn = QPushButton('Stop') # stop button volumeDescBtn = QPushButton('V (-)') # Decrease Volume volumeIncBtn = QPushButton('V (+)') # Increase Volume # creating playlist controls prevBtn = QPushButton('Prev Song') nextBtn = QPushButton('Next Song') # creating seek slider seekSlider = QSlider() seekSlider.setMinimum(0) seekSlider.setMaximum(100) seekSlider.setOrientation(Qt.Horizontal) seekSlider.setTracking(False) seekSlider.sliderMoved.connect(self.seek_position) # seekSlider.valueChanged.connect(self.seekPosition) seekSliderLabel1 = QLabel('0.00') seekSliderLabel2 = QLabel('0.00') seekSliderLayout.addWidget(seekSliderLabel1) seekSliderLayout.addWidget(seekSlider) seekSliderLayout.addWidget(seekSliderLabel2) # Add handler for each button. Not using the default slots. playBtn.clicked.connect(self.play_handler) pauseBtn.clicked.connect(self.pause_handler) stopBtn.clicked.connect(self.stop_handler) volumeDescBtn.clicked.connect(self.decrease_volume) volumeIncBtn.clicked.connect(self.increase_volume) # Adding to the horizontal layout controls.addWidget(volumeDescBtn) controls.addWidget(playBtn) controls.addWidget(pauseBtn) controls.addWidget(stopBtn) controls.addWidget(volumeIncBtn) # playlist control button handlers prevBtn.clicked.connect(self.prev_item_playlist) nextBtn.clicked.connect(self.next_item_playlist) playlistCtrlLayout.addWidget(prevBtn) playlistCtrlLayout.addWidget(nextBtn) # Adding to the vertical layout controlArea.addLayout(seekSliderLayout) controlArea.addLayout(controls) controlArea.addLayout(playlistCtrlLayout) return controlArea # Music playback function def play_handler(self): self.userAction = 1 self.statusBar().showMessage('Playing at Volume %d' % self.player.volume()) if self.player.state() == QMediaPlayer.StoppedState: if self.player.mediaStatus() == QMediaPlayer.NoMedia: print(self.currentPlaylist.mediaCount()) if self.currentPlaylist.mediaCount() == 0: self.open_file() if self.currentPlaylist.mediaCount() != 0: self.player.setPlaylist(self.currentPlaylist) elif self.player.mediaStatus() ==\ QMediaPlayer.LoadedMedia: self.player.play() elif self.player.mediaStatus() ==\ QMediaPlayer.BufferedMedia: self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: pass elif self.player.state() == QMediaPlayer.PausedState: self.player.play() # Music pause function def pause_handler(self): self.userAction = 2 self.statusBar().showMessage( 'Paused %s at position' ' %s at Volume %d' % (self.player.metaData(QMediaMetaData.Title), self.centralWidget().layout().itemAt(0).layout().itemAt( 0).widget().text(), self.player.volume())) self.player.pause() # Music stop function def stop_handler(self): self.userAction = 0 self.statusBar().showMessage('Stopped at Volume %d' % (self.player.volume())) if self.player.state() == QMediaPlayer.PlayingState: self.stopState = True self.player.stop() elif self.player.state() == QMediaPlayer.PausedState: self.player.stop() elif self.player.state() == QMediaPlayer.StoppedState: pass # Music status change function def qmp_media_status_changed(self): if self.player.mediaStatus() == QMediaPlayer.LoadedMedia \ and self.userAction == 1: durationT = self.player.duration() self.centralWidget().layout().itemAt(0).layout() \ .itemAt(1).widget().setRange(0, durationT) self.centralWidget().layout().itemAt(0).layout() \ .itemAt(2).widget().setText( '%d:%02d' % (int(durationT / 60000), int((durationT / 1000) % 60))) self.player.play() # Music playing change function def qmp_state_changed(self): if self.player.state() == QMediaPlayer.StoppedState: self.player.stop() # Music time change function def qmp_position_changed(self, position, senderType=False): sliderLayout = self.centralWidget().layout().itemAt(0)\ .layout() if not senderType: sliderLayout.itemAt(1).widget().setValue(position) # update the text label sliderLayout.itemAt(0).widget()\ .setText('%d:%02d' % (int(position / 60000), int((position / 1000) % 60))) def seek_position(self, position): sender = self.sender() if isinstance(sender, QSlider): if self.player.isSeekable(): self.player.setPosition(position) # Music volume change function def qmp_volume_changed(self): msg = self.statusBar().currentMessage() msg = msg[:-2] + str(self.player.volume()) self.statusBar().showMessage(msg) # Music volume + change function def increase_volume(self): vol = self.player.volume() vol = min(vol + 5, 100) self.player.setVolume(vol) # Music volume - change function def decrease_volume(self): vol = self.player.volume() vol = max(vol - 5, 0) self.player.setVolume(vol) # File open function def file_open(self): fileAc = QAction(QIcon('icons\\open.png'), 'Open File', self) fileAc.setShortcut('Ctrl+O') fileAc.setStatusTip('Open File') fileAc.triggered.connect(self.open_file) return fileAc # File opening function def open_file(self): file_Chosen = QFileDialog.getOpenFileUrl(self, 'Open Music File', expanduser('~'), 'Audio (*.mp3 *.ogg *.wav)', '*.mp3 *.ogg *.wav') if file_Chosen is not None: self.currentPlaylist.addMedia(QMediaContent(file_Chosen[0])) # Folder open function def folder_open(self): folderAc = QAction(QIcon('icons\\open_fld.png'), 'Open Folder', self) folderAc.setShortcut('Ctrl+D') folderAc.setStatusTip('Open Folder ' '(Will add all the files in' ' the folder)') folderAc.triggered.connect(self.add_files) return folderAc # Folder opening function def add_files(self): folder_Chosen = QFileDialog\ .getExistingDirectory(self, 'Open Music Folder', expanduser('~')) if folder_Chosen is not None: it = QDirIterator(folder_Chosen) it.next() while it.hasNext(): if it.fileInfo().isDir() == False\ and it.filePath() != '.': fInfo = it.fileInfo() print(it.filePath(), fInfo.suffix()) if fInfo.suffix() in ('mp3', 'ogg', 'wav'): print('added file ', fInfo.fileName()) self.currentPlaylist. \ addMedia(QMediaContent( QUrl.fromLocalFile(it.filePath()))) it.next() # Song information function def song_info(self): infoAc = QAction(QIcon('icons\\info.png'), 'Info', self) infoAc.setShortcut('Ctrl+I') infoAc.setStatusTip('Displays Current Song Information') infoAc.triggered.connect(self.display_song_info) return infoAc # Show song information def display_song_info(self): metaDataKeyList = self.player.availableMetaData() fullText = '<table class="tftable" border="0">' for key in metaDataKeyList: value = self.player.metaData(key) fullText = \ fullText + '<tr><td>' + key + '</td><td>' + \ str(value) + '</td></tr>' fullText = fullText + '</table>' infoBox = QMessageBox(self) infoBox.setWindowTitle('Detailed Song Information') infoBox.setTextFormat(Qt.RichText) infoBox.setText(fullText) infoBox.addButton('OK', QMessageBox.AcceptRole) infoBox.show() # Switch to previous song def prev_item_playlist(self): self.player.playlist().previous() # Switch to next song def next_item_playlist(self): self.player.playlist().next() # exit function def exit_action(self): exitAc = QAction(QIcon('icons\\exit.png'), '&Exit', self) exitAc.setShortcut('Ctrl+Q') exitAc.setStatusTip('Exit App') exitAc.triggered.connect(self.close) return exitAc # exiting function @staticmethod def exit(): sys.exit(app.exec_())
class TranquilityMP(QMainWindow, MainWindow): def __init__(self, playlist, parent=None): super(TranquilityMP, self).__init__(parent) self.statusInfo = "" self.trackInfo = "" self.theme = 0 self.colorTheme = 0 self.mediaPlayer = QMediaPlayer() self.playlist = QMediaPlaylist() self.mediaPlayer.setPlaylist(self.playlist) self.establishLayout() self.connectSignals() self.allPlaylists = self.loadPlaylists() self.toggleTheme() self.addToPlaylist(playlist) def connectSignals(self): self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.metaDataChanged.connect(self.metaDataChanged) self.mediaPlayer.mediaStatusChanged.connect(self.statusChanged) self.mediaPlayer.stateChanged.connect(self.stateChanged) def createPlaylist(self): root = QFileInfo(__file__).absolutePath() spot = (root + '/playlists/') playlistName = self.getText() completeName = os.path.join(spot, f'{playlistName}.m3u') file = open(completeName, 'w') file.close() self.playlistView.addItem(playlistName) self.allPlaylists = self.loadPlaylists() def savePlaylist(self): root = "C:\\Users\\dchtk\\Music\\Playlists" playlistName = self.getText() completeName = os.path.join(root, f'{playlistName}.m3u') file = open(completeName, 'a+') for i in range(self.currentPlaylist.count()): file.write(''.join( [str(self.currentPlaylist.item(i).text()), '\n'])) file.close() self.playlistView.addItem(playlistName) def getText(self): text, okPressed = QInputDialog.getText(self, "New Playlist", "Playlist Name:", QLineEdit.Normal, "") if okPressed and text != '': return text def loadPlaylists(self): playlists = [] root = "C:\\Users\\dchtk\\Music\\Playlists" songsPlaylist = os.listdir(root) for item in songsPlaylist: if str(item[-4:]) == '.m3u': self.playlistView.addItem(item[:-4]) playlists.append(root + item) return playlists def addToPlaylist(self, fileNames): for name in fileNames: fileInfo = QFileInfo(name) songFileTitle = os.path.basename(name) if fileInfo.exists(): url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(QMediaContent(url)) self.currentPlaylist.addItem(songFileTitle) else: url = QUrl(name) if url.isValid(): self.playlist.addMedia(QMediaContent(url)) self.currentPlaylist.addItem(songFileTitle) def metaDataChanged(self): if self.mediaPlayer.isMetaDataAvailable(): self.setTrackInfo( "%s - %s" % (self.mediaPlayer.metaData(QMediaMetaData.AlbumArtist), self.mediaPlayer.metaData(QMediaMetaData.Title))) def previousMedia(self): if self.mediaPlayer.position() <= 5000: self.playlist.previous() else: self.playlist.setPosition(0) def setRepeatOne(self): if self.mediaPlayer.state == QMediaPlayer.PlayingState: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) def setRepeatAll(self): if self.mediaPlayer.state == QMediaPlayer.PlayingState: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) def durationChanged(self, duration): self.duration = duration self.seekSlider.setMaximum(duration) if duration > 0: self.totalTimeLabel.setText(configureTime(self.duration)) def positionChanged(self, position): if not self.seekSlider.isSliderDown(): self.seekSlider.setValue(position) if position > 0: self.currentTimeLabel.setText(configureTime(position)) def seek(self, seconds): if self.mediaPlayer.isSeekable(): self.mediaPlayer.setPosition(seconds) def stateChanged(self): if self.mediaPlayer.state == QMediaPlayer.StoppedState: self.mediaPlayer.stop() def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo("Loading") elif status == QMediaPlayer.LoadedMedia: self.setStatusInfo("Loaded") self.mediaPlayer.play() elif status == QMediaPlayer.BufferingMedia: self.setStatusInfo("Buffering") elif status == QMediaPlayer.EndOfMedia: QApplication.alert(self) elif status == (QMediaPlayer.InvalidMedia or QMediaPlayer.NoMedia): self.displayError() else: self.setStatusInfo("") def handleCursor(self, status): if status == QMediaPlayer.LoadingMedia: self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo != "": self.statusBar().showMessage("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.statusBar().showMessage(self.trackInfo) def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo != "": self.statusBar().showMessage("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.statusBar().showMessage(self.trackInfo) def displayError(self): self.setStatusInfo(self.mediaPlayer.errorString()) def toggleTheme(self): """ Fusion dark palette from https://gist.github.com/QuantumCD/6245215. Modified by D.C """ app.setStyle("Fusion") palette = QPalette() if self.theme == 0: palette.setColor(QPalette.Window, QColor(53, 53, 53)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Base, QColor(25, 25, 25)) palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) palette.setColor(QPalette.ToolTipBase, Qt.white) palette.setColor(QPalette.ToolTipText, Qt.white) palette.setColor(QPalette.Text, Qt.white) palette.setColor(QPalette.Button, QColor(53, 53, 53)) palette.setColor(QPalette.ButtonText, Qt.white) palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.Link, QColor(235, 101, 54)) palette.setColor(QPalette.Highlight, QColor(66, 155, 248)) palette.setColor(QPalette.HighlightedText, Qt.black) app.setPalette(palette) self.theme = 1 elif self.theme == 1: palette.setColor(QPalette.Window, Qt.white) palette.setColor(QPalette.WindowText, Qt.black) palette.setColor(QPalette.Base, QColor(240, 240, 240)) palette.setColor(QPalette.AlternateBase, Qt.white) palette.setColor(QPalette.ToolTipBase, Qt.white) palette.setColor(QPalette.ToolTipText, Qt.white) palette.setColor(QPalette.Text, Qt.black) palette.setColor(QPalette.Button, Qt.white) palette.setColor(QPalette.ButtonText, Qt.black) palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.Link, QColor(66, 155, 248)) palette.setColor(QPalette.Highlight, QColor(66, 155, 248)) palette.setColor(QPalette.HighlightedText, Qt.black) app.setPalette(palette) self.theme = 0 def toggleColor(self): app.setStyle("Fusion") palette = QPalette() if self.colorTheme == 0: palette.setColor(QPalette.Window, QColor(178, 34, 34)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Base, QColor(128, 0, 0)) palette.setColor(QPalette.AlternateBase, QColor(178, 34, 34)) palette.setColor(QPalette.ToolTipBase, Qt.white) palette.setColor(QPalette.ToolTipText, Qt.white) palette.setColor(QPalette.Text, Qt.white) palette.setColor(QPalette.Button, QColor(178, 34, 34)) palette.setColor(QPalette.ButtonText, Qt.white) palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.Link, QColor(235, 101, 54)) palette.setColor(QPalette.Highlight, QColor(66, 155, 248)) palette.setColor(QPalette.HighlightedText, Qt.black) app.setPalette(palette) self.colorTheme = 1 elif self.colorTheme == 1: palette.setColor(QPalette.Window, QColor(72, 61, 139)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Base, QColor(75, 0, 130)) palette.setColor(QPalette.AlternateBase, QColor(72, 61, 139)) palette.setColor(QPalette.ToolTipBase, Qt.black) palette.setColor(QPalette.ToolTipText, Qt.black) palette.setColor(QPalette.Text, Qt.white) palette.setColor(QPalette.Button, QColor(72, 61, 139)) palette.setColor(QPalette.ButtonText, Qt.white) palette.setColor(QPalette.BrightText, Qt.red) palette.setColor(QPalette.Link, QColor(235, 101, 54)) palette.setColor(QPalette.Highlight, QColor(53, 53, 53)) palette.setColor(QPalette.HighlightedText, Qt.white) app.setPalette(palette) self.colorTheme = 0
class MediaPlayerTab(GalacteekTab): statePlaying = QMediaPlayer.PlayingState statePaused = QMediaPlayer.PausedState stateStopped = QMediaPlayer.StoppedState def __init__(self, *args, **kw): super(MediaPlayerTab, self).__init__(*args, **kw) self.playlistIpfsPath = None self.playlist = QMediaPlaylist() self.model = ListModel(self.playlist) self.playlistsMenu = QMenu(self) self.playlistsMenu.triggered.connect(self.onPlaylistsMenu) self.pListWidget = QWidget(self) self.uipList = ui_mediaplaylist.Ui_MediaPlaylist() self.uipList.setupUi(self.pListWidget) self.uipList.savePlaylistButton.clicked.connect(self.onSavePlaylist) self.uipList.savePlaylistButton.setEnabled(False) self.uipList.loadPlaylistButton.setPopupMode(QToolButton.InstantPopup) self.uipList.loadPlaylistButton.setMenu(self.playlistsMenu) self.clipMenu = QMenu(self) self.copyPathAction = QAction(getIconIpfsIce(), iCopyPlaylistPath(), self, triggered=self.onCopyPlaylistPath) self.loadPathAction = QAction(getIconIpfsIce(), iLoadPlaylistFromPath(), self, triggered=self.onLoadPlaylistPath) self.copyPathAction.setEnabled(False) self.clipMenu.addAction(self.copyPathAction) self.clipMenu.addAction(self.loadPathAction) self.uipList.clipPlaylistButton.setPopupMode(QToolButton.InstantPopup) self.uipList.clipPlaylistButton.setMenu(self.clipMenu) self.uipList.clearButton.clicked.connect(self.onClearPlaylist) self.uipList.nextButton.clicked.connect(self.onPlaylistNext) self.uipList.previousButton.clicked.connect(self.onPlaylistPrevious) self.uipList.nextButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.uipList.previousButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.pListView = self.uipList.listView self.pListView.mousePressEvent = self.playlistMousePressEvent self.pListView.setModel(self.model) self.pListView.setResizeMode(QListView.Adjust) self.pListView.setMinimumWidth(self.width() / 2) self.duration = None self.playerState = None self.player = QMediaPlayer(self) self.player.setPlaylist(self.playlist) self.videoWidget = MPlayerVideoWidget(self.player, self) self.useUpdates(True) self.videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.player.setVideoOutput(self.videoWidget) self.player.error.connect(self.onError) self.player.stateChanged.connect(self.onStateChanged) self.player.metaDataChanged.connect(self.onMetaData) self.player.durationChanged.connect(self.mediaDurationChanged) self.player.positionChanged.connect(self.mediaPositionChanged) self.player.videoAvailableChanged.connect(self.onVideoAvailable) self.pListView.activated.connect(self.onListActivated) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.playlist.currentMediaChanged.connect(self.playlistMediaChanged) self.playlist.mediaInserted.connect(self.playlistMediaInserted) self.playlist.mediaRemoved.connect(self.playlistMediaRemoved) self.togglePList = QToolButton(self) self.togglePList.setIcon(self.style().standardIcon( QStyle.SP_ArrowRight)) self.togglePList.setFixedSize(32, 128) self.togglePList.clicked.connect(self.onTogglePlaylist) self.clipboardMediaItem = None self.clipboardButton = QToolButton(clicked=self.onClipboardClicked) self.clipboardButton.setIcon(getIconClipboard()) self.clipboardButton.setEnabled(False) self.clipboardButton.setToolTip('Load media from clipboard') self.pinButton = QToolButton(clicked=self.onPinMediaClicked) self.pinButton.setIcon(getIcon('pin.png')) self.processClipboardItem(self.app.clipTracker.current, force=True) self.app.clipTracker.currentItemChanged.connect(self.onClipItemChange) self.playButton = QToolButton(clicked=self.onPlayClicked) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.pauseButton = QToolButton(clicked=self.onPauseClicked) self.pauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.pauseButton.setEnabled(False) self.stopButton = QToolButton(clicked=self.onStopClicked) self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopButton.setEnabled(False) self.fullscreenButton = QToolButton(clicked=self.onFullScreen) self.fullscreenButton.setIcon(getIcon('fullscreen.png')) self.fullscreenButton.setToolTip(iFullScreen()) self.seekSlider = QSlider(Qt.Horizontal, sliderMoved=self.onSeek) self.seekSlider.sliderReleased.connect(self.onSliderReleased) self.seekSlider.setObjectName('mediaPlayerSlider') self.durationLabel = QLabel() vLayout = QVBoxLayout() hLayoutControls = QHBoxLayout() hLayoutControls.setContentsMargins(0, 0, 0, 0) hLayoutControls.addWidget(self.clipboardButton) hLayoutControls.addWidget(self.pinButton) hLayoutControls.addWidget(self.playButton) hLayoutControls.addWidget(self.pauseButton) hLayoutControls.addWidget(self.stopButton) hLayoutControls.addWidget(self.seekSlider) hLayoutControls.addWidget(self.durationLabel) hLayoutControls.addWidget(self.fullscreenButton) vLayout.addWidget(self.videoWidget) vLayout.addLayout(hLayoutControls) hLayout = QHBoxLayout() hLayout.addLayout(vLayout) hLayout.addWidget(self.pListWidget) hLayout.addWidget(self.togglePList) self.pListWidget.hide() self.vLayout.addLayout(hLayout) self.update() self.videoWidget.changeFocus() @property def isPlaying(self): return self.playerState == self.statePlaying @property def isPaused(self): return self.playerState == self.statePaused @property def isStopped(self): return self.playerState == self.stateStopped def useUpdates(self, updates=True): # Enable widget updates or not on the video widget self.videoWidget.setUpdatesEnabled(updates) def update(self): self.app.task(self.updatePlaylistsMenu) def onFullScreen(self): self.videoWidget.viewFullScreen(True) def onClearPlaylist(self): self.copyPathAction.setEnabled(False) self.player.stop() self.clearPlaylist() def onLoadPlaylistPath(self): current = self.app.clipTracker.getCurrent() if current: self.app.task(self.loadPlaylistFromPath, current.path) def onCopyPlaylistPath(self): if self.playlistIpfsPath: self.app.setClipboardText(self.playlistIpfsPath) def onPinMediaClicked(self): currentMedia = self.playlist.currentMedia() if currentMedia.isNull(): return messageBox(iNoMediaInPlaylist()) ensure(self.pinMedia(currentMedia)) @ipfsOp async def pinMedia(self, ipfsop, media): mediaUrl = qurlPercentDecode(media.canonicalUrl()) path = IPFSPath(mediaUrl, autoCidConv=True) if path.valid: await ipfsop.ctx.pin(str(path), qname='mediaplayer') @ipfsOp async def updatePlaylistsMenu(self, ipfsop): currentList = [ action.text() for action in self.playlistsMenu.actions() ] listing = await ipfsop.filesList(self.profile.pathPlaylists) for entry in listing: if entry['Name'] in currentList: continue action = QAction(entry['Name'], self) action.setData(entry) self.playlistsMenu.addAction(action) def playlistShowContextMenu(self, event): selModel = self.pListView.selectionModel() idx = self.pListView.indexAt(event.pos()) if not idx.isValid(): return path = self.model.data(idx) if path: selModel.reset() selModel.select(idx, QItemSelectionModel.Select) menu = QMenu(self) menu.addAction(getIcon('clear-all.png'), iPlaylistRemoveMedia(), functools.partial(self.onRemoveMediaFromIndex, idx)) menu.exec_(event.globalPos()) def onRemoveMediaFromIndex(self, idx): self.playlist.removeMedia(idx.row()) def playlistMousePressEvent(self, event): if event.button() == Qt.RightButton: self.pListView.selectionModel().reset() self.playlistShowContextMenu(event) else: if not self.pListView.indexAt(event.pos()).isValid(): self.deselectPlaylistItems() QListView.mousePressEvent(self.pListView, event) def onPlaylistsMenu(self, action): entry = action.data() self.app.task(self.loadPlaylistFromPath, joinIpfs(entry['Hash'])) def onSavePlaylist(self): paths = self.playlistGetPaths() listName = inputText(title=iPlaylistName(), label=iPlaylistName()) if not listName: return obj = JSONPlaylistV1(listName=listName, itemPaths=paths) self.app.task(self.savePlaylist, obj, listName) @ipfsOp async def savePlaylist(self, ipfsop, obj, name): objPath = os.path.join(self.profile.pathPlaylists, name) exists = await ipfsop.filesStat(objPath) if exists: await ipfsop.filesRm(objPath) ent = await ipfsop.client.core.add_json(obj.root) if ent: await ipfsop.filesLinkFp(ent, objPath) self.playlistIpfsPath = joinIpfs(ent['Hash']) self.copyPathAction.setEnabled(True) self.update() @ipfsOp async def loadPlaylistFromPath(self, ipfsop, path): try: obj = await ipfsop.jsonLoad(path) except Exception: return messageBox(iCannotLoadPlaylist()) if obj is None: return messageBox(iCannotLoadPlaylist()) try: # Assume v1 format for now, when the format evolves we'll just # use json validation pList = JSONPlaylistV1(data=obj) self.clearPlaylist() for item in pList.items(): self.queueFromPath(item['path']) self.playlistIpfsPath = path self.copyPathAction.setEnabled(True) except Exception: return messageBox(iCannotLoadPlaylist()) def playlistMediaInserted(self, start, end): self.uipList.savePlaylistButton.setEnabled( self.playlist.mediaCount() > 0) def playlistMediaRemoved(self, start, end): self.uipList.savePlaylistButton.setEnabled( self.playlist.mediaCount() > 0) self.model.modelReset.emit() def playlistGetPaths(self): return [u.path() for u in self.playlistGetUrls()] def playlistGetUrls(self): urls = [] for idx in range(0, self.playlist.mediaCount()): media = self.playlist.media(idx) urls.append(media.canonicalUrl()) return urls def onClipItemChange(self, item): self.processClipboardItem(item) def processClipboardItem(self, item, force=False): if not item: return def analyzeMimeType(cItem): if cItem.mimeCategory in ['audio', 'video', 'image']: self.clipboardMediaItem = cItem self.clipboardButton.setEnabled(True) self.clipboardButton.setToolTip(cItem.path) else: self.clipboardButton.setEnabled(False) self.clipboardButton.setToolTip(iClipboardEmpty()) if force: analyzeMimeType(item) else: item.mimeTypeAvailable.connect(lambda mType: analyzeMimeType(item)) def onClipboardClicked(self): if self.clipboardMediaItem: self.playFromPath(self.clipboardMediaItem.path) else: messageBox('Not a multimedia resource') def onSliderReleased(self): pass def onPlaylistNext(self): self.playlist.next() def onPlaylistPrevious(self): self.playlist.previous() def onPlayClicked(self): self.player.play() def onPauseClicked(self): if self.isPlaying: self.player.pause() elif self.isPaused: self.player.play() def onStopClicked(self): self.player.stop() self.player.setPosition(0) self.seekSlider.setValue(0) self.seekSlider.setRange(0, 0) def onSeek(self, seconds): if self.player.isSeekable(): self.player.setPosition(seconds * 1000) def onTogglePlaylist(self): self.pListWidget.setVisible(self.pListWidget.isHidden()) def onError(self, error): messageBox(iPlayerError(error)) def onStateChanged(self, state): self.playerState = state self.updateControls(state) def updateControls(self, state): if self.isStopped: self.stopButton.setEnabled(False) self.pauseButton.setEnabled(False) self.playButton.setEnabled(True) self.seekSlider.setEnabled(False) self.duration = None elif self.isPlaying: self.seekSlider.setRange(0, self.player.duration() / 1000) self.seekSlider.setEnabled(True) self.pauseButton.setEnabled(True) self.playButton.setEnabled(False) self.stopButton.setEnabled(True) def onListActivated(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def onMetaData(self): # Unfinished if self.player.isMetaDataAvailable(): availableKeys = self.player.availableMetaData() for key in availableKeys: self.player.metaData(key) def playFromUrl(self, url, mediaName=None): if self.isPlaying: self.player.stop() cUrls = self.playlistGetUrls() for u in cUrls: if u.toString() == url.toString(): return messageBox(iAlreadyInPlaylist()) media = QMediaContent(url) if self.playlist.addMedia(media): count = self.model.rowCount() if count > 0: self.playlist.setCurrentIndex(count - 1) self.player.play() def playFromPath(self, path, mediaName=None): mediaUrl = self.app.subUrl(path) self.playFromUrl(mediaUrl) def queueFromPath(self, path, playLast=False, mediaName=None): mediaUrl = self.app.subUrl(path) self.playlist.addMedia(QMediaContent(mediaUrl)) if playLast: count = self.playlist.mediaCount() if count > 0: self.player.stop() self.playlist.setCurrentIndex(count - 1) self.player.play() def clearPlaylist(self): self.playlist.clear() self.pListView.reset() def playlistPositionChanged(self, position): self.pListView.setCurrentIndex(self.model.index(position, 0)) def deselectPlaylistItems(self): self.pListView.selectionModel().reset() def playlistMediaChanged(self, media): selModel = self.pListView.selectionModel() self.deselectPlaylistItems() self.model.modelReset.emit() idx = self.model.index(self.playlist.currentIndex(), 0) if idx.isValid(): selModel.select(idx, QItemSelectionModel.Select) def onVideoAvailable(self, available): if available: if self.isPlaying: self.useUpdates(False) elif self.isStopped or self.isPaused: self.useUpdates(True) else: self.useUpdates(True) def mediaDurationChanged(self, duration): self.duration = duration / 1000 self.seekSlider.setMaximum(self.duration) def mediaPositionChanged(self, progress): progress /= 1000 if self.duration: cTime = durationConvert(progress) tTime = durationConvert(self.duration) self.durationLabel.setText('{0} ({1})'.format( cTime.toString(), tTime.toString())) if not self.seekSlider.isSliderDown(): self.seekSlider.setValue(progress) async def onClose(self): self.player.stop() self.player.setMedia(QMediaContent(None)) return True def playerAvailable(self): return mediaPlayerAvailable(player=self.player)
class DBPlayer(QWidget): # signal signaltxt = pyqtSignal(str) signalnum = pyqtSignal(int) def __init__(self): super(DBPlayer, self).__init__() self.setMaximumSize(16777215, 35) # Init Player self.messtitle = TITL_PROG self.namemedia = '' self.albumname = '' self.currentPlaylist = QMediaPlaylist() self.player = QMediaPlayer() self.player.stateChanged.connect(self.qmp_stateChanged) self.player.positionChanged.connect(self.qmp_positionChanged) self.player.volumeChanged.connect(self.qmp_volumeChanged) self.player.durationChanged.connect(self.qmp_durationChanged) self.player.setVolume(60) # Init GUI self.setLayout(self.addControls()) self.infoBox = None def addControls(self): # buttons self.playBtn = QPushButton() self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.setStyleSheet('border: 0px;') stopBtn = QPushButton() stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) stopBtn.setStyleSheet('border: 0px;') prevBtn = QPushButton() prevBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipBackward)) prevBtn.setStyleSheet('border: 0px;') nextBtn = QPushButton() nextBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipForward)) nextBtn.setStyleSheet('border: 0px;') volumeDescBtn = QPushButton('▼') volumeDescBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume)) volumeDescBtn.setMaximumWidth(30) volumeDescBtn.setStyleSheet('border: 0px;') volumeIncBtn = QPushButton('▲') volumeIncBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume)) volumeIncBtn.setMaximumWidth(40) volumeIncBtn.setStyleSheet('border: 0px;') infoBtn = QPushButton() infoBtn.setIcon(self.style().standardIcon( QStyle.SP_FileDialogContentsView)) infoBtn.setStyleSheet('border: 0px;') # seek slider self.seekSlider = QSlider(Qt.Horizontal, self) self.seekSlider.setMinimum(0) self.seekSlider.setMaximum(100) self.seekSlider.setTracking(False) # labels position start/end self.seekSliderLabel1 = QLabel('0:00') self.seekSliderLabel2 = QLabel('0:00') # layout controlArea = QHBoxLayout() controlArea.addWidget(prevBtn) controlArea.addWidget(self.playBtn) controlArea.addWidget(stopBtn) controlArea.addWidget(nextBtn) controlArea.addWidget(self.seekSliderLabel1) controlArea.addWidget(self.seekSlider) controlArea.addWidget(self.seekSliderLabel2) controlArea.addWidget(infoBtn) controlArea.addWidget(volumeDescBtn) controlArea.addWidget(volumeIncBtn) # link buttons to media self.seekSlider.sliderMoved.connect(self.seekPosition) self.playBtn.clicked.connect(self.playHandler) stopBtn.clicked.connect(self.stopHandler) volumeDescBtn.clicked.connect(self.decreaseVolume) volumeIncBtn.clicked.connect(self.increaseVolume) prevBtn.clicked.connect(self.prevItemPlaylist) nextBtn.clicked.connect(self.nextItemPlaylist) infoBtn.clicked.connect(self.displaySongInfo) return controlArea def playHandler(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() message = (' [Paused at position %s]' % self.seekSliderLabel1.text()) self.messtitle = self.namemedia + message self.signaltxt.emit(self.messtitle) else: if self.player.state() == QMediaPlayer.StoppedState: if self.player.mediaStatus() == QMediaPlayer.NoMedia: if self.currentPlaylist.mediaCount() != 0: self.player.setPlaylist(self.currentPlaylist) elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia: self.player.play() elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia: self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: pass elif self.player.state() == QMediaPlayer.PausedState: self.player.play() if self.player.volume() is not None and self.player.state( ) == QMediaPlayer.PlayingState: message = ' [Volume %d]' % self.player.volume() self.messtitle = self.namemedia + message self.signaltxt.emit(self.messtitle) def stopHandler(self): if self.player.state() == QMediaPlayer.PlayingState: self.stopState = True self.player.stop() elif self.player.state() == QMediaPlayer.PausedState: self.player.stop() elif self.player.state() == QMediaPlayer.StoppedState: pass if self.player.volume() is not None and self.player.state( ) == QMediaPlayer.PlayingState: self.messtitle = self.namemedia + (' [Stopped]') self.signaltxt.emit(self.messtitle) def qmp_stateChanged(self): if self.player.state() == QMediaPlayer.StoppedState: self.player.stop() # buttons icon play/pause change if self.player.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def qmp_positionChanged(self, position): # update position slider self.seekSlider.setValue(position) # update the text label self.seekSliderLabel1.setText( '%d:%02d' % (int(position / 60000), int((position / 1000) % 60))) def seekPosition(self, position): sender = self.sender() if isinstance(sender, QSlider): if self.player.isSeekable(): self.player.setPosition(position) def qmp_volumeChanged(self): if self.player.volume() is not None: message = (' [Playing at Volume %d]' % (self.player.volume())) if self.namemedia != '': self.messtitle = self.namemedia + message else: self.messtitle = "Initialisation player " + message self.signaltxt.emit(self.messtitle) def qmp_durationChanged(self, duration): self.seekSlider.setRange(0, duration) self.seekSliderLabel2.setText( '%d:%02d' % (int(duration / 60000), int((duration / 1000) % 60))) nummedia = self.currentPlaylist.mediaCount() curmedia = self.currentPlaylist.currentIndex() #artist = self.player.metaData(QMediaMetaData.Author) #tittle = self.player.metaData(QMediaMetaData.Title) self.namemedia = path.basename(self.homMed[curmedia]) self.namemedia = '[%02d/%02d' % ( curmedia + 1, nummedia) + '] "' + self.namemedia + '"' self.buildPlaylist() message = (' [Playing at Volume %d]' % (self.player.volume())) if self.player.volume() is not None and self.player.state( ) == QMediaPlayer.PlayingState: self.messtitle = self.namemedia + message self.signaltxt.emit(self.messtitle) def buildPlaylist(self): """Build play list.""" nummedia = self.currentPlaylist.mediaCount() curmedia = self.currentPlaylist.currentIndex() + 1 compteur = 1 self.textplaylist = '<b>' + self.albumname + '</b>' self.textplaylist += '<table class="tftable" border="0">' for namemedia in self.homMed: media = path.basename(namemedia) media = '[%02d/%02d' % (compteur, nummedia) + '] "' + media + '"' if curmedia == compteur: self.textplaylist += '<tr><td><b>' + media + '</b></td></tr>' else: self.textplaylist += '<tr><td>' + media + '</td></tr>' compteur += 1 self.textplaylist = self.textplaylist + '</table>' self.playBtn.setToolTip(self.textplaylist) self.signalnum.emit(curmedia - 1) def increaseVolume(self): """Volume +.""" vol = self.player.volume() vol = min(vol + 5, 100) self.player.setVolume(vol) def decreaseVolume(self): """Volume -.""" vol = self.player.volume() vol = max(vol - 5, 0) self.player.setVolume(vol) def prevItemPlaylist(self): self.player.playlist().previous() if self.currentPlaylist.currentIndex() == -1: self.player.playlist().previous() def nextItemPlaylist(self): self.player.playlist().next() if self.currentPlaylist.currentIndex() == -1: self.player.playlist().next() def addMediaslist(self, listmedias, position, albumname): if self.currentPlaylist.mediaCount() > 0: self.currentPlaylist.removeMedia(0, self.currentPlaylist.mediaCount()) self.player.stop() self.stopHandler() self.currentPlaylist.removeMedia(0, self.currentPlaylist.mediaCount()) self.albumname = albumname if listmedias: self.homMed = listmedias for media in self.homMed: self.currentPlaylist.addMedia( QMediaContent(QUrl.fromLocalFile(media))) self.currentPlaylist.setCurrentIndex(position) self.playHandler() def displaySongInfo(self): # extract datas metaDataKeyList = self.player.availableMetaData() fullText = '<table class="tftable" border="0">' for key in metaDataKeyList: value = str(self.player.metaData(key)).replace("'", "").replace( "[", "").replace("]", "") if key == 'Duration': value = '%d:%02d' % (int( int(value) / 60000), int((int(value) / 1000) % 60)) fullText = fullText + '<tr><td>' + key + '</td><td>' + value + '</td></tr>' fullText = fullText + '</table>' # re-init if self.infoBox is not None: self.infoBox.destroy() # infos box self.infoBox = QMessageBox(self) self.infoBox.setWindowTitle('Detailed Song Information') self.infoBox.setTextFormat(Qt.RichText) self.infoBox.addButton('OK', QMessageBox.AcceptRole) self.infoBox.setText(fullText) self.infoBox.show()