class Player(QGraphicsVideoItem): def __init__(self, parent=None): super().__init__() self.parent = parent self.player = QMediaPlayer() self.player.setVideoOutput(self) def playerPlayOrOpen(self, arg=None): if type(arg) == list and len(arg) > 1: content = QMediaContent(QUrl.fromLocalFile(arg[1])) self.player.setMedia(content) self.play() def addVideo(self, video): content = QMediaContent(QUrl.fromLocalFile(video)) self.player.setMedia(content) self.play() def sliderChanged(self, pos): self.player.setPosition(pos) def mouseDoubleClickEvent(self, event): if not self.parent.isFullScreen(): self.parent.showFullScreen() else: self.parent.showNormal() def play(self): self.player.play() def stop(self): self.player.stop() def pause(self): self.player.pause() def setMuted(self, mute): self.player.setMuted(mute) def mutedState(self): if self.player.isMuted(): self.setMuted(False) else: self.setMuted(True) def isMuted(self): return self.player.isMuted() def setVolume(self, value): self.player.setVolume(value) def volume(self): return self.player.volume()
class VideoPlayerWidget(QWidget): def __init__(self, parent=None): super(VideoPlayerWidget, self).__init__(parent) self.scene = QGraphicsScene(self) self.scene.setBackgroundBrush(QBrush(QColor(0, 0, 0, 255))) self.graphics_view = QGraphicsView(self.scene) self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphics_view.setFrameStyle(0) self.graphics_view.setStyleSheet("QGraphicsView {background: transparent; border: 3px; outline: none;}") self.video_item = QGraphicsVideoItem() self.scene.addItem(self.video_item) self.layout = QVBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.graphics_view) self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.media_player.setVideoOutput(self.video_item) self.video_need_replay = False self.video_seek_durcation = 3000 # in milliseconds def resizeEvent(self, event): self.video_item.setSize(QSizeF(event.size().width(), event.size().height())) QWidget.resizeEvent(self, event) def play(self, url): self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(url))) self.media_player.play() def seek_forward(self): video_position = self.media_player.position() self.media_player.setPosition(video_position + self.video_seek_durcation) def seek_backward(self): video_position = self.media_player.position() self.media_player.setPosition(max(video_position - self.video_seek_durcation, 0)) def keyPressEvent(self, event): if event.key() == Qt.Key_Space: if self.media_player.state() == QMediaPlayer.PlayingState: self.media_player.pause() self.video_need_replay = False else: self.media_player.play() self.video_need_replay = True elif event.key() == Qt.Key_H: self.seek_backward() elif event.key() == Qt.Key_L: self.seek_forward()
class AudioPlayBack(): def __init__(self): self.__audioPlayback = QMediaPlayer() self.__audioPlayback.setVolume(50) self.__audioPlayback.positionChanged.connect(self.onTick) pass def onTick(self, e=None): print(self.__audioPlayback.position(), self.__audioPlayback.state()) Event.dis(AudioPlaybackEvent.TICK, self.__audioPlayback.position()) pass def load(self, path): content = QMediaContent(QUrl(path)) self.__audioPlayback.setMedia(content) self.__audioPlayback.play() pass def seek(self, position): self.__audioPlayback.setPosition(position) pass def play(self): if self.__audioPlayback.state() == QMediaPlayer.PausedState: self.__audioPlayback.play() pass pass def pause(self): if self.__audioPlayback.state() == QMediaPlayer.PlayingState: self.__audioPlayback.pause() pass pass # 0~100 def setVolume(self, vol): self.__audioPlayback.setVolume(vol) pass
class AudioPlayer(QObject): songPositionChanged = pyqtSignal(int) songDurationChanged = pyqtSignal(int) stateChanged = pyqtSignal(int) playlistChanged = pyqtSignal(QMediaPlaylist, int) currentSongChanged = pyqtSignal(str, str, bytes) currentSelectionChanged = pyqtSignal(UUID, int) customPlaylistCreated = pyqtSignal(UUID, str) libraryPlaylistCreated = pyqtSignal(UUID) addedToLibraryPlaylist = pyqtSignal(UUID, list) addedToCustomPlaylist = pyqtSignal(UUID, list) updatedLibraryPlaylist = pyqtSignal(UUID, list) playlistRemoved = pyqtSignal(UUID) def __init__(self, volumeLevel=40, playbackMode=QMediaPlaylist.Sequential, parent=None): super(AudioPlayer, self).__init__(parent) self.__player = QMediaPlayer() self.__player.setVolume(volumeLevel) self.__player.currentMediaChanged.connect(self._onMediaChanged) self.__player.stateChanged.connect( lambda state: self.stateChanged.emit(int(state))) self.__player.positionChanged.connect( lambda x: self.songPositionChanged.emit(x)) self.__player.durationChanged.connect( lambda x: self.songDurationChanged.emit(x)) self.__playlistManager = PlaylistManger() self.__playlistManager.customPlaylistCreated.connect( lambda uuid, name: self.customPlaylistCreated.emit(uuid, name)) self.__playlistManager.libraryPlaylistCreated.connect( lambda p: self.libraryPlaylistCreated.emit(p)) self.__playlistManager.currentPlaylistChanged.connect( self._onChangedPlaylist) self.__playlistManager.currentPlaylistChanged.connect( lambda p, i: self.playlistChanged.emit(p, i)) self.__playlistManager.playlistRemoved.connect( lambda uuid: self.playlistRemoved.emit(uuid)) self.__playlistManager.addedToLibraryPlaylist.connect( lambda uuid, l: self.addedToLibraryPlaylist.emit(uuid, l)) self.__playlistManager.addedToCustomPlaylist.connect( lambda uuid, l: self.addedToCustomPlaylist.emit(uuid, l)) self.__playlistManager.updatedLibraryPlaylist.connect( lambda uuid, l: self.updatedLibraryPlaylist.emit(uuid, l)) def createCustomPlaylist(self, name=None, urls=None): self.__playlistManager.createCustomPlaylist(name, urls) def createLibraryPlaylist(self, urls=None): self.__playlistManager.createLibraryPlaylist(urls) def addToLibraryPlaylist(self, url=None): self.__playlistManager.addToLibraryPlaylist(url) def updateLibraryPlaylist(self, url=None): self.__playlistManager.updateLibraryPlaylist(url) def renamePlaylist(self, uuid, newName): self.__playlistManager.renamePlaylist(uuid, newName) def addSongsToCustomPlaylist(self, uuid, urls=[]): self.__playlistManager.addSongsToCustomPlaylist(uuid, urls) def removeSong(self, uuid, row): self.__playlistManager.removeSong(uuid, row) def setPlaylist(self, uuid, index=0): if (self.__player.playlist() and self.__playlistManager.isCurrentPlaylist(uuid)): if index == self.__player.playlist().currentIndex(): if self.__player.state() == QMediaPlayer.PlayingState: self.__player.pause() else: self.__player.play() else: self.__player.playlist().setCurrentIndex(index) else: self.__playlistManager.setPlaylist(uuid, index) def hasLibraryPlaylist(self): return self.__playlistManager.hasLibraryPlaylist() def removePlaylist(self, uuid): self.__playlistManager.removePlaylist(uuid) def getCurrentPlaylist(self): self.__playlistManager.getCurrentPlaylist() def getCurrentQMediaPlaylist(self): self.__player.playlist() def isPlayerAvailable(self): return self.__player.isAvailable() def getDuration(self): return self.__player.duration() def getPlayer(self): return self.__player def getState(self): return self.__player.state() def play(self): if self.__player.playlist(): self.__player.play() def pause(self): if self.__player.playlist(): self.__player.pause() def stop(self): if self.__player.playlist(): self.__player.stop() def previousEnhanced(self, sameSongMillis): if self.__player.position() <= sameSongMillis: self.previous() else: self.__player.setPosition(0) def previous(self): if self.__player.playlist(): self.__player.playlist().previous() def next(self): if self.__player.playlist(): self.__player.playlist().next() def setVolume(self, value): self.__player.setVolume(value) def setPosition(self, milliseconds): self.__player.setPosition(milliseconds) def playlistCurrentIndex(self): if self.__player.playlist(): return self.__player.playlist().currentIndex() def setCurrentPlaylistIndex(self, index): if self.__player.playlist(): self.__player.playlist().setCurrentIndex(index) def _onChangedPlaylist(self, playlist, index, playIt=False): self.__player.setPlaylist(playlist) if playlist: playlist.setCurrentIndex(index) if playIt: self.play() def _onMediaChanged(self, media): if media.isNull() and self.__player.playlist(): self.__player.playlist().setCurrentIndex(0) media = self.__player.playlist().media(0) if media.isNull(): return title, artist, cover = self.__playlistManager.getBasicSongInfo(media) self.currentSongChanged.emit(title, artist, cover) uuid = self.__playlistManager.getCurrentPlaylistUuid() index = self.__playlistManager.getCurrentSongIndex() self.currentSelectionChanged.emit(uuid, index) # def saveSettings(self): # # settings = QSettings(QSettings.IniFormat, QSettings.UserScope, # # QCoreApplication.organizationName(), # # QCoreApplication.applicationName()) # # settings.beginGroup("music_player") # # # if self.__playlistManager.getLibraryPlaylist(): # # # libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories() # # # settings.beginWriteArray('library_playlist', # # # len(libraryDirectories)) # # # for index, value in enumerate(libraryDirectories): # # # settings.setArrayIndex(index) # # # settings.setValue("url", value) # # # settings.endArray() # # customPlaylists = self.__playlistManager.getCustomPlaylists() # # settings.beginWriteArray('custom_playlists', # # len(customPlaylists)) # # for index, value in enumerate(customPlaylists): # # settings.setArrayIndex(index) # # playlistName = settings.value('name', value.getName()) # # playlistUrls = value.getAddedSongUrls() # # settings.beginWriteArray(playlistName, # # len(playlistUrls)) # # for i, v in enumerate(playlistUrls): # # settings.setArrayIndex(i) # # settings.setValue("url", v) # # settings.endArray() # # settings.endArray() # # settings.endGroup() # # if self.__playlistManager.getLibraryPlaylist(): # # libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories() # # settings.beginWriteArray('library_playlist', # # len(libraryDirectories)) # # for index, value in enumerate(libraryDirectories): # # settings.setArrayIndex(index) # # settings.setValue("url", value) # # settings.endArray() # customPlaylists = self.__playlistManager.getCustomPlaylists() # for playlist in customPlaylists: # playlistName = playlist.getName() # for url in playlist: # pass # def restoreSettings(self): # settings = QSettings(QSettings.IniFormat, QSettings.UserScope, # QCoreApplication.organizationName(), # QCoreApplication.applicationName()) # settings.beginGroup("music_player") # # size = settings.beginReadArray('library_playlist') # # libraryDirectories = [] # # for i in range(size): # # settings.setArrayIndex(i) # # libraryDirectories.append(settings.value("url")) # # settings.endArray() # customPlaylists = {} # size = settings.beginReadArray('custom_playlists') # for i in range(size): # urls = [] # settings.setArrayIndex(i) # playlistName = settings.value('name') # print(playlistName) # size2 = settings.beginReadArray(playlistName) # for j in range(size2): # settings.setArrayIndex(j) # url = settings.value("url") # urls.append(url) # settings.endArray() # customPlaylists[playlistName] = urls # settings.endArray() # settings.endGroup() # print('-------') # print(customPlaylists) # settings = QSettings(QCoreApplication.organizationName(), # QCoreApplication.applicationName()) # settings.beginGroup("music_player") # size = settings.beginReadArray('library_playlist') # if not size == 0: # for i in range(0, size): # settings.setArrayIndex(i) # url = settings.value("url") # settings.endArray() # if url: # from audio.playlist_models import DirectoryPlaylist # playlist = DirectoryPlaylist() # playlist.add_directory(url) # self.addAndSetPlaylist(playlist, 2) # settings.endGroup() pass
class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt5 Media Player") self.setGeometry(350, 100, 700, 500) self.setWindowIcon(QIcon('player.png')) p = self.palette() p.setColor(QPalette.Window, Qt.black) self.setPalette(p) self.init_ui() self.show() def init_ui(self): #create media player object self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) #create videowidget object videowidget = QVideoWidget() #create open button openBtn = QPushButton('Open Video') openBtn.clicked.connect(self.open_file) #create button for playing self.playBtn = QPushButton() self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.clicked.connect(self.play_video) #create slider self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 0) self.slider.sliderMoved.connect(self.set_position) #create label self.label = QLabel() self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) #create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) #set widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.slider) #create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addWidget(videowidget) vboxLayout.addLayout(hboxLayout) vboxLayout.addWidget(self.label) self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videowidget) #media player signals self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Video") if filename != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediastate_changed(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def position_changed(self, position): self.slider.setValue(position) def duration_changed(self, duration): self.slider.setRange(0, duration) def set_position(self, position): self.mediaPlayer.setPosition(position) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText("Error: " + self.mediaPlayer.errorString())
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 jaabaGUI(QMainWindow): """ controller for the blob labeling GUI""" def __init__(self,parent=None): self.debugMode = True self.debugVideoPath = '/Users/071cht/Desktop/Lab/jaabagui/testt.mjpeg.avi' QMainWindow.__init__(self,parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.installEventFilter(self) self.setFocusPolicy(Qt.StrongFocus) #add new slider # self.positionSlider=QSlider(Qt.Horizontal) # self.positionSlider.setGeometry (800,800,100,30) # self.positionSlider.setRange(0, 0) # self.positionSlider.sliderMoved.connect(self.setPosition) #setup Video #video player self.mediaPlayer1 = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer2 = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer2.setNotifyInterval(10) #self.mediaPlayer.metaDataChanged.connect(self.metaDataChanged) self.mediaPlayer1.durationChanged.connect(self.durationChanged) self.mediaPlayer1.positionChanged.connect(self.positionChanged) self.mediaPlayer2.positionChanged.connect(self.positionChanged) #self.mediaPlayer2.positionChanged.connect(self.paintEvent) #visualizetion self.scene = QGraphicsScene() self.ui.graphicsView.setScene(self.scene) #self.scene.setBackgroundBrush(Qt.black) self.videoItem1 = QGraphicsVideoItem() self.videoItem2 = Video() self.scene.addItem(self.videoItem1) self.scene.addItem(self.videoItem2) self.mediaPlayer1.setVideoOutput(self.videoItem1) self.mediaPlayer2.setVideoOutput(self.videoItem2) #slider bar self.ui.horizontalSlider.setRange(0, 0) self.ui.horizontalSlider.sliderMoved.connect(self.setPosition) # self.ui.horizontalSlider.sliderPressed.connect(self.sliderPressed) #draw on video self.flyCanvas= TargetView() self.scene.addItem(self.flyCanvas) #give reference to target view self.flyCanvas.setWindowReference(self) #lineEdit signals: self.ui.lineEdit.returnPressed.connect(self.lineEditChanged) #callbacks self.ui.actionQuit.triggered.connect(self.quit) self.ui.actionLoad_Project.triggered.connect(self.loadVideo) self.ui.actionImport_Labels.triggered.connect(self.loadLabels) #self.ui.buttonPlay.clicked[bool].connect(self.setToggleText) self.ui.buttonPlay.clicked.connect(self.play) self.ui.actionSave.triggered.connect(self.saveLabels) ## print self.ui.graphicsView.sizeHint() #behavior Button self.ui.buttonBehavior.clicked.connect(self.behaviorButtonClick) self.ui.buttonNone.clicked.connect(self.noneButtonClick) #initialization self.loaded = False self.videoFilename = None self.frame_count=None self.width=None self.height=None self.frame_trans=None self.previous_frame=0 self.current_frame=0 self.behaviorButtonStart = False self.noneButtonStart = False self.currentFly=1 #initialize flyInfo #self.setCurrentFly(self.currentFly) # register flyid changed callback self.flyCanvas.onCurrentFlyIdChanged(self.currentFlyIdChangedCallback) self.flyCanvas.setCurrentFlyId(self.currentFly) # when double click on video, change fly id in target view self.videoItem2.onDoubleClick(self.flyCanvas.setCurrentFlyIdByXY) ######################## # DEBUG PART HERE!!!!! # ######################## if (self.debugMode): self.debugLoadVideo() # add label UI related when load video def showEvent(self, evt): super(jaabaGUI, self).showEvent(evt) ##### HERE THE WINDOW IS LOADED!!!!!!!! # self.loadLabelUI() def loadLabelUI(self): #labels self.labelScene = QGraphicsScene() self.ui.graphLabels.setScene(self.labelScene) # the size is only accurate after the window fully displayed labelUIWidth = self.ui.graphLabels.width() labelUIHeight = self.ui.graphLabels.height()-1 self.labelScene.setSceneRect(0,0,labelUIWidth,labelUIHeight) self.labelUI = LabelUI() # visiableWidth = 850 # height = 30 # visiableFrameNum = 850 self.labelUI.setWidthPerFrame(850.0/850.0) # print '850/500',850.0/850.0b # print 'length_perframe is ', self.labelUI.widthPerFrame # 850 is the original length of graphLabel total_length= self.labelUI.widthPerFrame * self.frame_count self.labelUI.setVisiableSize(total_length,30) # set start position self.labelUI.setPos(labelUIWidth/2,0) print 'frame_count is ', self.frame_count print 'total length is', total_length self.labelScene.addItem(self.labelUI) # middle line ui self.labelUIMiddleLine = LabelUIMiddleLine() self.labelScene.addItem(self.labelUIMiddleLine) self.labelUIMiddleLine.setPos(labelUIWidth/2,0) # self.labelUI.setPos(QPointF(-100,0)) self.writeLog('Label UI loaded') def eventFilter(self, obj, event): if (event.type() == PyQt5.QtCore.QEvent.KeyPress): # http://qt-project.org/doc/qt-4.8/qt.html#Key-enum key = event.key() if (key == Qt.Key_Up) : curr_frame= int(float(self.ui.lineEdit.text())) curr_frame= curr_frame-30 media_position= int(round(curr_frame*self.frame_trans)) # print curr_frame, media_position self.mediaPlayer1.setPosition(media_position) self.mediaPlayer2.setPosition(media_position) # print 'down -30' elif (key == Qt.Key_Right): curr_frame= int(float(self.ui.lineEdit.text())) # print 'right +1' # print curr_frame curr_frame= curr_frame+1 media_position= int(round(curr_frame*self.frame_trans)) # print 'curr_frame',curr_frame # print 'frame_trans',self.frame_trans # print ' curr_frame*self.frame_trans',curr_frame*self.frame_trans # print 'media_position',media_position # print curr_frame, media_position self.mediaPlayer1.setPosition(media_position) self.mediaPlayer2.setPosition(media_position) # self.mediaPlayerPositionChanged(media_position) elif (key == Qt.Key_Left): curr_frame= int(float(self.ui.lineEdit.text())) curr_frame= curr_frame-1 media_position= int(round(curr_frame*self.frame_trans)) self.mediaPlayer1.setPosition(media_position) self.mediaPlayer2.setPosition(media_position) # print 'left -1' elif (key == Qt.Key_Down): curr_frame= int(float(self.ui.lineEdit.text())) curr_frame= curr_frame+30 media_position= int(round(curr_frame*self.frame_trans)) self.mediaPlayer1.setPosition(media_position) self.mediaPlayer2.setPosition(media_position) # print 'up +30' return True return False # ###actions starts from here### def quit(self): QApplication.quit() def loadVideo(self): # print QMediaPlayer.supportedMimeTypes() self.writeLog("Loading video...") self.videoFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0] if not self.videoFilename: self.writeLog("User cancelled - no video loaded") return else: cap=cv2.VideoCapture(self.videoFilename) self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT) self.width=cap.get(3) self.height=cap.get(4) self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.ui.buttonPlay.setEnabled(True) # self.mediaPlayer2.setVideoOutput(self.videoItem2) # self.mediaPlayer1.setVideoOutput(self.videoItem1) # size= self.videoItem2.nativeSize() # # print size ## print self.mediaPlayer.duration() ## print self.mediaPlayer.metaData() self.writeLog("Video loaded!") # init label related ui self.loadLabelUI() def debugLoadVideo(self): self.videoFilename = self.debugVideoPath cap=cv2.VideoCapture(self.videoFilename) self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT) self.width=cap.get(3) self.height=cap.get(4) self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.ui.buttonPlay.setEnabled(True) self.writeLog("Video loaded!") QTimer.singleShot(1000, self.loadLabelUI) def play(self): self.videoItem1.setAspectRatioMode(0) self.videoItem2.setAspectRatioMode(0) self.scene.setSceneRect(0,0,self.ui.graphicsView.width(),self.ui.graphicsView.height()) self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height())) self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height())) self.videoItem1.setPos(QPointF(0,0)) self.videoItem2.setPos(QPointF(self.ui.graphicsView.width()/2,0)) self.flyCanvas.setPos(QPointF(self.ui.graphicsView.width()/2,0)) # custom function setXYScale self.videoItem2.setXYScale(self.width,self.height,self.ui.graphicsView.width()/2,self.ui.graphicsView.height()) self.flyCanvas.setXYScale(self.width,self.height,self.ui.graphicsView.width()/2,self.ui.graphicsView.height()) if self.mediaPlayer1.state() == QMediaPlayer.PlayingState: self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPlay)) self.ui.buttonPlay.setText("Play") self.mediaPlayer1.pause() self.writeLog("Video paused") else: self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPause)) self.ui.buttonPlay.setText("Stop") self.mediaPlayer1.play() self.writeLog("Playing video") if self.mediaPlayer2.state() == QMediaPlayer.PlayingState: self.mediaPlayer2.pause() else: self.mediaPlayer2.play() def loadLabels(self): self.writeLog("Loading labels from file...") self.labelFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0] self.labelUI.labelData = pickle.load(open(self.labelFilename,"rb")) self.writeLog("Label loaded from file:" + self.labelFilename) def saveLabels(self): # Now it can only save to current file. Will add an poput window to choose path later pickle.dump( self.labelUI.labelData, open( "newLabels.p", "wb" ) ) def setPosition(self, position): self.mediaPlayer1.setPosition(position) self.mediaPlayer2.setPosition(position) # when position of media changed, set slider and text box accordingly. def positionChanged(self, position): #test change labelui position # self.labelUI.startLabel(); # self.labelUI.update() previous_frame= self.previous_frame curr_frame= int(round(position/self.frame_trans)) self.current_frame=curr_frame frame_change= previous_frame-curr_frame move_width= frame_change * self.labelUI.widthPerFrame self.previous_frame= curr_frame self.labelUI.moveBy(move_width,0) self.labelUI.setCurrentFrame(curr_frame) # enforce labelUI paint once self.labelUI.update() # self.labelUI.setPos(self.labelUI.mapToParent(1,0)); # self.labelUI.update() # # print 'triggered position' # # print position # # print 'cur position' # # print self.mediaPlayer2.position() self.updateLineEdit(position) self.updateSliderAndGraph(position) # self.ui.horizontalSlider.setValue(position) # if isinstance(self.frame_trans,float): # # # print type(position),position # # # print type(self.frame_trans),self.frame_trans # # # print position/self.frame_trans # self.ui.lineEdit.setText(str(int(round(position/self.frame_trans)))) # self.flyCanvas.getFrame(int(round(position/self.frame_trans))) # self.flyCanvas.isManualCalled = True; # self.flyCanvas.update() # self.writeLog(str(position)) # # self.updateMediaControlUI(position) # # self.flyCanvas.update() def updateSliderAndGraph(self, position): self.ui.horizontalSlider.setValue(position) if isinstance(self.frame_trans,float): self.flyCanvas.getFrame(int(round(position/self.frame_trans))) self.flyCanvas.isManualCalled = True self.flyCanvas.update() #self.writeLog(str(position)) def updateLineEdit(self, position): # # print self.width # # print self.height if isinstance(self.frame_trans,float): # # print type(position),position # # print type(self.frame_trans),self.frame_trans # # print position/self.frame_trans self.ui.lineEdit.setText(str(int(round(position/self.frame_trans)))) def durationChanged(self, duration): self.ui.horizontalSlider.setRange(0, duration) self.frame_trans=self.mediaPlayer1.duration()/self.frame_count ## print self.frame_trans #def eventFilter(self,source,event): #if (event.type()==PyQt5.QtCore.QEvent.MousePress and source is self.videoItem2): # pos=event.pos() # # print('mouse position: (%d,%d)' % (pos.x(),pos.y())) # return PyQt5.QtGui.QWidget.eventFilter(self, source, event) def writeLog(self,text): self.ui.log.setText(text) # def eventFilter (self.ui.lineEdit,event): # if event.type()==PyQt5.QtCore.QEvent def lineEditChanged(self): #set position of media curr_frame= int(float(self.ui.lineEdit.text())) media_position= int(round(curr_frame*self.frame_trans)) self.mediaPlayer1.setPosition(media_position) self.mediaPlayer2.setPosition(media_position) # print 'setPosition' # print media_position # print 'after set' # print self.mediaPlayer2.position() # self.updateSliderAndGraph(media_position) def behaviorButtonClick(self): # flip flag self.behaviorButtonStart = not self.behaviorButtonStart # check click to start or stop if (self.behaviorButtonStart): # start labeling self.labelUI.startLabel(self.ui.comboBox.currentIndex(),'',self.current_frame) self.writeLog('start labeling') else: # stop lableing self.labelUI.stopLabel() self.writeLog('stop labeling') def noneButtonClick(self): # flip flag self.noneButtonStart = not self.noneButtonStart # check click to start or stop if (self.noneButtonStart): # start labeling self.labelUI.startLabel(self.ui.comboBox.currentIndex(),'_none',self.current_frame) self.writeLog('start labeling') else: # stop lableing self.labelUI.stopLabel() self.writeLog('stop labeling') # set CurrentFly when fly changed! def setCurrentFly(self,fly): self.currentFly = fly self.ui.flyInfo.setPlainText('FlyID:' + str(self.currentFly)) self.flyCanvas.currentFly=fly def currentFlyIdChangedCallback(self,fly): print 'callback!!!!!'; self.currentFly = fly self.ui.flyInfo.setPlainText('FlyID:' + str(self.currentFly))
class Start(QTabWidget, QMainWindow, QVideoWidget): switch_window = pyqtSignal() global what global ei, hsi, oi, ri, what, oe, ce, pe, ne, xsi, ysi, b, arr def __init__(self, *args): super(Start, self).__init__(*args) self.setWindowIcon(QIcon('icon.png')) self.setWindowTitle('Rujhaan') global fck, what ## me=1 #self.connect(lambda:cloud.new1()) self.tab1 = QWidget() self.tab2 = QWidget() self.tab4 = QWidget() self.tab5 = QWidget() self.addTab(self.tab4, " Profile ") self.addTab(self.tab2, "Lectures") self.addTab(self.tab1, "Today's Performance") self.addTab(self.tab5, "About Us") self.per() self.lec() self.pro() self.abt() self.laabel = QLabel(self) time_str = "Current time: {0}".format(QTime.currentTime().toString()) self.laabel.move(sw + 50, 0) self.laabel.resize(150, 30) self.laabel.setText(time_str) self.updateabelTime() def start(self): global fck, new, what, oi, ei oi = 0 ei = 0 hsi = 0 what = "Stop" self.st = QPushButton("Start", self) self.st.setToolTip('Click here To start Analysis') self.st.clicked.connect(camera.new) self.st.move(sw - 250, 0) self.st.resize(100, 30) self.st1 = QPushButton("Stop", self) self.st1.setToolTip('Click here To Stop Analysis') #self.st1.setEnabled(False) self.st1.clicked.connect(start) self.st1.move(sw - 100, 0) self.st1.resize(100, 30) self.timer = QTimer() self.timer.timeout.connect(self.updateabelTime) self.timer.start(1000) #self.Final() @pyqtSlot() def updateabelTime(self): time_str = "Current time: {0}".format(QTime.currentTime().toString()) self.laabel.setText(time_str) @pyqtSlot() def lec(self): self.tab = QtWidgets.QTabWidget() self.tabk = QWidget() self.tabk2 = QWidget() self.tab.addTab(self.tabk, "Offline Lectures") self.tab.addTab(self.tabk2, "Online Lectures") q = QBoxLayout(QBoxLayout.LeftToRight, self) q.addWidget(self.tab) self.tab2.setLayout(q) self.ok() self.off() #@pyqtSlot() def ok(self): link = "https://www.youtube.com" game = MainWindow2.kon(self, link) self.tabk2.setLayout(game) def off(self): self.now() #@pyqtSlot() def per(self): global ei, hsi, oi, ri, what, oe, ce, pe, ne, xsi, ysi, b self.pbar1 = QProgressBar(self) self.pbar1.setValue(1) self.pbar2 = QProgressBar(self) self.pbar2.setValue(1) self.pbar3 = QProgressBar(self) self.pbar3.setValue(1) self.bb = QLabel("Your OI is ", self) self.bb.setFont(QFont("Times", 10, QFont.Bold)) self.bb1 = QLabel("Your EI is ", self) self.bb1.setFont(QFont("Times", 10, QFont.Bold)) self.bb2 = QLabel("Your HSI is ", self) self.bb2.setFont(QFont("Times", 10, QFont.Bold)) self.bba = QLabel(str(oi), self) self.bba.setFont(QFont("Times", 11, QFont.Bold)) self.bb1a = QLabel(str(ei), self) self.bb1a.setFont(QFont("Times", 11, QFont.Bold)) self.bb2a = QLabel(str(hsi), self) self.bb2a.setFont(QFont("Times", 11, QFont.Bold)) self.bb4 = QPushButton("Summary", self) self.bb4.setFont(QFont("Times", 10, QFont.Bold)) self.bb4.clicked.connect(self.summ) self.update_labelTime() self.time = QTimer() self.time.timeout.connect(self.update_labelTime) self.time.start(1000) #self.button2.clicked.connect(self.on_signup) bbq = QFormLayout(self) bbq.setContentsMargins(100, 100, 700, 100) bbq.addRow(self.bb, self.bba) bbq.addRow(self.pbar1) bbq.addRow(self.bb1, self.bb1a) bbq.addRow(self.pbar2) bbq.addRow(self.bb2, self.bb2a) bbq.addRow(self.pbar3) #bbq.addRow(self.bb3,self.bb3a) bbq.addRow(self.bb4) self.tab1.setLayout(bbq) @pyqtSlot() def update_labelTime(self): global oi, hsi, ri, ei _oi = str(oi) self.bba.setText(_oi) _ei = str(ei) self.bb1a.setText(_ei) _hsi = str(hsi) self.bb2a.setText(_hsi) self.update() def update(self): global oi, hsi, ri, ei self.pbar1.setValue(int(oi)) self.pbar2.setValue(int(ei)) self.pbar3.setValue(int(hsi)) def summ(self): global oi, hsi, ri, ei pass def now(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() #self.videoWidget.setFullscreen(False) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QPushButton(QIcon('open.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.clicked.connect(self.openFile) self.setStyleSheet("QPushButton { margin: 150px; }") # Create a widget for window contents wid = QWidget(self) #self.setCentralWidget(wid) # Create layouts to place inside widget frm = QFormLayout() #frm.setContentsMargins(50, 300,100,10) frm.addRow(openAction, self.playButton) #50, 100,100,10 mylay = QBoxLayout(QBoxLayout.TopToBottom) mylay.stretch(1) #videoWidget.setFullscreen(False) mylay.addWidget(videoWidget) mylay.addLayout(frm) mylay.addWidget(self.positionSlider) controlLayout = QHBoxLayout() controlLayout.stretch(1) controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addLayout(mylay) layout = QVBoxLayout() layout.stretch(1) layout.addWidget(videoWidget) layout.addWidget(self.errorLabel) layout.addLayout(controlLayout) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.tabk.setLayout(layout) #self.show() #return self.wid def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def pro(self): qq = QBoxLayout(QBoxLayout.LeftToRight, self) stq = QLabel("Your Details Are listed Here ", self) stq.setFont(QFont("Times", 50, QFont.Bold)) self.bay = QPushButton('cloud', self) self.bay.setToolTip('refresh') self.bay.clicked.connect(cloud.new1) self.bay1 = QPushButton('check login', self) self.bay1.setToolTip('refresh') self.bay1.clicked.connect(cloud.new1) qq.addWidget(stq) qq.addWidget(self.bay) qq.addWidget(self.bay1) self.tab4.setLayout(qq) def abt(self): link = "https://humosys.com/team" game = MainWindow2.kon(self, link) self.tab5.setLayout(game)
class Player(Qt.QWidget): """docstring for Player""" fullScreenChanged = Qt.pyqtSignal(bool) def __init__(self, playlist, parent=None): # create player super(Player, self).__init__(parent) self.trackInfo = '' self.statusInfo = '' self.duration = 0 # create player object self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.name = 'Current playlist' self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) # self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) # connect with VideoWidget # self.videoWidget = VideoWidget() # self.player.setVideoOutput(self.videoWidget) # connect with PlaylistModel self.playlistModel = PlaylistModel() self.playlistModel.setPlaylist(self.playlist) self.playlistView = Qt.QListView() self.playlistView.setModel(self.playlistModel) self.playlistView.setCurrentIndex(self.playlistModel.index( self.playlist.currentIndex(), 0)) # change to next song self.playlistView.activated.connect(self.jump) self.slider = Qt.QSlider(QtCore.Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = Qt.QLabel() self.slider.sliderMoved.connect(self.seek) # create histogram self.labelHistogram = Qt.QLabel() self.labelHistogram.setText('Histogram: ') self.histogram = HistogramWidget() histogramLayout = Qt.QHBoxLayout() histogramLayout.addWidget(self.labelHistogram) histogramLayout.addWidget(self.histogram, 1) # create videoProbe self.videoProbe = Qt.QVideoProbe() self.videoProbe.videoFrameProbed.connect(self.histogram.processFrame) self.videoProbe.setSource(self.player) # add control controls = Controllers() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) controls.setMuted(controls.isMuted()) # connect player's controls with Controllers controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.player.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousAction) controls.changeVolume.connect(self.player.setVolume) controls.changeMuting.connect(self.player.setMuted) # setPlaybackRate is from QMediaPlayer controls.changeSpeed.connect(self.player.setPlaybackRate) # controls.stop.connect(self.videoWidget.update) self.player.stateChanged.connect(controls.setState) self.player.volumeChanged.connect(controls.setVolume) self.player.mutedChanged.connect(controls.setMuted) # create fullScreenButton # self.fullScreenButton = Qt.QPushButton('FullScreen') # self.fullScreenButton.setCheckable(True) # displayLayout displayLayout = Qt.QHBoxLayout() # displayLayout.addWidget(self.videoWidget, 2) displayLayout.addWidget(self.playlistView) # controlLayout controlLayout = Qt.QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) # connect controlLayout with controls controlLayout.addWidget(controls) controlLayout.addStretch(1) # connect controlLayout with fullScreenButton # controlLayout.addWidget(self.fullScreenButton) # visualize player layout = Qt.QVBoxLayout() layout.addLayout(displayLayout) # layout for sliding song playing hLayout = Qt.QHBoxLayout() hLayout.addWidget(self.slider) hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) layout.addLayout(histogramLayout) # set icon self.setWindowIcon(Qt.QIcon('favicon.ico')) # create menus toolBar = Qt.QToolBar() # create basic actions self.createActions() # create simple button to repeat song self.repeatButton = Qt.QToolButton() self.repeatButton.setDefaultAction(self.repeatAct) # create playOnceButton self.playOnceButton = Qt.QToolButton() self.playOnceButton.setDefaultAction(self.playOnceAct) self.playOnceButton.setEnabled(False) # create shuffleButton self.shuffleButton = Qt.QToolButton() self.shuffleButton.setDefaultAction(self.shuffleAct) # create sequentialButton self.sequentialButton = Qt.QToolButton() self.sequentialButton.setDefaultAction(self.sequentialAct) # create fileButton for fileMenu fileButton = Qt.QToolButton() fileButton.setText('File') fileButton.setPopupMode(Qt.QToolButton.MenuButtonPopup) fileButton.setMenu(self.popFileMenu()) # create editButton for editMenu closeButton = Qt.QToolButton() closeButton.setText('Edit') closeButton.setDefaultAction(self.fileCloseAct) # display in toolBar these buttons toolBar.addWidget(self.repeatButton) toolBar.addWidget(self.playOnceButton) toolBar.addWidget(self.shuffleButton) toolBar.addWidget(self.sequentialButton) toolBar.addWidget(fileButton) toolBar.addWidget(closeButton) # add toolBar to layout of the player layout.addWidget(toolBar) layout.addWidget(Qt.QGroupBox()) self.setWindowTitle("Python Music Player") self.setLayout(layout) if not self.player.isAvailable(): Qt.QMessageBox(self, 'Unavailable service') # self.displayErrorMessage() controls.setEnabled(False) self.playlistView.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self.addToPlaylist(playlist) # create fileMenu def popFileMenu(self): aMenu = Qt.QMenu(self) aMenu.addAction(self.fileOpenAct) aMenu.addAction(self.fileCloseAct) return aMenu def createActions(self): self.repeatAct = Qt.QAction('Repeat', self, triggered=self.repeatSong) self.playOnceAct = Qt.QAction( 'Play once', self, triggered=self.playOnceSong) self.shuffleAct = Qt.QAction( 'Shuffle', self, triggered=self.playlist.shuffle) self.sequentialAct = Qt.QAction( 'Sequential', self, triggered=self.playSequential) self.fileOpenAct = Qt.QAction('Open', self, triggered=self.open) self.fileOpenAct.setShortcut('Ctrl+O') self.fileCloseAct = Qt.QAction('Close', self, triggered=self.close) self.fileCloseAct.setShortcut('Ctrl+Q') def repeatSong(self): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.repeatButton.setEnabled(False) self.playOnceButton.setEnabled(True) def playOnceSong(self): self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.playOnceButton.setEnabled(False) self.repeatButton.setEnabled(True) # unproperly used def playSequential(self): self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) # get and display song duration def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) # change slider position def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QtCore.QTime( (currentInfo / 3600) % 60, # hours (currentInfo / 60) % 60, # minutes currentInfo % 60, # seconds (currentInfo * 1000) % 1000) # miliseconds totalTime = QtCore.QTime( (duration / 3600) % 60, # hours (duration / 60) % 60, # minutes duration % 60, # seconds (duration * 1000) % 1000) # miliseconds formating = 'hh:mm:ss' if duration > 3600 else 'mm:ss' toString = (currentTime.toString(formating) + ' / ' + totalTime.toString(formating)) else: toString = '' self.labelDuration.setText(toString) def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo('{0} - {1}'.format( self.player.metaData(Qt.QMediaMetaData.AlbumArtist), self.player.metaData(Qt.QMediaMetaData.Title))) def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo: self.setWindowTitle('{0} | {1}'.format( self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def playlistPositionChanged(self, position): self.playlistView.setCurrentIndex( self.playlistModel.index(position, 0)) def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo('Loading...') elif status == QMediaPlayer.StalledMedia: self.setStatusInfo('Media Stalled') elif status == QMediaPlayer.EndOfMedia: Qt.QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo('') def handleCursor(self, status): if status in [QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia]: self.setCursor(QtCore.Qt.BusyCursor) else: self.unsetCursor() def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo: self.setWindowTitle('{0} | {1}'.format( self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def bufferingProgress(self, progress): self.setStatusInfo('Buffering {0}'.format(progress)) def displayErrorMessage(self): self.statusInfo(self.player.errorString()) def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def seek(self, seconds): self.player.setPosition(seconds * 1000) def previousAction(self): self.playlist.previous() def close(self): choice = Qt.QMessageBox.question( self, 'Close', 'Close the app?', Qt.QMessageBox.Yes | Qt.QMessageBox.No) if choice == Qt.QMessageBox.Yes: sys.exit() def open(self): names, _ = Qt.QFileDialog.getOpenFileNames(self, 'Open Files') # ['/home/milka/Documents/MusicPlayer/song.mp3'] self.addToPlaylist(names) def addToPlaylist(self, names): for name in names: fileInfo = Qt.QFileInfo(name) if fileInfo.exists(): url = QtCore.QUrl.fromLocalFile(fileInfo.absoluteFilePath()) # save_to_db song url create_song( url.path(), self.duration, playlist_name=self.name) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(Qt.QMediaContent(url)) else: url = QtCore.QUrl(name) if url.isValid(): self.playlist.addMedia(Qt.QMediaContent(url))
class QGisMap(QtWidgets.QWidget, Ui_Form): def __init__(self,projectfile,MainWidget): QtWidgets.QMainWindow.__init__(self) if os.name == 'nt': ffmpeg = os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe' versione = 'ffmpeg.exe' else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' versione = 'ffmpeg' if os.path.exists(ffmpeg) == True: self.setupUi(self) self.setWindowFlags(Qt.WindowStaysOnTopHint) self.Main = MainWidget self.projectfile = projectfile with open(self.projectfile,'r') as File: for line in File: if line[0:19] == 'Video file location': self.videoFile = line.split('=')[-1][1:-1] elif line[0:23] == 'Video start at msecond:': self.fps = (1 / (float(line.split()[7]))) * 1000 self.StartMsecond = int(line.split()[4]) elif line[0:4] == 'DB =': DB = line.split('=')[-1][1:-1] if DB == 'None': self.DB = None else: self.DB = DB break self.pushButton_3.setCheckable(True) self.EnableMapTool = False self.ExtractTool = 0 self.dockWidget_4.hide() self.GPXList = [] self.positionMarker=PositionMarker(self.Main.iface.mapCanvas()) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) self.player = QMediaPlayer() self.player.setVideoOutput(self.video_frame) self.playButton.clicked.connect(self.PlayPause) self.muteButton.clicked.connect(self.MuteUnmute) self.toolButton_11.clicked.connect(self.SkipBackward) self.toolButton_12.clicked.connect(self.SkipForward) self.SkipBacktoolButton_8.clicked.connect(self.BackwardFrame) self.SkipFortoolButton_9.clicked.connect(self.ForwardFrame) self.toolButton_4.clicked.connect(self.ExtractToolbar) self.toolButton_5.clicked.connect(self.close) self.pushButtonCut_2.clicked.connect(self.ExtractCommand) self.pushButtonCutA_6.clicked.connect(self.ExtractFromA) self.pushButtonCutB_6.clicked.connect(self.ExtractToB) self.pushButton_5.clicked.connect(self.CancelVertex) self.progressBar.hide() self.Main.pushButton_2.hide() self.Main.pushButton_8.hide() self.Main.groupBox.show() self.Main.groupBox_4.hide() self.ExtractA = False self.ExtractB = False self.ExtractedDirectory = None self.pushButtonCut_2.setEnabled(False) self.toolButton_6.setEnabled(False) self.LoadGPXVideoFromPrj(self.projectfile) else: ret = QMessageBox.warning(self, "Warning", 'missing ffmpeg binaries, please download it from https://github.com/sagost/VideoUavTracker/blob/master/FFMPEG/'+versione+' and paste it in /.qgis3/python/plugins/Video_UAV_Tracker/FFMPEG/ ', QMessageBox.Ok) self.close() def LoadGPXVideoFromPrj(self,VideoGisPrj): self.Polyline = [] with open(VideoGisPrj,'r') as File: Counter = 0 for line in File: if Counter < 5: pass else: line = line.split() lat = float(line[0]) lon = float(line[1]) ele = float(line[2]) speed = float(line[3]) course = float(line[4]) time = line[5] Point = [lat,lon,ele,speed,course,time] qgsPoint = QgsPoint(lon,lat) self.Polyline.append(qgsPoint) self.GPXList.append(Point) Counter = Counter + 1 self.GpsLayer = QgsVectorLayer("LineString?crs=epsg:4326", self.videoFile.split('.')[-2].split('/')[-1], "memory") self.pr = self.GpsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolyline(self.Polyline)) self.pr.addFeatures([feat]) self.GpsLayer.updateExtents() if self.DB != None: try: self.DBLayer = QgsVectorLayer(self.DB,self.DB.split('.')[-2].split('/')[-1],'ogr') QgsProject.instance().addMapLayers([self.DBLayer,self.GpsLayer]) self.AddPointMapTool = AddPointTool(self.Main.iface.mapCanvas(),self.DBLayer,self) self.toolButton_6.clicked.connect(self.AddPointTool) self.toolButton_6.setEnabled(True) except: ret = QMessageBox.warning(self, "Warning", str(self.DB)+' is not a valid shapefile.', QMessageBox.Ok) return else: QgsProject.instance().addMapLayers([self.GpsLayer]) self.duration = len(self.GPXList) self.ExtractToB = self.duration self.horizontalSlider.setSingleStep(1000) self.horizontalSlider.setMinimum(0) self.horizontalSlider.setMaximum(len(self.GPXList)*1000) url = QUrl.fromLocalFile(str(self.videoFile)) mc = QMediaContent(url) self.player.setMedia(mc) self.player.setPosition(self.StartMsecond) self.player.play() self.horizontalSlider.sliderMoved.connect(self.setPosition) self.player.stateChanged.connect(self.mediaStateChanged) self.player.positionChanged.connect(self.positionChanged) self.pushButton_3.clicked.connect(self.MapTool) self.skiptracktool = SkipTrackTool( self.Main.iface.mapCanvas(),self.GpsLayer , self) def AddPointTool(self): self.Main.iface.mapCanvas().setMapTool(self.AddPointMapTool) def MapTool(self): if self.EnableMapTool == False: self.Main.iface.mapCanvas().setMapTool(self.skiptracktool) self.pushButton_3.setChecked(True) self.EnableMapTool = True else: self.Main.iface.mapCanvas().unsetMapTool(self.skiptracktool) self.pushButton_3.setChecked(False) self.EnableMapTool = False def closeEvent(self, *args, **kwargs): try: self.player.stop() self.Main.iface.mapCanvas().scene().removeItem(self.positionMarker) self.CancelVertex() self.Main.pushButton_2.show() #self.Main.horizontalSpacer_2.show() self.Main.groupBox.hide() self.Main.pushButton_8.show() self.Main.groupBox_4.show() self.dockWidget_2.close() except: pass return QtWidgets.QWidget.closeEvent(self, *args, **kwargs) def mediaStateChanged(self, state): if self.player.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def setPosition(self, position): self.player.setPosition(position+self.StartMsecond) def secTotime(self,seconds): m, s = divmod(seconds, 60) h, m = divmod(m, 60) return "%d:%02d:%02d" % (h, m, s) def positionChanged(self, progress): if progress < self.StartMsecond: self.player.setPosition(self.StartMsecond) progress = self.StartMsecond AssociatedGps = round((progress - self.StartMsecond )/1000) self.DisplayPoint(AssociatedGps) totalTime = self.secTotime(self.duration) actualTime = self.secTotime((progress - self.StartMsecond )/1000) self.replayPosition_label.setText(actualTime + ' / '+totalTime) if not self.horizontalSlider.isSliderDown(): self.horizontalSlider.setValue(progress - self.StartMsecond ) def DisplayPoint(self,Point): if Point >= len(self.GPXList): Point = len(self.GPXList) - 1 gpx = self.GPXList[Point] lat = round(gpx[0],7) lon = round(gpx[1],7) ele = gpx[2] speed = gpx[3] course = gpx[4] time = gpx[5] Point = QgsPointXY() Point.set(lon, lat) canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) self.positionMarker.setHasPosition(True) self.Point = xform.transform(Point) self.positionMarker.newCoords(self.Point) self.positionMarker.angle = float(course) extent = canvas.extent() boundaryExtent=QgsRectangle(extent) boundaryExtent.scale(0.7) if not boundaryExtent.contains(QgsRectangle(Point, self.Point)): extentCenter= self.Point newExtent=QgsRectangle( extentCenter.x()-extent.width()/2, extentCenter.y()-extent.height()/2, extentCenter.x()+extent.width()/2, extentCenter.y()+extent.height()/2 ) self.Main.iface.mapCanvas().setExtent(newExtent) self.Main.iface.mapCanvas().refresh() self.Main.label_14.setText('GPS Time: '+str(time)) self.Main.label_15.setText('Course: '+"%.2f" % (course)) self.Main.label_16.setText('Ele: '+"%.2f" %(ele)) self.Main.label_17.setText('Speed m/s: '+"%.2f" %(speed)) self.Main.label_19.setText('Lat : '+str(lat)) self.Main.label_18.setText('Lon : '+str(lon)) def MuteUnmute(self): if self.player.mediaStatus() == 6 : if self.player.isMuted() == 1: self.player.setMuted(0) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) elif self.player.isMuted() == 0: self.player.setMuted(1) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolumeMuted)) def SkipForward(self): position = self.player.position() self.player.setPosition(position+1000) def SkipBackward(self): position = self.player.position() self.player.setPosition(position-1000) def ForwardFrame(self): position = self.player.position() self.player.setPosition(position+int(self.fps)) def BackwardFrame(self): position = self.player.position() self.player.setPosition(position-int(self.fps)) def PlayPause(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() else: self.player.play() def findNearestPointInRecording(self, x,y): ClickPt = QgsPoint(x,y) Low = ClickPt.distanceSquared(self.Polyline[0]) NearPoint = 0 Counter = 0 for Point in self.Polyline: dist = ClickPt.distanceSquared(Point) if dist < Low: Low = dist NearPoint = Counter Counter = Counter + 1 else: Counter = Counter + 1 self.setPosition(NearPoint*1000) def ExtractSingleFrameOnTime(self, pos, outputfile): if os.name == 'nt': ffmpeg = ('"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"') os.popen(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str('"' +self.videoFile+ '"')+ ' -t 1 '+str('"'+outputfile+'"')) else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' os.system(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str(self.videoFile)+' -t 1 '+str(outputfile)) def AddPoint(self,x,y): self.Main.iface.mapCanvas().unsetMapTool(self.AddPointMapTool) Point = QgsPointXY(x,y) pos = self.player.position() if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() a = self.DBLayer.name() last_desc = '///' LayerName =str(a) last_desc2 = LayerName + ' Point N ' directory = str(self.DB.split('.')[0])+'_Image/' if not os.path.exists(directory): os.makedirs(directory) fc = int(self.DBLayer.featureCount()) self.ExtractSingleFrameOnTime(pos,directory+LayerName+'_'+str(fc)+'_.jpg') fields = self.DBLayer.fields() attributes = [] lat,lon = Point.y(), Point.x() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon(WGS84)': attributes.append(str(lon)) elif a == 'Lat(WGS84)': attributes.append(str(lat)) elif a == 'Image link': attributes.append(str(directory+LayerName+'_'+str(fc)+'_.jpg')) else: if b == 'String': (a,ok) = QInputDialog.getText( self.Main.iface.mainWindow(), "Attributes", a + ' = String', QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a,ok) = QInputDialog.getDouble( self.Main.iface.mainWindow(), "Attributes", a + ' = Real', decimals = 10) attributes.append(a) elif b == 'Integer64': (a,ok) = QInputDialog.getInt( self.Main.iface.mainWindow(), "Attributes", a + ' = Integer') attributes.append(a) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) self.DBLayer.startEditing() self.DBLayer.addFeature(feature) self.DBLayer.commitChanges() self.DBLayer.triggerRepaint() def ExtractCommand(self): if self.ExtractToB <= self.ExtractFromA: ret = QMessageBox.warning(self, "Warning", '"To B" point must be after "from A" point', QMessageBox.Ok) self.CancelVertex() else: if os.name == 'nt': ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"' else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' Directory,_ = QFileDialog.getSaveFileName(caption= 'Save georeferenced images') if Directory: self.progressBar.show() self.progressBar.setValue(0) start = self.ExtractFromA if self.comboBox_6.currentText() == 'seconds': finish = self.ExtractToB - self.ExtractFromA fps = self.doubleSpinBox_2.value() if fps < 1.0: fps = 1.0 / fps elif fps > 1: fps = 1.0 / fps if os.name == 'nt': os.popen(str(ffmpeg+ ' -ss ' + str(start) + ' -i '+ str('"'+self.videoFile+'"')+ ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + '"'+Directory + '_%d.png'+'"')) else: os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + Directory + '_%d.png') else: txtGPSFile = open(Directory + 'UTM_Coordinates.txt', 'w') txtGPSFile.close() txtGPSFile = open(Directory+ 'UTM_Coordinates.txt', 'a') txtGPSFile.write('filename # East UTM # North UTM # Ele '+ '\n') finish = self.ExtractToB meters = self.doubleSpinBox_2.value() Timerange = range(start, finish + 1) RemainToUseMeterTotal = 0 if os.name == 'nt': os.popen(ffmpeg+' -ss '+ str(start) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' + '"'+Directory + '_sec_' + str(start)+'.00.png'+'"') else: os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(start)+'.00.png') lonUTM, latUTM,quotainutile = self.transform_wgs84_to_utm(float(self.GPXList[start][1]) , float(self.GPXList[start][0])) ele = float(self.GPXList[start][2]) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(start)+'.00.png,'+' '+ str(lonUTM) + ', '+ str(latUTM) + ', ' + str(ele) + '\n') for i in Timerange: progessBarValue = ((i-start) * 100) // len(Timerange) self.progressBar.setValue(int(progessBarValue)) latitude1,longitude1 = float(self.GPXList[i][0]) ,float(self.GPXList[i][1]) latitude2,longitude2 = float(self.GPXList[i+1][0]) ,float(self.GPXList[i+1][1]) ele1 = float(self.GPXList[i][2]) ele2 = float(self.GPXList[i+1][2]) Calculus = Geodesic.WGS84.Inverse(latitude1, longitude1, latitude2, longitude2) DistanceBetweenPoint = Calculus['s12'] Azimuth = Calculus['azi2'] SpeedMeterSecond = DistanceBetweenPoint #GPS refresh rate is actually 1, change parameter for different rates # Time = 1 if RemainToUseMeterTotal == 0: if DistanceBetweenPoint >= meters: decimalSecondToAdd = meters / DistanceBetweenPoint RemainToUseMeter = DistanceBetweenPoint - meters if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') while RemainToUseMeter > meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') if RemainToUseMeter == meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' +str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') RemainToUseMeterTotal = 0 elif RemainToUseMeter < meters: RemainToUseMeterTotal = RemainToUseMeter pass else: RemainToUseMeterTotal = meters - DistanceBetweenPoint elif RemainToUseMeterTotal > 0: if DistanceBetweenPoint >= (meters - RemainToUseMeterTotal) : decimalSecondToAdd = (meters - RemainToUseMeterTotal) / DistanceBetweenPoint RemainToUseMeter = DistanceBetweenPoint - (meters - RemainToUseMeterTotal) if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') while RemainToUseMeter > meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') if RemainToUseMeter == meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') RemainToUseMeterTotal = 0 elif RemainToUseMeter < meters: RemainToUseMeterTotal = RemainToUseMeter else: RemainToUseMeterTotal = (meters - DistanceBetweenPoint) + RemainToUseMeterTotal txtGPSFile.close() self.progressBar.hide() def ExtractFromA(self): if self.ExtractA == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex) self.ExtractA = False self.ExtractFromA = round((self.player.position()- self.StartMsecond )/1000) canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) latitude,longitude = self.Polyline[self.ExtractFromA].y(), self.Polyline[self.ExtractFromA].x() self.ExtractAVertex = QgsVertexMarker(canvas) self.ExtractAVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude))) self.ExtractAVertex.setColor(QColor(0,255,0)) self.ExtractAVertex.setIconSize(10) self.ExtractAVertex.setIconType(QgsVertexMarker.ICON_X) self.ExtractAVertex.setPenWidth(10) self.ExtractA = True if self.ExtractB == True: self.pushButtonCut_2.setEnabled(True) else: self.pushButtonCut_2.setEnabled(False) def ExtractToB(self): if self.ExtractB == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex) self.ExtractB = False self.ExtractToB = round((self.player.position()- self.StartMsecond )/1000) if self.ExtractA == True: if self.ExtractToB > self.ExtractFromA: canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) latitude,longitude = self.Polyline[self.ExtractToB].y(), self.Polyline[self.ExtractToB].x() self.ExtractBVertex = QgsVertexMarker(canvas) self.ExtractBVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude))) self.ExtractBVertex.setColor(QColor(255,0,0)) self.ExtractBVertex.setIconSize(10) self.ExtractBVertex.setIconType(QgsVertexMarker.ICON_X) self.ExtractBVertex.setPenWidth(10) self.ExtractB = True self.pushButtonCut_2.setEnabled(True) else: self.pushButtonCut_2.setEnabled(False) def CancelVertex(self): if self.ExtractA == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex) self.ExtractA = False if self.ExtractB == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex) self.ExtractB = False self.pushButtonCut_2.setEnabled(False) def ExtractToolbar(self): if self.ExtractTool == 0: self.dockWidget_4.show() self.ExtractTool = 1 else: self.dockWidget_4.hide() self.ExtractTool = 0 def transform_wgs84_to_utm(self, lon, lat): def get_utm_zone(longitude): return (int(1+(longitude+180.0)/6.0)) def is_northern(latitude): """ Determines if given latitude is a northern for UTM """ if (latitude < 0.0): return 0 else: return 1 utm_coordinate_system = osr.SpatialReference() utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat)) wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>) return wgs84_to_utm_transform.TransformPoint(lon, lat, 0) # returns easting, northing, altitude
class Window(QMainWindow): def __init__(self): super().__init__() self.title = "Python Annotator for VideoS" # self.top = 100 # self.left = 100 # self.width = 300 # self.height = 400 # self.setWindowState = "Qt.WindowMaximized" iconName = "home.png" self.InitWindow() def InitWindow(self): self.setWindowTitle(self.title) # self.setWindowIcon(QtGui.QIcon(iconName)) self.setWindowState(QtCore.Qt.WindowMaximized) self.UiComponents() self.show() def UiComponents(self): self.rowNo = 1 self.colNo = 0 self.fName = "" self.fName2 = "" self.fileNameExist = "" self.dropDownName = "" self.model = QStandardItemModel() self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.tableWidget = QTableWidget() self.tableWidget.cellClicked.connect(self.checkTableFrame) self.videoWidget = QVideoWidget() self.frameID = 0 self.insertBaseRow() openButton = QPushButton("Open...") openButton.clicked.connect(self.openFile) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.lbl = QLabel('00:00:00') self.lbl.setFixedWidth(60) self.lbl.setUpdatesEnabled(True) # self.lbl.setStyleSheet(stylesheet(self)) self.elbl = QLabel('00:00:00') self.elbl.setFixedWidth(60) self.elbl.setUpdatesEnabled(True) # self.elbl.setStyleSheet(stylesheet(self)) self.nextButton = QPushButton("-->") self.nextButton.clicked.connect(self.next) self.delButton = QPushButton("Delete") self.delButton.clicked.connect(self.delete) self.exportButton = QPushButton("Export") self.exportButton.clicked.connect(self.export) self.importButton = QPushButton("Import") self.importButton.clicked.connect(self.importCSV) # self.ctr = QLineEdit() # self.ctr.setPlaceholderText("Extra") self.startTime = QLineEdit() self.startTime.setPlaceholderText("Select Start Time") self.endTime = QLineEdit() self.endTime.setPlaceholderText("Select End Time") self.iLabel = QComboBox(self) self.iLabel.addItem("1. Eye Contact") self.iLabel.addItem("2. Pointing") self.iLabel.addItem("3. Response to Names") self.iLabel.addItem("4. Following Pointing") self.iLabel.addItem("5. Babbling") self.iLabel.addItem("6. Question-Answering") self.iLabel.addItem("7. Showing") self.iLabel.addItem("8. Following Instructions") self.iLabel.activated[str].connect(self.style_choice) # self.iLabel = QLineEdit() # self.iLabel.setPlaceholderText("Label") self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 100) self.positionSlider.sliderMoved.connect(self.setPosition) self.positionSlider.sliderMoved.connect(self.handleLabel) self.positionSlider.setSingleStep(2) self.positionSlider.setPageStep(20) self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Main plotBox plotBox = QHBoxLayout() controlLayout = QHBoxLayout() # controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.lbl) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.elbl) wid = QWidget(self) self.setCentralWidget(wid) # Left Layout{ # layout.addWidget(self.videoWidget) layout = QVBoxLayout() layout.addWidget(self.videoWidget, 3) # layout.addLayout(self.grid_root) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) plotBox.addLayout(layout, 5) # } # Right Layout { inputFields = QHBoxLayout() inputFields.addWidget(self.startTime) inputFields.addWidget(self.endTime) inputFields.addWidget(self.iLabel) # inputFields.addWidget(self.ctr) feats = QHBoxLayout() feats.addWidget(self.nextButton) feats.addWidget(self.delButton) feats.addWidget(self.exportButton) feats.addWidget(self.importButton) layout2 = QVBoxLayout() layout2.addWidget(self.tableWidget) layout2.addLayout(inputFields, 1) layout2.addLayout(feats, 2) # layout2.addWidget(self.nextButton) # } plotBox.addLayout(layout2, 2) # self.setLayout(layout) wid.setLayout(plotBox) self.shortcut = QShortcut(QKeySequence("["), self) self.shortcut.activated.connect(self.addStartTime) self.shortcut = QShortcut(QKeySequence("]"), self) self.shortcut.activated.connect(self.addEndTime) self.shortcut = QShortcut(QKeySequence("L"), self) self.shortcut.activated.connect(self.openFile) self.shortcut = QShortcut(QKeySequence("C"), self) self.shortcut.activated.connect(self.clearTable) self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volumeUp) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volumeDown) self.shortcut = QShortcut( QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider10) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider10) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.positionChanged.connect(self.handleLabel) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.fileNameExist = fileName self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) self.videopath = QUrl.fromLocalFile(fileName) self.errorLabel.setText(fileName) self.errorLabel.setStyleSheet('color: black') def play(self): # self.is_playing_video = not self.is_playing_video if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() # self._play_video() # self.errorLabel.setText("Start: " + " -- " + " End:") def _play_video(self): if self.is_playing_video and self.video_fps: frame_idx = min(self.render_frame_idx + 1, self.frame_count) print(frame_idx) if frame_idx == self.frame_count: self.on_play_video_clicked() else: self.target_frame_idx = frame_idx def style_choice(self, text): self.dropDownName = text QApplication.setStyle(QStyleFactory.create(text)) def addStartTime(self): self.startTime.setText(self.lbl.text()) def addEndTime(self): self.endTime.setText(self.lbl.text()) def next(self): self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(self.startTime.text())) self.colNo += 1 self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(self.endTime.text())) self.colNo += 1 self.tableWidget.setItem( self.rowNo, self.colNo, QTableWidgetItem(str(self.iLabel.currentIndex() + 1))) self.colNo += 1 self.tableWidget.setItem( self.rowNo, self.colNo, QTableWidgetItem(self.iLabel.currentText().split(' ', 1)[1])) self.colNo = 0 self.rowNo += 1 # print(self.ctr.text(), self.startTime.text(), self.iLabel.text(), self.rowNo, self.colNo) # print(self.iLabel.currentIndex()) def delete(self): # print("delete") index_list = [] for model_index in self.tableWidget.selectionModel().selectedRows(): index = QtCore.QPersistentModelIndex(model_index) index_list.append(index) self.rowNo = self.rowNo - len(index_list) for index in index_list: self.tableWidget.removeRow(index.row()) def clearTable(self): while self.tableWidget.rowCount() > 0: self.tableWidget.removeRow(0) self.insertBaseRow() print("Clearing") def export(self): if self.fileNameExist: self.fName = ((self.fileNameExist.rsplit('/', 1)[1]).rsplit('.', 1))[0] path, _ = QFileDialog.getSaveFileName( self, 'Save File', QDir.homePath() + "/" + self.fName + ".csv", "CSV Files(*.csv *.txt)") if path: with open(path, 'w') as stream: print("saving", path) writer = csv.writer(stream) # writer = csv.writer(stream, delimiter=self.delimit) for row in range(self.tableWidget.rowCount()): rowdata = [] for column in range(self.tableWidget.columnCount()): item = self.tableWidget.item(row, column) if item is not None and item is not "": rowdata.append(item.text()) else: break writer.writerow(rowdata) # self.isChanged = False # self.setCurrentFile(path) def importCSV(self): # if fName2 != "": # self.fName2 = ((self.fileNameExist.rsplit('/', 1)[1]).rsplit('.',1))[0] # path, _ = QFileDialog.getSaveFileName(self, 'Save File', QDir.homePath() + "/"+self.fName2+".csv", "CSV Files(*.csv *.txt)") # else: self.clearTable() path, _ = QFileDialog.getOpenFileName(self, 'Save File', QDir.homePath(), "CSV Files(*.csv *.txt)") print(path) if path: with open(path, 'r') as stream: print("loading", path) reader = csv.reader(stream) # reader = csv.reader(stream, delimiter=';', quoting=csv.QUOTE_ALL) # reader = csv.reader(stream, delimiter=';', quoting=csv.QUOTE_ALL) # for row in reader: for i, row in enumerate(reader): if i == 0: continue else: if (len(row) == 4): st, et, li, ln = row self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(st)) self.colNo += 1 self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(et)) self.colNo += 1 self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(str(li))) self.colNo += 1 self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(ln)) self.rowNo += 1 self.colNo = 0 def insertBaseRow(self): self.tableWidget.setColumnCount(4) #, Start Time, End Time, TimeStamp self.tableWidget.setRowCount(50) self.rowNo = 1 self.colNo = 0 self.tableWidget.setItem(0, 0, QTableWidgetItem("Start Time")) self.tableWidget.setItem(0, 1, QTableWidgetItem("End Time")) self.tableWidget.setItem(0, 2, QTableWidgetItem("Label Index")) self.tableWidget.setItem(0, 3, QTableWidgetItem("Label Name")) def checkTableFrame(self, row, column): if ((row > 0) and (column < 2)): # print("Row %d and Column %d was clicked" % (row, column)) item = self.tableWidget.item(row, column) if (item != (None and "")): try: itemFrame = item.text() itemFrame = itemFrame.split(":") frameTime = int(itemFrame[2]) + int( itemFrame[1]) * 60 + int(itemFrame[0]) * 3600 elblFrames = self.elbl.text().split(":") elblFrameTime = int(elblFrames[2]) + int( elblFrames[1]) * 60 + int(elblFrames[0]) * 3600 # print("Elbl FT ", str(elblFrameTime)) # print("FT ", str(frameTime)) # print(frameTime) self.mediaPlayer.setPosition(frameTime * 1000 + 1 * 60) except: self.errorLabel.setText( "Some Video Error - Please Recheck Video Imported!") self.errorLabel.setStyleSheet('color: red') def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.mediaPlayer.duration()) self.elbl.setText(mtime.toString()) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) self.errorLabel.setStyleSheet('color: red') def forwardSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1 * 60) def forwardSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60) def backSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1 * 60) def backSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60) def volumeUp(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10) print("Volume: " + str(self.mediaPlayer.volume())) def volumeDown(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10) print("Volume: " + str(self.mediaPlayer.volume())) # def mouseMoveEvent(self, event): # if event.buttons() == Qt.LeftButton: # self.move(event.globalPos() \- QPoint(self.frameGeometry().width() / 2, \ # self.frameGeometry().height() / 2)) # event.accept() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() ##################### update Label ################################## def handleLabel(self): self.lbl.clear() mtime = QTime(0, 0, 0, 0) self.time = mtime.addMSecs(self.mediaPlayer.position()) self.lbl.setText(self.time.toString()) def dropEvent(self, event): f = str(event.mimeData().urls()[0].toLocalFile()) self.loadFilm(f) def clickFile(self): print("File Clicked") def clickExit(self): sys.exit()
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.player = QMediaPlayer(self) #创建视频播放器 self.player.setNotifyInterval(1000) #信息更新周期, ms scene = QGraphicsScene(self) self.ui.graphicsView.setScene(scene) self.videoItem = QGraphicsVideoItem() #视频显示画面 self.videoItem.setSize(QSizeF(320, 220)) self.videoItem.setFlag(QGraphicsItem.ItemIsMovable) self.videoItem.setFlag(QGraphicsItem.ItemIsSelectable) self.videoItem.setFlag(QGraphicsItem.ItemIsFocusable) scene.addItem(self.videoItem) self.player.setVideoOutput(self.videoItem) #设置视频显示图形项 self.textItem = QGraphicsTextItem("面朝大海,春暖花开") #弹幕文字 font = self.textItem.font() font.setPointSize(20) self.textItem.setFont(font) self.textItem.setDefaultTextColor(Qt.red) self.textItem.setPos(100, 220) self.textItem.setFlag(QGraphicsItem.ItemIsMovable) self.textItem.setFlag(QGraphicsItem.ItemIsSelectable) self.textItem.setFlag(QGraphicsItem.ItemIsFocusable) scene.addItem(self.textItem) self.ui.btnText.setCheckable(True) #弹幕文字按钮 self.ui.btnText.setChecked(True) self.__duration = "" self.__curPos = "" self.player.stateChanged.connect(self.do_stateChanged) self.player.positionChanged.connect(self.do_positionChanged) self.player.durationChanged.connect(self.do_durationChanged) ## ==============自定义功能函数======================== ## ==============event处理函数========================== def closeEvent(self, event): #窗体关闭时 # 窗口关闭时不能自动停止播放,需手动停止 if (self.player.state() == QMediaPlayer.PlayingState): self.player.stop() ## ==========由connectSlotsByName()自动连接的槽函数============ @pyqtSlot() ##打开文件 def on_btnOpen_clicked(self): curPath = QDir.currentPath() #获取系统当前目录 ## curPath=os.getcwd() title = "选择视频文件" filt = "视频文件(*.wmv *.avi);;所有文件(*.*)" fileName, flt = QFileDialog.getOpenFileName(self, title, curPath, filt) if (fileName == ""): return fileInfo = QFileInfo(fileName) baseName = fileInfo.fileName() ## baseName=os.path.basename(fileName) self.ui.LabCurMedia.setText(baseName) curPath = fileInfo.absolutePath() QDir.setCurrent(curPath) #重设当前目录 media = QMediaContent(QUrl.fromLocalFile(fileName)) self.player.setMedia(media) #设置播放文件 self.player.play() @pyqtSlot() ##播放 def on_btnPlay_clicked(self): self.player.play() @pyqtSlot() ##暂停 def on_btnPause_clicked(self): self.player.pause() @pyqtSlot() ##停止 def on_btnStop_clicked(self): self.player.stop() @pyqtSlot() ##全屏 def on_btnFullScreen_clicked(self): self.videoWidget.setFullScreen(True) @pyqtSlot() ##静音按钮 def on_btnSound_clicked(self): mute = self.player.isMuted() self.player.setMuted(not mute) if mute: self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp")) else: self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp")) @pyqtSlot(int) ##音量调节 def on_sliderVolumn_valueChanged(self, value): self.player.setVolume(value) @pyqtSlot(int) ##播放进度调节 def on_sliderPosition_valueChanged(self, value): self.player.setPosition(value) @pyqtSlot() ##放大 def on_btnZoomIn_clicked(self): sc = self.videoItem.scale() self.videoItem.setScale(sc + 0.1) @pyqtSlot() ##缩小 def on_btnZoomOut_clicked(self): sc = self.videoItem.scale() self.videoItem.setScale(sc - 0.1) @pyqtSlot(bool) ##弹幕 def on_btnText_clicked(self, checked): self.textItem.setVisible(checked) ## =============自定义槽函数=============================== def do_stateChanged(self, state): isPlaying = (state == QMediaPlayer.PlayingState) self.ui.btnPlay.setEnabled(not isPlaying) self.ui.btnPause.setEnabled(isPlaying) self.ui.btnStop.setEnabled(isPlaying) def do_durationChanged(self, duration): self.ui.sliderPosition.setMaximum(duration) secs = duration / 1000 #秒 mins = secs / 60 #分钟 secs = secs % 60 #余数秒 self.__duration = "%d:%d" % (mins, secs) self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration) def do_positionChanged(self, position): if (self.ui.sliderPosition.isSliderDown()): return #如果正在拖动滑条,退出 self.ui.sliderPosition.setSliderPosition(position) secs = position / 1000 #秒 mins = secs / 60 #分钟 secs = secs % 60 #余数秒 self.__curPos = "%d:%d" % (mins, secs) self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.readConfig() self.setWindowTitle("Endless Reddit Player") self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.data = requests.get( f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100', headers={ 'User-agent': 'endless video bot uwu' }).json() self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.skipButton = QPushButton() self.skipButton.setEnabled(True) self.skipButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.skipButton.clicked.connect(self.selectNewVideo) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QAction(QIcon('open.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create exit action exitAction = QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # Create menu bar and add action menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') #fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.skipButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.mediaStatusChanged.connect(self.mediaStatusChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def readConfig(self): with open('config.json', 'r') as file: config = json.load(file) self.subreddit = config['subreddit'] self.sortby = config['sortby'] self.offlineMode = config['offlineMode'] def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def exitCall(self): sys.exit(app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def mediaStatusChanged(self, status): if self.mediaPlayer.mediaStatus() == QMediaPlayer.EndOfMedia: self.mediaPlayer.pause() self.selectNewVideo() def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def selectNewVideo(self): if len(self.data['data']['children']) == 0: if (self.data["data"]["after"]): self.data = requests.get( f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100&after={self.data["data"]["after"]}', headers={ 'User-agent': 'endless video bot uwu' }).json() else: self.data = requests.get( f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100', headers={ 'User-agent': 'endless video bot uwu' }).json() number = random.randrange(len(self.data['data']['children'])) if self.data['data']['children'][number]['data']['is_video']: self.url = self.data['data']['children'][number]['data']['media'][ 'reddit_video']['fallback_url'] print("selected next: " + self.url + ", " + str(len(self.data['data']['children'])) + " left before rescan.") self.mediaPlayer.setMedia(QMediaContent(QUrl(self.url))) self.playButton.setEnabled(True) self.mediaPlayer.play() del self.data['data']['children'][number] else: del self.data['data']['children'][number] self.selectNewVideo()
class Player(QWidget): fullScreenChanged = pyqtSignal(bool) def __init__(self, playlist, parent=None): super(Player, self).__init__(parent) self.colorDialog = None self.trackInfo = "" self.statusInfo = "" self.duration = 0 self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) self.videoWidget = VideoWidget() self.player.setVideoOutput(self.videoWidget) self.playlistModel = PlaylistModel() self.playlistModel.setPlaylist(self.playlist) self.playlistView = QListView() self.playlistView.setModel(self.playlistModel) self.playlistView.setCurrentIndex( self.playlistModel.index(self.playlist.currentIndex(), 0)) self.playlistView.activated.connect(self.jump) self.script_box = QPlainTextEdit() self.segmentList = QTreeWidget() self.segmentList.setSortingEnabled(True) self.segmentList.setColumnCount(5) self.segmentList.setHeaderLabels(['Product','Start','Label','Tool','Behavior']) self.productTextInput = QLineEdit() self.startTextInput = QLineEdit() self.labelTextInput = QLineEdit() self.toolTextInput = QLineEdit() self.behaviorTextInput = QLineEdit() self.addBtn = QPushButton("Add") self.addBtn.clicked.connect(self.addSegment) self.removeBtn = QPushButton("Remove Segement") self.removeBtn.clicked.connect(self.removeItem) self.saveBtn = QPushButton("Save") self.saveBtn.clicked.connect(self.saveSegments) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = QLabel() self.slider.sliderMoved.connect(self.seek) self.labelHistogram = QLabel() self.labelHistogram.setText("Histogram:") self.histogram = HistogramWidget() histogramLayout = QHBoxLayout() histogramLayout.addWidget(self.labelHistogram) histogramLayout.addWidget(self.histogram, 1) self.probe = QVideoProbe() self.probe.videoFrameProbed.connect(self.histogram.processFrame) self.probe.setSource(self.player) openButton = QPushButton("Open", clicked=self.open) if os.path.isdir(VIDEO_DIR): self.open_folder(VIDEO_DIR) controls = PlayerControls() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) controls.setMuted(controls.isMuted()) controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.player.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousClicked) controls.changeVolume.connect(self.player.setVolume) controls.changeMuting.connect(self.player.setMuted) controls.changeRate.connect(self.player.setPlaybackRate) controls.stop.connect(self.videoWidget.update) self.player.stateChanged.connect(controls.setState) self.player.stateChanged.connect(self.StateChangeShortcut) self.player.volumeChanged.connect(controls.setVolume) self.player.mutedChanged.connect(controls.setMuted) self.segmentButton = QPushButton("Segment") self.segmentButton.clicked.connect(self.createNewSegment) self.segmentButton.clicked.connect(self.addSegment) # self.segmentButton.setCheckable(True) self.fullScreenButton = QPushButton("FullScreen") self.fullScreenButton.setCheckable(True) self.colorButton = QPushButton("Color Options...") self.colorButton.setEnabled(False) self.colorButton.clicked.connect(self.showColorDialog) displayLayout = QHBoxLayout() # videoLayout = QVBoxLayout() # videoLayout.addWidget(self.videoWidget) # videoLayout.addWidget(self.script_box) displayLayout.addWidget(self.videoWidget, 3) editLayout = QVBoxLayout() editLayout.addWidget(self.playlistView, 2) editLayout.addWidget(self.script_box, 4) editLayout.addWidget(self.segmentList, 3) segmentInputLayout = QHBoxLayout() segmentInputLayout.addWidget(self.productTextInput) segmentInputLayout.addWidget(self.startTextInput) segmentInputLayout.addWidget(self.labelTextInput) segmentInputLayout.addWidget(self.toolTextInput) segmentInputLayout.addWidget(self.behaviorTextInput) editLayout.addLayout(segmentInputLayout,1) displayLayout.addLayout(editLayout, 2) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addStretch(1) controlLayout.addWidget(controls) controlLayout.addStretch(1) controlLayout.addWidget(self.segmentButton) controlLayout.addWidget(self.removeBtn) controlLayout.addWidget(self.addBtn) controlLayout.addWidget(self.saveBtn) controlLayout.addWidget(self.fullScreenButton) # controlLayout.addWidget(self.colorButton) layout = QVBoxLayout() layout.addLayout(displayLayout, 2) hLayout = QHBoxLayout() hLayout.addWidget(self.slider) hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) # layout.addLayout(histogramLayout) self.setLayout(layout) self.pausePlayShortcut = QShortcut(QKeySequence(Qt.Key_Space), self) self.addSegmentShortcut = QShortcut(QKeySequence(Qt.Key_A), self) self.removeSegmentShortcut = QShortcut(QKeySequence(Qt.Key_S), self) self.shortcut() if not self.player.isAvailable(): QMessageBox.warning(self, "Service not available", "The QMediaPlayer object does not have a valid service.\n" "Please check the media service plugins are installed.") controls.setEnabled(False) self.playlistView.setEnabled(False) openButton.setEnabled(False) self.colorButton.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self.addToPlaylist(playlist) def shortcut(self): self.addSegmentShortcut.activated.connect(self.createNewSegment) self.addSegmentShortcut.activated.connect(self.addSegment) self.removeSegmentShortcut.activated.connect(self.removeItem) self.pausePlayShortcut.activated.connect(self.player.play); def StateChangeShortcut(self): if self.player.state() == QMediaPlayer.StoppedState: self.pausePlayShortcut.activated.connect(self.player.play); if self.player.state() == QMediaPlayer.PausedState: self.pausePlayShortcut.activated.connect(self.player.play); if self.player.state() == QMediaPlayer.PlayingState: self.pausePlayShortcut.activated.connect(self.player.pause); def open(self): fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files") self.addToPlaylist(fileNames) def open_folder(self, folder_path): # fileNames = [x in glob.glob(folder_path + "*") if x.endswith('.mp4')] fileNames = [x for x in glob.glob(folder_path + "**",recursive=True) if x.endswith('.mp4')] self.addToPlaylist(fileNames) def addToPlaylist(self, fileNames): for name in fileNames: fileInfo = QFileInfo(name) if fileInfo.exists(): url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(QMediaContent(url)) else: url = QUrl(name) if url.isValid(): self.playlist.addMedia(QMediaContent(url)) def addSegment(self): item = TreeWidgetItem(self.segmentList) item.setText(0, self.productTextInput.text()) item.setText(1, self.startTextInput.text()) item.setText(2, self.labelTextInput.text()) item.setText(3, self.toolTextInput.text()) item.setText(4, self.behaviorTextInput.text()) item.setFlags(item.flags() | Qt.ItemIsEditable) self.segmentList.addTopLevelItem(item) #self.segmentList.sortByColumn(1, Qt.AscendingOrder) def removeItem(self): self.segmentList.takeTopLevelItem(self.segmentList.topLevelItemCount()-1) def saveSegments(self): itemCnt = self.segmentList.topLevelItemCount() colCnt = self.segmentList.columnCount() save_dict = {'segments':[]} for i in range(itemCnt): item = self.segmentList.topLevelItem(i) temp_data = [] for j in range(colCnt): temp_data.append(item.text(j)) temp_dict = {'product': temp_data[0], 'start': temp_data[1], 'label': temp_data[2], 'tool': temp_data[3], 'behavior': temp_data[4]} save_dict['segments'].append(temp_dict) import json file_name = self.playlist.currentMedia().canonicalUrl().fileName() with open(SEGMENT_DIR+file_name.replace('.mp4','.json'),'w') as file: json.dump(save_dict, file) def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo("%s - %s" % ( self.player.metaData(QMediaMetaData.AlbumArtist), self.player.metaData(QMediaMetaData.Title))) def previousClicked(self): # Go to the 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() else: self.player.setPosition(0) def clear_input_boxes(self): self.productTextInput.clear() self.startTextInput.clear() self.labelTextInput.clear() self.toolTextInput.clear() self.behaviorTextInput.clear() def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() file_name = self.playlist.currentMedia().canonicalUrl().fileName() script_file_name = file_name.replace('.mp4','.txt') if os.path.isfile(SCRIPT_DIR+script_file_name): text=open(SCRIPT_DIR+script_file_name).read() self.script_box.setPlainText(text) segment_file_path = SEGMENT_DIR + file_name.replace('.mp4','.json') json_dict = self.open_json(segment_file_path) self.clear_input_boxes() self.segmentList.clear() for segment in json_dict["segments"]: item = TreeWidgetItem(self.segmentList) item.setText(0, segment['product']) item.setText(1, str(segment['start'])) item.setText(2, segment['label']) item.setText(3, segment['tool']) item.setText(4, segment['behavior']) item.setFlags(item.flags() | Qt.ItemIsEditable) self.segmentList.addTopLevelItem(item) # print([str(x.text()) for x in self.segmentList.currentItem()]) def open_json(self, file_path): import json try: with open(file_path, 'r') as file: json_dict = json.loads(file.read()) except: json_dict = {"segments":[]} # json_dict = {"segments":[{"product":"Sorry","start":"File not found.","label":"","tool":"","behavior":""}]} return json_dict def playlistPositionChanged(self, position): self.playlistView.setCurrentIndex( self.playlistModel.index(position, 0)) def seek(self, seconds): self.player.setPosition(seconds * 1000) def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo("Loading...") elif status == QMediaPlayer.StalledMedia: self.setStatusInfo("Media Stalled") elif status == QMediaPlayer.EndOfMedia: QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo("") def handleCursor(self, status): if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def bufferingProgress(self, progress): self.setStatusInfo("Buffering %d%" % progress) def videoAvailableChanged(self, available): if available: self.fullScreenButton.clicked.connect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.connect( self.fullScreenButton.setChecked) if self.fullScreenButton.isChecked(): self.videoWidget.setFullScreen(True) else: self.fullScreenButton.clicked.disconnect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.disconnect( self.fullScreenButton.setChecked) self.videoWidget.setFullScreen(False) self.colorButton.setEnabled(available) def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def displayErrorMessage(self): self.setStatusInfo(self.player.errorString()) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QTime((currentInfo/3600)%60, (currentInfo/60)%60, currentInfo%60, (currentInfo*1000)%1000) totalTime = QTime((duration/3600)%60, (duration/60)%60, duration%60, (duration*1000)%1000); format = 'hh:mm:ss' if duration > 3600 else 'mm:ss' tStr = currentTime.toString(format) + " / " + totalTime.toString(format) else: tStr = "" self.labelDuration.setText(tStr) def createNewSegment(self): self.startTextInput.setText(str(int(self.player.position()/1000))) def showColorDialog(self): if self.colorDialog is None: brightnessSlider = QSlider(Qt.Horizontal) brightnessSlider.setRange(-100, 100) brightnessSlider.setValue(self.videoWidget.brightness()) brightnessSlider.sliderMoved.connect( self.videoWidget.setBrightness) self.videoWidget.brightnessChanged.connect( brightnessSlider.setValue) contrastSlider = QSlider(Qt.Horizontal) contrastSlider.setRange(-100, 100) contrastSlider.setValue(self.videoWidget.contrast()) contrastSlider.sliderMoved.connect(self.videoWidget.setContrast) self.videoWidget.contrastChanged.connect(contrastSlider.setValue) hueSlider = QSlider(Qt.Horizontal) hueSlider.setRange(-100, 100) hueSlider.setValue(self.videoWidget.hue()) hueSlider.sliderMoved.connect(self.videoWidget.setHue) self.videoWidget.hueChanged.connect(hueSlider.setValue) saturationSlider = QSlider(Qt.Horizontal) saturationSlider.setRange(-100, 100) saturationSlider.setValue(self.videoWidget.saturation()) saturationSlider.sliderMoved.connect( self.videoWidget.setSaturation) self.videoWidget.saturationChanged.connect( saturationSlider.setValue) layout = QFormLayout() layout.addRow("Brightness", brightnessSlider) layout.addRow("Contrast", contrastSlider) layout.addRow("Hue", hueSlider) layout.addRow("Saturation", saturationSlider) button = QPushButton("Close") layout.addRow(button) self.colorDialog = QDialog(self) self.colorDialog.setWindowTitle("Color Options") self.colorDialog.setLayout(layout) button.clicked.connect(self.colorDialog.close) self.colorDialog.show()
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self._source = None self._total_duration = 0 self.widget_layout = QVBoxLayout() self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.video_player = QVideoWidget() self.widget_layout.addWidget(self.video_player) self.media_player.setVideoOutput(self.video_player) # self.media_player.stateChanged.connect(self.mediaStateChanged) self.media_player.positionChanged.connect(self.on_positionChanged) self.signals = VideoPlayerWidgetSignals() self.media_player.durationChanged.connect(self.on_durationChanged) self.setLayout(self.widget_layout) print(self.media_player.duration()) @property def total_duration(self): return self._total_duration @total_duration.setter def total_duration(self, val): self._total_duration = val @property def source(self): return self._source @source.setter def source(self, value): self._source = value self._total_duration = math.floor(VideoUtilities.duration(self.source)) def play(self): if self._source: self.media_player.setMedia( QMediaContent(QUrl.fromLocalFile(self._source))) self.media_player.play() def resume(self): if self.media_player.state() == QMediaPlayer.PlayingState: self.media_player.pause() else: self.media_player.play() def stop(self): if self.media_player.state() == QMediaPlayer.PlayingState: self.media_player.stop() def go_to(self, second: int): if self.media_player: self.media_player.setPosition(second * 1000) @QtCore.pyqtSlot('qint64') def on_positionChanged(self, position): self.signals.video_position_changed_signal.emit( math.floor(position / 1000), self.total_duration) if self.media_player.state() == QMediaPlayer.StoppedState: if 0 <= position <= self.total_duration * 1000: self.media_player.play() @QtCore.pyqtSlot('qint64') def on_durationChanged(self, duration): self.signals.video_duration_changed_signal.emit( math.floor(duration / 1000))
class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("Movie Night") self.setGeometry(350, 100, 700, 500) self.setWindowIcon(QIcon('network.png')) p = self.palette() p.setColor(QPalette.Window, Qt.black) self.setPalette(p) self.init_ui() def init_ui(self): # create media player object self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) #create video widget object videowidget = QVideoWidget() # create open button openBtn = QPushButton('Open Video') openBtn.clicked.connect(self.open_file) #create button or playing self.playBtn = QPushButton() self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.clicked.connect(self.play_video) #create slider self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 0) self.slider.sliderMoved.connect(self.set_position) #create label self.label = QLabel() self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) #create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) #add widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.slider) #create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addWidget(videowidget) vboxLayout.addLayout(hboxLayout) vboxLayout.addWidget(self.label) #mqtthandle self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videowidget) #media player signals self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Video") if filename != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediastate_changed(self, state): self.pos = self.mediaPlayer.position() print(self.pos) self.client.publish( self.topic, str(self.mediaPlayer.state()) + ";" + str(self.pos) + ";" + self.username) if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def position_changed(self, position): self.slider.setValue(position) def duration_changed(self, duration): self.slider.setRange(0, duration) def set_position(self, position): self.pos = position print(self.pos) self.mediaPlayer.setPosition(position) self.client.publish( self.topic, str(self.mediaPlayer.state()) + ";" + str(self.pos) + ";" + self.username) def connect_server(self): self.client.connect(self.broker, self.port) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText("Error: " + self.mediaPlayer.errorString()) def startServer(self, broker, port, username, password, topic): self.broker = broker self.port = port self.username = username self.password = password self.topic = topic def on_connect(client, userdata, flags, rc): print("connected -rc: ", rc) def on_message(client, userdata, message): msg = message.payload.decode("utf-8") x = msg.split(";") print(x) state = int(x[0]) pos = int(x[1]) user = x[2] if user != self.username: if state == QMediaPlayer.PlayingState: self.mediaPlayer.play() else: self.mediaPlayer.pause() self.mediaPlayer.setPosition(pos) def on_subscribe(client, userdata, mid, granted_qos): print("Subscribed: ", str(mid), str(granted_qos)) self.pos = "" self.client = mqtt_client.Client() self.client.on_connect = on_connect self.client.on_subscribe = on_subscribe self.client.on_message = on_message self.client.username_pw_set(self.username, self.password) self.connect_server() self.client.subscribe(self.topic) self.client.loop_start()
class CanvasVideo(QWidget): """Canvas for comparing videos. Now only support comparing two videos """ def __init__(self, parent): super(CanvasVideo, self).__init__() self.parent = parent self.info_text = [] self.flag_show_info = True # initialize widgets and layout self.init_widgets_layout() self.qview_bg_color = 'white' self.show_fingerprint = False # for auto zoom ratio self.target_zoom_width = 0 def init_player(self): if not hasattr(self, 'player1'): # the first video player self.videoitem1 = QGraphicsVideoItem() self.player1 = QMediaPlayer(self) self.player1.setVideoOutput(self.videoitem1) # the second video player self.videoitem2 = QGraphicsVideoItem() self.player2 = QMediaPlayer(self) self.player2.setVideoOutput(self.videoitem2) # signal-slot self.player1.stateChanged.connect(self.mediaStateChanged) self.player1.positionChanged.connect(self.positionChanged) self.player1.durationChanged.connect(self.durationChanged) # add to scene self.scene_text = self.qscenes[0].addText('') self.qscenes[0].addItem(self.videoitem1) self.qscenes[0].addItem(self.videoitem2) self.flag_front_player = '1' self.pause_pos = 0 def open_files(self): # init players self.init_player() # open the first video file self.video_file = self._open_one_file() self.player1.setMedia( QMediaContent(QUrl.fromLocalFile(self.video_file))) height, width = self.videoitem1.size().height(), self.videoitem1.size( ).width() self.qscenes[0].set_width_height(width, height) # put video always in the center of a QGraphicsView self.qscenes[0].setSceneRect(0, 0, width, height) # open the second video file self.video_file2 = self._open_one_file() self.player2.setMedia( QMediaContent(QUrl.fromLocalFile(self.video_file2))) self.playButton.setEnabled(True) self.syncButton.setEnabled(True) self.clearButton.setEnabled(True) self.infoButton.setEnabled(True) self.show_video(init=True) self.show_video_info() def _open_one_file(self): # get open file name try: with open(os.path.join(ROOT_DIR, 'history.txt'), 'r') as f: history = f.readlines()[0] history = history.strip() except Exception: history = '.' key, ok = QFileDialog.getOpenFileName(self, 'Open Video', history) if ok: # save history try: with open(os.path.join(ROOT_DIR, 'history.txt'), 'r') as f: lines = f.readlines() lines = [line.strip() for line in lines] if len(lines) == 5: del lines[-1] except Exception: lines = [] # add the new record to the first line if key not in lines: lines.insert(0, key) with open(os.path.join(ROOT_DIR, 'history.txt'), 'w') as f: for line in lines: f.write(f'{line}\n') return key def init_widgets_layout(self): # QGraphicsView - QGraphicsScene - QPixmap self.qscenes = [] self.qviews = [] show_info = False self.qscenes.append(HVScene(self, show_info=show_info)) self.qviews.append(HVView(self.qscenes[0], self, show_info=show_info)) # --------------------------------------- # layouts # --------------------------------------- main_layout = QGridLayout(self) # QGridLayout: # int row, int column, int rowSpan, int columnSpan main_layout.addWidget(self.qviews[0], 0, 0, -1, 50) self.infoButton = QPushButton() self.infoButton.setEnabled(False) self.infoButton.setFixedSize(QSize(80, 80)) self.infoButton.setIcon(self.style().standardIcon( QStyle.SP_MessageBoxInformation)) self.infoButton.clicked.connect(self.show_video_info) self.clearButton = QPushButton() self.clearButton.setEnabled(False) self.clearButton.setFixedSize(QSize(80, 80)) self.clearButton.setIcon(self.style().standardIcon( QStyle.SP_TrashIcon)) self.clearButton.clicked.connect(self.clear_players) self.syncButton = QPushButton() self.syncButton.setEnabled(False) self.syncButton.setFixedSize(QSize(80, 80)) self.syncButton.setIcon(self.style().standardIcon( QStyle.SP_BrowserReload)) self.syncButton.clicked.connect(self.sync_two_players) self.playButton = QPushButton() self.playButton.setFixedSize(QSize(80, 80)) self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.syncButton) controlLayout.addWidget(self.positionSlider) # controlLayout2 = QVBoxLayout() # controlLayout2.setContentsMargins(0, 0, 0, 0) # controlLayout2.addWidget(self.playButton) # controlLayout2.addLayout(controlLayout) main_layout.addWidget(self.clearButton, 59, 0, 1, 1) main_layout.addWidget(self.infoButton, 58, 0, 1, 1) main_layout.addLayout(controlLayout, 60, 0, -1, 49) self.qviews[0].set_shown_text( ['Click Open to open ·two· videos for comparison!']) def keyPressEvent(self, event): modifiers = QApplication.keyboardModifiers() if event.key() == QtCore.Qt.Key_F9: self.toggle_bg_color() elif event.key() == QtCore.Qt.Key_R: for qview in self.qviews: qview.set_zoom(1) elif event.key() == QtCore.Qt.Key_C: print('Enter C') self.compare_folders(1) elif event.key() == QtCore.Qt.Key_V: self.compare_folders(-1) elif event.key() == QtCore.Qt.Key_Space: if modifiers == QtCore.Qt.ShiftModifier: self.dir_browse(10) else: self.dir_browse(1) elif event.key() == QtCore.Qt.Key_Backspace: if modifiers == QtCore.Qt.ShiftModifier: self.dir_browse(-10) else: self.dir_browse(-1) elif event.key() == QtCore.Qt.Key_Right: if modifiers == QtCore.Qt.ShiftModifier: self.dir_browse(10) else: self.dir_browse(1) elif event.key() == QtCore.Qt.Key_Left: if modifiers == QtCore.Qt.ShiftModifier: self.dir_browse(-10) else: self.dir_browse(-1) elif event.key() == QtCore.Qt.Key_Up: if modifiers == QtCore.Qt.ShiftModifier: scale = 1.2 else: scale = 1.05 for qview in self.qviews: qview.zoom_in(scale=scale) elif event.key() == QtCore.Qt.Key_Down: if modifiers == QtCore.Qt.ShiftModifier: scale = 1.2 else: scale = 1.05 for qview in self.qviews: qview.zoom_out(scale=scale) elif event.key() == QtCore.Qt.Key_F11: self.parent.switch_fullscreen() def show_video_info(self): if self.flag_show_info is True: # if not self.info_text: if self.player1.metaData('Resolution') is not None: resolution_str1 = ( f"Resolution : {self.player1.metaData('Resolution').width()} " f"x {self.player1.metaData('Resolution').height()}") else: resolution_str1 = ('Resolution : None') if self.player2.metaData('Resolution') is not None: resolution_str2 = ( f"Resolution : {self.player2.metaData('Resolution').width()} " f"x {self.player2.metaData('Resolution').height()}") else: resolution_str2 = ('Resolution : None') self.info_text = [ f'Title : {os.path.basename(self.video_file)}', resolution_str1, f"Duration : {str(self.player1.metaData('Duration'))}", f"FrameRate : {str(self.player1.metaData('VideoFrameRate'))}", f"BitRate : {str(self.player1.metaData('VideoBitRate'))}", f"Video Codec: {str(self.player1.metaData('VideoCodec'))}", '', f'Title : {os.path.basename(self.video_file2)}', resolution_str2, f"Duration : {str(self.player2.metaData('Duration'))}", f"FrameRate : {str(self.player2.metaData('VideoFrameRate'))}", f"BitRate : {str(self.player2.metaData('VideoBitRate'))}", f"Video Codec: {str(self.player2.metaData('VideoCodec'))}", ] self.qviews[0].set_shown_text(self.info_text) self.flag_show_info = False else: self.qviews[0].set_shown_text( ['Click InfoButtion to show video information']) self.flag_show_info = True self.qscenes[0].update() # update the shown text def clear_players(self): if hasattr(self, 'player1'): self.player1.stop() self.player2.stop() self.qscenes[0].clear() del self.videoitem1 del self.videoitem2 del self.player1 del self.player2 gc.collect() self.playButton.setEnabled(False) self.syncButton.setEnabled(False) self.clearButton.setEnabled(False) self.infoButton.setEnabled(False) self.positionSlider.setRange(0, 0) # clear the shown text self.qviews[0].set_shown_text([]) self.qscenes[0].update() def sync_two_players(self): position = self.player1.position() self.player1.setPosition(position) self.player2.setPosition(position) def play(self): """only control player 1""" if self.player1.state() == QMediaPlayer.PlayingState: self.pause_pos = self.player1.position() print(self.pause_pos, self.player1.duration(), self.player2.duration()) self.player1.pause() self.player2.pause() else: self.player1.play() self.player2.play() def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.player1.setPosition(position) self.player2.setPosition(position) def mediaStateChanged(self, state): if self.player1.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def compare_folders(self, step): self.show_video() def show_video(self, init=False): if hasattr(self, 'player1'): if self.flag_front_player == '1': self.scene_text.setPlainText(os.path.basename(self.video_file)) self.flag_front_player = '2' self.qscenes[0].setFocusItem(self.videoitem2) self.videoitem2.stackBefore(self.videoitem1) # refresh frame in pause state # TODO: still have problem if self.player1.state() != QMediaPlayer.PlayingState: self.setPosition(self.pause_pos) else: self.scene_text.setPlainText(os.path.basename( self.video_file2)) self.flag_front_player = '1' self.qscenes[0].setFocusItem(self.videoitem1) self.videoitem1.stackBefore(self.videoitem2) # refresh frame in pause state # TODO: still have problem if self.player1.state() != QMediaPlayer.PlayingState: self.setPosition(self.pause_pos) self.qviews[0].set_transform() def dir_browse(self, step): self.show_video() def toggle_bg_color(self): if self.qview_bg_color == 'white': self.qview_bg_color = 'lightgray' for qscene in self.qscenes: qscene.setBackgroundBrush(QColor(211, 211, 211)) else: self.qview_bg_color = 'white' for qscene in self.qscenes: qscene.setBackgroundBrush(QtCore.Qt.white)
class Main(QWidget): """主窗口。""" def __init__(self, parent=None): super(Main, self).__init__(parent) # 信息。 self.result = {'uid': 0} # 歌单歌曲id。 self.playurl = {} # 搜索歌曲id。 self.ids = {} # 本地音乐地址。 self.local_url = {} # 歌曲图片。 self.pictures = {} # 歌曲列表id们。 self.playids = {} self.setObjectName('Main') self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowTitle('NetEase') self.setWindowIcon(QIcon('icons/format.ico')) # 功能。 self.function = api.WebApi() # 主页及其他功能。 self.index = Index(self) self.current_list = SongsWindow(self) # ------- # 待改进。 self.resize(1000, 650) # 按钮start. self.btn_exit = QPushButton(self) self.btn_min = QPushButton(self) self.btn_max = QPushButton(self) self.btn_login = QPushButton("Unlogin", self) self.btn_search = QPushButton(self) self.find_music = QPushButton(self) self.locale_music = QPushButton(self) self.select_path = QPushButton(self) self.play = QPushButton(self) self.stop = QPushButton(self) self.nextSong = QPushButton(self) self.beforeSong = QPushButton(self) self.pause = QPushButton(self) self.btn_list = QPushButton(self) self.add_all_song = QPushButton(self) self.single = QPushButton(self) self.cycle = QPushButton(self) self.loop_flags = True # 按钮end. # ------- # 标签start. self.lbe_pic = QLabel(self) self.header_hr = QLabel(self) self.header_icon = QLabel(self) self.header_text = QLabel(self) self.spacing = QLabel(self) self.spacing2 = QLabel(self) self.spacing3 = QFrame() self.spacing4 = QFrame() self.songs_list = QLabel(self) self.song_pic = QLabel(self) self.time1 = QLabel(self) self.time2 = QLabel(self) self.song_name = QLabel(self) # 歌单内的信息。 self.detail_pic = QLabel(self) self.detail_pic.hide() self.detail_author = QLabel(self) self.detail_author.hide() self.detail_tag = QLabel(self) self.detail_tag.hide() self.detail_name = QLabel(self) self.detail_name.hide() self.detail_description = QLabel(self) self.detail_description.hide() # 标签end. # ------- # 输入框start. self.search_line = QLineEdit(self) # 输入框end. # ------- # 列表框start. self.playlist = PlayList(self) # 列表框end. # ------- # 表格start. self.table = QTableWidget(self) self.table.setObjectName("tablelist") # 表格连接信号. self.table.itemDoubleClicked.connect(self.add_song) self.table.itemDoubleClicked.connect(self.play_song) self.table.hide() # 表格end. # ------- # 滚动条start。 self.slider = QSlider(self) # 滚动条end. # ------- # 播放功能。 self.player = QMediaPlayer() # ------- # 布局与属性设置。 self.mainLayout = QGridLayout() self.topLayout = QHBoxLayout() self.leftLayout = QVBoxLayout() self.centerLayout = QHBoxLayout() self.rightLayout = QVBoxLayout() self.rightLayout1 = QHBoxLayout() self.rightLayout2 = QVBoxLayout() self.rightLayout21 = QHBoxLayout() self.bottomLayout = QHBoxLayout() self.bottomLayout1 = QVBoxLayout() self.playLayout = QHBoxLayout() self.set_buttons() self.set_labels() self.set_lines() self.set_sliders() self.set_medias() # ------- # 其他功能。 self.load_login() self.manager = QNetworkAccessManager() self.setLayout(self.set_layouts()) # 登陆部分start. def lwindow(self): """ 登陆框。 """ login = LoginWindow(self) login.exec_() def load_login(self): """ 查看是否已经登陆。 """ os.chdir('.' + '/data' + '/cookies') filedir = os.listdir('.') if filedir: try: with open(filedir[0], 'r') as f: content = f.readlines() self.result['uid'] = content[1][:-1] # 读入当前用户uid. self.btn_login.setText(content[0][:-1]) # 加载昵称。 self.btn_login.disconnect() self.btn_login.clicked.connect(self.quit_login) # 改变登陆按钮连接到退出功能。 with open(filedir[-1], 'rb') as fi: p3 = QPixmap() p3.loadFromData(QByteArray(fi.read())) self.lbe_pic.setStyleSheet("border: 0px;") # 发现圆角只是边框,图片并不变化。 self.lbe_pic.setPixmap(p3.scaled(40, 40)) # 加载头像。 self.btn_login.setToolTip("登出") except: pass else: pass os.chdir('..') os.chdir('..') try: self.playlist.set_list() except: pass def quit_login(self): """ 退出登陆。 """ self.set_labels() self.lbe_pic.setStyleSheet("") self.btn_login.setText("Unlogin") self.btn_login.disconnect() self.btn_login.clicked.connect(self.lwindow) self.playlist.disconnect() self.playlist.clear() shutil.rmtree('data/cookies') os.makedirs('.' + '/data' + '/cookies') # 登陆部分end. # 内置组件部分start. def set_buttons(self): """ 全部的按钮组件。 """ # 退出。 self.btn_exit.setObjectName('exit') self.btn_exit.setText('×') self.btn_exit.clicked.connect(self.close) self.btn_exit.setToolTip('退出') # 最小化。 self.btn_min.setObjectName('mini') self.btn_min.setText('-') self.btn_min.clicked.connect(self.showMinimized) self.btn_min.setToolTip('最小化') # 最大化。 self.btn_max.setObjectName('maxi') self.btn_max.setText('□') self.btn_max.setToolTip('^_^此功能已上火星') # 登陆。 self.btn_login.setObjectName('login') self.btn_login.clicked.connect(self.lwindow) self.btn_login.setToolTip('登陆') # 搜索。 self.btn_search.setObjectName('searchBtn') self.btn_search.resize(48, 48) self.btn_search.clicked.connect(self.song_search) # 发现音乐。 self.find_music.setObjectName('find') self.find_music.setIcon(QIcon('icons/music.png')) self.find_music.setText("发现音乐") self.find_music.clicked.connect(self.show_index) # 本地音乐。 self.locale_music.setObjectName('locale') self.locale_music.setIcon(QIcon('icons/music.png')) self.locale_music.setText("本地音乐") self.locale_music.clicked.connect(self.looking_music) self.select_path.setObjectName('selection') self.select_path.clicked.connect(self.set_path) self.select_path.setText("选择目录") self.select_path.hide() # 播放页。 self.play.setObjectName('play') self.play.setToolTip("播放歌曲") self.play.clicked.connect(self.play_song) self.stop.setObjectName('stop') self.stop.setToolTip("停止播放") self.stop.clicked.connect(self.stop_song) self.nextSong.setObjectName('next') self.nextSong.setToolTip("下一首歌曲") self.nextSong.clicked.connect(self.next_song) self.beforeSong.setObjectName('before') self.beforeSong.setToolTip("上一首歌曲") self.beforeSong.clicked.connect(self.before_song) self.pause.setObjectName("pause") self.pause.setToolTip("暂停播放") self.pause.hide() self.pause.clicked.connect(self.pause_song) self.single.setObjectName('single') self.single.setToolTip('单曲循环') self.single.clicked.connect(self.set_modles) self.single.hide() self.cycle.setObjectName('cycle') self.cycle.setToolTip('循环播放') self.cycle.clicked.connect(self.set_modles) # 歌曲列表。 self.btn_list.setObjectName('songslist') self.btn_list.clicked.connect(self.songs_lists) # 歌单内功能。 self.add_all_song.setObjectName("addbutton") self.add_all_song.setText("播放全部") self.add_all_song.clicked.connect(self.add_all) self.add_all_song.hide() def set_labels(self): """ 全部的标签组件。 """ p = QPixmap() p.load('icons/unlogin.png') p2 = QPixmap() p2.load('icons/format_2.png') # 头部装饰start。 self.lbe_pic.setObjectName("headpic") self.lbe_pic.setPixmap(p.scaled(40, 40)) self.header_hr.setObjectName('Headerhr') self.header_hr.setText("推荐") self.header_icon.setObjectName('HIcon') self.header_icon.setPixmap(p2.scaled(50, 50)) self.header_text.setObjectName('HText') self.header_text.setText(" Music") # 头部装饰end。 # 头部竖线装饰start。 self.spacing.setObjectName('spacing1') self.spacing.resize(50, 50) self.spacing2.setObjectName('spacing2') self.spacing2.resize(50, 50) # 头部竖线装饰end。 self.songs_list.setObjectName("songlist") self.songs_list.setText("我的音乐") # 歌单标签设置start。 self.detail_pic.setObjectName("pic") self.detail_author.setObjectName("author") self.detail_tag.setObjectName("tag") self.detail_name.setObjectName("name") self.detail_description.setObjectName("description") # 歌单标签设置end。 # 歌曲图片。 self.song_pic.setObjectName("songpic") p3 = QPixmap() p3.load('icons/nosong.png') self.song_pic.setPixmap(p3) # 时间显示组件。 self.time1.setObjectName("time1") self.time1.setText('00:00') self.time1.setAlignment(Qt.AlignCenter | Qt.AlignRight | Qt.AlignBottom) self.time2.setObjectName("time2") self.time2.setText('00:00') self.time2.setAlignment(Qt.AlignBottom) # 间隔装饰。 self.spacing3.setFrameShape(QFrame.VLine) self.spacing3.setFrameShadow(QFrame.Plain) self.spacing3.setLineWidth(2) self.spacing4.setFrameShape(QFrame.HLine) self.spacing3.setFrameShadow(QFrame.Plain) self.spacing3.setLineWidth(2) # 歌曲名字。 self.song_name.setObjectName("songname") self.song_name.setAlignment(Qt.AlignCenter) self.song_name.setText("~~~还没有歌曲呦~~~") def set_lines(self): """ 输入框。 """ self.search_line.setObjectName('SearchLine') self.search_line.setPlaceholderText('搜索音乐。') def set_sliders(self): """ 滚动组件。 """ self.slider.setObjectName("slider") self.slider.setOrientation(Qt.Horizontal) self.slider.sliderMoved.connect(self.slider_media) self.slider.sliderReleased.connect(self.slider_setdone) # 内置组件备份end. # 歌曲部分start. # 框架,播放器及功能的处理。 def set_tables(self): """ 表格呈现歌单详细信息。 """ self.table.setColumnCount(6) self.table.setHorizontalHeaderLabels([' ', '操作', '音乐', '歌手', '专辑', '时长']) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) # 设置列宽。 self.table.setColumnWidth(0, 40) self.table.setColumnWidth(1, 40) self.table.setColumnWidth(2, 360) self.table.setColumnWidth(3, 140) self.table.setColumnWidth(4, 140) self.table.setColumnWidth(5, 60) # 设置充满表宽。 self.table.horizontalHeader().setStretchLastSection(True) # 设置表头亮度。 self.table.horizontalHeader().setHighlightSections(False) # 设置每次选择为一行。 self.table.setSelectionBehavior(QAbstractItemView.SelectRows) # 设置垂直表头不显示。 self.table.verticalHeader().setVisible(False) def set_medias(self): """ 设置播放器。 """ self.player.setVolume(100) self.player.stateChanged.connect(self.loop) self.player.positionChanged.connect(self.set_time) def song_search(self): """ 搜索功能。 name: 歌曲名称。 id: 歌曲id。 artists: [0][1]['name']歌曲作者可能不止一人,['img1v1Url']作者头像。 album: ['name']专辑名称。 """ # 暂时只做一页。翻页属后续功能。 text = self.search_line.text() if text: self.set_tables() self.hide_index() details = self.function.search(text) try: # 搜到没有的情况。 songs = details['songs'] except KeyError: self.table.hide() self.detail_description.setText('〖很抱歉,木有此歌曲〗') return songcount = details['songCount'] if songcount > 100: count = 100 else: count = songcount self.table.setRowCount(count) for i in range(count): self.ids[str(i)] = songs[i]['id'] self.table.setItem(i, 0, QTableWidgetItem(str(i))) self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), '')) self.table.setItem(i, 2, QTableWidgetItem(songs[i]['name'])) people = ','.join([c['name'] for c in songs[i]['artists']]) self.table.setItem(i, 3, QTableWidgetItem(people)) self.table.setItem(i, 4, QTableWidgetItem(songs[i]['album']['name'])) minuties = songs[i]['duration'] // 60000 seconds = songs[i]['duration'] // 1000 % 60 time = QTime(0, minuties, seconds) self.table.setItem(i, 5, QTableWidgetItem(time.toString("mm:ss"))) else: return # 加载图片。 pic = QPixmap() pic.load('icons/search2.jpg') self.detail_pic.setPixmap(pic.scaled(200, 200)) self.detail_name.setText('遨游在音乐的天空。') self.detail_author.setText("It's my sky!") self.detail_tag.setText('『Music, music』') self.detail_description.setText('〖Search Result〗') def show_playlist(self, name): """ 显示歌单详细信息。 trackCount: 总数。 name: 歌单名称。 tags: 歌单标签。 coverImgUrl: 歌单图片。 creator: ['nickname'] 创建者名字。 description: 歌单简介。 tracks: 歌曲总列表[] ,['bMusic']['id']歌曲id,['name']歌曲名称 , ['mp3Url']歌曲地址 , ['artists'][0]['name']歌曲作者,['id']作者id , ['album']['name']专辑名称,['blurPicUrl']图片。 """ self.set_tables() self.hide_index() details = self.function.details_playlist(self.result[name.replace('\n', '')]) self.table.setRowCount(details['trackCount']) # 加载在表格里。 for i in range(len(details['tracks'])): if not details['tracks'][i]['bMusic']['name']: self.playurl[str(i)] = details['tracks'][i]['id'] self.pictures[str(i)] = details['tracks'][i]['album']['blurPicUrl'] else: self.playurl[details['tracks'][i]['bMusic']['name']] = details['tracks'][i]['id'] self.pictures[details['tracks'][i]['bMusic']['name']] = details['tracks'][i]['album']['blurPicUrl'] # 设置序号。 self.table.setItem(i, 0, QTableWidgetItem(str(i))) self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), '')) if not details['tracks'][i]['bMusic']['name']: self.table.setItem(i, 2, QTableWidgetItem(str(i))) else: self.table.setItem(i, 2, QTableWidgetItem(details['tracks'][i]['bMusic']['name'])) people = ','.join([t['name'] for t in details['tracks'][i]['artists']]) self.table.setItem(i, 3, QTableWidgetItem(people)) self.table.setItem(i, 4, QTableWidgetItem(details['tracks'][i]['album']['name'])) minuties = details['tracks'][i]['bMusic']['playTime'] // 60000 seconds = details['tracks'][i]['bMusic']['playTime'] // 1000 % 60 time = QTime(0, minuties, seconds) self.table.setItem(i, 5, QTableWidgetItem(time.toString("mm:ss"))) # 加载歌单图片。 self.manager.clearAccessCache() pic = self.manager.get(QNetworkRequest(QUrl(details['coverImgUrl']))) self.manager.finished.connect(lambda: load_pic(pic)) def load_pic(picture): p4 = QPixmap() p4.loadFromData(picture.readAll()) self.detail_pic.setPixmap(p4.scaled(200, 200)) # 加载歌单名称,创建者,标签,简介。 self.detail_name.setText('::======>>歌单: ' + details['name']) self.detail_author.setText('Creator: ' + details['creator']['nickname']) self.detail_tag.setText('『' + str(details['tags'])[1:-1] + '』') try: self.detail_description.setText('〖' + details['description'] + '〗') self.detail_description.setWordWrap(True) except TypeError: self.detail_description.setText('〖〗') # 歌曲组件start。 def set_song(self, name, author): """ 设置歌曲链接连接。 """ try: self.manager.disconnect() except TypeError: pass self.manager.clearAccessCache() try: self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[name][author])))) data = self.manager.get(QNetworkRequest(QUrl(self.pictures[name]))) self.manager.finished.connect(lambda: self.load(data)) except KeyError: self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.playids[name][author]))) def add_song(self): """ 将歌曲加入到播放列表。 """ name = self.table.item(self.table.currentRow(), 2).text() author = self.table.item(self.table.currentRow(), 3).text() times = self.table.item(self.table.currentRow(), 5).text() content = author + ' - ' + name + ' - ' + times for i in range(self.current_list.count()): if self.current_list.item(i).text() == content: if self.current_list.currentItem().text() == content: break else: self.current_list.setCurrentRow(i) self.set_song(name, author) break else: self.current_list.addItem(content) self.current_list.setCurrentRow(self.current_list.count()-1) try: self.playids[name] except KeyError: self.playids[name] = {} try: self.playids[name][author] = self.playurl[name] except KeyError: self.playids[name][author] = self.ids[str(self.table.currentRow())] self.set_song(name, author) # 将列表保存到文件夹下。 with open('data/music/' + content.replace(':', '.'), 'w') as f: try: f.write(self.pictures[name]) except KeyError: pass def add_all(self): """ 将表格中所有的歌曲添加到播放列表。 """ for i in reversed(range(self.table.rowCount())): name = self.table.item(i, 2).text() author = self.table.item(i, 3).text() times = self.table.item(i, 5).text() content = name + ' - ' + author + ' - ' + times temp = [self.current_list.item(j).text() for j in range(self.current_list.count())] if content in temp: pass else: self.current_list.addItem(content) self.playids[name] = {} try: self.playids[name][author] = self.playurl[name] except KeyError: self.playids[name][author] = self.ids[str(self.table.currentRow())] with open('data/music/' + content.replace(':', '.'), 'w') as f: try: f.write(self.pictures[name]) except KeyError: pass self.set_song(name, author) self.play_song() def play_song(self): """ 播放组件。 """ # BUG: 用isAudio判断是否为有效音频是特么的双击居然显示无效。 try: self.song_name.setText(self.current_list.currentItem().text().split(' - ')[1]) self.time2.setText(self.current_list.currentItem().text().split(' - ')[2]) self.player.play() self.play.hide() self.pause.show() except AttributeError: return def pause_song(self): """ 暂停组件。 """ self.player.pause() self.pause.hide() self.play.show() def stop_song(self): """ 停止组件。 """ self.player.stop() self.pause.hide() self.play.show() def next_song(self): """ 下一首,若到头了则播放当前。 """ try: self.manager.disconnect() except TypeError: pass self.manager.clearAccessCache() try: content = self.current_list.item(self.current_list.currentRow()+1).text().split(' - ') self.song_name.setText(content[1]) self.time2.setText(content[2]) self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]])))) data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]]))) self.manager.finished.connect(lambda: self.load(data)) self.current_list.setCurrentRow(self.current_list.currentRow()+1) self.player.play() except AttributeError: self.player.play() def before_song(self): """ 前一首,若到头则播放当前。 """ try: self.manager.disconnect() except TypeError: pass self.manager.clearAccessCache() try: content = self.current_list.item(self.current_list.currentRow()-1).text().split(' - ') self.song_name.setText(content[1]) self.time2.setText(content[2]) self.player.setMedia(QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]])))) data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]]))) self.manager.finished.connect(lambda: self.load(data)) self.current_list.setCurrentRow(self.current_list.currentRow()-1) self.player.play() except AttributeError: self.player.play() # 本地音乐查找start. def looking_music(self): """本地音乐查找组件。""" p = QPixmap() p.load('icons/local.jpg') self.detail_pic.setPixmap(p.scaled(200, 200)) self.detail_name.setText("本地音乐") self.detail_author.setText("You, You, You") self.detail_tag.setText("Your Collection Music") self.hide_index() self.select_path.show() self.set_tables() self.locale_show_on_table(os.getcwd() + r"\myMusic") def set_path(self): file_path = QFileDialog.getExistingDirectory(self, 'Select Folder') self.locale_show_on_table(file_path) def locale_show_on_table(self, path): songs_list = [i for i in os.listdir(path) if i[-3:] == 'mp3'] print(songs_list) self.table.setRowCount(len(songs_list)) for i in range(len(songs_list)): temp = songs_list[i][:-4] temp2 = temp.split(' - ') self.table.setItem(i, 0, QTableWidgetItem(str(i))) self.table.setItem(i, 1, QTableWidgetItem(QIcon('icons/playlist.png'), '')) try: self.table.setItem(i, 2, QTableWidgetItem(temp2[1])) self.table.setItem(i, 3, QTableWidgetItem(temp2[0])) except IndexError: self.table.setItem(i, 2, QTableWidgetItem(temp)) self.table.setItem(i, 3, QTableWidgetItem("暂时无法获取")) self.table.setItem(i, 4, QTableWidgetItem("暂时无法获取")) self.table.setItem(i, 5, QTableWidgetItem("暂时无法获取")) self.playids[temp] = {} self.playids[temp]["暂时无法获取"] = path + '\\' + songs_list[i] continue self.table.setItem(i, 4, QTableWidgetItem("暂时无法获取")) self.table.setItem(i, 5, QTableWidgetItem("暂时无法获取")) self.playids[temp2[1]] = {} self.playids[temp2[1]][temp2[0]] = path + '\\' + songs_list[i] # 本地音乐查找end. # 歌曲组件end. # 歌曲图片,时间和滚动条的设置。 def load(self, data): """用于加载选中歌曲的图片。""" data = data.readAll() p = QPixmap() if data: p.loadFromData(data) self.song_pic.setPixmap(p.scaled(64, 64)) else: p.load('icons/nosong.png') self.song_pic.setPixmap(p.scaled(64, 64)) def set_time(self): """ 设置当前时间。 """ times = self.player.position() / 1000 minutes = times // 60 seconds = times % 60 time = QTime(0, minutes, seconds) self.time1.setText(time.toString("mm:ss")) try: alltime = float(self.current_list.item(\ self.current_list.currentRow()).text().split(' - ')[2].replace(':', '.')) except (AttributeError, ValueError): return curtime = float(time.toString('mm.ss')) self.slider.setValue((curtime / alltime) * 100) def slider_media(self): """ 拖动滚动条时时间的改变。基于时间的变化,若无法获取到时间是不变的,且会报ValueError的错误。当然可以随便写个2:00冒充。- -。 """ try: self.player.positionChanged.disconnect() except TypeError: pass content = self.current_list.item(self.current_list.currentRow()).text().split(' - ') alltime = float(content[2].replace(':', '.')) trans_alltime = int(alltime) * 60 + (alltime - int(alltime)) * 100 currentTime = trans_alltime * self.slider.value() minuties = currentTime / 100 // 60 seconds = currentTime / 100 % 60 time = QTime(0, minuties, seconds) self.time1.setText(time.toString("mm:ss")) def slider_setdone(self): """ 鼠标放开后播放位置。待改进。 """ self.player.positionChanged.connect(self.set_time) content = self.current_list.item(self.current_list.currentRow()).text().split(' - ') alltime = float(content[2].replace(':', '.')) trans_alltime = int(alltime) * 60 + (alltime - int(alltime)) * 100 currentTime = trans_alltime * self.slider.value() self.player.setPosition(currentTime * 10) # 设置歌曲播放模式。 def set_modles(self): """ 切换图标及将循环标志变false。 """ if self.loop_flags: self.cycle.hide() self.single.show() self.loop_flags = False else: self.single.hide() self.cycle.show() self.loop_flags = True def loop(self): """ 设置为循环播放。默认。 """ if self.player.position() > 0 and self.player.state() == 0 and self.loop_flags: try: self.manager.disconnect() except TypeError: pass self.manager.clearAccessCache() content = self.current_list.item(self.current_list.currentRow()+1).text().split(' - ') self.current_list.setCurrentRow(self.current_list.currentRow()+1) try: self.player.setMedia(\ QMediaContent(QUrl(self.function.details_search(self.playids[content[1]][content[0]])))) data = self.manager.get(QNetworkRequest(QUrl(self.pictures[content[1]]))) self.manager.finished.connect(lambda: self.load(data)) except KeyError: self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.playids[content[1]][content[0]]))) self.play_song() elif self.player.state() == 0: self.solo() def solo(self): """ 设置为单曲。 """ self.player.setPosition(0) self.play_song() # 歌曲部分end. # ------- # 切换页面start。 def songs_lists(self): """ 歌曲列表。 """ if self.current_list.flag: self.current_list.show() self.current_list.flag = False else: self.current_list.hide() self.current_list.flag = True def hide_index(self): """ 隐藏主页, 显示歌单详细信息。 """ self.centerLayout.setStretch(0, 160) self.centerLayout.setStretch(1, 1) self.centerLayout.setStretch(2, 850) self.centerLayout.setStretch(3, 0) self.centerLayout.setStretch(4, 0) self.index.hide() self.select_path.hide() self.current_list.hide() self.detail_pic.show() self.detail_name.show() self.detail_author.show() self.add_all_song.show() self.detail_tag.show() self.detail_description.show() self.table.show() def show_index(self): """ 显示主页。 """ self.centerLayout.setStretch(0, 160) self.centerLayout.setStretch(1, 1) self.centerLayout.setStretch(2, 0) self.centerLayout.setStretch(3, 850) self.centerLayout.setStretch(4, 0) self.current_list.hide() self.detail_pic.hide() self.detail_name.hide() self.select_path.hide() self.detail_author.hide() self.add_all_song.hide() self.detail_tag.hide() self.detail_description.hide() self.table.hide() self.index.show() # 切换页面end. # 设置布局。 def set_layouts(self): """ 布局。 """ # 头布局start. self.topLayout.setObjectName('Headerhbox') self.topLayout.addWidget(self.header_icon) self.topLayout.addWidget(self.header_text) self.topLayout.addWidget(self.spacing2) self.topLayout.addWidget(self.search_line) self.topLayout.addWidget(self.btn_search) self.topLayout.addStretch(1) self.topLayout.addWidget(self.lbe_pic) self.topLayout.addWidget(self.btn_login) self.topLayout.addWidget(self.spacing) self.topLayout.addWidget(self.btn_min) self.topLayout.addWidget(self.btn_max) self.topLayout.addWidget(self.btn_exit) self.topLayout.setSpacing(7) # ------- self.mainLayout.addLayout(self.topLayout, 0, 0, Qt.AlignTop) self.mainLayout.addWidget(self.header_hr, 1, 0, Qt.AlignTop) # 头布局end. # -------- # 中心布局start. # 左部分start. self.leftLayout.addWidget(self.find_music) self.leftLayout.addWidget(self.locale_music) self.leftLayout.addWidget(self.songs_list) self.leftLayout.addWidget(self.playlist) self.leftLayout.setSpacing(10) # 左部分end。 # ------- # 右部分start. self.rightLayout.addLayout(self.rightLayout1) self.rightLayout1.addWidget(self.detail_pic) self.rightLayout1.addLayout(self.rightLayout2) self.rightLayout1.setStretch(0, 1) self.rightLayout1.setStretch(1, 5) self.rightLayout21.addWidget(self.detail_name) self.rightLayout21.addWidget(self.select_path) self.rightLayout21.addStretch(1) self.rightLayout2.addLayout(self.rightLayout21) self.rightLayout2.addWidget(self.detail_author) self.playLayout.addWidget(self.add_all_song) self.playLayout.addStretch(1) self.rightLayout2.addLayout(self.playLayout) self.rightLayout2.addWidget(self.detail_tag) self.rightLayout2.addWidget(self.detail_description) self.rightLayout.addWidget(self.table) self.rightLayout.setStretch(0, 1) self.rightLayout.setStretch(1, 2) # 右部分end. # ------- self.centerLayout.addLayout(self.leftLayout) self.centerLayout.addWidget(self.spacing3) self.centerLayout.addLayout(self.rightLayout) self.centerLayout.addWidget(self.index) self.centerLayout.addWidget(self.current_list) self.centerLayout.setStretch(0, 180) self.centerLayout.setStretch(1, 1) self.centerLayout.setStretch(2, 0) self.centerLayout.setStretch(3, 830) self.centerLayout.setStretch(4, 0) self.mainLayout.addLayout(self.centerLayout, 2, 0, Qt.AlignTop | Qt.AlignLeft) # 中心布局end. # ------- # 下部分start. self.bottomLayout.addWidget(self.stop) self.bottomLayout.addWidget(self.beforeSong) self.bottomLayout.addWidget(self.play) self.bottomLayout.addWidget(self.pause) self.bottomLayout.addWidget(self.nextSong) self.bottomLayout.addWidget(self.song_pic) self.bottomLayout.addWidget(self.time1) self.bottomLayout1.addWidget(self.song_name) self.bottomLayout1.addWidget(self.slider) self.bottomLayout.addLayout(self.bottomLayout1) self.bottomLayout.addWidget(self.time2) self.bottomLayout.addWidget(self.cycle) self.bottomLayout.addWidget(self.single) self.bottomLayout.addWidget(self.btn_list) self.bottomLayout.setStretch(6, 1) self.bottomLayout.setStretch(7, 6) self.bottomLayout.setStretch(8, 1) self.mainLayout.addWidget(self.spacing4, 3, 0, Qt.AlignTop) self.mainLayout.addLayout(self.bottomLayout, 3, 0, Qt.AlignBottom) # self.mainLayout.addWidget(self.current_list, 2, 0, Qt.AlignBottom | Qt.AlignRight) # 下部分end. self.mainLayout.setRowStretch(1, 1) self.mainLayout.setRowStretch(2, 20) self.mainLayout.setRowStretch(3, 3) return self.mainLayout """重写鼠标事件,实现窗口拖动。""" def mousePressEvent(self, event): if event.buttons() == Qt.LeftButton: self.m_drag = True self.m_DragPosition = event.globalPos()-self.pos() event.accept() def mouseMoveEvent(self, event): try: if event.buttons() and Qt.LeftButton: self.move(event.globalPos()-self.m_DragPosition) event.accept() except AttributeError: pass def mouseReleaseEvent(self, event): self.m_drag = False """按键绑定。。""" def keyPressEvent(self, event): if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Enter-1: self.song_search() """退出窗口时做的一些事。""" def closeEvent(self, event): # 退出时保存歌曲列表缓存。 try: with open('data/music/load/playids.pkl', 'wb') as f: pickle.dump(self.playids, f) except FileNotFoundError: pass """界面开始前的一些事。""" def showEvent(self, event): # 查看是否有歌曲缓存。 try: with open('data/music/load/playids.pkl', 'rb') as r: self.playids = pickle.load(r) # 没有就算了。 except FileNotFoundError: pass # 没有也不会报错。 for i in os.listdir('.' + '/data/music/'): if os.path.isfile('.' + '/data/music/' + i): self.current_list.addItem(i.replace('.', ':')) with open('.' + '/data/music/' + i, 'r') as f: self.pictures[i.split(' - ')[1]] = f.read() # 有的话设置为0,防止其他功能报错。 self.current_list.setCurrentRow(0)
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoItem = QGraphicsVideoItem() self.videoItem.setSize(QSizeF(640, 480)) scene = QGraphicsScene(self) graphicsView = QGraphicsView(scene) scene.addItem(self.videoItem) rotateSlider = QSlider(Qt.Horizontal) rotateSlider.setRange(-180, 180) rotateSlider.setValue(0) rotateSlider.valueChanged.connect(self.rotateVideo) openButton = QPushButton("Open...") openButton.clicked.connect(self.openFile) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(graphicsView) layout.addWidget(rotateSlider) layout.addLayout(controlLayout) self.setLayout(layout) self.mediaPlayer.setVideoOutput(self.videoItem) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) def sizeHint(self): return QSize(800, 600) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def rotateVideo(self, angle): x = self.videoItem.boundingRect().width() / 2.0 y = self.videoItem.boundingRect().height() / 2.0 self.videoItem.setTransform( QTransform().translate(x, y).rotate(angle).translate(-x, -y))
class Window(QtWidgets.QDialog): def __init__(self): super().__init__() self.setGeometry(50, 50, 300, 400) self.setWindowTitle("Rolev Player") # LIBRARY ROOT DIR FOLDER self.search_label = QtWidgets.QLabel("Select a music folder:", self) self.search_label.setGeometry(10, 5, 205, 10) self.btn_root_folder = QtWidgets.QPushButton("Browse", self) self.btn_root_folder.setGeometry(215, 20, 75, 25) # the text field of the currently selected root directory self.dir_text_field = QtWidgets.QLineEdit(self) self.dir_text_field.setGeometry(10, 20, 200, 25) self.btn_root_folder.clicked.connect(self.on_btn_root_folder) # CURRENT MEDIA LABEL self.current_media_label = QtWidgets.QLabel("Now Playing: ", self) self.current_media_label.setGeometry(10, 260, 250, 15) # CURRENT ALBUM COVER self.current_album_cover = QtWidgets.QLabel("Image", self) self.current_album_cover.setGeometry(10, 180, 75, 75) self.current_album_cover.setScaledContents(True) # ARTIST DROP BOX self.artist_select_label = QtWidgets.QLabel("Artist", self) self.artist_select_label.setGeometry(10, 50, 250, 25) self.artist_select = QtWidgets.QComboBox(self) self.artist_select.setGeometry(10, 70, 250, 25) self.artist_select.activated[str].connect(self.on_artist_selection) # ALBUMS DROP BOX self.album_select_label = QtWidgets.QLabel("Albums", self) self.album_select_label.setGeometry(10, 90, 250, 25) self.album_select = QtWidgets.QComboBox(self) self.album_select.setGeometry(10, 110, 250, 25) self.album_select.activated[str].connect(self.on_album_selection) # SONGS DROP BOX self.song_select_label = QtWidgets.QLabel("Current Playlist", self) self.song_select_label.setGeometry(10, 130, 250, 25) self.song_select = QtWidgets.QComboBox(self) self.song_select.setGeometry(10, 150, 250, 25) self.song_select.activated[str].connect(self.on_song_selection) # PLAYLIST self.playlist = QMediaPlaylist() self.playlist.currentIndexChanged.connect(self.meta_data_changed) # MEDIA PLAYER self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.player.playlist().setPlaybackMode(QMediaPlaylist.Loop) self.player.setVolume(50) self.player.durationChanged.connect(self.on_dur_change) self.player.positionChanged.connect(self.on_pos_change) # VOLUME SLIDER self.slider_volume_label = QtWidgets.QLabel("Volume", self) self.slider_volume_label.setGeometry(10, 345, 50, 25) self.slider_volume = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.slider_volume.setGeometry(60, 350, 130, 20) self.slider_volume.setRange(0, 100) self.slider_volume.setValue(50) self.slider_volume.valueChanged.connect(self.volume_change) # PROGRESS SLIDER self.slider_progress_label = QtWidgets.QLabel("Progress", self) self.slider_progress_label.setGeometry(10, 315, 50, 25) self.slider_progress = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.slider_progress.setGeometry(60, 320, 130, 20) self.slider_progress.sliderMoved.connect(self.progress_change) # LYRICS SEARCH self.btn_lyrics = QtWidgets.QPushButton("Search\n Lyrics", self) self.btn_lyrics.setGeometry(220, 310, 70, 80) self.btn_lyrics.clicked.connect(self.on_lyrics) # ALBUM INFO SEARCH self.btn_album_info = QtWidgets.QPushButton( "Search\nAlbum\nInfo", self) self.btn_album_info.setGeometry(105, 180, 75, 75) self.btn_album_info.clicked.connect(self.on_album_info) # ARTIST INFO SEARCH self.btn_artist_info = QtWidgets.QPushButton( "Search\nArtist\nInfo", self) self.btn_artist_info.setGeometry(200, 180, 75, 75) self.btn_artist_info.clicked.connect(self.on_artist_info) # PREV SONG BUTTON self.btn_prev = QtWidgets.QPushButton("Prev", self) self.btn_prev.setGeometry(10, 280, 75, 25) self.btn_prev.clicked.connect(self.on_btn_prev) # NEXT SONG BUTTON self.btn_next = QtWidgets.QPushButton("Next", self) self.btn_next.setGeometry(200, 280, 75, 25) self.btn_next.clicked.connect(self.on_btn_next) # PLAY/PAUSE BUTTON self.btn_play_pause = QtWidgets.QPushButton("Play", self) self.btn_play_pause.setGeometry(105, 280, 75, 30) self.btn_play_pause.clicked.connect(self.on_btn_play_pause) self.show() def on_btn_root_folder(self): self.root_dir = QtWidgets.QFileDialog().getExistingDirectory() self.dir_text_field.setText(self.root_dir) self.library = LibraryLoader.load_music_from_dir( self.dir_text_field.text()) self.artist_select.clear() self.album_select.clear() self.song_select.clear() self.playlist.clear() self.btn_play_pause.setText("Play") self.artist_select.addItem("All Artists") for artist in self.library: self.artist_select.addItem(artist) for album in self.library[artist]: self.album_select.addItem(album) self.load_all_songs() def on_artist_selection(self): current_artist = self.artist_select.currentText() self.album_select.clear() self.song_select.clear() self.playlist.clear() self.btn_play_pause.setText("Play") self.album_select.addItem("All Albums") if current_artist == "All Artists": for artist in self.library: for album in self.library[artist]: self.album_select.addItem(album) self.load_all_songs() else: for album in self.library[current_artist]: self.album_select.addItem(album) self.load_all_from_artist(current_artist) def load_all_songs(self): for artist in self.library: for album in self.library[artist]: for song in self.library[artist][album]: self.song_select.addItem(song[0]) self.playlist.addMedia( QMediaContent(QtCore.QUrl.fromLocalFile(song[1]))) def load_all_from_artist(self, artist): for album in self.library[artist]: for song in self.library[artist][album]: self.song_select.addItem(song[0]) self.playlist.addMedia( QMediaContent(QtCore.QUrl.fromLocalFile(song[1]))) def on_album_selection(self): current_artist = self.artist_select.currentText() current_album = self.album_select.currentText() self.song_select.clear() self.playlist.clear() self.btn_play_pause.setText("Play") if current_album == "All Albums" and current_artist == "All Artists": self.load_all_songs() elif current_album == "All Albums": self.load_all_from_artist(current_artist) elif current_artist == "All Artists": for artist in self.library: for album in self.library[artist]: if album == self.album_select.currentText(): for song in self.library[artist][album]: self.song_select.addItem(song[0]) self.playlist.addMedia( QMediaContent( QtCore.QUrl.fromLocalFile(song[1]))) else: for song in self.library[current_artist][current_album]: self.song_select.addItem(song[0]) self.playlist.addMedia( QMediaContent(QtCore.QUrl.fromLocalFile(song[1]))) def on_song_selection(self): index = self.song_select.currentIndex() self.playlist.setCurrentIndex(index) # GETTING THE CURRENT SONG METADATA # Returns a SONG OBJECT and not the current song title # For the title of the currently playing song use get_current_title() def get_current_song(self): curr_url = self.playlist.currentMedia().canonicalUrl().toString()[8:] if curr_url: return LibraryLoader.create_song(curr_url) def get_current_artist(self): if self.get_current_song() is not None: return self.get_current_song().artist def get_current_album(self): if self.get_current_song() is not None: return self.get_current_song().album def get_current_path(self): if self.get_current_song() is not None: return self.get_current_song().path def get_current_album_path(self): if self.get_current_path() is not None: return self.get_current_path().rsplit("/", 1)[0] def get_current_title(self): if self.get_current_song() is not None: return self.get_current_song().name def on_lyrics(self): if self.get_current_song() is not None: curr_artist = self.get_current_artist() curr_song = self.get_current_title() found_lyrics = RequestLyrics.search_song_lyrics( curr_artist, curr_song) choice = QtWidgets.QMessageBox.question( self, "Lyrics", found_lyrics[0], QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if choice == QtWidgets.QMessageBox.Yes: webbrowser.open(found_lyrics[1]) else: QtWidgets.QMessageBox.information( self, "Lyrics", "No lyrics found or no media is loaded!") def on_album_info(self): album = self.get_current_album() artist = self.get_current_artist() if (album is None) or (artist is None): print("Please, load a song first!") else: artist_info, album_info = AlbumArtwork.album_artist_info( artist, album) if album_info is not None: webbrowser.open(album_info) def on_artist_info(self): album = self.get_current_album() artist = self.get_current_artist() if (album is None) or (artist is None): print("Please, load a song first!") else: artist_info, album_info = AlbumArtwork.album_artist_info( artist, album) if artist_info is not None: webbrowser.open(artist_info) def on_btn_play_pause(self): if self.player.state() in (0, 2): self.player.play() if self.player.state() == 1: self.btn_play_pause.setText("Pause") else: self.player.pause() self.btn_play_pause.setText("Play") def on_btn_next(self): self.player.playlist().next() def on_btn_prev(self): self.player.playlist().previous() def on_dur_change(self, length): self.slider_progress.setMaximum(length) def on_pos_change(self, position): self.slider_progress.setValue(position) def volume_change(self): volume = self.slider_volume.value() self.player.setVolume(volume) def progress_change(self): position = self.slider_progress.value() self.player.setPosition(position) def meta_data_changed(self): now_playing = self.get_current_title() self.current_media_label.setText("Now Playing: " + now_playing) # Updating the currently playing album cover curr_album_path = self.get_current_album_path() curr_album = self.get_current_album() curr_artist = self.get_current_artist() cover_url = AlbumArtwork.album_cover( curr_album_path, curr_artist, curr_album) self.current_album_cover.setPixmap(QPixmap(cover_url)) Scrobbler.scrobble(self.get_current_artist(), self.get_current_title())
class NewProject(QtWidgets.QWidget, Ui_NewProject): def __init__(self,projectfile,MainWidget): QtWidgets.QWidget.__init__(self) self.setupUi(self) self.setWindowFlags(Qt.WindowStaysOnTopHint) self.Main = MainWidget self.iface = self.Main.iface self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) self.replayPlay_pushButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) if projectfile.split('.')[-1] =="vgp": self.projectfile = projectfile else: self.projectfile = projectfile +'.vgp' self.videofile = None self.GPXfile = None self.GPXList = None self.fps = None self.RealFps = None self.DB = None self.player = QMediaPlayer() self.player.setVideoOutput(self.video_frame_2) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.stateChanged.connect(self.mediaStateChanged) self.toolButton_3.clicked.connect(self.ManageDB) self.pushButton_2.clicked.connect(self.Synchronize) self.pushButton.clicked.connect(self.SelectVideoGPX) self.replayPlay_pushButton.clicked.connect(self.PlayPause) self.muteButton.clicked.connect(self.MuteUnmute) self.horizontalSlider.sliderMoved.connect(self.setPosition) self.toolButton.clicked.connect(self.SkipBackward) self.toolButton_2.clicked.connect(self.SkipForward) self.SkipBacktoolButton_7.clicked.connect(self.BackwardFrame) self.SkipFortoolButton_8.clicked.connect(self.ForwardFrame) def closeEvent(self, *args, **kwargs): self.player.stop() return QtWidgets.QWidget.closeEvent(self, *args, **kwargs) def mediaStateChanged(self, state): if self.player.state() == QMediaPlayer.PlayingState: self.replayPlay_pushButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.replayPlay_pushButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def Synchronize(self): TimeItem = self.comboBox.currentIndex() duration = self.player.duration() position = self.player.position() VideoPartLen = round((duration-position) / 1000) GpxPartition = self.GPXList[TimeItem:VideoPartLen+TimeItem] outputFile = open(self.projectfile ,'w') if self.DB == None: outputFile.write('VideoGis Project v0.1 DO NOT MODIFY'+ '\nVideo file location = ' +self.videofile+ '\nVideo start at msecond: '+ str(self.player.position())+ ' #fps = '+str(self.RealFps)+ '\nDB = None'+ '\n'+'Latitude # Longitude # Ele # Speed (m/s) # Course # Time \n') else: outputFile.write('Video file location = ' +self.videofile+ '\nVideo start at msecond: '+ str(self.player.position())+ ' #fps = '+str(self.RealFps)+ '\nDB = '+str(self.DB.dataProvider().dataSourceUri().split('|')[0])+ '\n'+'Latitude # Longitude # Ele # Speed (m/s) # Course # Time \n') Counter = 0 for x in GpxPartition: if Counter != 0: ActualLatitude = x[1][0] ActualLongitude = x[1][1] PreviousLatitude = GpxPartition[Counter-1][1][0] PreviousLongitude = GpxPartition[Counter-1][1][1] GeodesicCalcolus = Geodesic.WGS84.Inverse(PreviousLatitude, PreviousLongitude, ActualLatitude, ActualLongitude) Speed = GeodesicCalcolus['s12'] /1 Course = GeodesicCalcolus['azi2'] if Course < 0: Course += 360 Ele = x[1][2] Time = x[1][3] Counter = Counter + 1 else: ActualLatitude = x[1][0] ActualLongitude = x[1][1] PreviousLatitude = GpxPartition[Counter+1][1][0] PreviousLongitude = GpxPartition[Counter+1][1][1] GeodesicCalcolus = Geodesic.WGS84.Inverse(ActualLatitude, ActualLongitude, PreviousLatitude, PreviousLongitude) Speed = GeodesicCalcolus['s12'] * 1 Course = GeodesicCalcolus['azi2'] if Course < 0: Course += 360 Ele = x[1][2] Time = x[1][3] Counter = Counter + 1 outputFile.write(str(ActualLatitude)+' '+str(ActualLongitude)+' '+str(Ele)+' '+str(Speed)+' '+str(Course)+' '+str(Time)+'\n') outputFile.close() self.Main.LoadProjFromNew(self.projectfile) if os.name == 'nt': os.remove (self.tmp) self.close() def SelectVideoGPX(self): if os.name == 'nt': ffmpeg = os.path.dirname(__file__)+'/FFMPEG/ffmpeg.exe' versione = 'ffmpeg.exe' else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' versione = 'ffmpeg' if os.path.exists(ffmpeg) == True: self.comboBox.clear() if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() self.videofile = None self.GPXfile = None options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog self.videofile, _ = QFileDialog.getOpenFileName(self,"Select Video File", "","All Files (*);;Video File (*.mp4 *.avi *.ogv)", options=options) if self.videofile: self.GPXfile, _ = QFileDialog.getOpenFileName(self,"Select GPX file", "","All Files (*);;Video File (*.gpx)", options=options) if self.GPXfile: self.ParseGpx(self.GPXfile) self.LoadVideo(self.videofile) self.replayPosition_label.setText( "-:- / -:-") else: ret = QMessageBox.warning(self, "Warning", 'missing ffmpeg binaries, please download it from https://github.com/sagost/VideoUavTracker/blob/master/FFMPEG/'+versione+' and paste it in /.qgis3/python/plugins/Video_UAV_Tracker/FFMPEG/ ', QMessageBox.Ok) self.close() def ParseGpx(self,GPXfile): gpx = parse(GPXfile) track = gpx.getElementsByTagName("trkpt") GPXList = [] Error = 0 GpxProgressiveNumber = 0 Timestamp = 'Segnaposto' for name in track: dict = {'Lat': 0, 'Lon': 0, 'Ele': 0, 'Time':0} a = (name.toprettyxml(indent = '') ).split() for x in a: if x.find('lat') == 0: lat = float(x.split('"')[1]) dict['Lat'] = float(x.split('"')[1]) elif x.find('lon') == 0: lon = float(x.split('"')[1]) dict['Lon'] = float(x.split('"')[1]) elif x.find('<ele>') == 0: dict['Ele'] = float(x[5:-6]) elif x.find('<time>') == 0: try: gpxtime = time.strftime('%Y-%m-%dT%H:%M:%S.%fZ',time.strptime(x[6:-7], '%Y-%m-%dT%H:%M:%S.%fZ')) dict['Time']= x[6:-7] except ValueError: try: gpxtime = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.strptime(x[6:-7],'%Y-%m-%dT%H:%M:%SZ')) dict['Time']= x[6:-7] except ValueError: try: gpxtime = time.strftime('%Y-%m-%dT%H:%M:%S',time.strptime(x[6:-7],'%Y-%m-%dT%H:%M:%S')) dict['Time']= x[6:-7] except ValueError: try: gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-7],'%Y-%m-%dT%H.%M.%S')) dict['Time']= x[6:-7] except ValueError: try: gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-13],'%Y-%m-%dT%H.%M.%S')) dict['Time']= x[6:-13] except ValueError: try: gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-13],'%Y-%m-%dT%H:%M:%S')) dict['Time']= x[6:-13] except ValueError: Error = 1 FormatoErrore = str(x) if dict['Time'] != Timestamp: Point = [dict['Lat'],dict['Lon'],dict['Ele'],dict['Time']] self.comboBox.addItem(str(GpxProgressiveNumber) + '-'+gpxtime ) GPXList.append([GpxProgressiveNumber,Point]) GpxProgressiveNumber = GpxProgressiveNumber + 1 Timestamp = dict['Time'] else: Timestamp = dict['Time'] if Error == 0: self.GPXList = GPXList else: ret = QMessageBox.warning(self, "Warning", FormatoErrore +' UNKOWN GPX TIME FORMAT - ABORTED', QMessageBox.Ok) self.close def LoadVideo(self,videofile): fps = self.getVideoDetails(str(videofile)) self.RealFps = float(fps) self.fps = (1 / self.RealFps )*1000 url = QUrl.fromLocalFile(str(self.videofile)) mc = QMediaContent(url) self.player.setMedia(mc) self.player.play() def setPosition(self, position): self.player.setPosition(position*1000) def durationChanged(self, duration): duration /= 1000 self.horizontalSlider.setMaximum(duration) def secTotime(self,seconds): m, s = divmod(seconds, 60) h, m = divmod(m, 60) return "%d:%02d:%02d" % (h, m, s) def positionChanged(self, progress): duration = self.player.duration() totalTime = self.secTotime(duration/1000) actualTime = self.secTotime(progress/1000) self.replayPosition_label.setText(actualTime + ' / '+totalTime) progress /= 1000 if not self.horizontalSlider.isSliderDown(): self.horizontalSlider.setValue(progress) def MuteUnmute(self): if self.player.mediaStatus() == 6 : if self.player.isMuted() == 1: self.player.setMuted(0) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) elif self.player.isMuted() == 0: self.player.setMuted(1) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolumeMuted)) def PlayPause(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() else: self.player.play() def getVideoDetails(self,filepath): if os.name == 'nt': tmp = os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/tmp' tmp2 = '"'+tmp+'"' filepath2 = '"'+filepath+'"' a = open(tmp,'w') a.close() ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"' a = os.popen(str(ffmpeg + ' -i '+filepath2+' 2> '+tmp2)) while os.stat(tmp).st_size < 1500: pass a = open(tmp,'r') lines = a.readlines() a.close() for l in lines: l = l.strip() if str(l).startswith("Stream #0:0"): linea = str(l).split(',')[-4] dopo = linea.find('fps') fps = float(linea[0:dopo]) self.tmp = tmp return fps else: tmpf = tempfile.NamedTemporaryFile() ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' os.system(str(ffmpeg)+" -i \"%s\" 2> %s" % (filepath, tmpf.name)) lines = tmpf.readlines() tmpf.close() for l in lines: l = l.strip() if str(l).startswith("b'Stream #0:0"): linea = str(l).split(',')[-4] dopo = linea.find('fps') fps = float(linea[0:dopo]) return fps def SkipForward(self): position = self.player.position() self.player.setPosition(position+1000) def SkipBackward(self): position = self.player.position() self.player.setPosition(position-1000) def ForwardFrame(self): position = self.player.position() self.player.setPosition(position+int(self.fps)) def BackwardFrame(self): position = self.player.position() self.player.setPosition(position-int(self.fps)) def ManageDB(self): self.player.pause() shapeFileFirst,_ = QFileDialog.getSaveFileName(caption = 'Save shape file', filter = "Esri shp (*.shp)") if shapeFileFirst: if shapeFileFirst.split('.')[-1] == 'shp': shapeFile = shapeFileFirst else: shapeFile = shapeFileFirst + '.shp' try: os.remove(shapeFile) os.remove(shapeFileFirst.split('.')[0]+'.qpg') os.remove(shapeFileFirst.split('.')[0]+'.prj') os.remove(shapeFileFirst.split('.')[0]+'.cpg') os.remove(shapeFileFirst.split('.')[0]+'.shx') os.remove(shapeFileFirst.split('.')[0]+'.dbf') except OSError: pass crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId) fields = QgsFields() QgsVectorFileWriter(shapeFile, "CP1250", fields, QgsWkbTypes.Point, crs, "ESRI Shapefile") EmptyLayer = QgsVectorLayer(shapeFile, shapeFile.split('.')[0].split('/')[-1], 'ogr') self.dialoga = TableManager(self.iface, EmptyLayer,self) self.dialoga.exec_() def AcceptNewDB(self,DB): self.DB = DB
class Player(QWidget): audio_path = "audio" lyrics_path = "lyrics" timings_path = os.path.join("lyrics", "timing") settings_path = "settings.json" fullScreenChanged = pyqtSignal(bool) def __init__(self, parent=None): super(Player, self).__init__(parent) self.setWindowTitle("SongScreen") self.setFocusPolicy(Qt.StrongFocus) self.colorDialog = None self.trackInfo = "" self.statusInfo = "" self.duration = 0 self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) # self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) # self.videoWidget = VideoWidget() # self.player.setVideoOutput(self.videoWidget) self.slider = MediaProgressWidget() # QSlider(Qt.Horizontal) self.markers = [] self.songtext_widget = SongTextWidget() self.songtext_widget.show() # self.playlistModel = PlaylistModel() # self.playlistModel.setPlaylist(self.playlist) # # self.playlistView = QListView() # self.playlistView.setModel(self.playlistModel) # self.playlistView.setCurrentIndex( # self.playlistModel.index(self.playlist.currentIndex(), 0)) # # self.playlistView.activated.connect(self.jump) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = QLabel() self.slider.sliderMoved.connect(self.seek) # openButton = QPushButton("Open", clicked=self.open) controls = PlayerControlsWidget() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) # controls.setMuted(controls.isMuted()) controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.stop_clicked) # controls.stop.connect(self.videoWidget.update) # controls.next.connect(self.playlist.next) # controls.previous.connect(self.previousClicked) controls.changeVolume.connect(self.player.setVolume) # controls.changeMuting.connect(self.player.setMuted) # controls.changeRate.connect(self.player.setPlaybackRate) self.player.stateChanged.connect(controls.setState) self.player.stateChanged.connect(self.setState) self.player.volumeChanged.connect(controls.setVolume) # self.player.mutedChanged.connect(controls.setMuted) # self.fullScreenButton = QPushButton("FullScreen") # self.fullScreenButton.setCheckable(True) # # self.colorButton = QPushButton("Color Options...") # self.colorButton.setEnabled(False) # self.colorButton.clicked.connect(self.showColorDialog) displayLayout = QHBoxLayout() # displayLayout.addWidget(self.videoWidget, 2) # displayLayout.addWidget(self.songtext_widget) # displayLayout.addWidget(self.playlistView) self.song_select_widget = SongSelectWidget() self.song_select_widget.song_selected.connect(self.load_song) self.screen_select_widget = ScreenSelectWidget() self.screen_select_widget.screen_selected.connect(self.display_lyrics_on_screen) self.screen_select_widget.active_screen = QApplication.desktop().screenNumber(self.songtext_widget) self.settings_button = QPushButton() self.settings_button.setText(self.tr("Settings...")) self.settings_button.clicked.connect(self.show_settings) sidebarLayout = QVBoxLayout() sidebarLayout.setContentsMargins(10, 1, 0, 1); sidebarLayout.addWidget(self.settings_button) sidebarLayout.addStretch(1); sidebarLayout.addWidget(self.screen_select_widget) displayLayout.addWidget(self.song_select_widget) displayLayout.addLayout(sidebarLayout) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) # controlLayout.addWidget(openButton) # controlLayout.addStretch(1) controlLayout.addWidget(controls) controlLayout.addStretch(1) controlLayout.addWidget(self.labelDuration) # controlLayout.addWidget(self.fullScreenButton) # controlLayout.addWidget(self.colorButton) layout = QVBoxLayout() layout.addLayout(displayLayout) hLayout = QHBoxLayout() hLayout.addWidget(self.slider) # hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) self.setLayout(layout) if not self.player.isAvailable(): QMessageBox.warning(self, "Service not available", "The QMediaPlayer object does not have a valid service.\n" "Please check the media service plugins are installed.") controls.setEnabled(False) self.playlistView.setEnabled(False) # openButton.setEnabled(False) self.colorButton.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self._loading_audio = False self._finished_song = False self._lyrics_fading = False self._song_number = -1 self.settings = { 'font_size': 40, 'line_increment': 2, 'lyrics_language': '', } self._load_settings() self.settings_widget = SettingsWidget(self.settings, self.lyrics_path) self.settings_widget.font_size_changed.connect(self.songtext_widget.set_font_size) self.settings_widget.line_increment_changed.connect(self.songtext_widget.set_line_increment) self.settings_widget.language_changed.connect(self._language_changed) self.song_select_widget.reset(self.available_song_numbers) @property def lyrics_language_path(self): path = QStandardPaths.locate(QStandardPaths.AppDataLocation, self.lyrics_path, QStandardPaths.LocateDirectory) return os.path.join(path, self.settings['lyrics_language']) @property def available_song_numbers(self): audios = set( [int(os.path.splitext(filename)[0]) for filename in os.listdir(self.audio_path) if filename[0] != '.']) try: lyrics = set( [int(os.path.splitext(filename)[0]) for filename in os.listdir(self.lyrics_language_path) if filename[0] != '.'] ) except (ValueError, FileNotFoundError): lyrics = set() return sorted(list(audios.intersection(lyrics))) def show_settings(self): self.settings_widget.hide() self.settings_widget.show() def display_lyrics_on_screen(self, screen_number): desktop = QApplication.desktop() if screen_number >= desktop.screenCount(): screen_number = desktop.screenNumber(self) rect = desktop.availableGeometry(screen_number) for _ in range(3): if screen_number != desktop.screenNumber(self): self.songtext_widget.setWindowFlags(Qt.FramelessWindowHint) self.songtext_widget.hide() self.songtext_widget.move(rect.x(), rect.y()) self.songtext_widget.resize(rect.width(), rect.height()) self.songtext_widget.showFullScreen() else: self.songtext_widget.setWindowFlags(Qt.WindowTitleHint) self.songtext_widget.hide() self.songtext_widget.move(rect.x(), rect.y()) self.songtext_widget.resize(self.songtext_widget.minimumSize()) self.songtext_widget.show() self.screen_select_widget.active_screen = screen_number self.activateWindow() def load_song(self, song_number): if self._song_number == song_number: self.seek(0) else: if self._song_number > 0: self._save_timings() self._song_number = song_number self.slider.dirty = False self._load_audio() self._load_lyrics() # self.player.play() def _load_audio(self): filename = os.path.join(self.audio_path, "{:03}.mp3".format(self._song_number)) self.playlist.clear() fileInfo = QFileInfo(filename) if fileInfo.exists(): url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(QMediaContent(url)) self._loading_audio = True self.player.play() def _load_lyrics(self): with open(os.path.join(self.lyrics_language_path, "{}.json".format(self._song_number)), 'r') as f: song_markers = json.load(f) self.markers = [] for m in song_markers['markers']: marker = MediaMarker(self.slider, m['name']) marker.text = m['text'] marker.progress = 0.0 self.markers.append(marker) self.songtext_widget.title = "{} {}".format(self._song_number, song_markers['title']) self.songtext_widget.markers = self.markers self.songtext_widget.fade_in() try: with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'r') as f: timings = json.load(f) for m, t in zip(self.markers, timings): m.progress = t except FileNotFoundError: pass self.slider.markers = self.markers def _language_changed(self, _): available_song_numbers = self.available_song_numbers self.song_select_widget.reset(available_song_numbers) if self._song_number in available_song_numbers: self._load_lyrics() # def open(self): # fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files") # self.addToPlaylist(fileNames) # # def addToPlaylist(self, fileNames): # for name in fileNames: # fileInfo = QFileInfo(name) # if fileInfo.exists(): # url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) # if fileInfo.suffix().lower() == 'm3u': # self.playlist.load(url) # else: # self.playlist.addMedia(QMediaContent(url)) # else: # url = QUrl(name) # if url.isValid(): # self.playlist.addMedia(QMediaContent(url)) def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) if self._loading_audio: self._loading_audio = False line_total = 0 for marker in self.markers: line_total += marker.linecount - 1 silence_ratio = 5.0 / self.duration offset = 1.8 / line_total linecount = 0 for marker in self.markers: if marker.progress == 0.0: marker.progress = offset + (1 - offset) * (1 - silence_ratio) * linecount / line_total linecount += marker.linecount - 1 self.player.pause() @property def _should_fade_out(self): return self.player.position() / 1000 >= self.duration - 5 def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) if self.duration > 0: # if self.player.state() == QMediaPlayer.PlayingState: self.songtext_widget.progress = progress / self.duration if self._should_fade_out: self._fade_out_lyrics() def _fade_out_lyrics(self): if not self._lyrics_fading: self._lyrics_fading = True self.songtext_widget.fade_out() def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo("%s - %s" % ( self.player.metaData(QMediaMetaData.AlbumArtist), self.player.metaData(QMediaMetaData.Title))) def previousClicked(self): # Go to the 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() else: self.player.setPosition(0) def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def seek(self, seconds): self.player.setPosition(seconds * 1000) def setState(self, status): if status == QMediaPlayer.StoppedState: self._finished_song = True elif status == QMediaPlayer.PlayingState: if self._finished_song or (self._lyrics_fading and not self._should_fade_out): self._finished_song = False self._lyrics_fading = False self.songtext_widget.fade_in() def stop_clicked(self): self.player.stop() self._fade_out_lyrics() def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo("Loading...") elif status == QMediaPlayer.StalledMedia: self.setStatusInfo("Media Stalled") elif status == QMediaPlayer.EndOfMedia: QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo("") def handleCursor(self, status): if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def bufferingProgress(self, progress): self.setStatusInfo("Buffering %d%" % progress) def videoAvailableChanged(self, available): if available: self.fullScreenButton.clicked.connect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.connect( self.fullScreenButton.setChecked) if self.fullScreenButton.isChecked(): self.videoWidget.setFullScreen(True) else: self.fullScreenButton.clicked.disconnect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.disconnect( self.fullScreenButton.setChecked) self.videoWidget.setFullScreen(False) self.colorButton.setEnabled(available) def setTrackInfo(self, info): self.trackInfo = info # if self.statusInfo != "": # self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) # else: # self.setWindowTitle(self.trackInfo) def setStatusInfo(self, info): self.statusInfo = info # if self.statusInfo != "": # self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) # else: # self.setWindowTitle(self.trackInfo) def displayErrorMessage(self): self.setStatusInfo(self.player.errorString()) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60, currentInfo % 60, (currentInfo * 1000) % 1000) totalTime = QTime((duration / 3600) % 60, (duration / 60) % 60, duration % 60, (duration * 1000) % 1000); format = 'hh:mm:ss' if duration > 3600 else 'mm:ss' tStr = currentTime.toString(format) + " / " + totalTime.toString(format) else: tStr = "" self.labelDuration.setText(tStr) def showColorDialog(self): if self.colorDialog is None: brightnessSlider = QSlider(Qt.Horizontal) brightnessSlider.setRange(-100, 100) brightnessSlider.setValue(self.videoWidget.brightness()) brightnessSlider.sliderMoved.connect( self.videoWidget.setBrightness) self.videoWidget.brightnessChanged.connect( brightnessSlider.setValue) contrastSlider = QSlider(Qt.Horizontal) contrastSlider.setRange(-100, 100) contrastSlider.setValue(self.videoWidget.contrast()) contrastSlider.sliderMoved.connect(self.videoWidget.setContrast) self.videoWidget.contrastChanged.connect(contrastSlider.setValue) hueSlider = QSlider(Qt.Horizontal) hueSlider.setRange(-100, 100) hueSlider.setValue(self.videoWidget.hue()) hueSlider.sliderMoved.connect(self.videoWidget.setHue) self.videoWidget.hueChanged.connect(hueSlider.setValue) saturationSlider = QSlider(Qt.Horizontal) saturationSlider.setRange(-100, 100) saturationSlider.setValue(self.videoWidget.saturation()) saturationSlider.sliderMoved.connect( self.videoWidget.setSaturation) self.videoWidget.saturationChanged.connect( saturationSlider.setValue) layout = QFormLayout() layout.addRow("Brightness", brightnessSlider) layout.addRow("Contrast", contrastSlider) layout.addRow("Hue", hueSlider) layout.addRow("Saturation", saturationSlider) button = QPushButton("Close") layout.addRow(button) self.colorDialog = QDialog(self) self.colorDialog.setWindowTitle("Color Options") self.colorDialog.setLayout(layout) button.clicked.connect(self.colorDialog.close) self.colorDialog.show() def closeEvent(self, close_event): self._save_timings() self._save_settings() self.songtext_widget.close() self.settings_widget.close() def keyPressEvent(self, key_event): if key_event.key() == Qt.Key_Space: key_event.accept() if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() elif self.player.state() in [QMediaPlayer.PausedState, QMediaPlayer.StoppedState]: self.player.play() elif key_event.key() == Qt.Key_M: key_event.accept() self.slider.set_closest_marker_to_current_progress() def _save_timings(self): if self.slider.dirty: with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'w') as f: json.dump([marker.progress for marker in self.markers], f, indent=2) def _save_settings(self): # TODO : refactor and use QSettings directly # with open(self.settings_path, 'w') as f: self.settings.update({ 'lyrics_screen': QApplication.desktop().screenNumber(self.songtext_widget), 'control_window_position': self.pos(), }) # json.dump(self.settings, f, indent=2) settings = QSettings("Maccesch", "SongScreen") for key, value in self.settings.items(): settings.setValue(key, value) def _load_settings(self): # try: # with open(self.settings_path, 'r') as f: # settings = json.load(f) settings = QSettings("Maccesch", "SongScreen") if settings.contains('lyrics_screen'): self.display_lyrics_on_screen(settings.value('lyrics_screen')) if settings.contains('control_window_position'): self.move(settings.value('control_window_position')) for key in settings.allKeys(): self.settings[key] = settings.value(key) # self.settings.update(settings) self.songtext_widget.set_font_size(self.settings['font_size']) self.songtext_widget.set_line_increment(self.settings['line_increment']) # except (FileNotFoundError, ValueError): # pass if not os.path.exists(self.lyrics_language_path) or not self.settings['lyrics_language']: languages = list( filter(lambda p: os.path.isdir(os.path.join(self.lyrics_path, p)) and p != "timings", os.listdir(self.lyrics_path)) ) self.settings['lyrics_language'] = languages[0] if languages else ""
class VideoPlayer(QWidget): def __init__(self): super().__init__() self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) btnSize = QSize(16, 16) videoWidget = QVideoWidget() openButton = QPushButton("Open Video") openButton.setToolTip("Open Video File") openButton.setStatusTip("Open Video File") openButton.setFixedHeight(24) openButton.setIconSize(btnSize) openButton.setFont(QFont("Noto Sans", 8)) openButton.setIcon( QIcon.fromTheme("document-open", QIcon("D:/_Qt/img/open.png"))) openButton.clicked.connect(self.abrir) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setFixedHeight(24) self.playButton.setIconSize(btnSize) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.statusBar = QStatusBar() self.statusBar.setFont(QFont("Noto Sans", 7)) self.statusBar.setFixedHeight(14) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.statusBar) self.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.statusBar.showMessage("Ready") self.video_name = None self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volumeUp) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volumeDown) self.video_id = None def abrir(self): fileName, _ = QFileDialog.getOpenFileName( self, "Selecciona los mediose", ".", "Video Files (*.mp4 *.flv *.ts *.mts *.avi)") if fileName != '': r = requests.post(POST_DATA_URL_VIDEO, json=dict(name=fileName)) self.video_id = int(r.text) self.video_name = os.path.basename(fileName) self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) self.statusBar.showMessage(fileName) self.play() def get_video_id(self): return self.video_id def pause_video(self): self.mediaPlayer.pause() def resume_video(self): self.mediaPlayer.play() def volumeUp(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10) print("Volume: " + str(self.mediaPlayer.volume())) def volumeDown(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10) print("Volume: " + str(self.mediaPlayer.volume())) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def is_paused(self): return not self.mediaPlayer.state() == QMediaPlayer.PlayingState def get_position(self): return self.mediaPlayer.position() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString())
class VideoPlayer(QVideoWidget): #doubleClicked = pyqtSignal() clicked = pyqtSignal() #keyPressed = pyqtSignal() #rtime_changed = pyqtSignal(str) #duration_changed = pyqtSignal(int) def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.playing = False self.full_screen = False self.media_player = QMediaPlayer() self.media_player.setVideoOutput(self) self.widescreen = True self.media_player.setVolume(0) def load_video(self, path): self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(path))) def play(self): if self.playing is False: self.media_player.play() self.playing = True else: self.media_player.pause() self.playing = False def stop(self): self.media_player.stop() self.playing = False def set_volume(self, volume): self.media_player.setVolume(volume) def mousePressEvent(self, event): #self.play() self.clicked.emit() super(VideoPlayer, self).mousePressEvent(event) def update_position(self, position): self.media_player.setPosition(position) def set_postion(self, position): self.media_player.setPosition(position) def mouseDoubleClickEvent(self, event): self.set_fullscreen() def set_fullscreen(self): self.setFullScreen(not self.isFullScreen()) def keyPressEvent(self, event): if event.key() == Qt.Qt.Key_Escape and self.isFullScreen(): self.setFullScreen(False) event.accept() else: super(VideoPlayer, self).keyPressEvent(event)
class VideoSortApp(QMainWindow, Ui_MainWindow, QWidget): def __init__(self): super(VideoSortApp, self).__init__() self.setupUi(self) self.filename = None self.directory = None self.sort.setEnabled(False) self.fileOpen.clicked.connect(self.fileDialog) self.dirOpen.clicked.connect(self.folderDialog) self.sort.clicked.connect(self.sortVideo) self.results.setViewMode(self.results.IconMode) self.results.setResizeMode(self.results.Adjust) self.features = [] self.sorted = None #player properties self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.playlist = QMediaPlaylist(self.player) self.videoItem = QGraphicsVideoItem() self.videoItem.setSize(QtCore.QSizeF(640, 480)) scene = QGraphicsScene(self) scene.addItem(self.videoItem) self.graphicsView.setScene(scene) self.player.setVideoOutput(self.videoItem) self.graphicsView.resize(640,480) self.graphicsView.show() self.results.itemDoubleClicked.connect(self.seekVideo) self.videoLoaded = False def sizeHint(self): return QtCore.QSize(640,480) def fileDialog(self): dialog = QFileDialog() if dialog.getOpenFileName: self.filename = dialog.getOpenFileName()[0] self.sort.setEnabled(True) def folderDialog(self): dialog = QFileDialog() if dialog.getExistingDirectory: self.directory = dialog.getExistingDirectory() self.sort.setEnabled(True) def sortVideo(self): dialog = QFileDialog() folder = dialog.getExistingDirectory(self, 'Select output directory for thumbnail images') if folder: if self.filename: self.getThread = VideoSort(self.filename, folder, 'frame') #self.results.setIconSize(QtCore.QSize(self.getThread.thumbInfo['resolution'][0], self.getThread.thumbInfo['resolution'][1])) #slot self.getThread.resultsSignal.connect(self.setFeatures) self.getThread.start() self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(self.filename))) self.currentMedia = self.filename if self.directory: formatList = ['.mp4', '.mov', '.mkv', '.avi'] for dirname, dirnames, filenames in os.walk(self.directory): supportedFiles = [os.path.abspath(os.path.join(dirname, path)) for path in filenames if os.path.splitext(path)[1] in formatList] for filename in supportedFiles: self.getThread = VideoSort(filename, folder, os.path.splitext(filename.split('/')[-1])[0]) self.getThread.resultsSignal.connect(self.setFeatures) self.getThread.start() self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(filename))) #Just set the last file as the current file self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(filename))) self.currentMedia = filename def setFeatures(self, features): for feature in features: self.features.append(feature) self.hue.toggled.connect(self.displayResults) self.saturation.toggled.connect(self.displayResults) self.contours.toggled.connect(self.displayResults) def displayResults(self): self.results.clear() if self.hue.isChecked(): sortedFeatures = sorted(self.features, key=lambda res: res['hue']['std'], reverse=False) self.sorted = True if self.saturation.isChecked(): sortedFeatures = sorted(self.features, key=lambda res: res['sat']['std'], reverse=False) self.sorted = True if self.contours.isChecked(): sortedFeatures = sorted(self.features, key=lambda res: res['contours']['area'], reverse=False) self.sorted = True if self.sorted: for feature in sortedFeatures: icon = QtGui.QIcon(feature['thumbnail']) item = VideoListItem(icon, feature) self.results.addItem(item) def seekVideo(self, Qitem): #Need to write a callback function to only seek once player is loaded - provide loading media graphic or progress bar self.player.stop() print self.player.mediaStatus() if Qitem.feature['video'] != self.currentMedia: self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(Qitem.feature['video']))) self.videoLoadProgress(self.player) self.currentMedia = Qitem.feature['video'] else: self.videoLoaded = True if self.videoLoaded: self.player.setPosition(Qitem.feature['milliseconds']) self.player.play() else: #set up progress bar here, or loading text def videoLoadProgress(self, QMediaPlayerObject): self.videoStatus = VideoLoadStatus(QMediaPlayerObject) self.videoStatus.videoLoaded.connect(self.getVideoStatus) def getVideoStatus(self, status): self.status = status
class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("PyQt5 Media Player") self.setGeometry(350, 100, 700, 500) self.setWindowIcon(QIcon('player.png')) #p =self.palette() #p.setColor(QPalette.Window, Qt.black) #self.setPalette(p) #self.clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #self.clientsocket.connect(('192.168.0.47',2000)) milli_sec = int(round(time.time() * 1000)) print(milli_sec) self.timer = QTimer() self.timer.timeout.connect(self.viewCam) fourcc = cv2.VideoWriter_fourcc(*'XVID') self.out = cv2.VideoWriter( 'C:/Users/brahm/OneDrive/Desktop/webcam/' + str(milli_sec) + '.mp4', fourcc, 30.0, (640, 480)) self.init_ui() self.show() def init_ui(self): #create media player object #canvas = Bar(self, width=9, height=4) #canvas.move(0, 0) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) #create videowidget object videowidget = QVideoWidget() #self.mediaPlayer.setVideoOutput(videowidget) #create open button openBtn = QPushButton('Open Video') openBtn.clicked.connect(self.open_file) self.videobutton = QPushButton('start') self.videobutton.clicked.connect(self.record) #create button for playing self.playBtn = QPushButton() #self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.clicked.connect(self.play_video) #create slider self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 0) self.slider.sliderMoved.connect(self.set_position) #create label self.label = QLabel() self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) #create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) #set widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.videobutton) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.slider) #create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addWidget(videowidget) vboxLayout.addLayout(hboxLayout) vboxLayout.addWidget(self.label) self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videowidget) #media player signals self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) self.mediaPlayer.error.connect(self.handle_errors) self.label.setText("Ready") self.mediaPlayer.setMedia( QMediaContent( QUrl.fromLocalFile( "C:/Users/brahm/OneDrive/Desktop/face exp node/రాష్ట్రపతి పాలన ఎప్పుడు, ఎందుకు విధిస్తారు_ ఆర్టికల్ 356 ఏం చెబుతోంది_ - BBC New.wmv" ))) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Video") if filename != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) print(filename, "file") def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() print(self.mediaPlayer.state(), "00000") else: self.mediaPlayer.play() print('mediaStatus: ' + str(self.mediaPlayer.mediaStatus())) print(self.mediaPlayer.state(), "2222") print(QMediaPlayer.PlayingState, "3333") def mediastate_changed(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def position_changed(self, position): self.slider.setValue(position) def duration_changed(self, duration): self.slider.setRange(0, duration) def set_position(self, position): self.mediaPlayer.setPosition(position) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText("Error: " + self.mediaPlayer.errorString()) print(self.mediaPlayer.error, 'error') print('mediaStatus: ' + str(self.mediaPlayer.mediaStatus())) print('error: ' + str(self.mediaPlayer.error())) def viewCam(self): # read image in BGR format ret, image = self.cap.read() encoded, buffer = cv2.imencode('.jpg', image) jpg_as_text = base64.b64encode(buffer) print("jpg_as_text", jpg_as_text) #print("buffer", buffer) #data = {'name': image} #resp = req.post("https://httpbin.org/post", data) #print(resp.text) #data = pickle.dumps(image) #print("data", data) #self.clientsocket.sendall(struct.pack("H", len(data))+data) self.out.write(image) # convert image to RGB format def record(self): if not self.timer.isActive(): self.cap = cv2.VideoCapture(0) self.timer.start() self.videobutton.setText("Stop") else: self.timer.stop() self.cap.release() print("data", self.out) self.out.release() # update control_bt text self.videobutton.setText("Start")
class VideoPlayer(QWidget): def __init__(self,aPath=None): super(VideoPlayer, self).__init__() self.setAttribute( Qt.WA_NoSystemBackground, True ) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVolume(80) self.videoWidget = QVideoWidget(self) self.lbl = QLineEdit('00:00:00') self.lbl.setFixedWidth(60) self.lbl.setUpdatesEnabled(True) self.lbl.setStyleSheet(stylesheet(self)) self.elbl = QLineEdit('00:00:00') self.elbl.setFixedWidth(60) self.elbl.setUpdatesEnabled(True) self.elbl.setStyleSheet(stylesheet(self)) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setFixedWidth(32) self.playButton.setStyleSheet("background-color: black") self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal, self) self.positionSlider.setStyleSheet (stylesheet(self)) self.positionSlider.setRange(0, 100) self.positionSlider.sliderMoved.connect(self.setPosition) self.positionSlider.sliderMoved.connect(self.handleLabel) self.positionSlider.setSingleStep(2) self.positionSlider.setPageStep(20) self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(5, 0, 5, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.lbl) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.elbl) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.videoWidget) layout.addLayout(controlLayout) self.setLayout(layout) self.myinfo = "nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \ "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \ "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes" self.widescreen = True if aPath is not None: self.loadFilm(aPath) #### shortcuts #### self.shortcut = QShortcut(QKeySequence("q"), self) self.shortcut.activated.connect(self.handleQuit) self.shortcut = QShortcut(QKeySequence("o"), self) self.shortcut.activated.connect(self.openFile) self.shortcut = QShortcut(QKeySequence(" "), self) self.shortcut.activated.connect(self.play) self.shortcut = QShortcut(QKeySequence("f"), self) self.shortcut.activated.connect(self.handleFullscreen) self.shortcut = QShortcut(QKeySequence("i"), self) self.shortcut.activated.connect(self.handleInfo) self.shortcut = QShortcut(QKeySequence("s"), self) self.shortcut.activated.connect(self.toggleSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self) self.shortcut.activated.connect(self.forwardSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self) self.shortcut.activated.connect(self.backSlider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volumeUp) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volumeDown) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Right) , self) self.shortcut.activated.connect(self.forwardSlider10) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left) , self) self.shortcut.activated.connect(self.backSlider10) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.positionChanged.connect(self.handleLabel) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) print("QT5 Player started") def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath(), "Videos (*.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v)") if fileName != '': self.loadFilm(fileName) print("File loaded") def playFromURL(self): self.mediaPlayer.pause() clip = QApplication.clipboard() myurl = clip.text() if myurl.startswith("http"): self.mediaPlayer.setMedia(QMediaContent(QUrl(myurl))) else: self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(myurl))) self.playButton.setEnabled(True) self.mediaPlayer.play() self.hideSlider() print(myurl) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) mtime = QTime(0,0,0,0) mtime = mtime.addMSecs(self.mediaPlayer.duration()) self.elbl.setText(mtime.toString()) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) print("Error: " + self.mediaPlayer.errorString()) def handleQuit(self): self.mediaPlayer.stop() print("Goodbye ...") app.quit() def contextMenuRequested(self,point): menu = QtWidgets.QMenu() actionFile = menu.addAction("open File (o)") actionclipboard = menu.addSeparator() actionURL = menu.addAction("URL / File from Clipboard (u)") actionclipboard = menu.addSeparator() actionToggle = menu.addAction("show / hide Slider (s)") actionFull = menu.addAction("Fullscreen (f)") action169 = menu.addAction("16 : 9") action43 = menu.addAction("4 : 3") actionSep = menu.addSeparator() actionInfo = menu.addAction("Info (i)") action5 = menu.addSeparator() actionQuit = menu.addAction("Exit (q)") actionFile.triggered.connect(self.openFile) actionQuit.triggered.connect(self.handleQuit) actionFull.triggered.connect(self.handleFullscreen) actionInfo.triggered.connect(self.handleInfo) actionToggle.triggered.connect(self.toggleSlider) actionURL.triggered.connect(self.playFromURL) action169.triggered.connect(self.screen169) action43.triggered.connect(self.screen43) menu.exec_(self.mapToGlobal(point)) def wheelEvent(self,event): mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mscale = event.angleDelta().y() / 5 if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth + mscale, (mwidth + mscale) / 1.778) else: self.setGeometry(mleft, mtop, mwidth + mscale, (mwidth + mscale) / 1.33) def screen169(self): self.widescreen = True mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.778 self.setGeometry(mleft, mtop, mwidth, mwidth / mratio) def screen43(self): self.widescreen = False mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() mratio = 1.33 self.setGeometry(mleft, mtop, mwidth, mwidth / mratio) def handleFullscreen(self): if self.windowState() & QtCore.Qt.WindowFullScreen: self.showNormal() print("no Fullscreen") else: self.showFullScreen() print("Fullscreen entered") def handleInfo(self): msg = QMessageBox() msg.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SplashScreen) msg.setGeometry(self.frameGeometry().left() + 30, self.frameGeometry().top() + 30, 300, 400) msg.setIcon(QMessageBox.Information) msg.setText("QT5 Player") msg.setInformativeText(self.myinfo) msg.setStandardButtons(QMessageBox.Close) #msg.exec() def toggleSlider(self): if self.positionSlider.isVisible(): self.hideSlider() else: self.showSlider() def hideSlider(self): self.playButton.hide() self.lbl.hide() self.positionSlider.hide() self.elbl.hide() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778) else: self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33) def showSlider(self): self.playButton.show() self.lbl.show() self.positionSlider.show() self.elbl.show() mwidth = self.frameGeometry().width() mheight = self.frameGeometry().height() mleft = self.frameGeometry().left() mtop = self.frameGeometry().top() if self.widescreen == True: self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55) else: self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33) def forwardSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000*60) def forwardSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000*60) def backSlider(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000*60) def backSlider10(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000*60) def volumeUp(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10) print("Volume: " + str(self.mediaPlayer.volume())) def volumeDown(self): self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10) print("Volume: " + str(self.mediaPlayer.volume())) def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: self.move(event.globalPos() \ - QPoint(self.frameGeometry().width() / 2, \ self.frameGeometry().height() / 2)) event.accept() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dropEvent(self, event): f = str(event.mimeData().urls()[0].toLocalFile()) self.loadFilm(f) def loadFilm(self, f): self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f))) self.playButton.setEnabled(True) self.mediaPlayer.play() print(self.mediaPlayer.media().canonicalResource().resolution()) def openFileAtStart(self, filelist): matching = [s for s in filelist if ".myformat" in s] if len(matching) > 0: self.loadFilm(matching) ##################### update Label ################################## def handleLabel(self): self.lbl.clear() mtime = QTime(0,0,0,0) self.time = mtime.addMSecs(self.mediaPlayer.position()) self.lbl.setText(self.time.toString())
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(772, 410) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.tabWidget.sizePolicy().hasHeightForWidth()) self.tabWidget.setSizePolicy(sizePolicy) self.tabWidget.setObjectName("tabWidget") self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.tab) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.labelip1 = QtWidgets.QLabel(self.tab) self.labelip1.setMinimumSize(QtCore.QSize(360, 240)) self.labelip1.setMaximumSize(QtCore.QSize(16777215, 500)) self.labelip1.setFrameShape(QtWidgets.QFrame.Box) self.labelip1.setScaledContents(True) self.labelip1.setObjectName("labelip1") self.verticalLayout_2.addWidget(self.labelip1) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.startbtn1 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.startbtn1.setFont(font) self.startbtn1.setObjectName("startbtn1") self.horizontalLayout.addWidget(self.startbtn1) self.prbtn1 = QtWidgets.QPushButton(self.tab) self.prbtn1.setMinimumSize(QtCore.QSize(100, 0)) font = QtGui.QFont() font.setPointSize(10) self.prbtn1.setFont(font) self.prbtn1.setObjectName("prbtn1") self.horizontalLayout.addWidget(self.prbtn1) self.frbtn1 = QtWidgets.QPushButton(self.tab) self.frbtn1.setMinimumSize(QtCore.QSize(150, 20)) font = QtGui.QFont() font.setPointSize(10) self.frbtn1.setFont(font) self.frbtn1.setObjectName("frbtn1") self.horizontalLayout.addWidget(self.frbtn1) self.verticalLayout_2.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.stopbtn1 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.stopbtn1.setFont(font) self.stopbtn1.setObjectName("stopbtn1") self.horizontalLayout_2.addWidget(self.stopbtn1) self.apbtn1 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.apbtn1.setFont(font) self.apbtn1.setObjectName("apbtn1") self.horizontalLayout_2.addWidget(self.apbtn1) self.fdbtn1 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.fdbtn1.setFont(font) self.fdbtn1.setObjectName("fdbtn1") self.horizontalLayout_2.addWidget(self.fdbtn1) self.verticalLayout_2.addLayout(self.horizontalLayout_2) self.verticalLayout_2.setStretch(0, 4) self.verticalLayout_2.setStretch(1, 1) self.verticalLayout_2.setStretch(2, 1) self.horizontalLayout_5.addLayout(self.verticalLayout_2) self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setObjectName("verticalLayout_3") self.labelip2 = QtWidgets.QLabel(self.tab) self.labelip2.setMinimumSize(QtCore.QSize(360, 240)) self.labelip2.setMaximumSize(QtCore.QSize(16777215, 500)) self.labelip2.setFrameShape(QtWidgets.QFrame.Box) self.labelip2.setScaledContents(True) self.labelip2.setObjectName("labelip2") self.verticalLayout_3.addWidget(self.labelip2) self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.startbtn2 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.startbtn2.setFont(font) self.startbtn2.setObjectName("startbtn2") self.horizontalLayout_3.addWidget(self.startbtn2) self.prbtn2 = QtWidgets.QPushButton(self.tab) self.prbtn2.setMinimumSize(QtCore.QSize(100, 0)) font = QtGui.QFont() font.setPointSize(10) self.prbtn2.setFont(font) self.prbtn2.setObjectName("prbtn2") self.horizontalLayout_3.addWidget(self.prbtn2) self.frbtn2 = QtWidgets.QPushButton(self.tab) self.frbtn2.setMinimumSize(QtCore.QSize(150, 0)) font = QtGui.QFont() font.setPointSize(10) self.frbtn2.setFont(font) self.frbtn2.setObjectName("frbtn2") self.horizontalLayout_3.addWidget(self.frbtn2) self.verticalLayout_3.addLayout(self.horizontalLayout_3) self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.stopbtn2 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.stopbtn2.setFont(font) self.stopbtn2.setObjectName("stopbtn2") self.horizontalLayout_4.addWidget(self.stopbtn2) self.apbtn2 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.apbtn2.setFont(font) self.apbtn2.setObjectName("apbtn2") self.horizontalLayout_4.addWidget(self.apbtn2) self.fdbtn2 = QtWidgets.QPushButton(self.tab) font = QtGui.QFont() font.setPointSize(10) self.fdbtn2.setFont(font) self.fdbtn2.setObjectName("fdbtn2") self.horizontalLayout_4.addWidget(self.fdbtn2) self.verticalLayout_3.addLayout(self.horizontalLayout_4) self.verticalLayout_3.setStretch(0, 4) self.verticalLayout_3.setStretch(1, 1) self.verticalLayout_3.setStretch(2, 1) self.horizontalLayout_5.addLayout(self.verticalLayout_3) self.tabWidget.addTab(self.tab, "") self.tab2 = QtWidgets.QWidget() self.tab2.setObjectName("tab2") self.videoslider = QtWidgets.QSlider(self.tab2) self.videoslider.setGeometry(QtCore.QRect(540, 20, 160, 22)) self.videoslider.setOrientation(QtCore.Qt.Horizontal) self.videoslider.setObjectName("videoslider") self.open = QtWidgets.QPushButton(self.tab2) self.open.setGeometry(QtCore.QRect(11, 17, 75, 26)) font = QtGui.QFont() font.setPointSize(11) self.open.setFont(font) self.open.setObjectName("open") self.stop = QtWidgets.QPushButton(self.tab2) self.stop.setGeometry(QtCore.QRect(92, 11, 42, 38)) self.stop.setText("") icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/icons/syop.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.stop.setIcon(icon) self.stop.setIconSize(QtCore.QSize(30, 30)) self.stop.setObjectName("stop") self.prev = QtWidgets.QPushButton(self.tab2) self.prev.setGeometry(QtCore.QRect(140, 11, 42, 38)) self.prev.setText("") icon1 = QtGui.QIcon() icon1.addPixmap(QtGui.QPixmap(":/icons/back.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.prev.setIcon(icon1) self.prev.setIconSize(QtCore.QSize(30, 30)) self.prev.setObjectName("prev") self.start = QtWidgets.QPushButton(self.tab2) self.start.setGeometry(QtCore.QRect(188, 11, 42, 38)) self.start.setText("") global icon2, icon5 icon2 = QtGui.QIcon() icon5 = QtGui.QIcon() icon2.addPixmap(QtGui.QPixmap(":/icons/play.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon5.addPixmap(QtGui.QPixmap(":/icons/pause.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.start.setIcon(icon2) self.start.setIconSize(QtCore.QSize(30, 30)) self.start.setObjectName("start") self.next = QtWidgets.QPushButton(self.tab2) self.next.setGeometry(QtCore.QRect(236, 11, 42, 38)) self.next.setText("") icon3 = QtGui.QIcon() icon3.addPixmap(QtGui.QPixmap(":/icons/forward.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.next.setIcon(icon3) self.next.setIconSize(QtCore.QSize(30, 30)) self.next.setObjectName("next") self.sound = QtWidgets.QPushButton(self.tab2) self.sound.setGeometry(QtCore.QRect(284, 11, 42, 38)) self.sound.setText("") icon4 = QtGui.QIcon() icon4.addPixmap( QtGui.QPixmap( ":/icons/audio-icon-music-icon-sound-icon-speaker-icon-volume-icon-logo-symbol-png-clip-art.png" ), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.sound.setIcon(icon4) self.sound.setIconSize(QtCore.QSize(30, 30)) self.sound.setObjectName("sound") self.volslider = QtWidgets.QSlider(self.tab2) self.volslider.setGeometry(QtCore.QRect(332, 19, 84, 22)) self.volslider.setOrientation(QtCore.Qt.Horizontal) self.volslider.setObjectName("volslider") self.fsbtn = QtWidgets.QPushButton(self.tab2) self.fsbtn.setGeometry(QtCore.QRect(422, 17, 77, 26)) font = QtGui.QFont() font.setPointSize(11) self.fsbtn.setFont(font) self.fsbtn.setObjectName("fsbtn") self.tabWidget.addTab(self.tab2, "") self.tab3 = QtWidgets.QWidget() self.tab3.setObjectName("tab3") self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.tab3) self.horizontalLayout_13.setObjectName("horizontalLayout_13") self.verticalLayout_6 = QtWidgets.QVBoxLayout() self.verticalLayout_6.setObjectName("verticalLayout_6") self.drlb1 = QtWidgets.QLabel(self.tab3) self.drlb1.setMinimumSize(QtCore.QSize(320, 240)) self.drlb1.setMaximumSize(QtCore.QSize(16777215, 500)) self.drlb1.setFrameShape(QtWidgets.QFrame.Box) self.drlb1.setObjectName("drlb1") self.drlb1.resize(int(self.labelip1.width()), int(self.labelip1.height())) self.drlb1.setScaledContents(True) self.verticalLayout_6.addWidget(self.drlb1) self.horizontalLayout_11 = QtWidgets.QHBoxLayout() self.horizontalLayout_11.setObjectName("horizontalLayout_11") self.draw1 = QtWidgets.QPushButton(self.tab3) font = QtGui.QFont() font.setPointSize(11) self.draw1.setFont(font) self.draw1.setObjectName("draw1") self.horizontalLayout_11.addWidget(self.draw1) self.remove1 = QtWidgets.QPushButton(self.tab3) self.remove1.setEnabled(False) font = QtGui.QFont() font.setPointSize(11) self.remove1.setFont(font) self.remove1.setObjectName("remove1") self.horizontalLayout_11.addWidget(self.remove1) self.verticalLayout_6.addLayout(self.horizontalLayout_11) self.verticalLayout_6.setStretch(0, 2) self.verticalLayout_6.setStretch(1, 1) self.horizontalLayout_13.addLayout(self.verticalLayout_6) self.verticalLayout_7 = QtWidgets.QVBoxLayout() self.verticalLayout_7.setObjectName("verticalLayout_7") self.drlb2 = QtWidgets.QLabel(self.tab3) self.drlb2.setMinimumSize(QtCore.QSize(320, 240)) self.drlb2.setMaximumSize(QtCore.QSize(16777215, 500)) self.drlb2.setFrameShape(QtWidgets.QFrame.Box) self.drlb2.setObjectName("drlb2") self.drlb2.resize(self.labelip2.width(), self.labelip2.height()) self.drlb2.setScaledContents(True) self.verticalLayout_7.addWidget(self.drlb2) self.horizontalLayout_12 = QtWidgets.QHBoxLayout() self.horizontalLayout_12.setObjectName("horizontalLayout_12") self.draw2 = QtWidgets.QPushButton(self.tab3) font = QtGui.QFont() font.setPointSize(11) self.draw2.setFont(font) self.draw2.setObjectName("draw2") self.horizontalLayout_12.addWidget(self.draw2) self.remove2 = QtWidgets.QPushButton(self.tab3) self.remove2.setEnabled(False) font = QtGui.QFont() font.setPointSize(11) self.remove2.setFont(font) self.remove2.setObjectName("remove2") self.horizontalLayout_12.addWidget(self.remove2) self.verticalLayout_7.addLayout(self.horizontalLayout_12) self.verticalLayout_7.setStretch(0, 2) self.verticalLayout_7.setStretch(1, 1) self.horizontalLayout_13.addLayout(self.verticalLayout_7) self.tabWidget.addTab(self.tab3, "") self.verticalLayout.addWidget(self.tabWidget) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 772, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videowidget = QVideoWidget() self.start.setEnabled(False) self.stop.setEnabled(False) self.start.clicked.connect(self.play_video) self.stop.clicked.connect(self.stop_video) self.open.clicked.connect(self.open_file) self.videoslider.setRange(0, 0) self.videoslider.sliderMoved.connect(self.set_position) self.volslider.setRange(0, 100) self.volslider.setValue(100) self.volslider.sliderMoved.connect(self.set_volume) hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) #set widgets to the hbox layout hboxLayout.addWidget(self.open) hboxLayout.addWidget(self.stop) hboxLayout.addWidget(self.prev) hboxLayout.addWidget(self.start) hboxLayout.addWidget(self.next) hboxLayout.addWidget(self.sound) hboxLayout.addWidget(self.volslider) hboxLayout.addWidget(self.fsbtn) vboxlayout = QVBoxLayout() vboxlayout.addWidget(videowidget) vboxlayout.addWidget(self.videoslider) vboxlayout.addLayout(hboxLayout) self.tab2.setLayout(vboxlayout) self.mediaPlayer.setVideoOutput(videowidget) self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) self.timer = QTimer() self.timer1 = QTimer() # set timer timeout callback function self.timer.timeout.connect(self.viewCam) self.timer1.timeout.connect(self.viewCam1) # set control_bt callback clicked function self.startbtn1.clicked.connect(self.startTimer1) self.stopbtn1.clicked.connect(self.stopTimer1) self.startbtn2.clicked.connect(self.startTimer2) self.stopbtn2.clicked.connect(self.stopTimer2) self.fsbtn.clicked.connect(self.fullscreen) self.next.clicked.connect(self.fast) self.prev.clicked.connect(self.slow) self.drlb1.mousePressEvent = self.mouseEventCAM1 self.drlb2.mousePressEvent = self.mouseEventCAM2 self.draw1.clicked.connect(self.startDrawAreaCAM1) self.remove1.clicked.connect(self.removeAreaCAM1) self.draw2.clicked.connect(self.startDrawAreaCAM2) self.remove2.clicked.connect(self.removeAreaCAM2) self.today = date.today() self.now = 0 self.now1 = 0 self.dir = os.path.join('IVA', 'IVA_IPCAM_1', str(self.today.year)) self.dir1 = os.path.join('IVA', 'IVA_IPCAM_2', str(self.today.year)) self.startt = 0 self.stopt = 0 self.path = 0 self.name = 0 self.startt1 = 0 self.stopt1 = 0 self.path1 = 0 self.name1 = 0 self.points_1 = [] self.points_2 = [] self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self.tab2, "Open Video") if filename != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.start.setEnabled(True) self.stop.setEnabled(True) def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def stop_video(self): self.mediaPlayer.stop() def mediastate_changed(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.start.setIcon(icon5) else: self.start.setIcon(icon2) def position_changed(self, position): self.videoslider.setValue(position) def duration_changed(self, duration): self.videoslider.setRange(0, duration) def set_position(self, position): self.mediaPlayer.setPosition(position) def set_volume(self, volume): self.mediaPlayer.setVolume(volume) def fullscreen(self): if MainWindow.windowState() & Qt.WindowFullScreen: MainWindow.showNormal() self.fsbtn.setText('Full Screen') else: MainWindow.showFullScreen() self.fsbtn.setText('Normal Screen') def fast(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10 * 60) def slow(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10 * 60) def viewCam(self): # read image in BGR format ret, image = self.cap.read() self.out.write(image) # convert image to RGB format image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) self.drlb1.setPixmap( QPixmap.fromImage( self.image_to_QImage( self.drawArea(image, self.points_1, self.labelip1), self.drlb1))) # show image in img_label # get image infos height, width, channel = image.shape step = channel * width # create QImage from image qImg = QImage(image.data, width, height, step, QImage.Format_RGB888) self.drlb1.setPixmap( QPixmap.fromImage( self.image_to_QImage( self.drawArea(image, self.points_1, self.labelip1), self.drlb1))) # show image in img_label self.labelip1.setPixmap(QPixmap.fromImage(qImg)) def viewCam1(self): # read image in BGR format ret1, image1 = self.cap1.read() self.out1.write(image1) # convert image to RGB format image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB) # get image infos height1, width1, channel1 = image1.shape step1 = channel1 * width1 # create QImage from image qImg1 = QImage(image1.data, width1, height1, step1, QImage.Format_RGB888) self.drlb2.setPixmap( QPixmap.fromImage( self.image_to_QImage( self.drawArea(image1, self.points_2, self.labelip2), self.drlb2))) # show image in img_label self.labelip2.setPixmap(QPixmap.fromImage(qImg1)) # start/stop timer def startTimer1(self): # if timer is stopped if not self.timer.isActive(): # create video capture self.cap = cv2.VideoCapture(0) width = int(self.cap.get(3)) height = int(self.cap.get(4)) self.out = cv2.VideoWriter( 'outpy1.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (width, height)) # start timer self.timer.start(20) self.now = datetime.now() self.startt = str(self.now.hour) + '.' + str(self.now.minute) def startTimer2(self): # if timer is stopped if not self.timer1.isActive(): # create video capture self.cap1 = cv2.VideoCapture(iplink) width1 = int(self.cap1.get(3)) height1 = int(self.cap1.get(4)) self.out1 = cv2.VideoWriter( 'outpy2.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10, (width1, height1)) # start timer self.timer1.start(20) self.now1 = datetime.now() self.startt1 = str(self.now1.hour) + '.' + str(self.now1.minute) def stopTimer1(self): if self.timer.isActive(): # stop timer self.timer.stop() # release video capture self.cap.release() self.out.release() self.stopt = str(self.now.hour) + '.' + str(self.now.minute) self.name = str(self.startt) + "-" + str(self.stopt) + ".avi" if not os.path.exists(self.dir): os.mkdir(self.dir) self.dir = os.path.join(self.dir, str(self.today.month)) if not os.path.exists(self.dir): os.mkdir(self.dir) self.path = os.path.join(str(self.dir), str(self.name)) os.rename('outpy1.avi', self.path) def stopTimer2(self): if self.timer1.isActive(): # stop timer self.timer1.stop() # release video capture self.cap1.release() self.out1.release() self.stopt1 = str(self.now1.hour) + '.' + str(self.now1.minute) self.name1 = str(self.startt1) + "-" + str(self.stopt1) + ".avi" if not os.path.exists(self.dir1): os.mkdir(self.dir1) self.dir1 = os.path.join(self.dir1, str(self.today1.month)) if not os.path.exists(self.dir1): os.mkdir(self.dir1) self.path1 = os.path.join(str(self.dir1), str(self.name1)) os.rename('outpy2.avi', self.path1) def image_to_QImage(self, image, label): # image = cv2.resize(image, (label.width(), label.height())) height, width, channel = image.shape step = channel * width return QImage(image.data, width, height, step, QImage.Format_RGB888) def mouseEventCAM1(self, event): if self.remove1.isEnabled() and self.timer.isActive( ) == True and self.cap.isOpened() == True: x = event.pos().x() y = event.pos().y() self.points_1.append([x, y]) print("Position clicked is ({}, {})".format(x, y)) def mouseEventCAM2(self, event): if self.remove2.isEnabled( ) and self.timer1.isActive == True and self.cap1.isOpened() == True: x = event.pos().x() y = event.pos().y() self.points_2.append([x, y]) print("Position clicked is ({}, {})".format(x, y)) def startDrawAreaCAM1(self): self.draw1.setEnabled(False) self.remove1.setEnabled(True) def removeAreaCAM1(self): while len(self.points_1): self.points_1.pop() self.draw1.setEnabled(True) self.remove1.setEnabled(False) def startDrawAreaCAM2(self): self.draw2.setEnabled(False) self.remove2.setEnabled(True) def removeAreaCAM2(self): while len(self.points_2): self.points_CAM2.pop() self.draw2.setEnabled(True) self.remove2.setEnabled(False) def drawArea(self, image, points: list, qlabel: QtWidgets.QLabel): image_draw = image.copy() image_draw = cv2.resize(image_draw, (qlabel.width(), qlabel.height())) # print(len(points)) if len(points) > 1: cv2.polylines(image_draw, np.array([points]), 1, (255, 0, 0), 1) b, g, r = cv2.split(image_draw) cv2.fillPoly(b, np.array([points]), (0, 255, 0)) cv2.fillPoly(r, np.array([points]), (0, 255, 0)) image_draw = cv2.merge([b, g, r]) return image_draw def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "IVA Application")) self.labelip1.setText(_translate("MainWindow", "IP Cam 1")) self.startbtn1.setText(_translate("MainWindow", "Start")) self.prbtn1.setText(_translate("MainWindow", "Person ReID")) self.frbtn1.setText(_translate("MainWindow", "Face Recognition")) self.stopbtn1.setText(_translate("MainWindow", "Stop")) self.apbtn1.setText(_translate("MainWindow", "Area Protection")) self.fdbtn1.setText(_translate("MainWindow", "Fall Detection")) self.labelip2.setText(_translate("MainWindow", "IP Cam 2")) self.startbtn2.setText(_translate("MainWindow", "Start")) self.prbtn2.setText(_translate("MainWindow", "Person ReID")) self.frbtn2.setText(_translate("MainWindow", "Face Recognition")) self.stopbtn2.setText(_translate("MainWindow", "Stop")) self.apbtn2.setText(_translate("MainWindow", "Area Protection")) self.fdbtn2.setText(_translate("MainWindow", "Fall Detection")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "2 IP CAMs")) self.open.setText(_translate("MainWindow", "Open")) self.fsbtn.setText(_translate("MainWindow", "Full Screen")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab2), _translate("MainWindow", "PLAY RECORD")) self.drlb1.setText(_translate("MainWindow", "Draw IP Cam 1")) self.draw1.setText(_translate("MainWindow", "Draw Area")) self.remove1.setText(_translate("MainWindow", "Remove Area ")) self.drlb2.setText(_translate("MainWindow", "Draw IP Cam 2")) self.draw2.setText(_translate("MainWindow", "Draw Area")) self.remove2.setText(_translate("MainWindow", "Remove Area")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab3), _translate("MainWindow", "SETTINGS"))
class Player(QGraphicsVideoItem): isSubtitle = pyqtSignal(bool) subtitlePos = pyqtSignal(int) def __init__(self, parent=None): super().__init__() self.parent = parent self.player = QMediaPlayer() self.player.setVolume(int(settings().value("Player/volume") or 100)) self.player.setVideoOutput(self) self.timer = QTimer(self) self.timer.timeout.connect(self.timerPos) self.player.currentMediaChanged.connect(self.signalStart) self.player.currentMediaChanged.connect(self.parent.subtitleitem.subtitleControl) self.player.currentMediaChanged.connect(self.videoConfigure) """self.player.mediaStatusChanged.connect(self.metadata) def metadata(self, data): if data and self.player.isMetaDataAvailable(): print(self.player.metaData("VideoCodec"))""" def videoConfigure(self, media): video_name = os.path.basename(media.canonicalUrl().toLocalFile()) videos = settings().value("Player/video_names") or [] videos_time = settings().value("Player/videos_time") or [] try: self.player.setPosition(int(videos_time[videos.index(video_name)])) except ValueError: pass def timerStart(self): self.timer.start(200) def signalStart(self, content): srt = content.canonicalUrl().toLocalFile().split(".") srt.pop(-1) srt.append("srt") srt = ".".join(srt) if QFile.exists(srt): self.isSubtitle.emit(True) self.timer.start(100) else: self.isSubtitle.emit(False) self.timer.stop() def timerPos(self): self.subtitlePos.emit(self.player.position()) def playerPlayOrOpen(self, arg=None): if type(arg) == list and len(arg) > 1: content = QMediaContent(QUrl.fromLocalFile(arg[1])) self.player.setMedia(content) self.play() def addVideo(self, video): content = QMediaContent(QUrl.fromLocalFile(video)) self.player.setMedia(content) self.play() def addYoutubeVideo(self, video): dm = DownloadManager(self) content = QMediaContent(dm.addUrl(video)) self.player.setMedia(content) self.play() def sliderChanged(self, pos): self.player.setPosition(pos) def play(self): self.player.play() def stop(self): self.player.stop() def pause(self): self.player.pause() def setMuted(self, mute): self.player.setMuted(mute) def mutedState(self): if self.player.isMuted(): self.setMuted(False) else: self.setMuted(True) def isMuted(self): return self.player.isMuted() def setVolume(self, value): self.player.setVolume(value) def volume(self): return self.player.volume()
class Window(QWidget): def __init__(self): super().__init__() self.audio = "" self.sampFreq = 0 self.setWindowTitle("Silence Skipper Video Player") self.setGeometry(350, 100, 700, 500) self.setWindowIcon(QIcon('helicopter.jpg')) p = self.palette() p.setColor(QPalette.Window, Qt.black) self.setPalette(p) self.init_ui() self.show() def init_ui(self): # create media player object self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) # create videowidget object videowidget = QVideoWidget() # create open button openBtn = QPushButton('Open Video') openBtn.clicked.connect(self.open_file) # create button for playing self.playBtn = QPushButton() self.playBtn.setEnabled(False) self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playBtn.clicked.connect(self.play_video) self.playBtnShortcut = QShortcut(QKeySequence('Space'), self) self.playBtnShortcut.activated.connect(self.play_video) # create skip forward button self.skipForward = QPushButton() self.skipForward.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.skipForward.setEnabled(False) self.skipForward.clicked.connect(self.skip_forward) self.forwardShortcut = QShortcut(QKeySequence('Right'), self) self.forwardShortcut.activated.connect(self.skip_forward) self.forwardShortcut = QShortcut(QKeySequence('Shift+Right'), self) self.forwardShortcut.activated.connect(self.skip_forward_tiny) #make mutton invis self.skipForward.setVisible(False) # create skip backward button self.skipBackwards = QPushButton() self.skipBackwards.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.skipBackwards.setEnabled(False) self.skipBackwards.clicked.connect(self.skip_backwards) self.backwardsShortcut = QShortcut(QKeySequence('Left'), self) self.backwardsShortcut.activated.connect(self.skip_backwards) self.backwardsShortcutTiny = QShortcut(QKeySequence('Shift+Left'), self) self.backwardsShortcutTiny.activated.connect(self.skip_backwards_tiny) #make mutton invis self.skipBackwards.setVisible(False) # create speed setter button self.speedButton = MyQLineEdit() self.speedButton.textChanged[str].connect(self.speed_popup) speed = "1" self.speedButton.setText(speed) self.speedButton.setMaxLength(4) self.speedButton.setFixedWidth(30) self.label = QLabel('Yellow', self) self.label.setStyleSheet("color:white;") self.label.setText("sound threshold factor: ") self.label.setAlignment(Qt.AlignRight) self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) #self.label.setFixedWidth(160) self.soundThreshold = MyQLineEdit() self.soundThreshold.textChanged[str].connect(self.sound_thresh) self.soundThreshold.setText(str(audioThreshold)) self.soundThreshold.setMaxLength(5) self.soundThreshold.setFixedWidth(35) self.soundThreshold.setAlignment(Qt.AlignLeft) #self.speedButton.editingFinished.connect(self.speed_popup) # create slider self.slider = QJumpSlider(Qt.Horizontal, mediaP=self.mediaPlayer) #self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, 0) self.slider.sliderMoved.connect(self.set_position) # create label self.label2 = QLabel('Yellow', self) self.label2.setStyleSheet( "background-color: yellow; border: 1px solid black;") self.label2.setText("duration") self.label2.setAlignment(Qt.AlignRight) self.label2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) hboxLayout2 = QHBoxLayout() hboxLayout2.setContentsMargins(0, 0, 0, 0) hboxLayout2.addWidget(self.label) hboxLayout2.addWidget(self.soundThreshold) # create hbox layout hboxLayout = QHBoxLayout() hboxLayout.setContentsMargins(0, 0, 0, 0) # set widgets to the hbox layout hboxLayout.addWidget(openBtn) hboxLayout.addWidget(self.playBtn) hboxLayout.addWidget(self.skipBackwards) hboxLayout.addWidget(self.skipForward) hboxLayout.addWidget(self.slider) hboxLayout.addWidget(self.speedButton) hboxLayout.addWidget(self.label2) # create vbox layout vboxLayout = QVBoxLayout() vboxLayout.addLayout(hboxLayout2) vboxLayout.addWidget(videowidget) vboxLayout.addLayout(hboxLayout) vboxLayout.setContentsMargins(10, 10, 10, 10) self.setLayout(vboxLayout) self.mediaPlayer.setVideoOutput(videowidget) # media player signals self.mediaPlayer.stateChanged.connect(self.mediastate_changed) self.mediaPlayer.positionChanged.connect(self.position_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) def open_file(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Video") print(filename) if filename != '': if os.path.exists("audio.wav"): os.remove("audio.wav") command = "ffmpeg_dir\\bin\\ffmpeg -i " + filename + " -ac 1 -ar 11025 -vn audio.wav" subprocess.call(command, shell=True) self.sampFreq, self.audio = wavfile.read('audio.wav') print(self.audio.shape) print(self.sampFreq) self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(filename))) self.playBtn.setEnabled(True) self.skipForward.setEnabled(True) self.skipBackwards.setEnabled(True) self.mediaPlayer.setPosition(1) def play_video(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def skip_forward(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.setPosition(self.mediaPlayer.position() + 5000) else: self.mediaPlayer.setPosition(self.mediaPlayer.position() + 33) def skip_forward_tiny(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000) def skip_backwards(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.setPosition(self.mediaPlayer.position() - 5000) else: self.mediaPlayer.setPosition(self.mediaPlayer.position() - 33) def skip_backwards_tiny(self): self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000) def mediastate_changed(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playBtn.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def position_changed(self, position): self.slider.setValue(position) print(self.mediaPlayer.duration()) self.label2.setText( str(convert(int(position / 1000))) + "/" + str(convert(int(self.mediaPlayer.duration() / 1000)))) def duration_changed(self, duration): self.slider.setRange(0, duration) def set_position(self, position): self.mediaPlayer.setPosition(position) def speed_popup(self, text): print(text) self.mediaPlayer.setPlaybackRate(float(text)) def sound_thresh(self, text): global audioThreshold audioThreshold = float(text) print(audioThreshold) def handle_errors(self): self.playBtn.setEnabled(False) self.label.setText("Error: " + self.mediaPlayer.errorString())
class VideoWindow(QWidget): def __init__(self, vidPath): super().__init__() self.fullPath = vidPath self.startTime = 0 self.endTime = 0 self.init_ui() def init_ui(self): layout = QVBoxLayout() self.setLayout(layout) self.setWindowTitle(self.fullPath) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(True) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.setFixedWidth(100) self.playButton.setFixedHeight(50) self.playButton.clicked.connect(self.play) self.trimButton = QPushButton("Trim") self.trimButton.setFixedWidth(150) self.trimButton.setFixedHeight(50) self.trimButton.clicked.connect(self.trimVid) self.positionSlider = QSlider(QtCore.Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.rangeSlider = qrangeslider.QRangeSlider() self.rangeSlider.setRange(0, 0) self.rangeSlider.endValueChanged.connect(self.adjustForEnd) self.rangeSlider.startValueChanged.connect(self.adjustForStart) self.rangeSlider.setFixedHeight(15) self.startTimeInput = QTimeEdit() self.endTimeInput = QTimeEdit() self.startTimeInput.setDisplayFormat('hh:mm:ss.zzz') self.endTimeInput.setDisplayFormat('hh:mm:ss.zzz') self.startTimeInput.timeChanged.connect(self.startInputChanged) self.endTimeInput.timeChanged.connect(self.endInputChanged) self.mediaPlayer.setMedia( QMediaContent(QtCore.QUrl.fromLocalFile(self.fullPath))) layout.addWidget(self.videoWidget) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.setNotifyInterval(10) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) controlLayout = QVBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.rangeSlider) controlLayout.addWidget(self.positionSlider) timeInputLayout = QHBoxLayout() timeInputLayout.addWidget(self.playButton) timeInputLayout.addWidget(self.startTimeInput) timeInputLayout.addWidget(self.endTimeInput) timeInputLayout.addWidget(self.trimButton) controlLayout.addLayout(timeInputLayout) layout.addLayout(controlLayout) self.mediaPlayer.play() self.resize(1024, 700) self.show() def closeEvent(self, event): self.mediaPlayer.stop() self.videoWidget.setParent(None) self.mediaPlayer.setParent(None) self.mediaPlayer.deleteLater() self.videoWidget.deleteLater() def trimVid(self): self.trimButton.setEnabled(False) outName = mytools.getAvailableName(self.fullPath, 'Trim') print(outName) trimStartTime = self.startTimeInput.time().toString('hh:mm:ss.zzz') trimEndTime = self.endTimeInput.time().toString('hh:mm:ss.zzz') try: ff = FFmpeg(inputs={self.fullPath: None}, outputs={ outName: [ '-ss', trimStartTime, '-to', trimEndTime, '-c:v', 'copy', '-c:a', 'copy', ] }) ff.run() except Exception as e: msg = QMessageBox() msg.setWindowTitle("Trim Failed") msg.setText(str(e)) msg.setIcon(QMessageBox.Critical) showMsg = msg.exec_() self.trimButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) if position > self.endTime: self.mediaPlayer.setPosition(self.startTime) def adjustForStart(self, startPos): self.startTime = startPos self.mediaPlayer.setPosition(startPos) self.startTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(startPos)) self.endTimeInput.setMinimumTime(QtCore.QTime(0, 0).addMSecs(startPos)) def adjustForEnd(self, endPos): self.endTime = endPos if self.positionSlider.value() > endPos: self.mediaPlayer.setPosition(endPos) self.endTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(endPos)) self.startTimeInput.setMaximumTime(QtCore.QTime(0, 0).addMSecs(endPos)) def startInputChanged(self, inputTime): self.rangeSlider.setStart(QtCore.QTime(0, 0, 0, 0).msecsTo(inputTime)) def endInputChanged(self, inputTime): self.rangeSlider.setEnd(QtCore.QTime(0, 0, 0, 0).msecsTo(inputTime)) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) self.rangeSlider.setMax(duration) self.rangeSlider.setEnd(duration) self.startTimeInput.setMinimumTime(QtCore.QTime(0, 0)) self.endTimeInput.setMinimumTime(QtCore.QTime(0, 0)) self.endTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(duration)) self.startTimeInput.setMaximumTime( QtCore.QTime(0, 0).addMSecs(duration)) self.endTimeInput.setMaximumTime(QtCore.QTime(0, 0).addMSecs(duration)) def setPosition(self, position): self.mediaPlayer.setPosition(position)
class MainWindow(QWidget): """ 主窗口 """ BORDER_WIDTH = 5 showSubPlayWindowSig = pyqtSignal() def __init__(self, parent=None): super().__init__(parent) # 实例化窗口特效 self.windowEffect = WindowEffect() # 实例化小部件 self.createWidgets() # 初始化标志位 self.isInSelectionMode = False # 初始化界面 self.__initWidget() def createWidgets(self): """ 创建小部件 """ self.totalStackWidget = OpacityAniStackedWidget(self) self.subMainWindow = QWidget(self) self.titleBar = TitleBar(self) # 实例化播放器和播放列表 self.player = QMediaPlayer(self) self.playlist = MediaPlaylist(self) # 实例化小部件 self.subStackWidget = PopUpAniStackedWidget(self.subMainWindow) self.settingInterface = SettingInterface(self.subMainWindow) # 从配置文件中的选择文件夹读取音频文件 t3 = time() self.myMusicInterface = MyMusicInterface( self.settingInterface.config.get('selected-folders', []), self.subMainWindow) t4 = time() print('创建整个我的音乐界面耗时:'.ljust(15), t4 - t3) # 将最后一首歌作为playBar初始化时用的songInfo self.lastSongInfo = self.settingInterface.config.get('last-song', {}) # 创建缩略图任务栏 self.thumbnailToolBar = ThumbnailToolBar(self) self.thumbnailToolBar.setWindow(self.windowHandle()) # 创建左上角播放窗口 self.subPlayWindow = SubPlayWindow(self, self.lastSongInfo) # 创建正在播放界面 self.playingInterface = PlayingInterface(self.playlist.playlist, self) # 创建专辑界面 self.albumInterface = AlbumInterface({}, self.subMainWindow) # 创建播放列表卡界面 self.readCustomPlaylists() # 读入所有播放列表 self.playlistCardInterface = PlaylistCardInterface( self.customPlaylists, self) # 创建导航界面 self.navigationInterface = NavigationInterface(self.subMainWindow) # 创建播放栏 self.playBar = PlayBar(self.lastSongInfo, self) # 创建快捷键 self.togglePlayPauseAct_1 = QAction(parent=self, shortcut=Qt.Key_Space, triggered=self.switchPlayState) self.showNormalAct = QAction(parent=self, shortcut=Qt.Key_Escape, triggered=self.exitFullScreen) self.lastSongAct = QAction(parent=self, shortcut=Qt.Key_MediaPrevious, triggered=self.playlist.previous) self.nextSongAct = QAction(parent=self, shortcut=Qt.Key_MediaNext, triggered=self.playlist.next) self.togglePlayPauseAct_2 = QAction(parent=self, shortcut=Qt.Key_MediaPlay, triggered=self.switchPlayState) self.addActions([ self.togglePlayPauseAct_1, self.showNormalAct, self.nextSongAct, self.lastSongAct, self.togglePlayPauseAct_2 ]) # 创建stackWidget字典 self.stackWidget_dict = { 'subStackWidget': self.subStackWidget, 'myMusicInterfaceStackWidget': self.myMusicInterface.stackedWidget } # 当前选中的专辑卡 self.currentAlbumCard = None def __initWidget(self): """ 初始化小部件 """ self.resize(1300, 1000) self.setMinimumSize(1030, 800) self.setWindowTitle('MyGroove音乐') self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowIcon(QIcon('resource\\images\\透明icon.png')) self.setAttribute(Qt.WA_TranslucentBackground | Qt.WA_StyledBackground) # 在去除任务栏的显示区域居中显示 desktop = QApplication.desktop().availableGeometry() self.move(int(desktop.width() / 2 - self.width() / 2), int(desktop.height() / 2 - self.height() / 2)) # 标题栏置顶 self.titleBar.raise_() # 设置窗口特效 self.setWindowEffect() # todo:将窗口添加到StackWidget中 self.subStackWidget.addWidget(self.myMusicInterface, 0, 70, False) self.subStackWidget.addWidget(self.playlistCardInterface, 0, 160, False) self.subStackWidget.addWidget(self.settingInterface, 0, 160, False) self.subStackWidget.addWidget(self.albumInterface, 0, 70) self.totalStackWidget.addWidget(self.subMainWindow) self.totalStackWidget.addWidget(self.playingInterface) # 初始化标题栏的下标列表 self.titleBar.stackWidgetIndex_list.append( ('myMusicInterfaceStackWidget', 0)) # 设置右边子窗口的位置 self.adjustWidgetGeometry() # 引用小部件 self.referenceWidgets() # 设置层叠样式 self.setObjectName('mainWindow') self.subMainWindow.setObjectName('subMainWindow') self.subStackWidget.setObjectName('subStackWidget') self.playingInterface.setObjectName('playingInterface') self.setQss() # 初始化播放列表 self.initPlaylist() # todo:设置全局热键 # self.setHotKey() # 将信号连接到槽函数 self.connectSignalToSlot() # 初始化播放栏 self.initPlayBar() # 安装事件过滤器 self.navigationInterface.navigationMenu.installEventFilter(self) def setHotKey(self): """ 设置全局热键 """ self.nextSongHotKey = SystemHotkey() self.lastSongHotKey = SystemHotkey() self.playHotKey = SystemHotkey() # callback会返回一个event参数,所以需要用lambda self.nextSongHotKey.register( ('f6', ), callback=lambda x: self.hotKeySlot(self.playlist.next)) self.lastSongHotKey.register( ('f4', ), callback=lambda x: self.hotKeySlot(self.playlist.previous)) self.playHotKey.register( ('f5', ), callback=lambda x: self.hotKeySlot(self.switchPlayState)) def setWindowEffect(self): """ 设置窗口特效 """ self.hWnd = HWND(int(self.winId())) # 开启窗口动画 self.windowEffect.setWindowAnimation(int(self.winId())) # 开启亚克力效果和阴影效果 self.windowEffect.setAcrylicEffect(self.hWnd, 'F2F2F299', True) def adjustWidgetGeometry(self): """ 调整小部件的geometry """ self.subMainWindow.resize(self.size()) self.totalStackWidget.resize(self.size()) self.titleBar.resize(self.width(), 40) if hasattr(self, 'navigationInterface'): self.navigationInterface.setOverlay(self.width() < 1280) self.subStackWidget.move(self.navigationInterface.width(), 0) self.subStackWidget.resize( self.width() - self.navigationInterface.width(), self.height()) self.navigationInterface.resize(self.navigationInterface.width(), self.height()) if hasattr(self, 'albumInterface'): if not self.playingInterface.smallestModeInterface.isVisible(): self.albumInterface.resize(self.myMusicInterface.size()) if hasattr(self, 'playBar'): if not self.playingInterface.smallestModeInterface.isVisible(): self.playBar.resize(self.width(), self.playBar.height()) def eventFilter(self, obj, e: QEvent): """ 过滤事件 """ if obj == self.navigationInterface.navigationMenu: # 显示导航菜单是更改标题栏返回按钮和标题的父级为导航菜单 isVisible = self.titleBar.returnBt.isVisible() if e.type() == QEvent.Show: self.titleBar.returnBt.setParent(obj) # 显示标题 self.titleBar.title.setParent(obj) self.titleBar.title.move(15, 10) self.titleBar.title.show() # 如果播放栏课件就缩短导航菜单 isScaled = self.playBar.isVisible() height = self.height() - isScaled * self.playBar.height() self.navigationInterface.navigationMenu.setBottomSpacingVisible( not isScaled) self.navigationInterface.navigationMenu.resize( self.navigationInterface.navigationMenu.width(), height) elif e.type() == QEvent.Hide: # 隐藏标题 self.titleBar.title.hide() self.titleBar.title.setParent(self.titleBar) self.titleBar.returnBt.setParent(self.titleBar) # 根据情况显示/隐藏返回按钮和标题 self.titleBar.returnBt.setVisible(isVisible) return super().eventFilter(obj, e) def resizeEvent(self, e): """ 调整尺寸时同时调整子窗口的尺寸 """ super().resizeEvent(e) self.adjustWidgetGeometry() # 更新标题栏图标 if isMaximized(int(self.winId())): self.titleBar.maxBt.setMaxState(True) def moveEvent(self, e): if hasattr(self, 'playBar'): if not self.isMaximized(): self.playBar.move( self.x() - 8, self.y() + self.height() - self.playBar.height()) else: self.playBar.move( self.x() + 1, self.y() + self.height() - self.playBar.height() + 9) def closeEvent(self, e: QCloseEvent): """ 关闭窗口前更新json文件 """ if self.playlist.currentIndex() >= 0: self.settingInterface.config['last-song'] = self.playlist.playlist[ self.playlist.currentIndex()] else: self.settingInterface.config['last-song'] = {} self.settingInterface.config[ 'volume'] = self.playBar.volumeSlider.value() self.settingInterface.config[ 'playBar-acrylicColor'] = self.playBar.acrylicColor self.settingInterface.writeConfig() self.playBar.close() self.subPlayWindow.close() self.playlist.save() e.accept() def nativeEvent(self, eventType, message): """ 处理windows消息 """ msg = MSG.from_address(message.__int__()) if msg.message == win32con.WM_NCHITTEST: xPos = win32api.LOWORD(msg.lParam) - self.frameGeometry().x() yPos = win32api.HIWORD(msg.lParam) - self.frameGeometry().y() w, h = self.width(), self.height() lx = xPos < self.BORDER_WIDTH rx = xPos + 9 > w - self.BORDER_WIDTH ty = yPos < self.BORDER_WIDTH by = yPos > h - self.BORDER_WIDTH if (lx and ty): return True, win32con.HTTOPLEFT elif (rx and by): return True, win32con.HTBOTTOMRIGHT elif (rx and ty): return True, win32con.HTTOPRIGHT elif (lx and by): return True, win32con.HTBOTTOMLEFT elif ty: return True, win32con.HTTOP elif by: return True, win32con.HTBOTTOM elif lx: return True, win32con.HTLEFT elif rx: return True, win32con.HTRIGHT elif msg.message == win32con.WM_NCCALCSIZE: if isMaximized(msg.hWnd): self.windowEffect.adjustMaximizedClientRect( HWND(msg.hWnd), msg.lParam) return True, 0 if msg.message == win32con.WM_GETMINMAXINFO: if isMaximized(msg.hWnd): window_rect = win32gui.GetWindowRect(msg.hWnd) if not window_rect: return False, 0 # 获取显示器句柄 monitor = win32api.MonitorFromRect(window_rect) if not monitor: return False, 0 # 获取显示器信息 monitor_info = win32api.GetMonitorInfo(monitor) monitor_rect = monitor_info['Monitor'] work_area = monitor_info['Work'] # 将lParam转换为MINMAXINFO指针 info = cast(msg.lParam, POINTER(MINMAXINFO)).contents # 调整位置 info.ptMaxSize.x = work_area[2] - work_area[0] info.ptMaxSize.y = work_area[3] - work_area[1] info.ptMaxTrackSize.x = info.ptMaxSize.x info.ptMaxTrackSize.y = info.ptMaxSize.y # 修改放置点的x,y坐标 info.ptMaxPosition.x = abs(window_rect[0] - monitor_rect[0]) info.ptMaxPosition.y = abs(window_rect[1] - monitor_rect[1]) return True, 1 return QWidget.nativeEvent(self, eventType, message) def connectSignalToSlot(self): """ 将信号连接到槽 """ # todo:设置界面信号连接到槽函数 self.settingInterface.crawlComplete.connect(self.crawCompleteSlot) self.settingInterface.selectedFoldersChanged.connect( self.myMusicInterface.scanTargetPathSongInfo) # todo:标题栏返回按钮功能 self.titleBar.returnBt.clicked.connect(self.returnButtonSlot) # todo:导航界面信号连接到槽函数 self.navigationInterface.displayModeChanged.connect( self.navigationDisplayModeChangedSlot) self.navigationInterface.switchInterfaceSig.connect( self.stackWidgetIndexChangedSlot) self.navigationInterface.showPlayingInterfaceSig.connect( self.showPlayingInterface) self.navigationInterface.showCreatePlaylistPanelSig.connect( self.showCreatePlaylistPanel) self.navigationInterface.switchToSettingInterfaceSig.connect( self.switchToSettingInterface) self.navigationInterface.switchToMyMusicInterfaceSig.connect( self.switchToMyMusicInterface) self.navigationInterface.switchToPlaylistCardInterfaceSig.connect( self.switchToPlaylistCardInterface) # todo:缩略图任务栏各按钮的功能 self.thumbnailToolBar.playButton.clicked.connect(self.switchPlayState) self.thumbnailToolBar.lastSongButton.clicked.connect( self.playlist.previous) self.thumbnailToolBar.nextSongButton.clicked.connect( self.playlist.next) # todo:播放栏各部件功能 self.playBar.playButton.clicked.connect(self.switchPlayState) self.playBar.nextSongButton.clicked.connect(self.playlist.next) self.playBar.volumeButton.muteStateChanged.connect(self.setMute) self.playBar.randomPlayButton.clicked.connect(self.setRandomPlay) self.playBar.lastSongButton.clicked.connect(self.playlist.previous) self.playBar.songInfoCard.clicked.connect(self.showPlayingInterface) self.playBar.volumeSlider.valueChanged.connect(self.volumeChangedSlot) self.playBar.progressSlider.sliderMoved.connect( self.progressSliderMoveSlot) self.playBar.progressSlider.clicked.connect( self.progressSliderMoveSlot) self.playBar.loopModeButton.loopModeChanged.connect( self.switchLoopMode) self.playBar.moreActionsMenu.fillScreenAct.triggered.connect( self.setFullScreen) self.playBar.moreActionsMenu.showPlayListAct.triggered.connect( self.showPlaylist) self.playBar.moreActionsMenu.clearPlayListAct.triggered.connect( self.clearPlaylist) self.playBar.smallPlayModeButton.clicked.connect( self.showSmallestModeInterface) self.playBar.moreActionsMenu.savePlayListAct.triggered.connect( lambda: self.showCreatePlaylistPanel(self.playlist.playlist)) # todo:将播放器的信号连接到槽函数 self.player.positionChanged.connect(self.playerPositionChangeSlot) self.player.durationChanged.connect(self.playerDurationChangeSlot) # todo:将播放列表的信号连接到槽函数 self.playlist.switchSongSignal.connect(self.updateWindow) self.playlist.currentIndexChanged.connect( self.playingInterface.setCurrentIndex) # todo:将正在播放界面信号连接到槽函数 self.playingInterface.currentIndexChanged.connect( self.playingInterfaceCurrrentIndexChangedSlot) self.playingInterface.switchPlayStateSig.connect(self.switchPlayState) self.playingInterface.lastSongSig.connect(self.playlist.previous) self.playingInterface.nextSongSig.connect(self.playlist.next) self.playingInterface.playBar.randomPlayButton.clicked.connect( self.setRandomPlay) self.playingInterface.playBar.volumeSlider.muteStateChanged.connect( self.setMute) self.playingInterface.playBar.volumeSlider.volumeSlider.valueChanged.connect( self.volumeChangedSlot) self.playingInterface.playBar.progressSlider.sliderMoved.connect( self.progressSliderMoveSlot) self.playingInterface.playBar.progressSlider.clicked.connect( self.progressSliderMoveSlot) self.playingInterface.playBar.fillScreenButton.clicked.connect( self.setFullScreen) self.playingInterface.playBar.loopModeButton.loopModeChanged.connect( self.switchLoopMode) self.playingInterface.removeMediaSignal.connect( self.playlist.removeMedia) self.playingInterface.randomPlayAllSignal.connect(self.disorderPlayAll) self.playingInterface.switchToAlbumInterfaceSig.connect( self.switchToAlbumInterfaceByName) self.playingInterface.playBar.moreActionsMenu.clearPlayListAct.triggered.connect( self.clearPlaylist) self.playingInterface.playBar.moreActionsMenu.savePlayListAct.triggered.connect( lambda: self.showCreatePlaylistPanel(self.playlist.playlist)) self.playingInterface.smallestModeStateChanged.connect( self.smallestModeStateChanedSlot) self.playingInterface.exitFullScreenSig.connect(self.exitFullScreen) # todo:歌曲界面歌曲卡列表视图的信号连接到槽函数 self.songTabSongListWidget.playSignal.connect(self.songCardPlaySlot) self.songTabSongListWidget.playOneSongSig.connect(self.playOneSongCard) self.songTabSongListWidget.nextToPlayOneSongSig.connect( self.songCardNextPlaySlot) self.songTabSongListWidget.addSongToPlayingSignal.connect( self.addOneSongToPlayingPlaylist) self.songTabSongListWidget.switchToAlbumInterfaceSig.connect( self.switchToAlbumInterfaceByName) self.songTabSongListWidget.editSongCardSignal.connect( self.editSongCardSlot) # todo:将专辑卡的信号连接到槽函数 self.albumCardViewer.playSignal.connect(self.playAlbum) self.albumCardViewer.nextPlaySignal.connect( self.multiSongsNextPlaySlot) self.albumCardViewer.switchToAlbumInterfaceSig.connect( self.switchToAlbumInterfaceByAlbumInfo) self.albumCardViewer.saveAlbumInfoSig.connect(self.updateAlbumInfo) # todo:将子播放窗口的信号连接槽槽函数 self.subPlayWindow.nextSongButton.clicked.connect(self.playlist.next) self.subPlayWindow.lastSongButton.clicked.connect( self.playlist.previous) self.subPlayWindow.playButton.clicked.connect(self.switchPlayState) # todo:将我的音乐界面连接到槽函数 self.myMusicInterface.randomPlayAllSig.connect(self.disorderPlayAll) self.myMusicInterface.playCheckedCardsSig.connect( self.playCheckedCards) self.myMusicInterface.currentIndexChanged.connect( self.stackWidgetIndexChangedSlot) self.myMusicInterface.nextToPlayCheckedCardsSig.connect( self.multiSongsNextPlaySlot) self.myMusicInterface.selectionModeStateChanged.connect( self.selectionModeStateChangedSlot) self.myMusicInterface.addSongsToCustomPlaylistSig.connect( self.addSongsToCustomPlaylist) self.myMusicInterface.addSongsToNewCustomPlaylistSig.connect( lambda songInfo_list: self.showCreatePlaylistPanel(songInfo_list)) self.myMusicInterface.addSongsToPlayingPlaylistSig.connect( self.addSongsToPlayingPlaylist) # todo:将自己的信号连接到槽函数 self.showSubPlayWindowSig.connect(self.subPlayWindow.show) # todo:将专辑界面的信号连接到槽函数 self.albumInterface.playAlbumSignal.connect(self.playAlbum) self.albumInterface.songCardPlaySig.connect( self.albumInterfaceSongCardPlaySlot) self.albumInterface.playOneSongCardSig.connect(self.playOneSongCard) self.albumInterface.nextToPlayOneSongSig.connect( self.songCardNextPlaySlot) self.albumInterface.addOneSongToPlayingSig.connect( self.addOneSongToPlayingPlaylist) self.albumInterface.addSongsToPlayingPlaylistSig.connect( self.addSongsToPlayingPlaylist) self.albumInterface.songListWidget.editSongCardSignal.connect( self.editSongCardSlot) self.albumInterface.saveAlbumInfoSig.connect(self.updateAlbumInfo) self.albumInterface.selectionModeStateChanged.connect( self.selectionModeStateChangedSlot) self.albumInterface.playCheckedCardsSig.connect(self.playCheckedCards) self.albumInterface.nextToPlayCheckedCardsSig.connect( self.multiSongsNextPlaySlot) self.albumInterface.addSongsToCustomPlaylistSig.connect( self.addSongsToCustomPlaylist) self.albumInterface.addSongsToNewCustomPlaylistSig.connect( lambda songInfo_list: self.showCreatePlaylistPanel(songInfo_list)) # todo:将播放列表界面信号连接到槽函数 self.playlistCardInterface.selectionModeStateChanged.connect( self.selectionModeStateChangedSlot) self.playlistCardInterface.createPlaylistButton.clicked.connect( self.showCreatePlaylistPanel) self.playlistCardInterface.renamePlaylistSig.connect( self.renamePlaylistSlot) self.playlistCardInterface.deletePlaylistSig.connect( self.removePlaylistSlot) self.playlistCardInterface.playSig.connect(self.playCustomPlaylist) self.playlistCardInterface.nextToPlaySig.connect( self.multiSongsNextPlaySlot) def referenceWidgets(self): """ 引用小部件 """ self.songTabSongListWidget = self.myMusicInterface.songCardListWidget self.albumCardViewer = self.myMusicInterface.albumCardViewer def navigationDisplayModeChangedSlot(self, diaPlayMode: int): """ 导航界面显示模式改变对应的槽函数 """ self.titleBar.title.setVisible(self.navigationInterface.isExpanded) self.adjustWidgetGeometry() self.navigationInterface.navigationMenu.stackUnder(self.playBar) def initPlaylist(self): """ 初始化播放列表 """ self.player.setPlaylist(self.playlist) # 如果没有上一次的播放列表数据,就设置默认的播放列表 if not self.playlist.playlist: songInfo_list = self.songTabSongListWidget.songInfo_list self.playingInterface.setPlaylist(songInfo_list) self.playlist.setPlaylist(songInfo_list) self.playlist.playlistType = PlaylistType.ALL_SONG_PLAYLIST # 将当前歌曲设置为上次关闭前播放的歌曲 if self.lastSongInfo in self.playlist.playlist: index = self.playlist.playlist.index(self.lastSongInfo) self.playlist.setCurrentIndex(index) self.playingInterface.setCurrentIndex(index) def switchPlayState(self): """ 播放按钮按下时根据播放器的状态来决定是暂停还是播放 """ if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() self.setPlayButtonState(False) self.thumbnailToolBar.setButtonsEnabled(True) else: self.play() def setPlayButtonState(self, isPlay: bool): """ 设置播放按钮状态 """ self.subPlayWindow.setPlay(isPlay) self.playBar.playButton.setPlay(isPlay) self.thumbnailToolBar.playButton.setPlay(isPlay) self.playingInterface.playBar.playButton.setPlay(isPlay) self.playingInterface.smallestModeInterface.playButton.setPlay(isPlay) def volumeChangedSlot(self, value): """ 音量滑动条数值改变时更换图标并设置音量 """ self.player.setVolume(value) self.playBar.volumeButton.setVolumeLevel(value) if self.sender() == self.playBar.volumeSlider: self.playingInterface.playBar.volumeSlider.setValue(value) elif self.sender( ) == self.playingInterface.playBar.volumeSlider.volumeSlider: self.playBar.volumeSlider.setValue(value) def playerPositionChangeSlot(self): """ 播放器的播放进度改变时更新当前播放进度标签和进度条的值 """ self.playBar.progressSlider.setValue(self.player.position()) self.playBar.setCurrentTime(self.player.position()) self.playingInterface.playBar.progressSlider.setValue( self.player.position()) self.playingInterface.playBar.setCurrentTime(self.player.position()) self.playingInterface.smallestModeInterface.progressBar.setValue( self.player.position()) def playerDurationChangeSlot(self): """ 播放器当前播放的歌曲变化时更新进度条的范围和总时长标签 """ # 刚切换时得到的时长为0,所以需要先判断一下 if self.player.duration() >= 1: self.playBar.setTotalTime(self.player.duration()) self.playBar.progressSlider.setRange(0, self.player.duration()) self.playingInterface.playBar.progressSlider.setRange( 0, self.player.duration()) self.playingInterface.playBar.setTotalTime(self.player.duration()) self.playingInterface.smallestModeInterface.progressBar.setRange( 0, self.player.duration()) def progressSliderMoveSlot(self): """ 手动拖动进度条时改变当前播放进度标签和播放器的值 """ if self.sender() == self.playBar.progressSlider: self.player.setPosition(self.playBar.progressSlider.value()) elif self.sender() == self.playingInterface.playBar.progressSlider: self.player.setPosition( self.playingInterface.playBar.progressSlider.value()) self.playBar.setCurrentTime(self.player.position()) self.playingInterface.playBar.setCurrentTime(self.player.position()) self.playingInterface.smallestModeInterface.progressBar.setValue( self.player.position()) def songCardNextPlaySlot(self, songInfo: dict): """ 下一首播放动作触发对应的槽函数 """ # 直接更新正在播放界面的播放列表 index = self.playlist.currentIndex() newPlaylist = self.playlist.playlist[:index + 1] + \ [songInfo] + self.playlist.playlist[index + 1:] self.playingInterface.setPlaylist(newPlaylist, False) self.playingInterface.setCurrentIndex(self.playlist.currentIndex()) self.playlist.insertMedia(self.playlist.currentIndex() + 1, songInfo) def songCardPlaySlot(self, songInfo: dict): """ 歌曲界面歌曲卡的播放按钮按下或者双击歌曲卡时播放这首歌 """ # 如果当前播放列表模式不是歌曲文件夹的所有歌曲或者指定的歌曲不在播放列表中就刷新播放列表 if self.playlist.playlistType != PlaylistType.ALL_SONG_PLAYLIST or songInfo not in self.playlist.playlist: self.playlist.playlistType = PlaylistType.ALL_SONG_PLAYLIST songInfo_list = self.songTabSongListWidget.songInfo_list index = songInfo_list.index(songInfo) newPlaylist = songInfo_list[index:] + songInfo_list[0:index] self.playlist.setPlaylist(newPlaylist) self.playingInterface.setPlaylist(newPlaylist) # 将播放列表的当前歌曲设置为指定的歌曲 self.playlist.setCurrentSong(songInfo) self.play() def playOneSongCard(self, songInfo: dict): """ 将播放列表重置为一首歌 """ self.playlist.playlistType = PlaylistType.SONG_CARD_PLAYLIST self.setPlaylist([songInfo]) def switchLoopMode(self, loopMode): """ 根据随机播放按钮的状态和循环模式的状态决定播放器的播放模式 """ # 记录按下随机播放前的循环模式 self.playlist.prePlayMode = loopMode # 更新按钮样式 if self.sender() == self.playBar.loopModeButton: self.playingInterface.playBar.loopModeButton.setLoopMode(loopMode) elif self.sender() == self.playingInterface.playBar.loopModeButton: self.playBar.loopModeButton.setLoopMode(loopMode) if not self.playlist.randPlayBtPressed: # 随机播放按钮没按下时,直接设置播放模式为循环模式按钮的状态 self.playlist.setPlaybackMode(loopMode) else: # 随机播放按钮按下时,如果选了单曲循环就直接设置为单曲循环,否则设置为随机播放 if self.playBar.loopModeButton.loopMode == QMediaPlaylist.CurrentItemInLoop: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Random) def setRandomPlay(self): """ 选择随机播放模式 """ isRandomPlay = self.sender().isSelected self.playlist.setRandomPlay(isRandomPlay) if self.sender() == self.playBar.randomPlayButton: self.playingInterface.playBar.randomPlayButton.setRandomPlay( isRandomPlay) elif self.sender() == self.playingInterface.playBar.randomPlayButton: self.playBar.randomPlayButton.setRandomPlay(isRandomPlay) def updateWindow(self, songInfo): """ 切换歌曲时更新歌曲卡、播放栏和子播放窗口 """ self.playBar.updateSongInfoCard(songInfo) index = self.songTabSongListWidget.songInfo_list.index(songInfo) self.songTabSongListWidget.setPlay(index) # 更新专辑界面的歌曲卡 if songInfo in self.albumInterface.songListWidget.songInfo_list: index = self.albumInterface.songListWidget.songInfo_list.index( songInfo) self.albumInterface.songListWidget.setPlay(index) self.subPlayWindow.updateWindow(songInfo) def hotKeySlot(self, funcObj): """ 热键按下时显示子播放窗口并执行对应操作 """ funcObj() self.showSubPlayWindowSig.emit() def playAlbum(self, playlist: list): """ 播放专辑中的歌曲 """ # 直接更新播放列表 self.playingInterface.setPlaylist(playlist) self.playlist.playAlbum(playlist) self.play() def multiSongsNextPlaySlot(self, songInfo_list: list): """ 多首歌下一首播放动作触发对应的槽函数 """ index = self.playlist.currentIndex() newPlaylist = self.playlist.playlist[:index + 1] + \ songInfo_list + self.playlist.playlist[index + 1:] self.playingInterface.setPlaylist(newPlaylist, isResetIndex=False) self.playingInterface.setCurrentIndex(self.playlist.currentIndex()) # insertMedia的时候自动更新playlist列表,所以不必手动更新列表 self.playlist.insertMedias(self.playlist.currentIndex() + 1, songInfo_list) def disorderPlayAll(self): """ 无序播放所有 """ self.playlist.playlistType = PlaylistType.ALL_SONG_PLAYLIST newPlaylist = deepcopy(self.songTabSongListWidget.songInfo_list) shuffle(newPlaylist) self.setPlaylist(newPlaylist) def play(self): """ 播放歌曲并改变按钮样式 """ self.player.play() self.setPlayButtonState(True) # 显示被隐藏的歌曲信息卡 if self.playlist.playlist: if not self.playBar.songInfoCard.isVisible( ) and self.playBar.isVisible(): self.playBar.songInfoCard.show() self.playBar.songInfoCard.updateSongInfoCard( self.playlist.playlist[0]) def initPlayBar(self): """ 从配置文件中读取配置数据来初始化播放栏 """ # 初始化音量 volume = self.settingInterface.config.get('volume', 20) self.playingInterface.playBar.volumeSlider.setValue(volume) # 初始化亚克力颜色 acrylicColor = self.settingInterface.config.get( 'playBar-acrylicColor', '225c7fCC') self.playBar.setAcrylicColor(acrylicColor) def showPlayingInterface(self): """ 显示正在播放界面 """ # 先退出选择模式 self.exitSelectionMode() self.playBar.hide() self.titleBar.title.hide() self.titleBar.returnBt.show() if not self.playingInterface.isPlaylistVisible: self.playingInterface.songInfoCardChute.move( 0, -self.playingInterface.playBar.height() + 68) self.playingInterface.playBar.show() self.totalStackWidget.setCurrentIndex(1) self.titleBar.setWhiteIcon(True) def hidePlayingInterface(self): """ 隐藏正在播放界面 """ self.playBar.show() self.totalStackWidget.setCurrentIndex(0) # 根据当前界面设置标题栏按钮颜色 if self.subStackWidget.currentWidget() == self.albumInterface: self.titleBar.returnBt.setWhiteIcon(False) else: self.titleBar.setWhiteIcon(False) # 隐藏返回按钮 if len( self.titleBar.stackWidgetIndex_list ) == 1 and self.subStackWidget.currentWidget() != self.albumInterface: self.titleBar.returnBt.hide() self.titleBar.title.setVisible(self.navigationInterface.isExpanded) def setQss(self): """ 设置层叠样式 """ with open(r'resource\css\mainWindow.qss', encoding='utf-8') as f: self.setStyleSheet(f.read()) def playingInterfaceCurrrentIndexChangedSlot(self, index): """ 正在播放界面下标变化槽函数 """ self.playlist.setCurrentIndex(index) self.play() def setMute(self, isMute): """ 设置静音 """ self.player.setMuted(isMute) if self.sender() == self.playBar.volumeButton: self.playingInterface.playBar.volumeButton.setMute(isMute) self.playingInterface.playBar.volumeSlider.volumeButton.setMute( isMute) elif self.sender() == self.playingInterface.playBar.volumeSlider: self.playBar.volumeButton.setMute(isMute) def setFullScreen(self): """ 设置全屏 """ if not self.isFullScreen(): # 更新标题栏 self.playBar.hide() self.titleBar.title.hide() self.titleBar.setWhiteIcon(True) self.titleBar.hide() # 切换到正在播放界面 self.totalStackWidget.setCurrentIndex(1) self.showFullScreen() self.playingInterface.playBar.fillScreenButton.setFillScreen(True) if self.playingInterface.isPlaylistVisible: self.playingInterface.songInfoCardChute.move( 0, 258 - self.height()) else: self.exitFullScreen() def exitFullScreen(self): """ 退出全屏 """ if not self.isFullScreen(): return self.showNormal() # 更新最大化按钮图标 self.titleBar.maxBt.setMaxState(False) self.titleBar.returnBt.show() self.titleBar.show() self.playingInterface.playBar.fillScreenButton.setFillScreen(False) if self.playingInterface.isPlaylistVisible: self.playingInterface.songInfoCardChute.move( 0, 258 - self.height()) def crawCompleteSlot(self): """ 爬虫完成信号槽函数 """ self.myMusicInterface.scanTargetPathSongInfo( self.settingInterface.config.get('selected-folders')) def showPlaylist(self): """ 显示正在播放界面的播放列表 """ self.playingInterface.showPlaylist() # 直接设置播放栏上拉箭头按钮箭头方向朝下 self.playingInterface.playBar.pullUpArrowButton.setArrowDirection( 'down') if self.playingInterface.isPlaylistVisible: self.showPlayingInterface() def clearPlaylist(self): """ 清空播放列表 """ self.playlist.playlistType = PlaylistType.NO_PLAYLIST self.playlist.clear() self.playingInterface.clearPlaylist() def addOneSongToPlayingPlaylist(self, songInfo: dict): """ 向正在播放列表尾部添加一首歌 """ self.playlist.addMedia(songInfo) self.playingInterface.setPlaylist(self.playlist.playlist, False) def addSongsToPlayingPlaylist(self, songInfo_list: list): """ 向正在播放列表尾部添加多首歌 """ self.playlist.addMedias(songInfo_list) self.playingInterface.setPlaylist(self.playlist.playlist, False) def switchToAlbumInterfaceByName(self, albumName: str, songerName: str): """ 由名字切换到专辑界面 """ # 处于选择模式下直接返回 if self.isInSelectionMode: return if self.albumInterface.albumInfo.get('album') != albumName or \ self.albumInterface.albumInfo.get('songer') != songerName or not self.currentAlbumCard: self.currentAlbumCard = self.albumCardViewer.findAlbumCardByName( albumName, songerName) if self.currentAlbumCard: self.__switchToAlbumInterface(self.currentAlbumCard.albumInfo) def switchToAlbumInterfaceByAlbumInfo(self, albumInfo: dict): """ 由专辑信息切换到专辑界面 """ # 处于选择模式下直接返回 if self.isInSelectionMode: return # 引用对应的专辑卡 if self.albumInterface.albumInfo != albumInfo or not self.currentAlbumCard: self.currentAlbumCard = self.albumCardViewer.findAlbumCardByAlbumInfo( albumInfo) self.__switchToAlbumInterface(albumInfo) def __switchToAlbumInterface(self, albumInfo: dict): """ 切换到专辑界面 """ # 退出全屏 if self.isFullScreen(): self.exitFullScreen() # 显示返回按钮 self.titleBar.returnBt.show() QApplication.processEvents() self.albumInterface.updateWindow(albumInfo) self.subStackWidget.setCurrentWidget(self.albumInterface, duration=300) self.totalStackWidget.setCurrentIndex(0) self.playBar.show() self.titleBar.setWhiteIcon(True) self.titleBar.returnBt.setWhiteIcon(False) # 根据当前播放的歌曲设置歌曲卡播放状态 songInfo = self.playlist.playlist[self.playlist.currentIndex()] if songInfo in self.albumInterface.songInfo_list: index = self.albumInterface.songInfo_list.index(songInfo) self.albumInterface.songListWidget.setPlay(index) else: self.albumInterface.songListWidget.songCard_list[ self.albumInterface.songListWidget.playingIndex].setPlay(False) def albumInterfaceSongCardPlaySlot(self, index): """ 专辑界面歌曲卡播放按钮按下时 """ albumSongList = self.albumInterface.songInfo_list # 播放模式不为专辑播放模式或者播放列表不同时直接刷新播放列表 cond = self.playlist.playlistType != PlaylistType.ALBUM_CARD_PLAYLIST \ or self.playlist.playlist != albumSongList if cond: self.playAlbum(albumSongList) self.playlist.setCurrentIndex(index) def returnButtonSlot(self): """ 标题栏返回按钮的槽函数 """ if self.isInSelectionMode: return # 隐藏音量条 self.playingInterface.playBar.volumeSlider.hide() if self.totalStackWidget.currentWidget() == self.playingInterface: self.hidePlayingInterface() else: # 当前界面不是albumInterface时弹出下标列表的最后一个下标 if self.titleBar.stackWidgetIndex_list and self.subStackWidget.currentWidget( ) != self.albumInterface: self.titleBar.stackWidgetIndex_list.pop() if self.titleBar.stackWidgetIndex_list: stackWidgetName, index = self.titleBar.stackWidgetIndex_list[ -1] if stackWidgetName == 'myMusicInterfaceStackWidget': self.myMusicInterface.stackedWidget.setCurrentIndex(index) if self.subStackWidget.currentWidget( ) != self.albumInterface: self.subStackWidget.setCurrentIndex( 0, True, False, duration=200, easingCurve=QEasingCurve.InCubic) else: self.subStackWidget.setCurrentIndex(0, True) self.navigationInterface.setCurrentIndex(0) self.myMusicInterface.setSelectedButton(index) elif stackWidgetName == 'subStackWidget': isShowNextWidgetDirectly = not ( self.subStackWidget.currentWidget() is self.settingInterface) self.subStackWidget.setCurrentIndex( index, True, isShowNextWidgetDirectly, 200, QEasingCurve.InCubic) self.navigationInterface.setCurrentIndex(index) if len(self.titleBar.stackWidgetIndex_list) == 1: # 没有上一个下标时隐藏返回按钮 self.titleBar.returnBt.hide() # 更新按钮颜色 self.titleBar.setWhiteIcon(False) def stackWidgetIndexChangedSlot(self, index): """ 堆叠窗口下标改变时的槽函数 """ if self.sender() is self.navigationInterface: if self.subStackWidget.currentIndex() == index: return self.titleBar.stackWidgetIndex_list.append( ('subStackWidget', index)) self.titleBar.setWhiteIcon(False) elif self.sender() is self.myMusicInterface: self.titleBar.stackWidgetIndex_list.append( ('myMusicInterfaceStackWidget', index)) self.titleBar.returnBt.show() def editSongCardSlot(self, oldSongInfo: dict, newSongInfo: dict): """ 编辑歌曲卡完成信号的槽函数 """ self.playlist.updateOneSongInfo(oldSongInfo, newSongInfo) self.playingInterface.updateOneSongCard(oldSongInfo, newSongInfo) if self.sender() == self.albumInterface.songListWidget: self.songTabSongListWidget.updateOneSongCard( oldSongInfo, newSongInfo) elif self.sender() == self.songTabSongListWidget: # 获取专辑信息并更新专辑界面和专辑信息 albumInfo = self.albumCardViewer.updateOneAlbumCardSongInfo( newSongInfo) if albumInfo: self.albumInterface.updateWindow(albumInfo) self.albumInterface.updateOneSongCard(oldSongInfo, newSongInfo) def updateAlbumInfo(self, oldAlbumInfo: dict, newAlbumInfo: dict): """ 更新专辑卡及其对应的歌曲卡信息 """ oldSongInfo_list = oldAlbumInfo['songInfo_list'] newSongInfo_list = newAlbumInfo['songInfo_list'] self.songTabSongListWidget.updateMultiSongCards( deepcopy(oldSongInfo_list), deepcopy(newSongInfo_list)) self.playlist.updateMultiSongInfo(deepcopy(oldSongInfo_list), deepcopy(newSongInfo_list)) self.playingInterface.updateMultiSongCards(deepcopy(oldSongInfo_list), deepcopy(newSongInfo_list)) # 更新专辑标签界面 with open('Data\\songInfo.json', encoding='utf-8') as f: songInfo_list = json.load(f) self.myMusicInterface.updateAlbumCardViewer(songInfo_list) def smallestModeStateChanedSlot(self, state: bool): """ 最小播放模式状态改变时更改标题栏按钮可见性和窗口是否置顶 """ self.titleBar.closeBt.show() self.titleBar.returnBt.setHidden(state) self.titleBar.minBt.setHidden(state) self.titleBar.maxBt.setHidden(state) self.windowEffect.setWindowStayOnTop(self.winId(), state) def showSmallestModeInterface(self): """ 切换到最小化播放模式 """ self.showPlayingInterface() self.playingInterface.showSmallestModeInterface() def selectionModeStateChangedSlot(self, isOpenSelectionMode: bool): """ 进入/退出选择模式信号的槽函数 """ self.isInSelectionMode = isOpenSelectionMode self.playBar.setHidden(isOpenSelectionMode) def playCheckedCards(self, songInfo_list: list): """ 重置播放列表为所有选中的歌曲卡中的歌曲 """ self.playlist.playlistType = PlaylistType.CUSTOM_PLAYLIST self.setPlaylist(songInfo_list) def setPlaylist(self, playlist: list): """ 设置播放列表 """ self.playingInterface.setPlaylist(playlist) self.playlist.setPlaylist(playlist) self.play() def switchToSettingInterface(self): """ 切换到设置界面 """ # 先退出选择模式再切换界面 self.exitSelectionMode() self.subStackWidget.setCurrentWidget(self.settingInterface, duration=300) def switchToMyMusicInterface(self): """ 切换到我的音乐界面 """ self.exitSelectionMode() self.subStackWidget.setCurrentWidget(self.myMusicInterface) def switchToPlaylistCardInterface(self): """ 切换到播放列表卡界面 """ self.exitSelectionMode() self.subStackWidget.setCurrentWidget(self.playlistCardInterface, duration=300) def exitSelectionMode(self): """ 退出选择模式 """ if not self.isInSelectionMode: return self.myMusicInterface.exitSelectionMode() self.albumInterface.exitSelectionMode() self.playlistCardInterface.exitSelectionMode() def readCustomPlaylists(self): """ 读取自定义播放列表 """ # 如果没有播放列表文件夹就创建一个 if not os.path.exists('Playlists'): os.mkdir('Playlists') # 获取播放列表 self.customPlaylists = [] playlistFile_list = os.listdir('Playlists') for playlistFile in playlistFile_list: with open(os.path.join('Playlists', playlistFile), encoding='utf-8') as f: self.customPlaylists.append(json.load(f)) def showCreatePlaylistPanel(self, songInfo_list: list = None): """ 显示创建播放列表面板 """ createPlaylistPanel = CreatePlaylistPanel(self, songInfo_list) createPlaylistPanel.createPlaylistSig.connect(self.createPlaylistSlot) createPlaylistPanel.exec_() def createPlaylistSlot(self, playlist: dict): """ 创建播放列表 """ self.customPlaylists.append(playlist) self.playlistCardInterface.addOnePlaylistCard(playlist) self.navigationInterface.updateWindow() def renamePlaylistSlot(self, oldPlaylist: dict, newPlaylist: dict): """ 重命名播放列表槽函数 """ index = self.customPlaylists.index(oldPlaylist) self.customPlaylists[index] = newPlaylist self.navigationInterface.updateWindow() def removePlaylistSlot(self, playlist: dict): """ 删除播放列表槽函数 """ self.customPlaylists.remove(playlist) self.navigationInterface.updateWindow() def playCustomPlaylist(self, songInfo_list: list): """ 播放自定义播放列表中的所有歌曲 """ self.playCheckedCards(songInfo_list) def addSongsToCustomPlaylist(self, playlistName: str, songInfo_list: list): """ 将歌曲添加到自定义播放列表中 """ playlist = self.playlistCardInterface.addSongsToPlaylist( playlistName, songInfo_list) index = self.getCustomPlaylistIndexByName(playlistName) self.customPlaylists[index] = deepcopy(playlist) def getCustomPlaylistIndexByName(self, playlistName: str) -> int: """ 通过播放列表名字得到播放列表的下标 """ for index, playlist in enumerate(self.customPlaylists): if playlist['playlistName'] == playlistName: return index raise Exception(f'指定的播放列表"{playlistName}"不存在')
class MusicPlayer(QMainWindow): """MusicPlayer houses all of elements that directly interact with the main window.""" def __init__(self, parent=None): """Initialize the QMainWindow widget. The window title, window icon, and window size are initialized here as well as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar, QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and QVBoxLayout. The connect signals for relavant widgets are also initialized. """ super(MusicPlayer, self).__init__(parent) self.setWindowTitle('Mosaic') window_icon = utilities.resource_filename('mosaic.images', 'icon.png') self.setWindowIcon(QIcon(window_icon)) self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) # Initiates Qt objects to be used by MusicPlayer self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist_location = defaults.Settings().playlist_path self.content = QMediaContent() self.menu = self.menuBar() self.toolbar = QToolBar() self.art = QLabel() self.pixmap = QPixmap() self.slider = QSlider(Qt.Horizontal) self.duration_label = QLabel() self.playlist_dock = QDockWidget('Playlist', self) self.library_dock = QDockWidget('Media Library', self) self.playlist_view = QListWidget() self.library_view = library.MediaLibraryView() self.library_model = library.MediaLibraryModel() self.preferences = configuration.PreferencesDialog() self.widget = QWidget() self.layout = QVBoxLayout(self.widget) self.duration = 0 self.playlist_dock_state = None self.library_dock_state = None # Sets QWidget() as the central widget of the main window self.setCentralWidget(self.widget) self.layout.setContentsMargins(0, 0, 0, 0) self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # Initiates the playlist dock widget and the library dock widget self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock) self.playlist_dock.setWidget(self.playlist_view) self.playlist_dock.setVisible(defaults.Settings().playlist_on_start) self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable) self.addDockWidget(defaults.Settings().dock_position, self.library_dock) self.library_dock.setWidget(self.library_view) self.library_dock.setVisible( defaults.Settings().media_library_on_start) self.library_dock.setFeatures(QDockWidget.DockWidgetClosable) self.tabifyDockWidget(self.playlist_dock, self.library_dock) # Sets the range of the playback slider and sets the playback mode as looping self.slider.setRange(0, self.player.duration() / 1000) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) # OSX system menu bar causes conflicts with PyQt5 menu bar if sys.platform == 'darwin': self.menu.setNativeMenuBar(False) # Initiates Settings in the defaults module to give access to settings.toml defaults.Settings() # Signals that connect to other methods when they're called self.player.metaDataChanged.connect(self.display_meta_data) self.slider.sliderMoved.connect(self.seek) self.player.durationChanged.connect(self.song_duration) self.player.positionChanged.connect(self.song_position) self.player.stateChanged.connect(self.set_state) self.playlist_view.itemActivated.connect(self.activate_playlist_item) self.library_view.activated.connect(self.open_media_library) self.playlist.currentIndexChanged.connect(self.change_index) self.playlist.mediaInserted.connect(self.initialize_playlist) self.playlist_dock.visibilityChanged.connect( self.dock_visiblity_change) self.library_dock.visibilityChanged.connect(self.dock_visiblity_change) self.preferences.dialog_media_library.media_library_line.textChanged.connect( self.change_media_library_path) self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect( self.change_window_size) self.art.mousePressEvent = self.press_playback # Creating the menu controls, media controls, and window size of the music player self.menu_controls() self.media_controls() self.load_saved_playlist() def menu_controls(self): """Initiate the menu bar and add it to the QMainWindow widget.""" self.file = self.menu.addMenu('File') self.edit = self.menu.addMenu('Edit') self.playback = self.menu.addMenu('Playback') self.view = self.menu.addMenu('View') self.help_ = self.menu.addMenu('Help') self.file_menu() self.edit_menu() self.playback_menu() self.view_menu() self.help_menu() def media_controls(self): """Create the bottom toolbar and controls used for media playback.""" self.addToolBar(Qt.BottomToolBarArea, self.toolbar) self.toolbar.setMovable(False) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action = QAction(QIcon(play_icon), 'Play', self) self.play_action.triggered.connect(self.player.play) stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png') self.stop_action = QAction(QIcon(stop_icon), 'Stop', self) self.stop_action.triggered.connect(self.player.stop) previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png') self.previous_action = QAction(QIcon(previous_icon), 'Previous', self) self.previous_action.triggered.connect(self.previous) next_icon = utilities.resource_filename('mosaic.images', 'md_next.png') self.next_action = QAction(QIcon(next_icon), 'Next', self) self.next_action.triggered.connect(self.playlist.next) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self) self.repeat_action.triggered.connect(self.repeat_song) self.toolbar.addAction(self.play_action) self.toolbar.addAction(self.stop_action) self.toolbar.addAction(self.previous_action) self.toolbar.addAction(self.next_action) self.toolbar.addAction(self.repeat_action) self.toolbar.addWidget(self.slider) self.toolbar.addWidget(self.duration_label) def file_menu(self): """Add a file menu to the menu bar. The file menu houses the Open File, Open Multiple Files, Open Playlist, Open Directory, and Exit Application menu items. """ self.open_action = QAction('Open File', self) self.open_action.setShortcut('O') self.open_action.triggered.connect(self.open_file) self.open_multiple_files_action = QAction('Open Multiple Files', self) self.open_multiple_files_action.setShortcut('M') self.open_multiple_files_action.triggered.connect( self.open_multiple_files) self.open_playlist_action = QAction('Open Playlist', self) self.open_playlist_action.setShortcut('CTRL+P') self.open_playlist_action.triggered.connect(self.open_playlist) self.open_directory_action = QAction('Open Directory', self) self.open_directory_action.setShortcut('D') self.open_directory_action.triggered.connect(self.open_directory) self.save_playlist_action = QAction('Save Playlist', self) self.save_playlist_action.setShortcut('CTRL+S') self.save_playlist_action.triggered.connect(self.save_playlist) self.exit_action = QAction('Quit', self) self.exit_action.setShortcut('CTRL+Q') self.exit_action.triggered.connect(self.closeEvent) self.file.addAction(self.open_action) self.file.addAction(self.open_multiple_files_action) self.file.addAction(self.open_playlist_action) self.file.addAction(self.open_directory_action) self.file.addSeparator() self.file.addAction(self.save_playlist_action) self.file.addSeparator() self.file.addAction(self.exit_action) def edit_menu(self): """Add an edit menu to the menu bar. The edit menu houses the preferences item that opens a preferences dialog that allows the user to customize features of the music player. """ self.preferences_action = QAction('Preferences', self) self.preferences_action.setShortcut('CTRL+SHIFT+P') self.preferences_action.triggered.connect( lambda: self.preferences.exec_()) self.edit.addAction(self.preferences_action) def playback_menu(self): """Add a playback menu to the menu bar. The playback menu houses """ self.play_playback_action = QAction('Play', self) self.play_playback_action.setShortcut('P') self.play_playback_action.triggered.connect(self.player.play) self.stop_playback_action = QAction('Stop', self) self.stop_playback_action.setShortcut('S') self.stop_playback_action.triggered.connect(self.player.stop) self.previous_playback_action = QAction('Previous', self) self.previous_playback_action.setShortcut('B') self.previous_playback_action.triggered.connect(self.previous) self.next_playback_action = QAction('Next', self) self.next_playback_action.setShortcut('N') self.next_playback_action.triggered.connect(self.playlist.next) self.playback.addAction(self.play_playback_action) self.playback.addAction(self.stop_playback_action) self.playback.addAction(self.previous_playback_action) self.playback.addAction(self.next_playback_action) def view_menu(self): """Add a view menu to the menu bar. The view menu houses the Playlist, Media Library, Minimalist View, and Media Information menu items. The Playlist item toggles the playlist dock into and out of view. The Media Library items toggles the media library dock into and out of view. The Minimalist View item resizes the window and shows only the menu bar and player controls. The Media Information item opens a dialog that shows information relevant to the currently playing song. """ self.dock_action = self.playlist_dock.toggleViewAction() self.dock_action.setShortcut('CTRL+ALT+P') self.library_dock_action = self.library_dock.toggleViewAction() self.library_dock_action.setShortcut('CTRL+ALT+L') self.minimalist_view_action = QAction('Minimalist View', self) self.minimalist_view_action.setShortcut('CTRL+ALT+M') self.minimalist_view_action.setCheckable(True) self.minimalist_view_action.triggered.connect(self.minimalist_view) self.view_media_info_action = QAction('Media Information', self) self.view_media_info_action.setShortcut('CTRL+SHIFT+M') self.view_media_info_action.triggered.connect( self.media_information_dialog) self.view.addAction(self.dock_action) self.view.addAction(self.library_dock_action) self.view.addSeparator() self.view.addAction(self.minimalist_view_action) self.view.addSeparator() self.view.addAction(self.view_media_info_action) def help_menu(self): """Add a help menu to the menu bar. The help menu houses the about dialog that shows the user information related to the application. """ self.about_action = QAction('About', self) self.about_action.setShortcut('H') self.about_action.triggered.connect( lambda: about.AboutDialog().exec_()) self.help_.addAction(self.about_action) def open_file(self): """Open the selected file and add it to a new playlist.""" filename, success = QFileDialog.getOpenFileName( self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: file_info = QFileInfo(filename).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.clear() self.playlist_view.clear() self.playlist.addMedia( QMediaContent(QUrl().fromLocalFile(filename))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_multiple_files(self): """Open the selected files and add them to a new playlist.""" filenames, success = QFileDialog.getOpenFileNames( self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: self.playlist.clear() self.playlist_view.clear() for file in natsort.natsorted(filenames, alg=natsort.ns.PATH): file_info = QFileInfo(file).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.addMedia( QMediaContent(QUrl().fromLocalFile(file))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_playlist(self): """Load an M3U or PLS file into a new playlist.""" playlist, success = QFileDialog.getOpenFileName( self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly) if success: playlist = QUrl.fromLocalFile(playlist) self.playlist.clear() self.playlist_view.clear() self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media( song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def save_playlist(self): """Save the media in the playlist dock as a new M3U playlist.""" playlist, success = QFileDialog.getSaveFileName( self, 'Save Playlist', '', 'Playlist (*.m3u)', '') if success: saved_playlist = "{}.m3u".format(playlist) self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u") def load_saved_playlist(self): """Load the saved playlist if user setting permits.""" saved_playlist = "{}/.m3u".format(self.playlist_location) if os.path.exists(saved_playlist): playlist = QUrl().fromLocalFile(saved_playlist) self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media( song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) def open_directory(self): """Open the selected directory and add the files within to an empty playlist.""" directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly) if directory: self.playlist.clear() self.playlist_view.clear() for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia( QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.playlist_view.setCurrentRow(0) self.player.play() def open_media_library(self, index): """Open a directory or file from the media library into an empty playlist.""" self.playlist.clear() self.playlist_view.clear() if self.library_model.fileName(index).endswith(('mp3', 'flac')): self.playlist.addMedia( QMediaContent(QUrl().fromLocalFile( self.library_model.filePath(index)))) self.playlist_view.addItem(self.library_model.fileName(index)) elif self.library_model.isDir(index): directory = self.library_model.filePath(index) for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia( QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.player.play() def display_meta_data(self): """Display the current song's metadata in the main window. If the current song contains metadata, its cover art is extracted and shown in the main window while the track number, artist, album, and track title are shown in the window title. """ if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path) try: self.pixmap.loadFromData(artwork) except TypeError: self.pixmap = QPixmap(artwork) meta_data = '{} - {} - {} - {}'.format(track_number, artist, album, title) self.setWindowTitle(meta_data) self.art.setScaledContents(True) self.art.setPixmap(self.pixmap) self.layout.addWidget(self.art) def initialize_playlist(self, start): """Display playlist and reset playback mode when media inserted into playlist.""" if start == 0: if self.library_dock.isVisible(): self.playlist_dock.setVisible(True) self.playlist_dock.show() self.playlist_dock.raise_() if self.playlist.playbackMode() != QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename( 'mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def press_playback(self, event): """Change the playback of the player on cover art mouse event. When the cover art is clicked, the player will play the media if the player is either paused or stopped. If the media is playing, the media is set to pause. """ if event.button() == 1 and configuration.Playback( ).cover_art_playback.isChecked(): if (self.player.state() == QMediaPlayer.StoppedState or self.player.state() == QMediaPlayer.PausedState): self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: self.player.pause() def seek(self, seconds): """Set the position of the song to the position dragged to by the user.""" self.player.setPosition(seconds * 1000) def song_duration(self, duration): """Set the slider to the duration of the currently played media.""" duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def song_position(self, progress): """Move the horizontal slider in sync with the duration of the song. The progress is relayed to update_duration() in order to display the time label next to the slider. """ progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.update_duration(progress) def update_duration(self, current_duration): """Calculate the time played and the length of the song. Both of these times are sent to duration_label() in order to display the times on the toolbar. """ duration = self.duration if current_duration or duration: time_played = QTime( (current_duration / 3600) % 60, (current_duration / 60) % 60, (current_duration % 60), (current_duration * 1000) % 1000) song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60), (duration * 1000) % 1000) if duration > 3600: time_format = "hh:mm:ss" else: time_format = "mm:ss" time_display = "{} / {}".format(time_played.toString(time_format), song_length.toString(time_format)) else: time_display = "" self.duration_label.setText(time_display) def set_state(self, state): """Change the icon in the toolbar in relation to the state of the player. The play icon changes to the pause icon when a song is playing and the pause icon changes back to the play icon when either paused or stopped. """ if self.player.state() == QMediaPlayer.PlayingState: pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png') self.play_action.setIcon(QIcon(pause_icon)) self.play_action.triggered.connect(self.player.pause) elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState): self.play_action.triggered.connect(self.player.play) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action.setIcon(QIcon(play_icon)) def previous(self): """Move to the previous song in the playlist. Moves to the previous song in the playlist if the current song is less than five seconds in. Otherwise, restarts the current song. """ if self.player.position() <= 5000: self.playlist.previous() else: self.player.setPosition(0) def repeat_song(self): """Set the current media to repeat and change the repeat icon accordingly. There are four playback modes: repeat none, repeat all, repeat once, and shuffle. Clicking the repeat button cycles through each playback mode. """ if self.playlist.playbackMode() == QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) repeat_on_icon = utilities.resource_filename( 'mosaic.images', 'md_repeat_all.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Loop: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) repeat_on_icon = utilities.resource_filename( 'mosaic.images', 'md_repeat_once.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop: self.playlist.setPlaybackMode(QMediaPlaylist.Random) repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png') self.repeat_action.setIcon(QIcon(repeat_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Random: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def activate_playlist_item(self, item): """Set the active media to the playlist item dobule-clicked on by the user.""" current_index = self.playlist_view.row(item) if self.playlist.currentIndex() != current_index: self.playlist.setCurrentIndex(current_index) if self.player.state() != QMediaPlayer.PlayingState: self.player.play() def change_index(self, row): """Highlight the row in the playlist of the active media.""" self.playlist_view.setCurrentRow(row) def minimalist_view(self): """Resize the window to only show the menu bar and audio controls.""" if self.minimalist_view_action.isChecked(): if self.playlist_dock.isVisible(): self.playlist_dock_state = True if self.library_dock.isVisible(): self.library_dock_state = True self.library_dock.close() self.playlist_dock.close() QTimer.singleShot(10, lambda: self.resize(500, 0)) else: self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) if self.library_dock_state: self.library_dock.setVisible(True) if self.playlist_dock_state: self.playlist_dock.setVisible(True) def dock_visiblity_change(self, visible): """Change the size of the main window when the docks are toggled.""" if visible and self.playlist_dock.isVisible( ) and not self.library_dock.isVisible(): self.resize( defaults.Settings().window_size + self.playlist_dock.width() + 6, self.height()) elif visible and not self.playlist_dock.isVisible( ) and self.library_dock.isVisible(): self.resize( defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif visible and self.playlist_dock.isVisible( ) and self.library_dock.isVisible(): self.resize( defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif (not visible and not self.playlist_dock.isVisible() and not self.library_dock.isVisible()): self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def media_information_dialog(self): """Show a dialog of the current song's metadata.""" if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() else: file_path = None dialog = information.InformationDialog(file_path) dialog.exec_() def change_window_size(self): """Change the window size of the music player.""" self.playlist_dock.close() self.library_dock.close() self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def change_media_library_path(self, path): """Change the media library path to the new path selected in the preferences dialog.""" self.library_model.setRootPath(path) self.library_view.setModel(self.library_model) self.library_view.setRootIndex(self.library_model.index(path)) def closeEvent(self, event): """Override the PyQt close event in order to handle save playlist on close.""" playlist = "{}/.m3u".format(self.playlist_location) if defaults.Settings().save_playlist_on_close: self.playlist.save(QUrl().fromLocalFile(playlist), "m3u") else: if os.path.exists(playlist): os.remove(playlist) QApplication.quit()
class VideoPlayer(QWidget): def __init__(self, parent = None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setMuted(True) #******************************************************************************* # The media player projects the media onto the videoWidget self.videoWidget = QVideoWidget() self.videoWidget.setFixedSize(450,300) #******************************************************************************* # When play is pressed, 'play' is run, and the icon changes according to # its state self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) #******************************************************************************* # This is a movable Qslider self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) #******************************************************************************* # The widgets are thrown together in a layout self.controlLayout = QHBoxLayout() self.controlLayout.setContentsMargins(0,0,0,0) self.controlLayout.addWidget(self.playButton) self.controlLayout.addWidget(self.positionSlider) self.controlLayout.setAlignment(Qt.AlignBottom) self.superLayout = QVBoxLayout() self.superLayout.addWidget(self.videoWidget) self.superLayout.addLayout(self.controlLayout) self.superLayout.addStretch(1) self.setLayout(self.superLayout) #******************************************************************************* self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) # This is where the selected video location is stored self.videoPath = None # Makes sure the videoWidget is centred frame = self.videoWidget.frameGeometry() centre = frame.center() frame.moveCenter(centre) self.move(frame.topLeft()) #******************************************************************************* def openFile(self): if self.videoPath != None: content = QMediaContent(QUrl.fromLocalFile(self.videoPath)) self.playButton.setEnabled(True) self.mediaPlayer.setMedia(content) #******************************************************************************* def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() self.videoWidget.setFixedSize(451,301) else: self.mediaPlayer.play() self.videoWidget.setFixedSize(452,301) #******************************************************************************* def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) #******************************************************************************* def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position)
class frame(QWidget): def __init__(self, parent=None): super().__init__(parent) self.resize(300, 300) self.setFixedSize(300, 300) self.playbtn = QPushButton(self) self.playbtn.setText("播放") self.playbtn.clicked.connect(self.play) self.stopbtn = QPushButton(self) self.stopbtn.setText("暂停") self.stopbtn.clicked.connect(self.stop) self.addbtn = QPushButton(self) self.addbtn.setText("添加") self.addbtn.clicked.connect(self.add) self.nextbtn = QPushButton(self) self.nextbtn.setText("下一首") self.nextbtn.clicked.connect(self.nextsong) self.previousbtn = QPushButton(self) self.previousbtn.setText("上一首") self.previousbtn.clicked.connect(self.previous) self.modebtn = QPushButton(self) self.modebtn.setText("列表循环") self.modebtn.clicked.connect(self.Playback_mode) self.deletebtn = QPushButton(self) self.deletebtn.setText("删除") self.deletebtn.clicked.connect(self.delete) self.list = QListWidget() self.list.itemDoubleClicked.connect(self.play) self.slider = QSlider(Qt.Horizontal, self) #进度条 self.slider.setMinimumHeight(5) self.slider.setMinimumWidth(250) # self.slider.setRange(0, 300) # self.slider.setOrientation(Qt.Horizontal) #设置水平方向 self.timeLabel = QLabel(self) self.timeLabel.setText("00:00 / 00:00") self.volumeslilder = QSlider(Qt.Horizontal, self) #音量 self.volumeslilder.setMaximumHeight(4) self.volumeslilder.setMinimumWidth(50) self.volumeslilder.setRange(0, 100) self.volumeslilder.setValue(25) # self.volumeslilder.setOrientation(Qt.Horizontal) self.volumeslilder.valueChanged.connect(self.volume) #滑块值变化信号 # self.connect(self.volumeslilder, QtCore.SIGNAL('valueChanged(int)'),self.volume) self.sound = QLabel(self) # self.sound.setFixedWidth(20) # self.sound.setFixedHeight(20) self.sound.setFixedSize(20, 20) self.sound.setPixmap(QPixmap("F:\\untitled\\volume.png")) #在label上显示图片 self.sound.setScaledContents(True) #让图片自适应label大小 self.soundlayout = QHBoxLayout() self.soundlayout.addWidget(self.sound) self.soundlayout.addWidget(self.volumeslilder) self.soundlayout.addStretch() slqW = QWidget() slqW.setLayout(self.soundlayout) self.timelayout = QVBoxLayout() self.timelayout.addWidget(self.slider) self.timelayout.addWidget(self.timeLabel) self.layout = QHBoxLayout() self.layout.addWidget(self.stopbtn) self.layout.addWidget(self.playbtn) self.layout.addWidget(self.deletebtn) self.layout.addWidget(self.addbtn) self.la = QHBoxLayout() self.la.addWidget(self.previousbtn) self.la.addWidget(self.modebtn) self.la.addWidget(self.nextbtn) qW = QWidget() qW.setLayout(self.layout) qW2 = QWidget() qW2.setLayout(self.la) qW3 = QWidget() qW3.setLayout(self.timelayout) self.layout2 = QVBoxLayout() self.layout2.addWidget(self.list) self.layout2.addWidget(qW3) self.layout2.addWidget(slqW) self.layout2.addWidget(qW) self.layout2.addWidget(qW2) self.setLayout(self.layout2) self.player = QMediaPlayer() # 创建播放媒体 self.player.setVolume(10) self.playlist = QMediaPlaylist() # 创建播放列表 self.player.setPlaylist(self.playlist) self.timer = QTimer(self) self.timer.setInterval(400) self.timer.timeout.connect(self.update) self.slider.sliderMoved.connect(self.timedate) self.slider.sliderReleased.connect(self.SliderMoved) def timedate(self): pass def add(self): FileName, FileType = QFileDialog.getOpenFileName( self, "添加音乐", "F:\\M", "All Files (*);;Mp3 Files (*.mp3);; Wma Files (*.wma);;M4a Files (*.m4a)" ) if FileName: search = re.compile(r".*/(.*)") SongName = search.search(FileName) self.list.addItem(SongName.group(1)) self.player.playlist().addMedia( QMediaContent(QUrl.fromLocalFile(FileName))) #添加到播放列表 # self.player.setPlaylist(self.playlist) else: pass # self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def play(self): if self.list.currentRow() == -1: pass else: # print(self.list.currentRow()) self.player.playlist().setPlaybackMode(QMediaPlaylist.Loop) self.player.playlist().setCurrentIndex(self.list.currentRow()) # self.player.positionChanged() self.player.play() self.timer.start() def stop(self): if self.player.playlist().currentIndex() == -1: pass else: print(self.player.playlist().currentIndex()) if self.stopbtn.text() == "暂停": self.player.pause() self.timer.stop() self.stopbtn.setText("继续") else: self.player.play() self.timer.start() self.stopbtn.setText("暂停") def nextsong(self): #下一首 if self.list.currentRow() != -1: self.player.playlist().next() def previous(self): #上一首 print(self.list.currentRow()) if self.list.currentRow() != -1: self.player.playlist().previous() def Playback_mode(self): if self.modebtn.text() == "列表循环": self.player.playlist().setPlaybackMode( QMediaPlaylist.CurrentItemInLoop) # 单曲循环 self.modebtn.setText("单曲循环") else: self.player.playlist().setPlaybackMode(QMediaPlaylist.Loop) #列表循环 self.modebtn.setText("列表循环") def delete(self): self.player.playlist().removeMedia( self.player.playlist().currentIndex()) self.list.takeItem(self.list.currentRow()) def volume(self): #改变音量 self.player.setVolume(self.volumeslilder.value() * 2) def SliderMoved(self): #滑动滑块 self.player.setPosition(self.slider.value()) self.slider.setSliderPosition(self.player.position()) self.timer.start() def update(self): self.slider.setMaximum(self.player.duration()) self.timeLabel.setText( str( strftime("%M:%S", localtime(self.player.position() / 1000.0)) + " / " + str( strftime("%M:%S", localtime(self.player.duration() / 1000.0)))) ) #将毫秒转换为分秒(时间戳为秒,需要除以1000.0) self.slider.setSliderPosition(self.player.position())
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle( "PyQt Video Player Widget Example - pythonprogramminglanguage.com") self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QAction(QIcon('icon/folder.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create menu bar and add action menuBar = self.addToolBar('open') #fileMenu.addAction(newAction) menuBar.addAction(openAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def openFile(self, filename): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def exitCall(self): sys.exit(app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
class VideoPlayer(QWidget): def __init__(self, repl_globals=None, position_var_name=None, file_name_var_name=None, parent=None): super(VideoPlayer, self).__init__(parent) self.uuid = uuid.uuid4() self.repl_globals = repl_globals self.position_var_name = position_var_name self.file_name_var_name = file_name_var_name self.frame_position = self.repl_globals[self.position_var_name] self.setGeometry(100, 300, 600, 380) self.timer = QTimer() self.timer.timeout.connect(self.on_timer_tick) self.timer.start(ct.TIMER_UPDATE_TIME_MILLIS) self.setAttribute(Qt.WA_NoSystemBackground, True) self.setAcceptDrops(True) self.media_player = QMediaPlayer(None, QMediaPlayer.StreamPlayback) self.media_player.setVolume(80) self.video_widget = QVideoWidget(self) self.media_player.setVideoOutput(self.video_widget) self.media_player.stateChanged.connect(self.on_media_state_changed) self.media_player.positionChanged.connect(self.on_position_change) self.media_player.positionChanged.connect(self.handle_label) self.media_player.durationChanged.connect(self.on_duration_changed) self.media_player.error.connect(self.handle_error) self.frame_viewer = QLineEdit(str(self.media_player.position())) self.frame_viewer.setReadOnly(True) self.frame_viewer.setFixedWidth(70) self.frame_viewer.setUpdatesEnabled(True) self.frame_viewer.setStyleSheet(stylesheet(self)) self.time_viewer = QLineEdit('00:00:00') self.time_viewer.setReadOnly(True) self.time_viewer.setFixedWidth(70) self.time_viewer.setUpdatesEnabled(True) self.time_viewer.setStyleSheet(stylesheet(self)) self.full_time_viewer = QLineEdit('00:00:00') self.full_time_viewer.setReadOnly(True) self.full_time_viewer.setFixedWidth(70) self.full_time_viewer.setUpdatesEnabled(True) self.full_time_viewer.setStyleSheet(stylesheet(self)) self.playButton = QPushButton() self.playButton.setFixedWidth(32) self.playButton.setStyleSheet("background-color: black") self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.position_slider = QSlider(Qt.Horizontal, self) self.position_slider.setStyleSheet(stylesheet(self)) self.position_slider.setRange(0, 100) self.position_slider.sliderMoved.connect(self.set_position) self.position_slider.sliderMoved.connect(self.handle_label) self.position_slider.setSingleStep(1) self.position_slider.setPageStep(20) self.position_slider.setAttribute(Qt.WA_TranslucentBackground, True) slider_controls_layout = QHBoxLayout() slider_controls_layout.setContentsMargins(5, 0, 5, 0) slider_controls_layout.addWidget(self.playButton) slider_controls_layout.addWidget(self.frame_viewer) slider_controls_layout.addWidget(self.time_viewer) slider_controls_layout.addWidget(self.position_slider) slider_controls_layout.addWidget(self.full_time_viewer) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.video_widget) layout.addLayout(slider_controls_layout) self.setLayout(layout) self.myinfo = "©2019\nGeorge Dimitriadis\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \ "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \ "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes" #### shortcuts #### self.shortcut = QShortcut(QKeySequence("q"), self) self.shortcut.activated.connect(self.handle_quit) self.shortcut = QShortcut(QKeySequence(" "), self) self.shortcut.activated.connect(self.play) self.shortcut = QShortcut(QKeySequence("f"), self) self.shortcut.activated.connect(self.handle_fullscreen) self.shortcut = QShortcut(QKeySequence("i"), self) self.shortcut.activated.connect(self.handle_info) self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self) self.shortcut.activated.connect(self.forward_slider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self) self.shortcut.activated.connect(self.back_slider) self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self) self.shortcut.activated.connect(self.volume_up) self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self) self.shortcut.activated.connect(self.volume_down) self.shortcut = QShortcut( QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self) self.shortcut.activated.connect(self.forward_slider_10) self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left), self) self.shortcut.activated.connect(self.back_slider_10) self.widescreen = True self.setAcceptDrops(True) self.load_film(self.repl_globals[self.file_name_var_name]) def on_position_change(self, position): self.position_slider.setValue(position) self.repl_globals[self.position_var_name] = position def play(self): if self.media_player.state() == QMediaPlayer.PlayingState: self.media_player.pause() else: self.media_player.play() def on_media_state_changed(self, state): if self.media_player.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def on_duration_changed(self, duration): self.position_slider.setRange(0, duration) mtime = QTime(0, 0, 0, 0) mtime = mtime.addMSecs(self.media_player.duration()) self.full_time_viewer.setText(mtime.toString()) def set_position(self, position): self.media_player.setPosition(position) self.media_player.pause() def handle_error(self): self.playButton.setEnabled(False) print("Error: ", self.media_player.errorString()) def handle_quit(self): self.media_player.stop() del open_windows[self.uuid] self.close() def closeEvent(self, event): self.handle_quit() event.accept() def handle_fullscreen(self): if self.windowState() & Qt.WindowFullScreen: self.showNormal() print("no Fullscreen") else: self.showFullScreen() print("Fullscreen entered") def handle_info(self): msg = QMessageBox.about(self, "QT5 Player", self.myinfo) def forward_slider(self): self.media_player.setPosition(self.media_player.position() + 1000 * 60) def forward_slider_10(self): self.media_player.setPosition(self.media_player.position() + 10000 * 60) def back_slider(self): self.media_player.setPosition(self.media_player.position() - 1000 * 60) def back_slider_10(self): self.media_player.setPosition(self.media_player.position() - 10000 * 60) def volume_up(self): self.media_player.setVolume(self.media_player.volume() + 10) print("Volume: " + str(self.media_player.volume())) def volume_down(self): self.media_player.setVolume(self.media_player.volume() - 10) print("Volume: " + str(self.media_player.volume())) def load_film(self, f): self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(f))) self.playButton.setEnabled(True) self.media_player.pause() def handle_label(self): self.time_viewer.clear() mtime = QTime(0, 0, 0, 0) self.time = mtime.addMSecs(self.media_player.position()) self.time_viewer.setText(self.time.toString()) self.frame_viewer.setText(str(self.media_player.position())) def on_timer_tick(self): if self.media_player.state() != QMediaPlayer.PlayingState: self.media_player.setPosition( self.repl_globals[self.position_var_name]) def mouseMoveEvent(self, event): if event.buttons() == Qt.LeftButton: self.move(event.globalPos() \ - QPoint(self.frameGeometry().width() / 2, \ self.frameGeometry().height() / 2)) event.accept()
class EventAction(): def __init__(self): #self.parent = parent self.isLoop = 0 #0循环列表,1单曲循环 self.isRandom = 0 #0不随机,1随机 self.fileList = [] #曲目名称列表 self.randomList =[] #播放列表 self.soundID = 0 #当前歌曲ID self.playStat = False #当前播放状态 (0未播放,1播放) self.openPath = "F:/mp3/" #歌曲目录 self.isPreview = 0 #试用开关,0正常播放,1列表中的歌曲每首歌曲放10秒 self.currentVolume = 0.1#默认的起始音量 self.isInitPlay = 1 #是否是初始播放 #==>>打开目录 self.config=configparser.ConfigParser() self.config.read('config.ini') self.openDir() #打开目录<<== self.playObj = QMediaPlayer() self.currentImg = "" #当前图片 self.songText = {} #歌词 self.songTextKey=[] #歌词KEY #打开歌曲目录 def openDir(self): self.openPath = self.config.get('Save','musicPath') isMusicDir = os.path.isdir(self.openPath)#检查是否为目录 if isMusicDir: dirFile = os.listdir(self.openPath)#目录中的所有文件 #遍历有效音乐文件 i=0; for file in dirFile: fileName,fileType=os.path.splitext(file) if fileType==".mp3" or fileType==".wav": self.fileList.append(file) self.randomList.append(i) i+=1 if self.isRandom==1: self.shuffleMusic(1) #随机(打乱播放顺序) def shuffleMusic(self,isshuffle): if isshuffle: random.shuffle(self.randomList)#乱序 else: self.randomList.sort()#排序 #初始化播放 def initPlay(self): self.soundID = int(self.config.get('Save','soundID')) self.playStat = self.config.get('Save','playStat') self.pastTime = self.config.getint('Save','pastTime') self.currentVolume = self.config.getint('Save','volume') self.isRandom = self.config.getint('Save','isRandom') self.isLoop = self.config.getint('Save','isLoop') if self.soundID!="": self.play(self.soundID) if self.isRandom:#打乱列表 self.shuffleMusic(1) self.playObj.setVolume(self.currentVolume) #播放 def play(self,i): source = self.openPath + self.fileList[i] self.playObj.setMedia(QMediaContent(QUrl.fromLocalFile(source))) #解析文件中的ID3V2 self.currentImg = "" f = QFile(source) if f.open(QIODevice.ReadOnly): #读取标签 headData = f.read(10) data = headData[:0] if self.id3v2(headData):#检测是否有ID3 #标签的大小计算 tag = headData[6:10] tagSize = (tag[0]&0x7f)*0x200000+(tag[1]&0x7f)*0x4000+(tag[2]&0x7f)*0x80+(tag[3]&0x7f) data =f.read(tagSize) while len(data)>10: data = self.resolve(data) f.close() self.playObj.play() def testPlay(self): #ps =QMediaMetaData() #print("QMediaMetaData",ps) #print("metaData",self.playObj.metaData(QMediaMetaData.Title)) #print("position",self.playObj.position()) #print("playlist",self.playObj.playlist) #print("availability",self.playObj.availability()) #print("bufferStatus",self.playObj.bufferStatus()) #print("currentMedia",self.playObj.currentMedia()) #print("currentNetworkConfiguration",self.playObj.currentNetworkConfiguration()) #print("duration",self.playObj.duration()) #print("error",self.playObj.error()) #print("errorString",self.playObj.errorString()) #print("isAudioAvailable",self.playObj.isAudioAvailable()) #print("isMuted",self.playObj.isMuted()) #print("isSeekable",self.playObj.isSeekable()) #print("media",self.playObj.media()) #print("media:::::::A",self.playObj.media().canonicalResource().audioBitRate()) #print("media:::::::B",self.playObj.media().canonicalResource().audioCodec()) #print("media:::::::C",self.playObj.media().canonicalResource().channelCount()) #print("media:::::::D",self.playObj.media().canonicalResource().dataSize()) #print("media:::::::e",self.playObj.media().canonicalResource().isNull()) #print("media:::::::f",self.playObj.media().canonicalResource().language()) #print("media:::::::g",self.playObj.media().canonicalResource().mimeType()) #print("media:::::::h",self.playObj.media().canonicalResource().request()) #print("isVideoAvailable",self.playObj.isVideoAvailable()) #print("mediaStatus",self.playObj.mediaStatus()) #print("mediaStream",self.playObj.mediaStream()) #print("playbackRate",self.playObj.playbackRate()) #print("state",self.playObj.state()) #print("volume",self.playObj.volume()) # print("volume",self.playObj.filename) pass #换歌之前先停止,释放内存 def stopPlay(self): self.playObj.pause() #上一首 def prevPlay(self): self.stopPlay() if self.isRandom: key = self.searchID(self.soundID)-1 if key<0: key=0 self.soundID = self.randomList[key] else: self.soundID-=1 if self.soundID< 0: self.soundID = len(self.randomList)-1 self.play(self.soundID) #下一首 def nextPlay(self): self.stopPlay() if self.isRandom: key = self.searchID(self.soundID)+1 if key>(len(self.randomList)-1): key=len(self.randomList)-1 self.soundID = self.randomList[key] else: self.soundID+=1 if self.soundID > (len(self.randomList)-1): self.soundID = 0 #print("next:::",self.soundID) self.play(self.soundID) #快退 def rewindPlay(self): #print("<<") rewindTime = int(self.playObj.position()) - 10*1000 if rewindTime < 0: rewindTime = 0 self.playObj.setPosition(rewindTime) #快进 def forwardPlay(self): #print(">>") forwardTime = int(self.playObj.position()) + 10*1000 if forwardTime > int(self.playObj.duration()): forwardTime = int(self.playObj.duration()) self.playObj.setPosition(forwardTime) #播放/暂停 def playORpause(self): if self.playObj.state()==1: self.playObj.pause() else: self.playObj.play() #音量加 def raisevolPlay(self): self.playObj.setVolume(self.playObj.volume()+10) self.currentVolume = self.playObj.volume() #音量减 def lowervolPlay(self): self.playObj.setVolume(self.playObj.volume()-10) self.currentVolume = self.playObj.volume() #静音 def mutePlay(self): if self.playObj.isMuted(): self.playObj.setMuted(False) else: self.playObj.setMuted(True) #volume #跟据v找K def searchID(self,v): for index, item in enumerate(self.randomList): if item ==v: return index return 0 #解析文件中是否有id3v2 def id3v2(self,headData): if str(headData[:3],encoding=("utf-8")) != "ID3": return False return True #解析文件中的歌词与图片 def resolve(self,data): tagName = str(data[:4],encoding=("utf-8")) size = data[4:8] #sizeS = size[0]*0x1000000 + size[1]*0x10000 + size[2]*0x100 + size[3] sizeS=int.from_bytes(size, byteorder='big') flags = data[8:10] tagContent = data[10:sizeS+10] if tagName=="TEXT":#歌词 #print("歌词") condingType=int.from_bytes(tagContent[:1], byteorder='big') if condingType == 0:#0代表字符使用ISO-8859-1编码方式; try: content = str(tagContent[1:],encoding="gbk") except: content ="" elif condingType == 1:#1代表字符使用UTF-16编码方式; try: content = str(tagContent[1:],encoding="UTF-16") except: content ="" elif condingType == 2:#2代表字符使用 UTF-16BE编码方式; content ="" elif condingType == 3:#3代表字符使用UTF-8编码方式。 try: content = str(tagContent[1:],encoding="UTF-8") except: content ="" if content!="": temp={} self.songTextKey=[] contentSplit = content.splitlines() for k in range(len(contentSplit)): if contentSplit[k][1].isdigit(): xxx = contentSplit[k].split("]") tempKey = "%d" %(int(xxx[0][1:3])*60 +int(xxx[0][4:6]) ) temp[str(tempKey)] = xxx[1] self.songTextKey.append(tempKey) else: endKey = contentSplit[k].find("]",0) self.songTextKey.append(k) temp[str(k)] = contentSplit[k][1:endKey] self.songText = temp else: self.songText = {} elif tagName=="APIC":#图片 #print("图片") self.currentImg = tagContent[17:] return data[10+sizeS:]
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() openButton = QPushButton("Open...") openButton.clicked.connect(self.openFile) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) self.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) print(fileName) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
class MusicPlayer(QMainWindow): """MusicPlayer houses all of elements that directly interact with the main window.""" def __init__(self, parent=None): """Initialize the QMainWindow widget. The window title, window icon, and window size are initialized here as well as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar, QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and QVBoxLayout. The connect signals for relavant widgets are also initialized. """ super(MusicPlayer, self).__init__(parent) self.setWindowTitle('Mosaic') window_icon = utilities.resource_filename('mosaic.images', 'icon.png') self.setWindowIcon(QIcon(window_icon)) self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) # Initiates Qt objects to be used by MusicPlayer self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.playlist_location = defaults.Settings().playlist_path self.content = QMediaContent() self.menu = self.menuBar() self.toolbar = QToolBar() self.art = QLabel() self.pixmap = QPixmap() self.slider = QSlider(Qt.Horizontal) self.duration_label = QLabel() self.playlist_dock = QDockWidget('Playlist', self) self.library_dock = QDockWidget('Media Library', self) self.playlist_view = QListWidget() self.library_view = library.MediaLibraryView() self.library_model = library.MediaLibraryModel() self.preferences = configuration.PreferencesDialog() self.widget = QWidget() self.layout = QVBoxLayout(self.widget) self.duration = 0 self.playlist_dock_state = None self.library_dock_state = None # Sets QWidget() as the central widget of the main window self.setCentralWidget(self.widget) self.layout.setContentsMargins(0, 0, 0, 0) self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # Initiates the playlist dock widget and the library dock widget self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock) self.playlist_dock.setWidget(self.playlist_view) self.playlist_dock.setVisible(defaults.Settings().playlist_on_start) self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable) self.addDockWidget(defaults.Settings().dock_position, self.library_dock) self.library_dock.setWidget(self.library_view) self.library_dock.setVisible(defaults.Settings().media_library_on_start) self.library_dock.setFeatures(QDockWidget.DockWidgetClosable) self.tabifyDockWidget(self.playlist_dock, self.library_dock) # Sets the range of the playback slider and sets the playback mode as looping self.slider.setRange(0, self.player.duration() / 1000) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) # OSX system menu bar causes conflicts with PyQt5 menu bar if sys.platform == 'darwin': self.menu.setNativeMenuBar(False) # Initiates Settings in the defaults module to give access to settings.toml defaults.Settings() # Signals that connect to other methods when they're called self.player.metaDataChanged.connect(self.display_meta_data) self.slider.sliderMoved.connect(self.seek) self.player.durationChanged.connect(self.song_duration) self.player.positionChanged.connect(self.song_position) self.player.stateChanged.connect(self.set_state) self.playlist_view.itemActivated.connect(self.activate_playlist_item) self.library_view.activated.connect(self.open_media_library) self.playlist.currentIndexChanged.connect(self.change_index) self.playlist.mediaInserted.connect(self.initialize_playlist) self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change) self.library_dock.visibilityChanged.connect(self.dock_visiblity_change) self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path) self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size) self.art.mousePressEvent = self.press_playback # Creating the menu controls, media controls, and window size of the music player self.menu_controls() self.media_controls() self.load_saved_playlist() def menu_controls(self): """Initiate the menu bar and add it to the QMainWindow widget.""" self.file = self.menu.addMenu('File') self.edit = self.menu.addMenu('Edit') self.playback = self.menu.addMenu('Playback') self.view = self.menu.addMenu('View') self.help_ = self.menu.addMenu('Help') self.file_menu() self.edit_menu() self.playback_menu() self.view_menu() self.help_menu() def media_controls(self): """Create the bottom toolbar and controls used for media playback.""" self.addToolBar(Qt.BottomToolBarArea, self.toolbar) self.toolbar.setMovable(False) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action = QAction(QIcon(play_icon), 'Play', self) self.play_action.triggered.connect(self.player.play) stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png') self.stop_action = QAction(QIcon(stop_icon), 'Stop', self) self.stop_action.triggered.connect(self.player.stop) previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png') self.previous_action = QAction(QIcon(previous_icon), 'Previous', self) self.previous_action.triggered.connect(self.previous) next_icon = utilities.resource_filename('mosaic.images', 'md_next.png') self.next_action = QAction(QIcon(next_icon), 'Next', self) self.next_action.triggered.connect(self.playlist.next) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self) self.repeat_action.setShortcut('R') self.repeat_action.triggered.connect(self.repeat_song) self.toolbar.addAction(self.play_action) self.toolbar.addAction(self.stop_action) self.toolbar.addAction(self.previous_action) self.toolbar.addAction(self.next_action) self.toolbar.addAction(self.repeat_action) self.toolbar.addWidget(self.slider) self.toolbar.addWidget(self.duration_label) def file_menu(self): """Add a file menu to the menu bar. The file menu houses the Open File, Open Multiple Files, Open Playlist, Open Directory, and Exit Application menu items. """ self.open_action = QAction('Open File', self) self.open_action.setShortcut('O') self.open_action.triggered.connect(self.open_file) self.open_multiple_files_action = QAction('Open Multiple Files', self) self.open_multiple_files_action.setShortcut('M') self.open_multiple_files_action.triggered.connect(self.open_multiple_files) self.open_playlist_action = QAction('Open Playlist', self) self.open_playlist_action.setShortcut('CTRL+P') self.open_playlist_action.triggered.connect(self.open_playlist) self.open_directory_action = QAction('Open Directory', self) self.open_directory_action.setShortcut('D') self.open_directory_action.triggered.connect(self.open_directory) self.save_playlist_action = QAction('Save Playlist', self) self.save_playlist_action.setShortcut('CTRL+S') self.save_playlist_action.triggered.connect(self.save_playlist) self.exit_action = QAction('Quit', self) self.exit_action.setShortcut('CTRL+Q') self.exit_action.triggered.connect(self.closeEvent) self.file.addAction(self.open_action) self.file.addAction(self.open_multiple_files_action) self.file.addAction(self.open_playlist_action) self.file.addAction(self.open_directory_action) self.file.addSeparator() self.file.addAction(self.save_playlist_action) self.file.addSeparator() self.file.addAction(self.exit_action) def edit_menu(self): """Add an edit menu to the menu bar. The edit menu houses the preferences item that opens a preferences dialog that allows the user to customize features of the music player. """ self.preferences_action = QAction('Preferences', self) self.preferences_action.setShortcut('CTRL+SHIFT+P') self.preferences_action.triggered.connect(lambda: self.preferences.exec_()) self.edit.addAction(self.preferences_action) def playback_menu(self): """Add a playback menu to the menu bar. The playback menu houses """ self.play_playback_action = QAction('Play', self) self.play_playback_action.setShortcut('P') self.play_playback_action.triggered.connect(self.player.play) self.stop_playback_action = QAction('Stop', self) self.stop_playback_action.setShortcut('S') self.stop_playback_action.triggered.connect(self.player.stop) self.previous_playback_action = QAction('Previous', self) self.previous_playback_action.setShortcut('B') self.previous_playback_action.triggered.connect(self.previous) self.next_playback_action = QAction('Next', self) self.next_playback_action.setShortcut('N') self.next_playback_action.triggered.connect(self.playlist.next) self.playback.addAction(self.play_playback_action) self.playback.addAction(self.stop_playback_action) self.playback.addAction(self.previous_playback_action) self.playback.addAction(self.next_playback_action) def view_menu(self): """Add a view menu to the menu bar. The view menu houses the Playlist, Media Library, Minimalist View, and Media Information menu items. The Playlist item toggles the playlist dock into and out of view. The Media Library items toggles the media library dock into and out of view. The Minimalist View item resizes the window and shows only the menu bar and player controls. The Media Information item opens a dialog that shows information relevant to the currently playing song. """ self.dock_action = self.playlist_dock.toggleViewAction() self.dock_action.setShortcut('CTRL+ALT+P') self.library_dock_action = self.library_dock.toggleViewAction() self.library_dock_action.setShortcut('CTRL+ALT+L') self.minimalist_view_action = QAction('Minimalist View', self) self.minimalist_view_action.setShortcut('CTRL+ALT+M') self.minimalist_view_action.setCheckable(True) self.minimalist_view_action.triggered.connect(self.minimalist_view) self.view_media_info_action = QAction('Media Information', self) self.view_media_info_action.setShortcut('CTRL+SHIFT+M') self.view_media_info_action.triggered.connect(self.media_information_dialog) self.view.addAction(self.dock_action) self.view.addAction(self.library_dock_action) self.view.addSeparator() self.view.addAction(self.minimalist_view_action) self.view.addSeparator() self.view.addAction(self.view_media_info_action) def help_menu(self): """Add a help menu to the menu bar. The help menu houses the about dialog that shows the user information related to the application. """ self.about_action = QAction('About', self) self.about_action.setShortcut('H') self.about_action.triggered.connect(lambda: about.AboutDialog().exec_()) self.help_.addAction(self.about_action) def open_file(self): """Open the selected file and add it to a new playlist.""" filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: file_info = QFileInfo(filename).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.clear() self.playlist_view.clear() self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_multiple_files(self): """Open the selected files and add them to a new playlist.""" filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly) if success: self.playlist.clear() self.playlist_view.clear() for file in natsort.natsorted(filenames, alg=natsort.ns.PATH): file_info = QFileInfo(file).fileName() playlist_item = QListWidgetItem(file_info) self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) self.player.setPlaylist(self.playlist) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def open_playlist(self): """Load an M3U or PLS file into a new playlist.""" playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly) if success: playlist = QUrl.fromLocalFile(playlist) self.playlist.clear() self.playlist_view.clear() self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media(song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) self.player.play() def save_playlist(self): """Save the media in the playlist dock as a new M3U playlist.""" playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '') if success: saved_playlist = "{}.m3u" .format(playlist) self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u") def load_saved_playlist(self): """Load the saved playlist if user setting permits.""" saved_playlist = "{}/.m3u" .format(self.playlist_location) if os.path.exists(saved_playlist): playlist = QUrl().fromLocalFile(saved_playlist) self.playlist.load(playlist) self.player.setPlaylist(self.playlist) for song_index in range(self.playlist.mediaCount()): file_info = self.playlist.media(song_index).canonicalUrl().fileName() playlist_item = QListWidgetItem(file_info) playlist_item.setToolTip(file_info) self.playlist_view.addItem(playlist_item) self.playlist_view.setCurrentRow(0) def open_directory(self): """Open the selected directory and add the files within to an empty playlist.""" directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly) if directory: self.playlist.clear() self.playlist_view.clear() for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.playlist_view.setCurrentRow(0) self.player.play() def open_media_library(self, index): """Open a directory or file from the media library into an empty playlist.""" self.playlist.clear() self.playlist_view.clear() if self.library_model.fileName(index).endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index)))) self.playlist_view.addItem(self.library_model.fileName(index)) elif self.library_model.isDir(index): directory = self.library_model.filePath(index) for dirpath, __, files in os.walk(directory): for filename in natsort.natsorted(files, alg=natsort.ns.PATH): file = os.path.join(dirpath, filename) if filename.endswith(('mp3', 'flac')): self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file))) playlist_item = QListWidgetItem(filename) playlist_item.setToolTip(filename) self.playlist_view.addItem(playlist_item) self.player.setPlaylist(self.playlist) self.player.play() def display_meta_data(self): """Display the current song's metadata in the main window. If the current song contains metadata, its cover art is extracted and shown in the main window while the track number, artist, album, and track title are shown in the window title. """ if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path) try: self.pixmap.loadFromData(artwork) except TypeError: self.pixmap = QPixmap(artwork) meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title) self.setWindowTitle(meta_data) self.art.setScaledContents(True) self.art.setPixmap(self.pixmap) self.layout.addWidget(self.art) def initialize_playlist(self, start): """Display playlist and reset playback mode when media inserted into playlist.""" if start == 0: if self.library_dock.isVisible(): self.playlist_dock.setVisible(True) self.playlist_dock.show() self.playlist_dock.raise_() if self.playlist.playbackMode() != QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def press_playback(self, event): """Change the playback of the player on cover art mouse event. When the cover art is clicked, the player will play the media if the player is either paused or stopped. If the media is playing, the media is set to pause. """ if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked(): if (self.player.state() == QMediaPlayer.StoppedState or self.player.state() == QMediaPlayer.PausedState): self.player.play() elif self.player.state() == QMediaPlayer.PlayingState: self.player.pause() def seek(self, seconds): """Set the position of the song to the position dragged to by the user.""" self.player.setPosition(seconds * 1000) def song_duration(self, duration): """Set the slider to the duration of the currently played media.""" duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def song_position(self, progress): """Move the horizontal slider in sync with the duration of the song. The progress is relayed to update_duration() in order to display the time label next to the slider. """ progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.update_duration(progress) def update_duration(self, current_duration): """Calculate the time played and the length of the song. Both of these times are sent to duration_label() in order to display the times on the toolbar. """ duration = self.duration if current_duration or duration: time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60, (current_duration % 60), (current_duration * 1000) % 1000) song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60), (duration * 1000) % 1000) if duration > 3600: time_format = "hh:mm:ss" else: time_format = "mm:ss" time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format)) else: time_display = "" self.duration_label.setText(time_display) def set_state(self, state): """Change the icon in the toolbar in relation to the state of the player. The play icon changes to the pause icon when a song is playing and the pause icon changes back to the play icon when either paused or stopped. """ if self.player.state() == QMediaPlayer.PlayingState: pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png') self.play_action.setIcon(QIcon(pause_icon)) self.play_action.triggered.connect(self.player.pause) elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState): self.play_action.triggered.connect(self.player.play) play_icon = utilities.resource_filename('mosaic.images', 'md_play.png') self.play_action.setIcon(QIcon(play_icon)) def previous(self): """Move to the previous song in the playlist. Moves to the previous song in the playlist if the current song is less than five seconds in. Otherwise, restarts the current song. """ if self.player.position() <= 5000: self.playlist.previous() else: self.player.setPosition(0) def repeat_song(self): """Set the current media to repeat and change the repeat icon accordingly. There are four playback modes: repeat none, repeat all, repeat once, and shuffle. Clicking the repeat button cycles through each playback mode. """ if self.playlist.playbackMode() == QMediaPlaylist.Sequential: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Loop: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png') self.repeat_action.setIcon(QIcon(repeat_on_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop: self.playlist.setPlaybackMode(QMediaPlaylist.Random) repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png') self.repeat_action.setIcon(QIcon(repeat_icon)) elif self.playlist.playbackMode() == QMediaPlaylist.Random: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png') self.repeat_action.setIcon(QIcon(repeat_icon)) def activate_playlist_item(self, item): """Set the active media to the playlist item dobule-clicked on by the user.""" current_index = self.playlist_view.row(item) if self.playlist.currentIndex() != current_index: self.playlist.setCurrentIndex(current_index) if self.player.state() != QMediaPlayer.PlayingState: self.player.play() def change_index(self, row): """Highlight the row in the playlist of the active media.""" self.playlist_view.setCurrentRow(row) def minimalist_view(self): """Resize the window to only show the menu bar and audio controls.""" if self.minimalist_view_action.isChecked(): if self.playlist_dock.isVisible(): self.playlist_dock_state = True if self.library_dock.isVisible(): self.library_dock_state = True self.library_dock.close() self.playlist_dock.close() QTimer.singleShot(10, lambda: self.resize(500, 0)) else: self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) if self.library_dock_state: self.library_dock.setVisible(True) if self.playlist_dock_state: self.playlist_dock.setVisible(True) def dock_visiblity_change(self, visible): """Change the size of the main window when the docks are toggled.""" if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6, self.height()) elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible(): self.resize(defaults.Settings().window_size + self.library_dock.width() + 6, self.height()) elif (not visible and not self.playlist_dock.isVisible() and not self.library_dock.isVisible()): self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def media_information_dialog(self): """Show a dialog of the current song's metadata.""" if self.player.isMetaDataAvailable(): file_path = self.player.currentMedia().canonicalUrl().toLocalFile() else: file_path = None dialog = information.InformationDialog(file_path) dialog.exec_() def change_window_size(self): """Change the window size of the music player.""" self.playlist_dock.close() self.library_dock.close() self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63) def change_media_library_path(self, path): """Change the media library path to the new path selected in the preferences dialog.""" self.library_model.setRootPath(path) self.library_view.setModel(self.library_model) self.library_view.setRootIndex(self.library_model.index(path)) def closeEvent(self, event): """Override the PyQt close event in order to handle save playlist on close.""" playlist = "{}/.m3u" .format(self.playlist_location) if defaults.Settings().save_playlist_on_close: self.playlist.save(QUrl().fromLocalFile(playlist), "m3u") else: if os.path.exists(playlist): os.remove(playlist) QApplication.quit()
class VideoWindow(QMainWindow): def __init__(self, parent=None): super(VideoWindow, self).__init__(parent) self.setWindowTitle(title + ' ' + version) self.setWindowFlags(Qt.X11BypassWindowManagerHint) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) # Create new action openAction = QAction(QIcon('open.png'), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open movie') openAction.triggered.connect(self.openFile) # Create new action downloadAction = QAction('&Download Youtube Video', self) downloadAction.setStatusTip('Download youtube video') downloadAction.triggered.connect(self.youtubeDownloadPopup) # Create exit action exitAction = QAction(QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self.exitCall) # Create menu bar and add action menuBar = self.menuBar() fileMenu = menuBar.addMenu('&File') #fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(downloadAction) fileMenu.addAction(exitAction) # Create a widget for window contents wid = QWidget(self) self.setCentralWidget(wid) # Create layouts to place inside widget controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) # Set widget to contain window contents wid.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) # app.setStyleSheet(qdarkgraystyle.load_stylesheet()) # Force the style to be the same on all OSs: # app.setStyle("Fusion") app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5()) # # Now use a palette to switch to dark colors: # palette = QPalette() # 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(42, 130, 218)) # palette.setColor(QPalette.Highlight, QColor(42, 130, 218)) # palette.setColor(QPalette.HighlightedText, Qt.black) # app.setPalette(palette) def openFile(self): fileName, _ = QFileDialog.getOpenFileName( self, "Open Movie", QDir.homePath() + "/Videos", "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)" ) if fileName.endswith('.mp4'): reader = imageio.get_reader(fileName) fps = reader.get_meta_data()['fps'] fileName = fileName.replace('.mp4', '.avi') writer = imageio.get_writer(fileName, fps=fps) for im in reader: writer.append_data(im[:, :, :]) writer.close() if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) self.play() def exitCall(self): sys.exit(app.exec_()) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString()) def youtubeDownloadPopup(self): # self.close() self.youtube_download_popup = youtube_download( 'Download Youtube Video') self.youtube_download_popup.setFixedSize(300, 120) self.youtube_download_popup.setWindowTitle('Download Youtube Video') # self.youtube_download_popup.setWindowIcon(QtGui.QIcon('add.png')) self.youtube_download_popup.show()
class GameWindow(QWidget): def __init__(self, parent=None): super(GameWindow,self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.mediaPlayer.setVideoOutput(self.videoWidget) self.stringLabel = QLabel() self.stringLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.stringLabel.setTextFormat(Qt.RichText) self.stringLabel.setAlignment(Qt.AlignHCenter) layout = QVBoxLayout() layout.addWidget(self.videoWidget) layout.addWidget(self.stringLabel) self.setLayout(layout) self.mediaPlayer.positionChanged.connect(self.positionChanged) def openFile(self, fileName): if fileName != '': self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(fileName))) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def playV(self, file, rate, visibility, labelString): self.position = 0 self.startPos = 0 self.duration = 0 self.durChanged = False self.stopPos = False self.openFile(file) self.mediaPlayer.setPlaybackRate(rate) if visibility: self.videoWidget.show() self.stringLabel.show() self.stringLabel.setText(labelString) else: self.videoWidget.hide() self.stringLabel.show() self.stringLabel.setText(labelString) self.play() def closeEvent(self, event): event.ignore() self.mediaPlayer.stop() super(GameWindow, self).closeEvent(event) def positionChanged(self, pos): self.position = pos if not self.durChanged and self.position > 0: self.durationChanged(self.mediaPlayer.duration()) self.durChanged = True if self.startPos > 0 and not self.stopPos and not self.videoWidget.isVisible(): if self.position > self.startPos + 20000: self.play() self.stopPos = True def durationChanged(self, dur): self.duration = dur if self.duration > 40000 and not self.videoWidget.isVisible(): self.startPos = random.randint(5000, self.duration - 25000) self.mediaPlayer.setPosition(self.startPos) def showPoints(self, pointsString): self.videoWidget.hide() self.stringLabel.show() self.stringLabel.setText(pointsString)
class BasicVideoWidget(QVideoWidget): def __init__(self, *args, **kwargs): super(BasicVideoWidget, self).__init__(*args, **kwargs) self.mediaPlayer = QMediaPlayer(parent=self) self.setMediaObject(self.mediaPlayer) 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.mediaPlayer.setMedia(mc) def load(self, path): self.loadUrl(QUrl.fromLocalFile(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 PlaybackPanel(SpecialLabel): desktop_lyric_state_changed_signal = pyqtSignal(bool) playmode_changed_signal = pyqtSignal(int, int) media_player_notify_signal = pyqtSignal(int) muted_changed_signal = pyqtSignal(int) mark_favorite_completed_signal = pyqtSignal() current_media_changed_signal = pyqtSignal() music_ended_signal = pyqtSignal() update_window_lyric_signal = pyqtSignal(str, str) show_artist_info_signal = pyqtSignal(str) dont_hide_main_window_signal = pyqtSignal() def __init__(self, parent=None): super(PlaybackPanel, self).__init__(parent) self.initial_mediaplayer() self.create_actions() self.setup_ui() self.create_connections() self.initial_params() def create_connections(self): self.artistHeadLabel.clicked.connect(self.show_artist_info) self.desktopLyric.hide_desktop_lyric_signal.connect(self.desktop_lyric_closed) self.seekSlider.valueChanged.connect(self.slider_value_changed) self.seekSlider.sliderPressed.connect(self.slider_pressed) self.seekSlider.sliderReleased.connect(self.seek) self.mediaPlayer.positionChanged.connect(self.tick) self.mediaPlayer.mutedChanged.connect(self.muted_changed_signal.emit) self.mediaPlayer.stateChanged.connect(self.state_changed) self.mediaPlayer.durationChanged.connect(self.duration_changed) self.mediaPlayer.mediaStatusChanged.connect(self.media_status_changed) self.mediaPlayer.currentMediaChanged.connect(self.current_media_changed) def initial_mediaplayer(self): self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setNotifyInterval(500) self.set_volume(globalSettings.Volume) def initial_params(self): self.playlist = None self.artistName = "Zheng-Yejian" self.clickPlayFlag = False # 用来标志一首歌是否是主动点击选中的 self.timerFlag = False self.timeStart = 0 self.timeSpan = 0 self.sourcePath = "" self.errorType = Configures.NoError self.currentSourceRow = -1 self.nearPlayedSongs = [] self.downloadDir = globalSettings.DownloadfilesPath self.songinfosManager = SonginfosManager() self.totalTime = Configures.ZeroTime self.playmode = Configures.PlaymodeRandom # 播放模式指示器 playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) self.lovedSongs = playlistTemp.get_titles() def set_playlist(self, playlist): self.playlist = playlist self.currentSourceRow = self.playlist.get_current_row() def create_actions(self): self.nextAction = QAction(QIcon(IconsHub.ControlNext), "下一首", self, enabled=True, triggered=self.next_song) self.playAction = QAction(QIcon(IconsHub.ControlPlay), "播放/暂停", self, enabled=True, triggered=self.play_music) self.previousAction = QAction( QIcon(IconsHub.ControlPrevious), "上一首", self, enabled=True, triggered=self.previous_song ) self.stopAction = QAction( QIcon(IconsHub.ControlStop), "停止", self, enabled=True, triggered=self.stop_music_but_timing ) def get_play_button_action(self): return self.playAction def get_previous_button_action(self): return self.previousAction def get_next_button_action(self): return self.nextAction def get_stop_button_action(self): return self.stopAction def set_download_dir(self, dir): self.downloadDir = dir def get_loved_songs(self): return self.lovedSongs def get_songinfos_manager(self): return self.songinfosManager def setup_ui(self): self.setFixedHeight(50) # 桌面歌词标签 self.desktopLyric = desktop_lyric.DesktopLyric() self.desktopLyric.set_color(globalSettings.DesktoplyricColors) # 3个标签 self.artistHeadLabel = LabelButton() self.artistHeadLabel.setToolTip(self.tr("查看歌手信息")) self.artistHeadLabel.setFixedSize(QSize(42, 42)) self.artistHeadLabel.setScaledContents(True) self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous)) self.musicTitleLabel = NewLabel() self.musicTitleLabel.setObjectName("musicTitleLabel") self.musicTitleLabel.setFixedSize(QSize(370, 20)) self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER") self.timeLabel = QLabel("00:00/00:00") self.timeLabel.setObjectName("timeLabel") self.timeLabel.setFixedHeight(20) self.timeLabel.setAlignment(Qt.AlignRight and Qt.AlignVCenter) # 五个基本按键 self.playmodeButton = QToolButton(clicked=self.change_playmode) self.playmodeButton.setFocusPolicy(Qt.NoFocus) self.playmodeButton.setIcon(QIcon(IconsHub.PlaymodeRandom)) self.playmodeButton.setIconSize(QSize(25, 25)) self.playmodeButton.setToolTip("随机播放") self.favoriteButton = QToolButton(clicked=self.mark_as_favorite) self.favoriteButton.setFocusPolicy(Qt.NoFocus) self.favoriteButton.setToolTip("收藏") self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setIconSize(QSize(20, 20)) self.previousButton = QToolButton() self.previousButton.setFocusPolicy(Qt.NoFocus) self.previousButton.setIconSize(QSize(40, 40)) self.previousButton.setShortcut(QKeySequence("Ctrl + Left")) self.previousButton.setDefaultAction(self.previousAction) self.playButton = QToolButton() self.playButton.setFocusPolicy(Qt.NoFocus) self.playButton.setIconSize(QSize(40, 40)) self.playButton.setShortcut(QKeySequence("Ctrl + Down")) self.playButton.setDefaultAction(self.playAction) self.nextButton = QToolButton() self.nextButton.setFocusPolicy(Qt.NoFocus) self.nextButton.setIconSize(QSize(40, 40)) self.nextButton.setFocusPolicy(Qt.NoFocus) self.nextButton.setShortcut(QKeySequence("Ctrl + Right")) self.nextButton.setDefaultAction(self.nextAction) self.desktopLyricButton = QToolButton(clicked=self.show_desktop_lyric) self.desktopLyricButton.setToolTip(self.tr("桌面歌词")) self.desktopLyricButton.setFocusPolicy(Qt.NoFocus) self.desktopLyricButton.setIcon(QIcon(IconsHub.DesktopLyric)) self.desktopLyricButton.setIconSize(QSize(25, 25)) self.seekSlider = QSlider(Qt.Horizontal) self.seekSlider.setObjectName("seekSlider") self.seekSlider.setFixedHeight(20) self.seekSlider.setFocusPolicy(Qt.NoFocus) self.seekSlider.setRange(0, 0) hbox1 = QHBoxLayout() hbox1.addWidget(self.favoriteButton) hbox1.addWidget(self.musicTitleLabel) hbox1.addStretch() hbox1.addWidget(self.timeLabel) vbox1 = QVBoxLayout() vbox1.addLayout(hbox1) vbox1.setSpacing(5) vbox1.addWidget(self.seekSlider) mainLayout = QHBoxLayout(self) mainLayout.setContentsMargins(2, 0, 0, 0) mainLayout.addWidget(self.artistHeadLabel) mainLayout.addWidget(self.previousButton) mainLayout.addWidget(self.playButton) mainLayout.addWidget(self.nextButton) mainLayout.addLayout(vbox1) mainLayout.addWidget(self.playmodeButton) mainLayout.addWidget(self.desktopLyricButton) def show_desktop_lyric(self): if self.desktopLyric.isHidden(): beToOff = True self.desktopLyric.show() self.desktopLyric.original_place() else: beToOff = False self.desktopLyric.hide() self.desktop_lyric_state_changed_signal.emit(beToOff) def desktop_lyric_closed(self): self.desktop_lyric_state_changed_signal.emit(False) def change_playmode(self): oldPlaymode = self.playmode if self.playmode == Configures.PlaymodeRandom: self.set_new_playmode(Configures.PlaymodeOrder) elif self.playmode == Configures.PlaymodeOrder: self.set_new_playmode(Configures.PlaymodeSingle) elif self.playmode == Configures.PlaymodeSingle: self.set_new_playmode(Configures.PlaymodeRandom) self.playmode_changed_signal.emit(oldPlaymode, self.playmode) def set_new_playmode(self, playmode): self.playmode = playmode if playmode == Configures.PlaymodeRandom: iconPath = IconsHub.PlaymodeRandom toolTip = Configures.PlaymodeRandomText elif playmode == Configures.PlaymodeOrder: iconPath = IconsHub.PlaymodeOrder toolTip = Configures.PlaymodeOrderText else: iconPath = IconsHub.PlaymodeSingle toolTip = Configures.PlaymodeSingleText self.playmodeButton.setIcon(QIcon(iconPath)) self.playmodeButton.setToolTip(toolTip) def ui_initial(self): self.mediaPlayer.stop() self.totalTime = "00:00" self.playAction.setIcon(QIcon(IconsHub.ControlPlay)) self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER") self.artistName = "Zheng-Yejian" self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous)) self.seekSlider.setRange(0, 0) self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setToolTip("收藏") self.timeLabel.setText("00:00/00:00") def set_volume(self, volume): self.mediaPlayer.setVolume(volume) def set_muted(self, muted): self.mediaPlayer.setMuted(muted) def tick(self): currentTime = self.mediaPlayer.position() self.seekSlider.setValue(currentTime) cTime = format_position_to_mmss(currentTime // 1000) self.timeLabel.setText(cTime + "/" + self.totalTime) self.media_player_notify_signal.emit(currentTime) def slider_value_changed(self, value): cTime = format_position_to_mmss(value // 1000) self.timeLabel.setText("%s/%s" % (cTime, self.totalTime)) self.media_player_notify_signal.emit(value) def slider_pressed(self): self.mediaPlayer.positionChanged.disconnect(self.tick) def seek(self): if self.mediaPlayer.state() == QMediaPlayer.StoppedState: self.mediaPlayer.play() self.mediaPlayer.setPosition(self.seekSlider.value()) else: self.mediaPlayer.setPosition(self.seekSlider.value()) self.mediaPlayer.play() self.mediaPlayer.positionChanged.connect(self.tick) def duration_changed(self, duration): self.seekSlider.setMaximum(duration) exactTotalTime = format_position_to_mmss(self.mediaPlayer.duration() // 1000) self.timeLabel.setText("%s/%s" % (Configures.ZeroTime, exactTotalTime)) if self.totalTime != exactTotalTime: self.totalTime = exactTotalTime self.playlist.set_music_time_at(self.currentSourceRow, exactTotalTime) def check_favorite(self): if self.currentSourceRow >= 0: if self.playlist.get_music_title_at(self.currentSourceRow) in self.lovedSongs: self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setToolTip("取消收藏") else: self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo)) self.favoriteButton.setToolTip("收藏") if self.playlist.get_name() == Configures.PlaylistFavorite: self.favoriteButton.setToolTip("收藏") def mark_as_favorite(self): if ( self.playlist.get_name() == Configures.PlaylistFavorite or not self.playlist.length() or self.currentSourceRow < 0 ): return path = self.playlist.get_music_path_at(self.currentSourceRow) title = self.playlist.get_music_title_at(self.currentSourceRow) if self.playlist.get_name() == Configures.PlaylistOnline: musicName = get_full_music_name_from_title(title) musicPath = os.path.join(self.downloadDir, musicName) musicPathO = os.path.join(Configures.MusicsDir, musicName) if not os.path.exists(musicPath) and not os.path.exists(musicPathO): QMessageBox.information(self, "提示", "请先下载该歌曲再添加喜欢!") return if os.path.exists(musicPath): path = musicPath else: path = musicPathO elif not os.path.exists(path): QMessageBox.information(self, "提示", "路径'" + "%s" % path + "'无效,无法标记喜欢!") return playlistTemp = Playlist() playlistTemp.fill_list(Configures.PlaylistFavorite) if title in self.lovedSongs: playlistTemp.remove_item_at(self.lovedSongs.index(title)) playlistTemp.commit_records() self.lovedSongs.remove(title) self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo)) self.favoriteButton.setToolTip("收藏") else: playlistTemp.add_item_from_path(path) playlistTemp.commit_records() self.lovedSongs.append(title) self.favoriteButton.setIcon(QIcon(IconsHub.Favorites)) self.favoriteButton.setToolTip("取消收藏") self.mark_favorite_completed_signal.emit() def show_artist_info(self): if self.artistName: self.show_artist_info_signal.emit(self.artistName) def decide_to_play_or_pause(self, row): if row != self.currentSourceRow: self.set_media_source_at_row(row, clickPlayFlag=True) elif self.mediaPlayer.state() in (QMediaPlayer.PausedState, QMediaPlayer.StoppedState): self.mediaPlayer.play() elif self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() def set_media_source_at_row(self, row, clickPlayFlag=False): if not self.playlist.length() or row < 0: return self.stop_music() self.clickPlayFlag = clickPlayFlag self.playlist.set_current_row(row) sourcePath = self.playlist.get_music_path_at(row) self.title = self.playlist.get_music_title_at(row) self.sourceTrace = "local" if self.playlist.get_music_id_at(row) == Configures.LocalMusicId else "online" self.artistName, self.musicName = get_artist_and_musicname_from_title(self.title) self.playlistName = self.playlist.get_name() self.totalTime = self.playlist.get_music_time_at(row) self.album = self.playlist.get_music_album_at(row) self.errorType = Configures.NoError isAnUrl = False if not os.path.exists(sourcePath): if self.playlist.get_name() == Configures.PlaylistOnline: if sourcePath == Configures.NoLink: musicId = self.playlist.get_music_id_at(row) sourcePath = SearchOnline.get_song_link(musicId) if sourcePath: self.playlist.set_music_path_at(row, sourcePath) else: self.errorType = Configures.UrlError isAnUrl = True else: self.errorType = Configures.PathError sourcePath = "/usr/share/sounds/error_happened.ogg" if self.errorType == Configures.NoError: self.sourcePath = sourcePath self.musicFileName = get_base_name_from_path(sourcePath) self.playedDate = get_time_of_now() self.songinfosManager.update_datas_of_item( self.musicFileName, self.playedDate, self.musicName, self.artistName, self.totalTime, self.album, self.playlistName, ) if not self.timerFlag: self.timerFlag = True self.timeSpan = 0 if isAnUrl: url = QUrl(sourcePath) else: url = QUrl.fromLocalFile(sourcePath) self.play_from_url(url) else: self.timerFlag = False self.dont_hide_main_window_signal.emit() if self.errorType == Configures.DisnetError: QMessageBox.critical( self, "错误", "联网出错!\n无法联网播放歌曲'%s'!\n您最好在网络畅通时下载该曲目!" % self.playlist.get_music_title_at(row) ) elif self.errorType == Configures.PathError: QMessageBox.information(self, "提示", "路径'%s'无效,请尝试重新下载并添加对应歌曲!" % self.playlist.get_music_path_at(row)) def play_from_url(self, url): mediaContent = QMediaContent(url) self.mediaPlayer.setMedia(mediaContent) self.mediaPlayer.play() def state_changed(self, newState): if self and newState in [QMediaPlayer.PlayingState, QMediaPlayer.PausedState, QMediaPlayer.StoppedState]: if not self.playlist.length(): return iconPath = IconsHub.ControlPause if newState in [QMediaPlayer.StoppedState, QMediaPlayer.PausedState]: iconPath = IconsHub.ControlPlay icon = QIcon(iconPath) self.playAction.setIcon(icon) if self.timerFlag: if newState == QMediaPlayer.PlayingState: self.timeStart = time.time() else: self.timeSpan += time.time() - self.timeStart def media_status_changed(self, status): if status == QMediaPlayer.EndOfMedia: self.music_finished() def music_finished(self): if self.errorType == Configures.NoError: self.next_song() def play_music(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def stop_music_but_timing(self): self.mediaPlayer.stop() self.seekSlider.setValue(0) self.media_player_notify_signal.emit(-0.5) def stop_music(self): self.stop_music_but_timing() if self.timerFlag: self.timerFlag = False InfosList = [ self.playedDate, self.musicFileName, self.musicName, self.artistName, self.album, "%i" % change_mmss_to_seconds(self.totalTime), "%.1f" % self.timeSpan, self.playlistName, self.sourcePath, "%i" % (self.title in self.lovedSongs), self.sourceTrace, Configures.Playmodes[self.playmode], "%i" % self.clickPlayFlag, ] log_playback_history(organized_list_as_str(InfosList)) self.songinfosManager.update_time_span_relate_of_item(self.musicFileName, self.timeSpan, self.clickPlayFlag) self.clickPlayFlag = False def get_next_random_row(self): listTemp = list(self.playlist.get_ids() - set(self.nearPlayedSongs)) ran = random.randint(0, len(listTemp) - 1) return self.playlist.get_items_queue().index(listTemp[ran]) def get_next_single_row(self): nextRow = self.currentSourceRow if nextRow < 0: nextRow = 0 return nextRow def get_next_order_row(self, reverse=False): if reverse: if self.currentSourceRow < 0: self.currentSourceRow = 0 return (self.currentSourceRow - 1) % self.playlist.length() return (self.currentSourceRow + 1) % self.playlist.length() def previous_song(self): self.play_source_on_next_row(reverse=True) def next_song(self): self.play_source_on_next_row() def play_source_on_next_row(self, reverse=False): if not self.playlist.length(): return if self.mediaPlayer.position() > 20: self.music_ended_signal.emit() nextRow = 0 if self.playmode == Configures.PlaymodeRandom: nextRow = self.get_next_random_row() elif self.playmode == Configures.PlaymodeOrder: nextRow = self.get_next_order_row(reverse) elif self.playmode == Configures.PlaymodeSingle: nextRow = self.get_next_single_row() self.set_media_source_at_row(nextRow) def current_media_changed(self): if not self.playlist.length(): return self.current_media_changed_signal.emit() self.update_parameters() self.update_near_played_queue() self.check_favorite() def update_parameters(self): self.currentSourceRow = self.playlist.get_current_row() self.musicTitleLabel.setText(self.title) self.playAction.setText(self.musicName) imagePath = SearchOnline.get_artist_image_path(self.artistName) if imagePath: pixmap = QPixmap(imagePath) else: pixmap = QPixmap(IconsHub.Anonymous) self.artistHeadLabel.setPixmap(pixmap) musicId = self.playlist.get_music_id_at(self.currentSourceRow) self.update_window_lyric_signal.emit(self.title, musicId) def update_near_played_queue(self): self.currentSourceId = self.playlist.get_music_path_at(self.currentSourceRow) if self.playlist.get_name() == Configures.PlaylistOnline: self.currentSourceId = self.playlist.get_music_id_at(self.currentSourceRow) if self.currentSourceId not in self.nearPlayedSongs: self.nearPlayedSongs.append(self.currentSourceId) while len(self.nearPlayedSongs) >= self.playlist.length() * 4 / 5: del self.nearPlayedSongs[0] def add_title_into_loved_songs(self, title): self.lovedSongs.append(title)
class SongList(QWidget): def __init__(self, parent=None): super(SongList, self).__init__(parent) os.chdir(os.path.dirname(os.path.abspath(__file__))) resourcesPath = os.getcwd() resourcesPath = os.path.join(resourcesPath, "resources") self.PLAY_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "play.png"))) self.PAUSE_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "pause.png"))) self.STOP_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "stop.png"))) self.DELETE_ICON = QIcon(QPixmap(os.path.join(resourcesPath, "delete.png"))) self.setupMediaPlayer() self.setupUi() def setupMediaPlayer(self): self.mediaPlayer = QMediaPlayer() self.mediaPlayer.setNotifyInterval(1) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) def setupUi(self): self.setWindowTitle("List of songs") mainLayout = QHBoxLayout(self) verticalListLayout = QVBoxLayout() self.songsListWidget = QListWidget() self.songsListWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.songsListWidget.customContextMenuRequested.connect(self.listWidgetRightClick) verticalListLayout.addWidget(self.songsListWidget) miniHorizontalLayout = QHBoxLayout() locatorLine = QLineEdit() locatorLine.setPlaceholderText("Locator") locatorBox = QComboBox() items = ["Title", "Status", "Description", "Style", "All"] locatorBox.addItems(items) locatorBox.setCurrentIndex(len(items)-1) miniHorizontalLayout.addWidget(locatorLine) miniHorizontalLayout.addWidget(locatorBox) locatorLine.textChanged.connect(lambda:self.populateList(locatorLine.text(), locatorBox.currentText())) verticalListLayout.addLayout(miniHorizontalLayout) self.mainForm = QGroupBox() self.mainForm.setTitle("Details") mainLayout.addLayout(verticalListLayout) mainLayout.addWidget(self.mainForm) self.populateList() self.mainFormSetupUi() #self.show() self.songsListWidget.currentRowChanged.connect(self.changePage) def mainFormSetupUi(self): """title, status style, duration, descriptin, location, project, variation_another_song, timestamp""" mainLayout = QVBoxLayout(self.mainForm) #Horizontal Layout 1 horizontalLayout1 = QHBoxLayout() titleLabel = QLabel("Song name:") self.titleEdit = QLineEdit() self.titleEdit.editingFinished.connect(self.checkSong) self.titleEdit.textChanged.connect(self.validateSong) horizontalLayout1.addWidget(titleLabel) horizontalLayout1.addWidget(self.titleEdit) #Horizontal Layout 2 horizontalLayout2 = QHBoxLayout() statusLabel = QLabel("Status:") self.statusBox = QComboBox() dateLabel = QLabel("Date:") self.dateEdit = QDateTimeEdit() self.dateEdit.setCalendarPopup(True) horizontalLayout2.addWidget(statusLabel) horizontalLayout2.addWidget(self.statusBox) horizontalLayout2.addStretch(1) horizontalLayout2.addWidget(dateLabel) horizontalLayout2.addWidget(self.dateEdit) #Style Groupbox, widgets added automatically self.styleGroupBox = QGroupBox() self.styleGroupBox.setTitle("Style:") self.styleLayout = QGridLayout(self.styleGroupBox) horizontalLayout3 = QHBoxLayout() durationLabel = QLabel("Duration:") self.durationLine = QTimeEdit() self.durationLine.setDisplayFormat("mm:ss") projectLabel = QLabel("Project") self.projectComboBox = QComboBox() self.projectComboBox.setEditable(True) horizontalLayout3.addWidget(durationLabel) horizontalLayout3.addWidget(self.durationLine) horizontalLayout3.addWidget(projectLabel) horizontalLayout3.addWidget(self.projectComboBox) horizontalLayout4 = QHBoxLayout() descriptionLabel = QLabel("Description:") variationLabel = QLabel("Variation from another song: ") self.variationLine = QLineEdit() horizontalLayout4.addWidget(descriptionLabel) horizontalLayout4.addStretch(1) horizontalLayout4.addWidget(variationLabel) horizontalLayout4.addWidget(self.variationLine) self.descriptionTextEdit = QTextEdit() horizontalLayout5 = QHBoxLayout() locationLabel = QLabel("Location:") self.locationLine = QLineEdit() self.locationButton = QPushButton("...") self.locationButton.clicked.connect(self.locateFile) horizontalLayout5.addWidget(locationLabel) horizontalLayout5.addWidget(self.locationLine) horizontalLayout5.addWidget(self.locationButton) horizontalLayout6 = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.sliderReleased.connect(self.playSlider) self.slider.setStyleSheet("QSlider::handle:horizontal { border: 1px solid #777; background:#b55858;}") horizontalLayout6.addWidget(self.slider) horizontalLayout7 = QHBoxLayout() self.playButton = QPushButton() self.stopButton = QPushButton() self.playButton.setIcon(self.PLAY_ICON) self.stopButton.setIcon(self.STOP_ICON) self.playButton.clicked.connect(self.playSong) self.stopButton.clicked.connect(self.stopSong) horizontalLayout7.addStretch(1) horizontalLayout7.addWidget(self.playButton) horizontalLayout7.addWidget(self.stopButton) horizontalLayout7.addStretch(1) horizontalLayout8 = QHBoxLayout() self.saveButton = QPushButton() self.saveButton.setText("Save") self.saveButton.clicked.connect(self.saveSong) horizontalLayout8.addStretch(1) horizontalLayout8.addWidget(self.saveButton) mainLayout.addLayout(horizontalLayout1) mainLayout.addLayout(horizontalLayout2) mainLayout.addWidget(self.styleGroupBox) mainLayout.addLayout(horizontalLayout3) mainLayout.addLayout(horizontalLayout4) mainLayout.addWidget(self.descriptionTextEdit) mainLayout.addLayout(horizontalLayout5) mainLayout.addLayout(horizontalLayout6) mainLayout.addLayout(horizontalLayout7) mainLayout.addLayout(horizontalLayout8) def clearForm(self): self.titleEdit.clear() self.statusBox.clear() for widget in self.styleGroupBox.children(): if not isinstance(widget, QGridLayout): widget.deleteLater() self.durationLine.clear() self.projectComboBox.clear() self.variationLine.clear() self.descriptionTextEdit.clear() self.locationLine.clear() def changePage(self, index): title = self.songsListWidget.item(index).data(Qt.UserRole) self.clearForm() self.populateForm(title) self.slider.setValue(0) def populateForm(self, title): #title is the primary key listArray = queries("""SELECT title, status, style, duration, description, location, project, variation_another_song, timestamp from songs WHERE title = ?""", (title,)) print(listArray) if len(listArray) != 0: title = listArray[0][0] status = listArray[0][1] styles = [] styleArray = listArray[0][2] if styleArray != None: if "," in styleArray: styles = styleArray.split(",") else: styles.append(styleArray) duration = listArray[0][3] description = listArray[0][4] location = listArray[0][5] project = listArray[0][6] variation_another_song = listArray[0][7] timestamp = listArray[0][8] else: title = None status = None styles = None duration = None description = None location = None project = None variation_another_song = None timestamp = None if title != None: self.titleEdit.setText(title) self.statusBox.addItems(["Select...", "Demo", "WIP", "Idea", "Unfinished song", "EQ", "Master", "Finished"]) if status != None: self.statusBox.setCurrentText(status) if timestamp != None: self.dateEdit.setDateTime(datetime.strptime(timestamp, '%d/%m/%Y %H:%M')) else: self.dateEdit.setDateTime(datetime.now())#default styleArray = queries("select style from songs where style is not null") """ print(styleArray) if styleArray != None: styleArray = styleArray[0][0] if "," in styleArray: styles = styleArray.split(",") else: styles.append(styleArray)""" stylesArray = [] query = queries("select style from songs where style is not null") if len(query) != 0: for style in query: stylesMiniArray = style[0].split(",") stylesMiniArray = list(filter(None, stylesMiniArray)) for item in stylesMiniArray: if item not in stylesArray: if item != '': stylesArray.append(item) self.x = 0 self.y = 0 if len(stylesArray) != 0: for style in stylesArray: print("style", style) checkBox = QCheckBox(style) self.styleLayout.addWidget(checkBox, self.x, self.y) self.checkBoxPositionAsignment() self.addStyle() if styles!= None: if len(styles) != 0: for style in styles: for checkbox in self.styleGroupBox.children(): if isinstance(checkbox, QCheckBox): if checkbox.text() == style: checkbox.setChecked(True) if duration != None: time = QTime(0,0,0) self.durationLine.setTime(time.addSecs(duration)) projectsArray = ["Select..."] projectsArrayQuery = queries("SELECT project from songs") if len(projectsArrayQuery) != 0: for project in projectsArrayQuery[0]: if project not in projectsArray: projectsArray.append(project) if project != None: self.projectComboBox.setCurrentText(project) if variation_another_song != None: self.variationLine.setText(variation_another_song) if description != None: self.descriptionTextEdit.setText(description) available = False if location != None: self.locationLine.setText(location) if len(self.locationLine.text()) != 0: try: self.playlist = QMediaPlaylist() self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(location))) self.mediaPlayer.setPlaylist(self.playlist) except: pass available = True#I know this is stupid but just in case self.slider.setVisible(available) self.playButton.setVisible(available) self.stopButton.setVisible(available) def populateList(self, locatorItem=None, locatorColumn=None): print(locatorItem, locatorColumn) self.songsListWidget.blockSignals(True) self.songsListWidget.clear() if locatorItem == None or locatorItem == "": listArray = queries("""SELECT title, status, timestamp from songs """) print(listArray) else: if locatorColumn != "All": #No strings concatenation, no security holes if locatorColumn == "Title": sql = """SELECT title, status, timestamp from songs where title LIKE ?""" elif locatorColumn == "Status": sql = """SELECT title, status, timestamp from songs where status LIKE ?""" elif locatorColumn == "Description": sql = """SELECT title, status, timestamp from songs where description LIKE ?""" elif locatorColumn == "Style": sql = """SELECT title, status, timestamp from songs where style LIKE ?""" locatorItem = "%" + locatorItem + "%" listArray = queries(sql, (locatorItem,)) else: locatorItem = "%" + locatorItem + "%" variables = [locatorItem, locatorItem, locatorItem, locatorItem, locatorItem] listArray = queries("""SELECT title, status, timestamp from songs where title LIKE ? OR type LIKE ? OR original_song LIKE ? OR link LIKE ? OR description LIKE ?""", variables) for item in listArray: title = item[0] status = item[1] timestamp = item[2] try: timestamp = datetime.strptime(timestamp, "%d/%m/%Y %H:%M") timestamp = timestamp.strftime("%d/%m/%Y") except: timestamp = "" text = "%s %s %s" % (title, status, timestamp) qItem = QListWidgetItem(text) qItem.setData(Qt.UserRole, title) self.songsListWidget.addItem(qItem) #new idea qItem = QListWidgetItem("New song...") qItem.setData(Qt.UserRole, "New song...") #otherwise that would be an error self.songsListWidget.addItem(qItem) self.songsListWidget.blockSignals(False) def listWidgetRightClick(self, position): widgetItem = self.songsListWidget.itemAt(position) if widgetItem != None: #quick lazy text fix if widgetItem.text() != "New song...": print(widgetItem.text()) menu = QMenu() deleteAction = QAction(self.DELETE_ICON, "Delete song") menu.addAction(deleteAction) action = menu.exec(self.mapToGlobal(position)) if action == deleteAction: msg = QMessageBox.question(None, "Delete?", "Are you sure you want to delete this entry?") if msg == QMessageBox.Yes: title = widgetItem.data(Qt.UserRole) queries("DELETE from songs where title = ?", (title,)) self.populateList() self.songsListWidget.setCurrentRow(0) def songVariations(self): sql = "SELECT title from songs" songArray = [] for song in queries(sql)[0]: songArray.append(song) return songArray def checkBoxPositionAsignment(self): self.y += 1 if self.y == 4: self.y = 0 self.x += 1 def addStyle(self, text=""): "text = "" if comes from outside" self.styleEdit = QLineEdit() self.styleEdit.setPlaceholderText("Style") self.styleEdit.textChanged.connect(self.validateStyle) self.styleEdit.returnPressed.connect(lambda: self.addStyle(self.styleEdit.text())) if text != "": self.styleLayout.takeAt(self.styleLayout.count()-1).widget().deleteLater() styleCheckBox = QCheckBox() styleCheckBox.setText(text) print(text) self.styleLayout.addWidget(styleCheckBox, self.x, self.y) self.checkBoxPositionAsignment() print(self.durationLine.text()) self.styleLayout.addWidget(self.styleEdit) def checkSong(self): text = self.titleEdit.text() sql = "SELECT title from songs where title = ?" if len(queries(sql, (text,))) != 0: self.titleEdit.setText("") def validateSong(self): pass #VALIDATE REG EXP def validateStyle(self, text): if "," in text: self.styleEdit.undo() def playSong(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.PAUSE_ICON) else: self.playButton.setIcon(self.PLAY_ICON) def positionChanged(self, position): if position != self.mediaPlayer.duration(): self.slider.setValue(position) def durationChanged(self, duration): if duration != self.mediaPlayer.position(): print("duration chagned") self.slider.setRange(0, duration) def playSlider(self): self.mediaPlayer.setPosition(self.slider.value()) def stopSong(self): self.mediaPlayer.stop() def locateFile(self): self.fileSystem = QFileDialog(filter="Sound files (*.wav *.mp3 *.flac)") self.fileSystem.show() self.fileSystem.fileSelected.connect(self.fileLoaded) def fileLoaded(self, path): self.locationLine.setText(path) try: self.playlist = QMediaPlaylist() self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(path))) self.mediaPlayer.setPlaylist(self.playlist) except: print("fail") self.slider.setVisible(True) self.playButton.setVisible(True) self.stopButton.setVisible(True) def saveSong(self): title = self.titleEdit.text() status = self.statusBox.currentText() date = self.dateEdit.text() style = "" print(status, style) x = 0 for checkBox in self.styleGroupBox.children(): if isinstance(checkBox, QCheckBox): if checkBox.isChecked(): style += (checkBox.text()) + "," x+=1 if x != 0: style = style.rstrip(",") else: style = None duration = self.durationLine.time() duration = QTime(0, 0).secsTo(duration) project = self.projectComboBox.currentText() variation = self.variationLine.text() description = self.descriptionTextEdit.toPlainText() location = self.locationLine.text() variables = [title, status, description, location, project,\ variation, date, style, duration] print("---------", variables) sql = """INSERT OR REPLACE into songs (title, status, description, location, project, variation_another_song, timestamp, style, duration) values (?, ?, ?, ?, ?, ?, ?, ?, ?)""" queries(sql, variables) self.populateList()
class jaabaGUI(QMainWindow): """ controller for the blob labeling GUI""" def __init__(self,parent=None): QMainWindow.__init__(self,parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) #add new slider # self.positionSlider=QSlider(Qt.Horizontal) # self.positionSlider.setGeometry (800,800,100,30) # self.positionSlider.setRange(0, 0) # self.positionSlider.sliderMoved.connect(self.setPosition) #setup Video #video player self.mediaPlayer1 = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer2 = QMediaPlayer(None, QMediaPlayer.VideoSurface) #self.mediaPlayer.metaDataChanged.connect(self.metaDataChanged) self.mediaPlayer1.durationChanged.connect(self.durationChanged) self.mediaPlayer1.positionChanged.connect(self.positionChanged) self.mediaPlayer2.positionChanged.connect(self.positionChanged) #visualizetion self.scene = QGraphicsScene() self.ui.graphicsView.setScene(self.scene) #self.scene.setBackgroundBrush(Qt.black) self.videoItem1 = QGraphicsVideoItem() self.videoItem2 = QGraphicsVideoItem() self.scene.addItem(self.videoItem1) self.scene.addItem(self.videoItem2) self.mediaPlayer1.setVideoOutput(self.videoItem1) self.mediaPlayer2.setVideoOutput(self.videoItem2) #slide bar print self.ui.horizontalSlider self.ui.horizontalSlider.setRange(0, 0) self.ui.horizontalSlider.sliderMoved.connect(self.setPosition) # self.ui.horizontalSlider.sliderPressed.connect(self.sliderPressed) #print self.ui.graphicsView.width()/2,self.ui.graphicsView.height() #self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height())) #self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()*10,self.ui.graphicsView.height()*10)) # self.videoItem2.setSize(graphicsView.size()) #self.videoItem2.setOffset(QPointF(500,500)) #self.videoItem2.setOffset(QPointF(self.ui.graphicsView.width()/2,0)) #self.videoItem2.setPos(QPointF(0,0)) # print self.ui.graphicsView.width(), self.ui.graphicsView.height() # print self.ui.graphicsView.size() # print self.videoItem2.boundingRect().width(), self.videoItem2.boundingRect().height() # print self.ui.graphicsView.sceneRect() #self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) #callbacks self.ui.actionQuit.triggered.connect(self.quit) self.ui.actionLoad_Project.triggered.connect(self.loadVideo) #self.ui.buttonPlay.clicked[bool].connect(self.setToggleText) self.ui.buttonPlay.clicked.connect(self.play) #print self.ui.graphicsView.sizeHint() #initialization self.loaded = False self.videoFilename = None self.frame_count=None self.width=None self.height=None self.frame_trans=None # ###actions starts from here### def quit(self): QApplication.quit() def loadVideo(self): self.writeLog("Loading video...") self.videoFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0] if not self.videoFilename: self.writeLog("User cancelled - no video loaded") return else: cap=cv2.VideoCapture(self.videoFilename) self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT) self.width=cap.get(3) self.height=cap.get(4) self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename ))) self.ui.buttonPlay.setEnabled(True) # self.mediaPlayer2.setVideoOutput(self.videoItem2) # self.mediaPlayer1.setVideoOutput(self.videoItem1) # size= self.videoItem2.nativeSize() # print size #print self.mediaPlayer.duration() #print self.mediaPlayer.metaData() self.writeLog("Video loaded!") def play(self): self.videoItem1.setAspectRatioMode(0) self.videoItem2.setAspectRatioMode(0) self.scene.setSceneRect(0,0,self.ui.graphicsView.width(),self.ui.graphicsView.height()) self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height())) self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height())) self.videoItem1.setPos(QPointF(0,0)) self.videoItem2.setPos(QPointF(self.ui.graphicsView.width()/2,0)) #self.ui.graphicsView.setGeometry(0,0, 600,800) #print 'graphicsView size', self.ui.graphicsView.size() #print 'graphicsScene size', self.scene.sceneRect() #self.videoItem2.setSize(QSizeF(1000,300)) #print 'graphicsVideoItem size',self.videoItem2.size() # print 'item x',self.videoItem2.scenePos().x() # print 'item y', self.videoItem2.scenePos().y() # print 'item x',self.videoItem1.scenePos().x() # print 'item y', self.videoItem1.scenePos().y() if self.mediaPlayer1.state() == QMediaPlayer.PlayingState: self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPlay)) self.ui.buttonPlay.setText("Play") self.mediaPlayer1.pause() self.writeLog("Video paused") else: self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPause)) self.ui.buttonPlay.setText("Stop") self.mediaPlayer1.play() self.writeLog("Playing video") if self.mediaPlayer2.state() == QMediaPlayer.PlayingState: self.mediaPlayer2.pause() else: self.mediaPlayer2.play() #size= self.videoItem2.nativeSize() # print self.mediaPlayer.duration() #print self.mediaPlayer.metaData() # print self.ui.graphicsView.width(), self.ui.graphicsView.height() # print self.ui.graphicsView.size() # print self.videoItem2.boundingRect().width(), self.videoItem2.boundingRect().height() # print self.ui.graphicsView.sceneRect() # print self.scene.sceneRect() # print self.ui.graphicsView.sizeHint() def setPosition(self, position): self.mediaPlayer1.setPosition(position) self.mediaPlayer2.setPosition(position) # when position of media changed, set slider and text box accordingly. def positionChanged(self, position): self.ui.horizontalSlider.setValue(position) if isinstance(self.frame_trans,float): # print type(position),position # print type(self.frame_trans),self.frame_trans # print position/self.frame_trans self.ui.lineEdit.setText(str(int(round(position/self.frame_trans,0)))) self.writeLog(str(position)) def durationChanged(self, duration): self.ui.horizontalSlider.setRange(0, duration) self.frame_trans=self.mediaPlayer1.duration()/self.frame_count print self.frame_trans def writeLog(self,text): self.ui.log.setText(text)
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) btnSize = QSize(16, 16) videoWidget = QVideoWidget() openButton = QPushButton("Open Video") openButton.setToolTip("Open Video File") openButton.setStatusTip("Open Video File") openButton.setFixedHeight(24) openButton.setIconSize(btnSize) openButton.setFont(QFont("Noto Sans", 8)) openButton.setIcon(QIcon.fromTheme("document-open", QIcon("D:/_Qt/img/open.png"))) openButton.clicked.connect(self.abrir) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setFixedHeight(24) self.playButton.setIconSize(btnSize) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.statusBar = QStatusBar() self.statusBar.setFont(QFont("Noto Sans", 7)) self.statusBar.setFixedHeight(14) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.statusBar) self.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.statusBar.showMessage("Ready") def abrir(self): fileName, _ = QFileDialog.getOpenFileName(self, "Selecciona los mediose", ".", "Video Files (*.mp4 *.flv *.ts *.mts *.avi)") if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) self.statusBar.showMessage(fileName) self.play() def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString())
class Controller: def __init__(self, view, log): self.log = log self.view = view self._player = QMediaPlayer() self._player.mediaStatusChanged.connect(self._player_status_changed) self._player.mediaChanged.connect(self._player_media_changed) self._player.currentMediaChanged.connect(self._player_current_media_changed) self._player.stateChanged.connect(self._player_state_changed) self._player.positionChanged.connect(self._player_position_changed) self._player.durationChanged.connect(self._player_duration_changed) self._searched_tracks = [] self.playlists = [] self.playing_playlist = 0 self.last_colored_item = None def _player_status_changed(self, status): self.log.debug('_player_status_changed: %s', str(status)) if status in [QMediaPlayer.EndOfMedia, QMediaPlayer.InvalidMedia]: self.next() if status in [QMediaPlayer.EndOfMedia, QMediaPlayer.NoMedia, QMediaPlayer.UnknownMediaStatus, QMediaPlayer.InvalidMedia]: self.view.set_title() else: try: pos = self.playlists[self.playing_playlist].active_track if pos >= 0: track = self.playlists[self.playing_playlist].tracks[pos] self.view.set_title(track.title) self.update_list_position(pos) except IndexError: self.log.error('Index error in _player_status_changed') def _player_media_changed(self, media): self.log.debug('_player_media_changed: %s' % str(media)) def _player_current_media_changed(self, media): self.log.debug('_player_current_media_changed: %s' % str(media)) def _player_state_changed(self, state): self.log.debug('_player_state_changed: %s' % str(state)) def _player_duration_changed(self, duration): self.log.debug('_player_duration_changed: %s' % str(duration)) self.view.track_position.setMaximum(duration) def _player_position_changed(self, pos): self.view.track_position.setValue(pos) def volume_changed(self, value): self._player.setVolume(value) def update_status(self): total_duration = 0 playlist_index = self.view.tabs.currentIndex() for track in self.playlists[playlist_index].tracks: total_duration += track.duration self.view.playlist_status.setText("%i tracks. Total duration %i:%02i:%02i:%02i" % (self.playlists[playlist_index].count(), total_duration // 86400, total_duration // 3600 % 24, total_duration // 60 % 60, total_duration % 60)) def add_track(self, track, playlist_index=None): if playlist_index is None: playlist_index = self.view.tabs.currentIndex() self.playlists[playlist_index].add(track) self.view.tabs.widget(playlist_index).addItem(track.title) def remove_track(self, track_pos=None): if track_pos is None: track_pos = self.view.tabs.currentWidget().currentRow() if track_pos != -1: self.view.tabs.currentWidget().takeItem(track_pos) playlist_index = self.view.tabs.currentIndex() self.playlists[playlist_index].remove(track_pos) self.update_status() def remove_all_tracks(self): playlist_index = self.view.tabs.currentIndex() self.playlists[playlist_index].clear() self.view.tabs.currentWidget().clear() self.update_status() def next(self): self.log.debug('next') # if we close last tab with current track, after it ended, we stop playing # todo: need check, that if we close not last tab with current song, we also need stop after song ended if self.playing_playlist >= len(self.playlists): return next_pos = self.playlists[self.playing_playlist].get_next_track(shuffle=bool(self.view.shuffle.checkState())) if next_pos is not None: self.playlists[self.playing_playlist].active_track = next_pos url = self.playlists[self.playing_playlist].tracks[next_pos].stream_url() self._player.setMedia(QMediaContent(QUrl(url))) self.play() def previous(self): self.log.debug('previous') prev_pos = self.playlists[self.playing_playlist].get_prev_track(shuffle=bool(self.view.shuffle.checkState())) if prev_pos is not None: self.playlists[self.playing_playlist].active_track = prev_pos url = self.playlists[self.playing_playlist].tracks[prev_pos].stream_url() self._player.setMedia(QMediaContent(QUrl(url))) self.play() def play(self): self.log.debug('play') self._player.play() def pause(self): self.log.debug('pause') self._player.pause() def update_list_position(self, position): showed_list = self.view.tabs.currentWidget() if self.last_colored_item: self.last_colored_item.setBackground(QBrush()) if (position >= 0) and (position <= showed_list.count()): self.last_colored_item = showed_list.item(position) self.last_colored_item.setBackground(QBrush(QColor('red'))) def change_track(self): self.log.debug('change_track') playlist_index = self.view.tabs.currentIndex() self.playing_playlist = playlist_index position = self.view.tabs.currentWidget().currentRow() self.playlists[self.playing_playlist].active_track = position self.log.debug('position: %i' % position) url = self.playlists[self.playing_playlist].tracks[position].stream_url() self._player.setMedia(QMediaContent(QUrl(url))) if self._player.state() in [QMediaPlayer.StoppedState, QMediaPlayer.PausedState]: self.play() def change_track_position(self): self._player.setPosition(self.view.track_position.value()) def remove_dublicates(self): selected_playlist = self.view.tabs.currentIndex() playlist = self.playlists[selected_playlist] processed_ids = [] position_for_removing = [] for index in range(len(playlist.tracks)): if playlist.tracks[index].id in processed_ids: position_for_removing.append(index) else: processed_ids.append(playlist.tracks[index].id) self.log.debug('tracks count: %i' % len(playlist.tracks)) counter = 0 for index in reversed(position_for_removing): self.log.debug('track index for removing: %i' % index) self.remove_track(track_pos=index) counter += 1 self.log.info('Removed %i tracks.' % counter) def save_track(self, playlist_pos=None, track_pos=None): if track_pos is None: track_pos = self.view.tabs.currentWidget().currentRow() if playlist_pos is None: playlist_pos = self.view.tabs.currentIndex() playlist = self.playlists[playlist_pos] track = playlist.tracks[track_pos] track.save() def download_playlist(self): selected_playlist = self.view.tabs.currentIndex() playlist = self.playlists[selected_playlist] for track_pos in range(playlist.count()): self.log.info('Saving %i/%s track...' % (track_pos+1, playlist.count())) self.save_track(playlist_pos=selected_playlist, track_pos=track_pos) self.log.info('Saving done.') def load_playlist(self): playlist_index = self.view.tabs.currentIndex() playlist = self.playlists[playlist_index] loaded_playlist = sc_load_playlist(playlist.name) if not loaded_playlist: self.log.error('Playlist not exists.') return self.remove_all_tracks() for track in loaded_playlist: self.add_track(track) self.update_status() def save_playlist(self): playlist_index = self.view.tabs.currentIndex() playlist = self.playlists[playlist_index] sc_save_playlist(playlist.name, playlist) def add_playlist(self, name): self.playlists.append(Playlist(name)) def remove_playlist(self, index): self.log.debug('remove playlist with index = %i' % index) del (self.playlists[index]) def search_tracks(self): self.view.search_list.clear() tracks = sc_search_tracks(self.view.input.text()) self._searched_tracks = tracks total_duration = 0 for track in self._searched_tracks: self.view.search_list.addItem(track.title) total_duration += track.duration self.view.search_status.setText("Founded %i tracks. Total duration %i:%02i:%02i:%02i" % (len(self._searched_tracks), total_duration // 86400000, total_duration // 3600000 % 24, total_duration // 60000 % 60, total_duration // 1000 % 60)) def search_similar(self): self.view.search_list.clear() position = self.view.tabs.currentWidget().currentRow() playlist_index = self.view.tabs.currentIndex() track = self.playlists[playlist_index].tracks[position] related_tracks = track.search_related() self._searched_tracks = related_tracks total_duration = 0 for track in self._searched_tracks: self.view.search_list.addItem(track.title) total_duration += track.duration self.view.search_status.setText("Founded %i tracks. Total duration %i:%02i:%02i:%02i" % (len(self._searched_tracks), total_duration // 86400000, total_duration // 3600000 % 24, total_duration // 60000 % 60, total_duration // 1000 % 60)) def clicked_add_track(self): position = self.view.search_list.currentRow() self.add_track(self._searched_tracks[position]) def clicked_add_all_tracks(self): for row in range(self.view.search_list.count()): self.add_track(self._searched_tracks[row]) def load_current_state(self): if not os.path.isfile('state.pickle'): return f = open('state.pickle', 'rb') state = pickle.load(f) f.close() loaded_playlists = state['playlists'] self.log.debug('loaded %i playlists.' % len(loaded_playlists)) for i in range(len(loaded_playlists) - len(self.playlists)): self.view.tab_add() self.playlists.clear() index = 0 for playlist in loaded_playlists: self.log.debug('playlist: %s, len: %i' % (playlist.name, len(playlist.tracks))) self.add_playlist(playlist.name) for track in playlist.tracks: self.add_track(track, playlist_index=index) index += 1 self.log.debug(len(self.playlists)) self.log.debug('curent tab: %i' % state['current_playlist']) self.view.tabs.setCurrentIndex(state['current_playlist']) self.log.debug('volume: %i' % state['volume']) self.view.volume.setValue(state['volume']) self.view.shuffle.setCheckState(state['shuffle']) def save_current_state(self): state = dict() self.log.debug('playlists count: %i' % len(self.playlists)) state['playlists'] = self.playlists state['current_playlist'] = self.view.tabs.currentIndex() state['volume'] = self.view.volume.value() state['shuffle'] = self.view.shuffle.checkState() f = open('state.pickle', 'wb') pickle.dump(state, f) f.close()
class Window(QMainWindow): save_crop_signal = pyqtSignal() samling_ratio = 60 class State(Enum): Initial = 1 OneCursorPlaced = 2 TwoCursorPlaced = 3 def __init__(self): super().__init__() self.player = QMediaPlayer() self.ui = Ui_MainWindow() # setup main Window's UI self.ui.setupUi(self) self._setup_connections() self._setup_matplotlib() self._setup_directory_browser() self.play_timer = QTimer(self) self.play_timer.timeout.connect(self.plot_animator) self.ymax = 30000 self.state = None self.crop_line_1_pos = None self.crop_line_2_pos = None self.play_limit = (0, 0) self.current_zoom = 100 self.seconds_to_prefetch = 60 self.minimum_file_file_length = 2.5 self.save_crop_signal.connect(self.save_crop_to_file) def _setup_matplotlib(self): self.figure = Figure() self.canvas = FigureCanvas(self.figure) layout = self.ui.graph_widget.layout() layout.addWidget(self.canvas) self.canvas_click_connection = None self.canvas_scroll_connection = None self.subplot = self.figure.add_subplot(111) self.audio_plot, = self.subplot.plot([0], [0], '-', color=(0.70, 0.70, 0.70)) self.playIndicator, = self.subplot.plot([0], [0], '^') self.crop_line_1, = self.subplot.plot([], [], '-r') self.crop_line_2, = self.subplot.plot([], [], '-r') self.ui.vertical_splitter.setSizes([2, 12]) def _setup_directory_browser(self): curdir = os.path.abspath(os.path.curdir) self.file_system_model = QFileSystemModel(self) self.file_system_model.setReadOnly(True) self.file_system_model.setFilter(QDir.AllDirs | QDir.AllEntries | QDir.NoDotAndDotDot) self.file_system_model.setNameFilters(['*.wav', '*.txt']) self.file_system_model.setNameFilterDisables(False) self.ui.directory_view.setModel(self.file_system_model) self.file_system_model.setRootPath(curdir) index = self.file_system_model.index(curdir) self.ui.directory_view.setRootIndex(index) self.ui.directory_view.hideColumn(1) self.ui.directory_view.hideColumn(2) self.ui.directory_view.hideColumn(3) # index: QModelIndex = model.index(os.path.abspath(os.path.curdir)) # self.ui.directory_view.expand(index); # self.ui.directory_view.scrollTo(index) # self.ui.directory_view.setCurrentIndex(index) self.ui.directory_view.doubleClicked.connect(self.file_selected) def plot(self, ydata_byte, start_pos=0): ''' plot some random stuff ''' ploty = numpy.fromstring(ydata_byte, numpy.int16) plotdatay = ploty[0:len(ploty):Window.samling_ratio] plotdatax = [ x for x in range(start_pos, len(ploty) + start_pos, Window.samling_ratio) ] self.set_view_range(start_pos, plotdatax[-1]) self.view_limit_range = (start_pos, plotdatax[-1]) _max = max(plotdatay) self.figure.get_axes()[0].set_ylim(-_max, _max) print("The real plot limit", (start_pos, plotdatax[-1])) self.audio_plot.set_data(plotdatax, plotdatay) # refresh canvas self.canvas.draw() def set_view_range(self, start, end): self.figure.get_axes()[0].set_xlim(start, end) self.current_view = [start, end] def plot_animator(self): # current_music_time = self.play_started_audio_time + diff current_time_ms = self.player.position() current_music_frame = int( (current_time_ms * self.wave.getframerate()) / 1000) self.playIndicator.set_data([current_music_frame], [0]) self.canvas.draw() if current_time_ms >= self.play_limit[1]: self.player.pause() self.play_timer.stop() self.playIndicator.set_data(self.crop_line_2_pos, 0) self.canvas.draw() def _setup_connections(self): self.player.stateChanged.connect(self.player_status_changed) self.player.positionChanged.connect(self.playback_progress_change) def toggle_pause(self): if self.playing: self.player.pause() self.play_timer.stop() else: self.player.play() self.play_timer.start() self.playing = not self.playing def seek(self, pos): self.player.setPosition(pos) self.player.play() if self.player.state() != QMediaPlayer.PlayingState: self.player.play() if not self.play_timer.isActive(): self.play_timer.start() def seek_frame(self, frame_pos): self.seek(int((frame_pos * 1000) / (self.wave.getframerate()))) # self.seek(int(frame_pos / (self.wave.getframerate() * 1000))) def canvas_click_listener(self, event): if not event.xdata: return currentframe = event.xdata current_time_in_milli = int(currentframe / self.wave.getframerate() * 1000) if (current_time_in_milli < 0): current_time_in_milli = 0 current_x = int(event.xdata) if (current_x < 0): current_x = 0 if self.state == Window.State.Initial: self.crop_line_1.set_data([current_x, current_x], [-self.ymax, self.ymax]) self.crop_line_1_pos = current_x elif self.state == Window.State.OneCursorPlaced: if current_x > self.crop_line_1_pos: self.crop_line_2_pos = current_x self.crop_line_2.set_data([current_x, current_x], [-self.ymax, self.ymax]) self.canvas.draw() self.seek(current_time_in_milli) def canvas_scroll_listener(self, event): current_range = self.current_view[1] - self.current_view[0] if current_range < 0: return if event.button == 'down': new_range = current_range / 1.3 else: new_range = current_range * 1.3 new_view = [event.xdata - new_range / 2, event.xdata + new_range / 2] count = 0 if new_view[0] < self.view_limit_range[0]: new_view[1] += self.view_limit_range[0] - new_view[0] new_view[0] = self.view_limit_range[0] if new_view[1] > self.view_limit_range[1]: new_view[1] = self.view_limit_range[1] elif new_view[1] > self.view_limit_range[1]: new_view[0] -= new_view[1] - self.view_limit_range[1] new_view[1] = self.view_limit_range[1] if new_view[0] < self.view_limit_range[0]: new_view[0] = self.view_limit_range[0] if new_view[0] > new_view[1]: return self.figure.get_axes()[0].set_xlim(new_view[0], new_view[1]) self.current_view = new_view self.canvas.draw() def eventFilter(self, event): print("New Event", event.type()) return False def keyPressEvent(self, event): key = event.key() if key == Qt.Key_Space: self.toggle_pause() if key == Qt.Key_Return: if self.state == Window.State.Initial: if self.crop_line_1_pos: self.state = Window.State.OneCursorPlaced self.crop_line_1.set_data( [self.crop_line_1_pos, self.crop_line_1_pos], [-self.ymax, self.ymax]) self.crop_line_1.set_color("green") self.canvas.draw() elif self.state == Window.State.OneCursorPlaced: if self.crop_line_2_pos: self.crop_line_2.set_color("green") self.zoom_to_crop() self.state = Window.State.TwoCursorPlaced self.ui.statusbar.showMessage( "Press Enter to save the clip to file", 3000) elif self.state == Window.State.TwoCursorPlaced: self.crop_to_save = self.data[self.crop_line_1_pos * 2:self.crop_line_2_pos * 2] self.crop_nchannel = self.wave.getnchannels() self.crop_stampwidth = self.wave.getsampwidth() self.crop_framerate = self.wave.getframerate() self.save_crop_signal.emit() self.update_cropped_plot() if key == Qt.Key_Backspace: if self.state == Window.State.OneCursorPlaced: self.state = Window.State.Initial self.crop_line_1_pos = None self.crop_line_1.set_color("red") self.crop_line_2.set_data([], []) self.canvas.draw() elif self.state == Window.State.TwoCursorPlaced: self.play_limit = self.play_limit_bak self.state = Window.State.OneCursorPlaced self.crop_line_2_pos = None self.crop_line_2.set_color("red") self.canvas.draw() @pyqtSlot(QMediaPlayer.State) def player_status_changed(self, x): if x == QMediaPlayer.StoppedState: self.play_timer.stop() pass elif x == QMediaPlayer.PlayingState: pass elif x == QMediaPlayer.PausedState: pass @pyqtSlot('qint64') def playback_progress_change(self, position): pass # self.ui.progressBar.setValue(int(position / self.player.duration() * 100)) def read_file(self, filename): # reset the cursors to default values self.wave = wave.open(filename, 'rb') self.channels = self.wave.getnchannels() self.rate = self.wave.getframerate() nframes = self.seconds_to_prefetch * self.wave.getframerate() self.playing = False self.data = self.wave.readframes(nframes) self.total_frames_read = len(self.data) // 2 if self.total_frames_read / self.wave.getframerate( ) < self.minimum_file_file_length: self.ui.statusbar.showMessage("The file is too short.") return self.player.setMedia(QMediaContent(QUrl.fromLocalFile(filename))) self.plot(self.data) nframes = min(self.wave.getnframes(), nframes) self.data_shift = 0 self.play_limit = (0, (nframes * 1000) / self.wave.getframerate()) self.crop_count = 0 self.current_open_file_name = filename[:-4] self.toggle_pause() if not self.canvas_scroll_connection: self.canvas_click_connection = self.canvas.mpl_connect( "button_press_event", self.canvas_click_listener) self.canvas_scroll_connection = self.canvas.mpl_connect( "scroll_event", self.canvas_scroll_listener) self.crop_line_1_pos = None self.crop_line_2_pos = None self.state = Window.State.Initial self.crop_line_2.set_data([], []) self.crop_line_2.set_color("red") self.crop_line_1.set_data([], []) self.crop_line_1.set_color("red") def zoom_to_crop(self): ##TODO : make crop from line1 and line2 position self.set_view_range(self.crop_line_1_pos - 1000, self.crop_line_2_pos + 1000) # cropped_data = self.data[self.crop_line_1_pos:self.crop_line_2_pos] self.play_limit_bak = self.play_limit self.play_limit = ((self.crop_line_1_pos * 1000) / self.wave.getframerate(), (1000 * self.crop_line_2_pos) / self.wave.getframerate()) self.seek_frame(self.crop_line_1_pos) self.canvas.draw() def update_cropped_plot(self): # frames remain in the total sound clip remaining_frames = (self.wave.getnframes()) - int(self.crop_line_2_pos) # time remain for compleliton of sound clip remaining_ms = (remaining_frames * 1000) / self.wave.getframerate() if remaining_ms < 3000: return self.crop_completed(remaining_ms) # the no of frames that have been loaded into memory frames_in_memory = int(self.total_frames_read - self.crop_line_2_pos) data_pos = int(self.crop_line_2_pos * 2 - self.data_shift) self.data_shift = self.crop_line_2_pos * 2 # all the data from sound have been read into the memory if frames_in_memory == remaining_frames: self.data = self.data[data_pos:len(self.data)] else: # the no of maximum frames that will be showed in preview total_frames_required = self.seconds_to_prefetch * self.wave.getframerate( ) # the no of frames that needs to be read from disk frames_to_read = total_frames_required - frames_in_memory # the file may not have that many frames, so it's the minimun of frames to read and frames in disk remain # to read frames_that_will_be_read = min( self.wave.getnframes() - self.total_frames_read, frames_to_read) self.total_frames_read += frames_that_will_be_read self.data = self.data[data_pos:len( self.data)] + self.wave.readframes(frames_that_will_be_read) self.plot(self.data, self.crop_line_2_pos) # frames_remain_to_read = self.wave.getnframes() - self.total_frames_read self.state = Window.State.Initial self.play_limit = ((self.crop_line_2_pos * 1000) / self.wave.getframerate(), (self.total_frames_read * 1000) / self.wave.getframerate()) self.view_limit_range = (self.crop_line_2_pos, self.total_frames_read) self.seek_frame(self.crop_line_2_pos) self.crop_line_1.set_data([], []) self.crop_line_2.set_data([], []) self.crop_line_1.set_color("red") self.crop_line_2.set_color("red") self.crop_line_1_pos = None self.crop_line_2_pos = None @pyqtSlot(QModelIndex) def file_selected(self, index): filename = self.file_system_model.filePath(index) if filename.endswith('.txt'): self.text_file = QFile(filename) if not self.text_file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning(self, "Application", "Cannot read file", self.text_file.errorString()) return in_stream = QTextStream(self.text_file) # self.ui.text_edit.setPlainText(in_stream.readAll()) # font: QFont = self.ui.text_browser.font() # font.setPixelSize(40) # self.ui.text_browser.setFont(font) data = in_stream.readAll() self.ui.text_browser.setPlainText(data) self.ui.text_edit.setPlainText(data) else: try: self.read_file(filename) except: traceback.print_exc(2) self.ui.statusbar.showMessage("Reading the file failed", 300) @pyqtSlot() def save_crop_to_file(self): self.crop_count += 1 wave_file = wave.open( self.current_open_file_name + "_crop_" + str(self.crop_count) + '.wav', 'wb') wave_file.setnchannels(self.crop_nchannel) wave_file.setsampwidth(self.crop_stampwidth) wave_file.setframerate(self.crop_framerate) wave_file.writeframes(self.crop_to_save) wave_file.close() def crop_completed(self, remaining_ms): self.state = Window.State.Initial self.crop_line_1.set_data([], []) self.crop_line_2.set_data([], []) self.crop_line_1.set_color("red") self.crop_line_2.set_color("red") self.crop_line_1_pos = None self.crop_line_2_pos = None self.audio_plot.set_data([], []) self.ui.statusbar.showMessage("Cropping this file has been completed") self.canvas.mpl_disconnect(self.canvas_click_connection) self.canvas.mpl_disconnect(self.canvas_scroll_connection) self.canvas_scroll_connection = None self.canvas_click_connection = None self.canvas.draw() self.player.stop() self.play_timer.stop() self.wave.close() self.ui.statusbar.showMessage( "Only %f seconds left thus this file is considered completed" % (remaining_ms / 1000))
class ApplicationWindow(QtWidgets.QMainWindow): global wavFileName global fig,chartFig global duration, counterClick global colorName, text_ global startAnnotation, endTimeToPlay # >> QtMultimedia Signals #---------------------- play = pyqtSignal() pause = pyqtSignal() stop = pyqtSignal() def __init__(self): global playerStarted global wavFileName, fig, chartFig global playerStarted, durationFlag, duration global colorName, text_, counterClick global startAnnotation, endTimeToPlay QtWidgets.QMainWindow.__init__(self) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.main_widget = QtWidgets.QWidget(self) playerStarted = False #DEFINE PLAYER-PLAYLIST #---------------------- self.source = QtCore.QUrl.fromLocalFile(os.path.abspath(wavFileName)) self.content = QMediaContent(self.source) self.player = QMediaPlayer() self.playlist = QMediaPlaylist(self) self.playlist.addMedia(self.content) self.player.setPlaylist(self.playlist) # >> Define annotations and gantt chart #---------------------- self.wave = Waveform() fig = self.wave self.chart = Chart() chartFig = self.chart # >> Define player buttons #---------------------- playButton = QPushButton("Play") pauseButton = QPushButton("Pause") stopButton = QPushButton("Stop") # >> Define layouts #---------------------- waveLayout = QVBoxLayout() waveLayout.addWidget(self.wave) waveLayout.addWidget(self.chart) line = QFrame() line.setFrameShape(QFrame.VLine) line.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding) waveLayout.addWidget(line) #Buttons layout buttonLayout = QVBoxLayout() buttonLayout.addWidget(playButton) buttonLayout.addWidget(pauseButton) buttonLayout.addWidget(stopButton) buttonLayout.setAlignment(Qt.AlignTop) # >> Specify final layout align #---------------------- layout = QHBoxLayout(self.main_widget) layout.addLayout(waveLayout) layout.addLayout(buttonLayout) # >> Define buttons connections #---------------------- playButton.clicked.connect(self.Play) pauseButton.clicked.connect(self.Pause) stopButton.clicked.connect(self.Stop) self.main_widget.setFocus() self.setCentralWidget(self.main_widget) # PLAYER BUTTON FUNCTIONS # >> Play audio (whole signal or segment) #---------------------- def Play(self): global playerStarted global durationFlag global duration, counterClick global startTimeToPlay, endTimeToPlay, first #GET CLICKS FROM WAVEFORM #---------------------- #Initialize connection-position ONCE if not playerStarted: #10ms for changePosition -> Not Delaying self.player.positionChanged.connect(self.checkPositionToStop) self.player.setNotifyInterval(10) if durationFlag==0: playerStarted = True startTimeToPlay = 0 self.start = startTimeToPlay self.end = duration*1000 - 10 endTimeToPlay = self.end counterClick = 3 elif durationFlag==1: playerStarted = True self.start = startTimeToPlay self.end = duration*1000 - 10 endTimeToPlay = self.end counterClick = 3 elif durationFlag==2: playerStarted = True self.start = startTimeToPlay self.end = endTimeToPlay self.player.setPosition(self.start) playFlag = True self.player.play() # >> Pause audio playing #---------------------- def Pause(self): #Not begging from self.start playerStarted = True self.player.setPosition(self.time_) self.player.pause() # >> Stop audio playing #---------------------- def Stop(self): self.player.stop() #Begin again segment self.start = startTimeToPlay self.player.setPosition(self.start) # >> Check ms in audio to stop play #---------------------- def checkPositionToStop(self): self.time_ = self.player.position() print self.time_ if self.time_ >= self.end: self.Stop() self.player.setPosition(self.start) def fileQuit(self): self.close() def closeEvent(self, ce): self.fileQuit()
class Player(QWidget): fullScreenChanged = pyqtSignal(bool) def __init__(self, playlist, parent=None): super(Player, self).__init__(parent) self.colorDialog = None self.trackInfo = "" self.statusInfo = "" self.duration = 0 self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) self.videoWidget = VideoWidget() self.player.setVideoOutput(self.videoWidget) self.playlistModel = PlaylistModel() self.playlistModel.setPlaylist(self.playlist) self.playlistView = QListView() self.playlistView.setModel(self.playlistModel) self.playlistView.setCurrentIndex( self.playlistModel.index(self.playlist.currentIndex(), 0)) self.playlistView.activated.connect(self.jump) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = QLabel() self.slider.sliderMoved.connect(self.seek) self.labelHistogram = QLabel() self.labelHistogram.setText("Histogram:") self.histogram = HistogramWidget() histogramLayout = QHBoxLayout() histogramLayout.addWidget(self.labelHistogram) histogramLayout.addWidget(self.histogram, 1) self.probe = QVideoProbe() self.probe.videoFrameProbed.connect(self.histogram.processFrame) self.probe.setSource(self.player) openButton = QPushButton("Open", clicked=self.open) controls = PlayerControls() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) controls.setMuted(controls.isMuted()) controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.player.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousClicked) controls.changeVolume.connect(self.player.setVolume) controls.changeMuting.connect(self.player.setMuted) controls.changeRate.connect(self.player.setPlaybackRate) controls.stop.connect(self.videoWidget.update) self.player.stateChanged.connect(controls.setState) self.player.volumeChanged.connect(controls.setVolume) self.player.mutedChanged.connect(controls.setMuted) self.fullScreenButton = QPushButton("FullScreen") self.fullScreenButton.setCheckable(True) self.colorButton = QPushButton("Color Options...") self.colorButton.setEnabled(False) self.colorButton.clicked.connect(self.showColorDialog) displayLayout = QHBoxLayout() displayLayout.addWidget(self.videoWidget, 2) displayLayout.addWidget(self.playlistView) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addStretch(1) controlLayout.addWidget(controls) controlLayout.addStretch(1) controlLayout.addWidget(self.fullScreenButton) controlLayout.addWidget(self.colorButton) layout = QVBoxLayout() layout.addLayout(displayLayout) hLayout = QHBoxLayout() hLayout.addWidget(self.slider) hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) layout.addLayout(histogramLayout) self.setLayout(layout) if not self.player.isAvailable(): QMessageBox.warning(self, "Service not available", "The QMediaPlayer object does not have a valid service.\n" "Please check the media service plugins are installed.") controls.setEnabled(False) self.playlistView.setEnabled(False) openButton.setEnabled(False) self.colorButton.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self.addToPlaylist(playlist) def open(self): fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files") self.addToPlaylist(fileNames) def addToPlaylist(self, fileNames): for name in fileNames: fileInfo = QFileInfo(name) if fileInfo.exists(): url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(QMediaContent(url)) else: url = QUrl(name) if url.isValid(): self.playlist.addMedia(QMediaContent(url)) def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo("%s - %s" % ( self.player.metaData(QMediaMetaData.AlbumArtist), self.player.metaData(QMediaMetaData.Title))) def previousClicked(self): # Go to the 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() else: self.player.setPosition(0) def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def playlistPositionChanged(self, position): self.playlistView.setCurrentIndex( self.playlistModel.index(position, 0)) def seek(self, seconds): self.player.setPosition(seconds * 1000) def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo("Loading...") elif status == QMediaPlayer.StalledMedia: self.setStatusInfo("Media Stalled") elif status == QMediaPlayer.EndOfMedia: QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo("") def handleCursor(self, status): if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def bufferingProgress(self, progress): self.setStatusInfo("Buffering %d%" % progress) def videoAvailableChanged(self, available): if available: self.fullScreenButton.clicked.connect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.connect( self.fullScreenButton.setChecked) if self.fullScreenButton.isChecked(): self.videoWidget.setFullScreen(True) else: self.fullScreenButton.clicked.disconnect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.disconnect( self.fullScreenButton.setChecked) self.videoWidget.setFullScreen(False) self.colorButton.setEnabled(available) def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def displayErrorMessage(self): self.setStatusInfo(self.player.errorString()) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QTime((currentInfo/3600)%60, (currentInfo/60)%60, currentInfo%60, (currentInfo*1000)%1000) totalTime = QTime((duration/3600)%60, (duration/60)%60, duration%60, (duration*1000)%1000); format = 'hh:mm:ss' if duration > 3600 else 'mm:ss' tStr = currentTime.toString(format) + " / " + totalTime.toString(format) else: tStr = "" self.labelDuration.setText(tStr) def showColorDialog(self): if self.colorDialog is None: brightnessSlider = QSlider(Qt.Horizontal) brightnessSlider.setRange(-100, 100) brightnessSlider.setValue(self.videoWidget.brightness()) brightnessSlider.sliderMoved.connect( self.videoWidget.setBrightness) self.videoWidget.brightnessChanged.connect( brightnessSlider.setValue) contrastSlider = QSlider(Qt.Horizontal) contrastSlider.setRange(-100, 100) contrastSlider.setValue(self.videoWidget.contrast()) contrastSlider.sliderMoved.connect(self.videoWidget.setContrast) self.videoWidget.contrastChanged.connect(contrastSlider.setValue) hueSlider = QSlider(Qt.Horizontal) hueSlider.setRange(-100, 100) hueSlider.setValue(self.videoWidget.hue()) hueSlider.sliderMoved.connect(self.videoWidget.setHue) self.videoWidget.hueChanged.connect(hueSlider.setValue) saturationSlider = QSlider(Qt.Horizontal) saturationSlider.setRange(-100, 100) saturationSlider.setValue(self.videoWidget.saturation()) saturationSlider.sliderMoved.connect( self.videoWidget.setSaturation) self.videoWidget.saturationChanged.connect( saturationSlider.setValue) layout = QFormLayout() layout.addRow("Brightness", brightnessSlider) layout.addRow("Contrast", contrastSlider) layout.addRow("Hue", hueSlider) layout.addRow("Saturation", saturationSlider) button = QPushButton("Close") layout.addRow(button) self.colorDialog = QDialog(self) self.colorDialog.setWindowTitle("Color Options") self.colorDialog.setLayout(layout) button.clicked.connect(self.colorDialog.close) self.colorDialog.show()
class VideoPlayer(QWidget): def __init__(self, parent=None): super(VideoPlayer, self).__init__(parent) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) videoWidget = QVideoWidget() openButton = QPushButton("Open...") openButton.clicked.connect(self.openFile) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.errorLabel = QLabel() self.errorLabel.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) layout = QVBoxLayout() layout.addWidget(videoWidget) layout.addLayout(controlLayout) layout.addWidget(self.errorLabel) self.setLayout(layout) self.mediaPlayer.setVideoOutput(videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) def openFile(self): fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie", QDir.homePath()) if fileName != '': self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) self.playButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
class VideoPlayer(QWidget): """ Arguments --------- parent: QWidget, the parent widget of VideoPlayer display_status: bool, default False, will show the status of the media player in the gui """ def __init__(self, parent=None, display_status=False): super(VideoPlayer, self).__init__(parent) self.display_status = display_status self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoItem = QGraphicsVideoItem() scene = QGraphicsScene(self) graphicsView = QGraphicsView(scene) scene.addItem(self.videoItem) self.playButton = QPushButton() self.playButton.setEnabled(False) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.clicked.connect(self.play) self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) if self.display_status: self.status_mapping = { QMediaPlayer.UnknownMediaStatus: "UnknownMediaStatus", QMediaPlayer.NoMedia: "NoMedia", QMediaPlayer.LoadingMedia: "LoadingMedia", QMediaPlayer.LoadedMedia: "LoadedMedia", QMediaPlayer.StalledMedia: "StalledMedia", QMediaPlayer.BufferingMedia: "BufferingMedia", QMediaPlayer.BufferedMedia: "BufferedMedia", QMediaPlayer.EndOfMedia: "EndOfMedia", QMediaPlayer.InvalidMedia: "InvalidMedia" } self.statusText = QPlainTextEdit() self.statusText.setReadOnly(True) self.statusText.setFixedHeight(25) self.statusText.setFixedWidth(150) self.mediaPlayer.mediaStatusChanged.connect(self.mediaStatusChanged) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) if self.display_status: controlLayout.addWidget(self.statusText) layout = QVBoxLayout() layout.addWidget(graphicsView) layout.addLayout(controlLayout) self.setFixedWidth(WIDTH + WIGGLE) self.setLayout(layout) self.mediaPlayer.setVideoOutput(self.videoItem) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) def openFile(self, fileName): if fileName != '' or fileName is not None: self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) # set resolution res_orig = get_video_resolution(fileName) self.aspect_ratio = float(res_orig[0]) / res_orig[1] self.videoItem.setSize(QSizeF(WIDTH, WIDTH / self.aspect_ratio)) self.setFixedHeight(WIDTH / self.aspect_ratio + 2*WIGGLE) self.playButton.setEnabled(True) # trick to show screenshot of the first frame of video self.mediaPlayer.play() self.mediaPlayer.pause() def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def mediaStatusChanged(self, status): self.statusText.setPlaceholderText(self.status_mapping[status]) def positionChanged(self, position): self.positionSlider.setValue(position) print self.positionSlider.value() # if position slider has reached the end, let's stop the video if self.positionSlider.value() >= self.positionSlider.maximum() - 1: self.mediaPlayer.stop() # play/pause hack to show the first frame of video self.mediaPlayer.play() self.mediaPlayer.pause() def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position)
class Player(QWidget): fullScreenChanged = pyqtSignal(bool) def __init__(self, playlist, parent=None): super(Player, self).__init__(parent) self.colorDialog = None self.trackInfo = "" self.statusInfo = "" self.duration = 0 self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.metaDataChanged.connect(self.metaDataChanged) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.player.mediaStatusChanged.connect(self.statusChanged) self.player.bufferStatusChanged.connect(self.bufferingProgress) self.player.videoAvailableChanged.connect(self.videoAvailableChanged) self.player.error.connect(self.displayErrorMessage) self.videoWidget = VideoWidget() self.player.setVideoOutput(self.videoWidget) self.playlistModel = PlaylistModel() self.playlistModel.setPlaylist(self.playlist) self.playlistView = QListView() self.playlistView.setModel(self.playlistModel) self.playlistView.setCurrentIndex( self.playlistModel.index(self.playlist.currentIndex(), 0)) self.playlistView.activated.connect(self.jump) self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.labelDuration = QLabel() self.slider.sliderMoved.connect(self.seek) self.labelHistogram = QLabel() self.labelHistogram.setText("Histogram:") self.histogram = HistogramWidget() histogramLayout = QHBoxLayout() histogramLayout.addWidget(self.labelHistogram) histogramLayout.addWidget(self.histogram, 1) self.probe = QVideoProbe() self.probe.videoFrameProbed.connect(self.histogram.processFrame) self.probe.setSource(self.player) openButton = QPushButton("Open", clicked=self.open) controls = PlayerControls() controls.setState(self.player.state()) controls.setVolume(self.player.volume()) controls.setMuted(controls.isMuted()) controls.play.connect(self.player.play) controls.pause.connect(self.player.pause) controls.stop.connect(self.player.stop) controls.next.connect(self.playlist.next) controls.previous.connect(self.previousClicked) controls.changeVolume.connect(self.player.setVolume) controls.changeMuting.connect(self.player.setMuted) controls.changeRate.connect(self.player.setPlaybackRate) controls.stop.connect(self.videoWidget.update) self.player.stateChanged.connect(controls.setState) self.player.volumeChanged.connect(controls.setVolume) self.player.mutedChanged.connect(controls.setMuted) self.fullScreenButton = QPushButton("FullScreen") self.fullScreenButton.setCheckable(True) self.colorButton = QPushButton("Color Options...") self.colorButton.setEnabled(False) self.colorButton.clicked.connect(self.showColorDialog) displayLayout = QHBoxLayout() displayLayout.addWidget(self.videoWidget, 2) displayLayout.addWidget(self.playlistView) controlLayout = QHBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(openButton) controlLayout.addStretch(1) controlLayout.addWidget(controls) controlLayout.addStretch(1) controlLayout.addWidget(self.fullScreenButton) controlLayout.addWidget(self.colorButton) layout = QVBoxLayout() layout.addLayout(displayLayout) hLayout = QHBoxLayout() hLayout.addWidget(self.slider) hLayout.addWidget(self.labelDuration) layout.addLayout(hLayout) layout.addLayout(controlLayout) layout.addLayout(histogramLayout) self.setLayout(layout) if not self.player.isAvailable(): QMessageBox.warning(self, "Service not available", "The QMediaPlayer object does not have a valid service.\n" "Please check the media service plugins are installed.") controls.setEnabled(False) self.playlistView.setEnabled(False) openButton.setEnabled(False) self.colorButton.setEnabled(False) self.fullScreenButton.setEnabled(False) self.metaDataChanged() self.addToPlaylist(playlist) def open(self): fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files") self.addToPlaylist(fileNames) def addToPlaylist(self, fileNames): for name in fileNames: fileInfo = QFileInfo(name) if fileInfo.exists(): url = QUrl.fromLocalFile(fileInfo.absoluteFilePath()) if fileInfo.suffix().lower() == 'm3u': self.playlist.load(url) else: self.playlist.addMedia(QMediaContent(url)) else: url = QUrl(name) if url.isValid(): self.playlist.addMedia(QMediaContent(url)) def durationChanged(self, duration): duration /= 1000 self.duration = duration self.slider.setMaximum(duration) def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) self.updateDurationInfo(progress) def metaDataChanged(self): if self.player.isMetaDataAvailable(): self.setTrackInfo("%s - %s" % ( self.player.metaData(QMediaMetaData.AlbumArtist), self.player.metaData(QMediaMetaData.Title))) def previousClicked(self): # Go to the 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() else: self.player.setPosition(0) def jump(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def playlistPositionChanged(self, position): self.playlistView.setCurrentIndex( self.playlistModel.index(position, 0)) def seek(self, seconds): self.player.setPosition(seconds * 1000) def statusChanged(self, status): self.handleCursor(status) if status == QMediaPlayer.LoadingMedia: self.setStatusInfo("Loading...") elif status == QMediaPlayer.StalledMedia: self.setStatusInfo("Media Stalled") elif status == QMediaPlayer.EndOfMedia: QApplication.alert(self) elif status == QMediaPlayer.InvalidMedia: self.displayErrorMessage() else: self.setStatusInfo("") def handleCursor(self, status): if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia): self.setCursor(Qt.BusyCursor) else: self.unsetCursor() def bufferingProgress(self, progress): self.setStatusInfo("Buffering %d%" % progress) def videoAvailableChanged(self, available): if available: self.fullScreenButton.clicked.connect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.connect( self.fullScreenButton.setChecked) if self.fullScreenButton.isChecked(): self.videoWidget.setFullScreen(True) else: self.fullScreenButton.clicked.disconnect( self.videoWidget.setFullScreen) self.videoWidget.fullScreenChanged.disconnect( self.fullScreenButton.setChecked) self.videoWidget.setFullScreen(False) self.colorButton.setEnabled(available) def setTrackInfo(self, info): self.trackInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def setStatusInfo(self, info): self.statusInfo = info if self.statusInfo != "": self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo)) else: self.setWindowTitle(self.trackInfo) def displayErrorMessage(self): self.setStatusInfo(self.player.errorString()) def updateDurationInfo(self, currentInfo): duration = self.duration if currentInfo or duration: currentTime = QTime((currentInfo/3600)%60, (currentInfo/60)%60, currentInfo%60, (currentInfo*1000)%1000) totalTime = QTime((duration/3600)%60, (duration/60)%60, duration%60, (duration*1000)%1000); format = 'hh:mm:ss' if duration > 3600 else 'mm:ss' tStr = currentTime.toString(format) + " / " + totalTime.toString(format) else: tStr = "" self.labelDuration.setText(tStr) def showColorDialog(self): if self.colorDialog is None: brightnessSlider = QSlider(Qt.Horizontal) brightnessSlider.setRange(-100, 100) brightnessSlider.setValue(self.videoWidget.brightness()) brightnessSlider.sliderMoved.connect( self.videoWidget.setBrightness) self.videoWidget.brightnessChanged.connect( brightnessSlider.setValue) contrastSlider = QSlider(Qt.Horizontal) contrastSlider.setRange(-100, 100) contrastSlider.setValue(self.videoWidget.contrast()) contrastSlider.sliderMoved.connect(self.videoWidget.setContrast) self.videoWidget.contrastChanged.connect(contrastSlider.setValue) hueSlider = QSlider(Qt.Horizontal) hueSlider.setRange(-100, 100) hueSlider.setValue(self.videoWidget.hue()) hueSlider.sliderMoved.connect(self.videoWidget.setHue) self.videoWidget.hueChanged.connect(hueSlider.setValue) saturationSlider = QSlider(Qt.Horizontal) saturationSlider.setRange(-100, 100) saturationSlider.setValue(self.videoWidget.saturation()) saturationSlider.sliderMoved.connect( self.videoWidget.setSaturation) self.videoWidget.saturationChanged.connect( saturationSlider.setValue) layout = QFormLayout() layout.addRow("Brightness", brightnessSlider) layout.addRow("Contrast", contrastSlider) layout.addRow("Hue", hueSlider) layout.addRow("Saturation", saturationSlider) button = QPushButton("Close") layout.addRow(button) self.colorDialog = QDialog(self) self.colorDialog.setWindowTitle("Color Options") self.colorDialog.setLayout(layout) button.clicked.connect(self.colorDialog.close) self.colorDialog.show()