class Window(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) # load config self.data = yaml_loader() # load ui self.setupUi(self) # load icons self.setWindowTitle("Sputofy") self.setWindowIcon(QIcon(os.path.join(RES_PATH, "logo.svg"))) loopIcon = QIcon() loopIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.loopBtn.setIcon(loopIcon) prevIcon = QIcon() prevIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "backwardIcon.svg"))) self.prevBtn.setIcon(prevIcon) playIcon = QIcon() playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg"))) self.playBtn.setIcon(playIcon) nextIcon = QIcon() nextIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "forwardIcon.svg"))) self.nextBtn.setIcon(nextIcon) randomIcon = QIcon() randomIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "randomIconOFF.svg"))) self.randomBtn.setIcon(randomIcon) volumeIcon = QIcon() volumeIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "volumeIcon.svg"))) self.volumeBtn.setIcon(volumeIcon) # window's settings self.xCor = self.data['last_position']['xPos'] self.yCor = self.data['last_position']['yPos'] self.widthSize = self.data['last_window_size']['width'] self.heightSize = self.data['last_window_size']['height'] self.setGeometry(self.xCor, self.yCor, self.widthSize, self.heightSize) # load YouTubeToMP3 self.YouTubeToMP3 = YouTubeToMP3Window() # open YouTubeToMP3 using button self.actionYT_MP3.triggered.connect(self.YouTubeToMP3.show_window) # info action self.actionInfo.triggered.connect(self.info_handle) #=========================== mediaplayer ============================== # create media player object self.mediaPlayer = QMediaPlayer(None) # open button self.actionOpen_Song.triggered.connect(self.open_song) self.actionOpen_Folder.triggered.connect(self.open_folder) # play button self.playBtn.setEnabled(False) self.playBtn.clicked.connect( self.play_video ) # when btn is pressed: if it is playing it pause, if it is paused it plays # QShortcut(QKeySequence("Space"), self).activated.connect(self.play_video)metodo da ricordare in caso di problemi #TODO # duration slider self.durationSlider.setEnabled(False) self.durationSliderMaxValue = 0 self.durationSlider.valueChanged.connect( self.mediaPlayer.setPosition ) # set mediaPlayer position using the value took from the slider QShortcut('Right', self, lambda: self.durationSlider.setValue( self.durationSlider.value() + 10000)) # 1s = 1000ms QShortcut('Left', self, lambda: self.durationSlider.setValue( self.durationSlider.value() - 10000)) # 1s = 1000ms QShortcut('Shift+Right', self, lambda: self.durationSlider.setValue( self.durationSliderMaxValue - 1000)) # jump to the end-1s of song QShortcut('Shift+Left', self, lambda: self.durationSlider.setValue(0)) # restart song # volumeSlider self.volumeSlider.setProperty("value", 100) self.volumeSlider.setRange(0, 100) self.volumeSlider.setValue( self.data['volume'] if self.data['volume'] != 0 else self.data['volume'] + 1 ) # set slider value | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.mediaPlayer.setVolume( self.data['volume'] if self.data['volume'] != 0 else self.data['volume'] + 1 ) # set mediaPlayer volume | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.volumeLabel.setText( f"{self.data['volume']}%" if self.data['volume'] != 0 else f"{self.data['volume']+1}%" ) # set volume label text | if saved volume is equal to 0 load with volume = 1 else load the saved volume self.volumeSlider.valueChanged.connect( self.mediaPlayer.setVolume ) # set mediaPlayer volume using the value took from the slider QShortcut('Up', self, lambda: self.volumeSlider.setValue( self.volumeSlider.value() + 1)) # volume + 1 QShortcut('Down', self, lambda: self.volumeSlider.setValue( self.volumeSlider.value() - 1)) # volume - 1 QShortcut( 'Shift+Up', self, lambda: self.volumeSlider.setValue(100)) # set maximum volume QShortcut( 'Shift+Down', self, lambda: self.volumeSlider.setValue(0)) # set minimun volume(mute) # volumeBtn self.volumeBtn.clicked.connect( self.volume_toggle) # mute/unmute volume pressing btn self.isMuted = False # starting with a non-muted volume self.previousVolume = self.data[ 'volume'] # loading last registered volume # media player signals self.mediaPlayer.durationChanged.connect( self.duration_changed) # set range of duration slider self.mediaPlayer.positionChanged.connect( self.position_changed) # duration slider progress self.mediaPlayer.stateChanged.connect( self.player_state) # see when it's playing or in pause self.mediaPlayer.volumeChanged.connect( self.volume_icon) # change volumebtn icon #=========================== playlist ============================== # create the playlist self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(2) self.mediaPlayer.setPlaylist(self.playlist) # clear the playlist self.playlistIsEmpty = True # playlistList model self.model = PlaylistModel(self.playlist) self.playlistView.setModel(self.model) self.playlist.currentIndexChanged.connect( self.playlist_position_changed) selection_model = self.playlistView.selectionModel() selection_model.selectionChanged.connect( self.playlist_selection_changed) #=========================== playlist function ============================== self.mediaList = [] # array of loaded songs self.currentPlaylist = "" # current loaded playlist name self.isCustomPlaylist = False # add song name on title self.playlist.currentMediaChanged.connect(self.set_title) # playlist buttons self.nextBtn.clicked.connect(self.next_song) # seek track forward self.prevBtn.clicked.connect(self.prev_song) # seek track backward self.mediaPlayer.mediaStatusChanged.connect( self.auto_next_track ) # once song is ended seek track forward and play it self.actionLoopIt.triggered.connect( self.loop_song) # (1) loop the same song self.actionShuffle.triggered.connect( self.shuffle_playlist) # change song's order self.loopBtn.clicked.connect(self.loop) # (3) loop the playlist self.randomBtn.clicked.connect( self.random) # (4) play random song without end # create new playlist self.actionCreatePlaylist.triggered.connect(self.custom_playlist) # delete current playlist self.actionDeletePlaylist.triggered.connect(self.delete_playlist) # remove all songs self.actionClearQueue.triggered.connect(self.clear_queue) # load playlist self.actionDict = {} # dictionary of action Objects for action in self.data['playlistList']: self.actionDict[action] = self.menuPlaylist.addAction( action, partial(self.load_playlist, action)) if len(self.data['playlistList']) == 0: self.menuPlaylist.menuAction().setVisible(False) #================== Songs opening ==================# def open_folder(self): foldername = QFileDialog.getExistingDirectory(self, "Open folder", "c:\\") if foldername: self.playlist.clear() self.mediaList.clear() for song in os.listdir(foldername): media = f"{foldername}/{song}" self.playlist.addMedia(QMediaContent(QUrl(media))) self.mediaList.append(media) self.playlist.setCurrentIndex(0) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.playlistIsEmpty = False self.isCustomPlaylist = False self.model.layoutChanged.emit() # load songs in list view self.set_title() self.mediaPlayer.pause() # adjust play/pause icon def open_song(self): filename, _ = QFileDialog.getOpenFileName(self, "Open Song", "c:\\") if filename: if self.playlistIsEmpty == False: self.playlist.clear() self.mediaList.clear() self.playlistIsEmpty = True self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(filename))) self.mediaList.append(filename) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.isCustomPlaylist = False self.model.layoutChanged.emit() # load song in list view self.set_title() # adjust play/pause icon if self.playlist.mediaCount( ) == 1: # if there is 1 song and you add another self.playlist.setCurrentIndex(0) self.mediaPlayer.pause() def load_playlist(self, playlistName): self.playlist.clear() self.mediaList.clear() # reload config self.data = yaml_loader() for song in self.data['playlistList'][playlistName]: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(song))) self.mediaList.append(song) self.playlist.setCurrentIndex(0) self.playBtn.setEnabled(True) self.durationSlider.setEnabled(True) self.playlistIsEmpty = False self.isCustomPlaylist = True self.model.layoutChanged.emit() # load songs in list view self.currentPlaylist = playlistName # name of current loaded playlist self.set_title() self.statusbar.showMessage(f'Playlist "{playlistName}" loaded', 4000) self.menuPlaylist.menuAction().setVisible(True) # adjust play/pause icon self.mediaPlayer.pause() def set_title(self): if self.playlist.mediaCount() == 0: self.setWindowTitle("Sputofy") else: if self.isCustomPlaylist == False: self.setWindowTitle( f"Sputofy - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}" ) else: self.setWindowTitle( f"Sputofy - {self.currentPlaylist} - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}" ) #=======================================================# #================== Player Functions ==================# def play_video(self): if self.durationSlider.isEnabled(): # if slider was enabled if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def duration_changed(self, duration): self.durationSlider.setRange(0, duration) if duration > 0: self.totalTime_Label.setText(time_format(round( duration / 1000))) # duration is in ms self.durationSliderMaxValue = duration def position_changed(self, position): if position >= 0: self.elapsedTime_Label.setText(time_format( (position / 1000))) # position is in ms # Disable the events to prevent updating triggering a setPosition event (can cause stuttering). self.durationSlider.blockSignals(True) self.durationSlider.setValue(position) self.durationSlider.blockSignals(False) #=======================================================# #================== Playlist Settings ==================# #TODO Work in progress def playlist_array(self): index = self.playlist.mediaCount() mediaList = [] for i in range(index): # songPath = (self.playlist.media(path).canonicalUrl().path())#.split("/",1)[1] # mediaList.append(songPath) # print(self.playlist.media(i).canonicalUrl().path()) mediaList.append(self.playlist.media(i).canonicalUrl().fileName()) return mediaList def custom_playlist(self): if not self.playlist.mediaCount() == 0: name, is_notEmpty = QInputDialog.getText(self, "playlist", "save playlist as:") if name: if name in self.data['playlistList']: self.statusbar.showMessage( "playlist not created (name is already used)", 4000) else: self.data['playlistList'][name] = self.mediaList yaml_dump(self.data) # add new action Object to dictionary self.actionDict[name] = self.menuPlaylist.addAction( name, partial(self.load_playlist, name)) self.load_playlist( name) # instantly loading the new playlist else: self.statusbar.showMessage( "playlist not created (you should give a name to your baby :/)", 4000) else: self.statusbar.showMessage("there are no songs to playlist", 4000) def delete_playlist(self): if self.isCustomPlaylist: if len(self.data['playlistList']) == 1: self.menuPlaylist.menuAction().setVisible(False) self.data['playlistList'].pop( self.currentPlaylist) # remove playlist from dictionary self.menuPlaylist.removeAction(self.actionDict[ self.currentPlaylist]) # remove relative action self.actionDict.pop( self.currentPlaylist) # remove relative action Object self.playlist.clear() self.model.layoutChanged.emit() self.setWindowTitle("Sputofy") yaml_dump(self.data) self.statusbar.showMessage( 'succesfully deleted "' + self.currentPlaylist + '" playlist', 4000) else: self.statusbar.showMessage("cannot delete a non custom playlist", 4000) def clear_queue(self): self.playlist.clear() self.mediaList.clear() self.playBtn.setEnabled(False) self.model.layoutChanged.emit() def playlist_position_changed(self, i): if i > -1: ix = self.model.index(i) self.playlistView.setCurrentIndex(ix) def playlist_selection_changed(self, ix): # We receive a QItemSelection from selectionChanged. i = ix.indexes()[0].row() self.posizione = i self.playlist.setCurrentIndex(i) self.mediaPlayer.play() #=======================================================# #================== Playback Settings ==================# def next_song(self): if self.playlist.currentIndex() == self.playlist.mediaCount() - 1: self.playlist.setCurrentIndex(0) else: self.playlist.next() def prev_song(self): if self.playlist.currentIndex() == 0: self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1) else: self.playlist.previous() def loop_song(self): if self.playlist.playbackMode() != 1: self.playlist.setPlaybackMode(1) self.actionLoopIt.setText("Loop it: ON") self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) else: self.playlist.setPlaybackMode(2) self.actionLoopIt.setText("Loop it: OFF") def shuffle_playlist(self): if self.playlist.mediaCount(): self.playlist.shuffle() self.model.layoutChanged.emit() else: self.statusbar.showMessage("there are no songs to shuffle", 4000) def loop(self): if self.playlist.playbackMode() != 3: self.playlist.setPlaybackMode(3) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconON.svg"))) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) self.actionLoopIt.setText("Loop it: OFF") else: self.playlist.setPlaybackMode(2) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) def random(self): if self.playlist.playbackMode() != 4: self.playlist.setPlaybackMode(4) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconON.svg"))) self.loopBtn.setIcon( QIcon(os.path.join(RES_PATH, "loopIconOFF.svg"))) self.actionLoopIt.setText("Loop it: OFF") else: self.playlist.setPlaybackMode(2) self.randomBtn.setIcon( QIcon(os.path.join(RES_PATH, "randomIconOFF.svg"))) def auto_next_track(self): if self.mediaPlayer.mediaStatus() == QMediaPlayer.EndOfMedia: if self.playlist.playbackMode() == 2: # index starts from 0 mediacount starts from 1 if self.playlist.currentIndex( ) != self.playlist.mediaCount() - 1: self.playlist.next() self.mediaPlayer.play() else: # if ended song was the last one set the index to the first one and pause self.playlist.setCurrentIndex(0) self.mediaPlayer.pause() # loop playlist elif self.playlist.playbackMode() == 3: self.playlist.next() self.mediaPlayer.play() # random song elif self.playlist.playbackMode() == 4: while self.playlist.previousIndex( ) == self.playlist.currentIndex( ): # preventing repeating the same song self.playlist.setCurrentIndex( random.randint(0, self.playlist.mediaCount() - 1)) #=======================================================# #================== Volume Settings ==================# def volume_icon(self, volume): self.volumeLabel.setText(f"{volume}%") if volume: volumeIcon = QIcon() volumeIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "volumeIcon.svg")), QIcon.Normal, QIcon.Off) self.volumeBtn.setIcon(volumeIcon) self.previousVolume = self.volumeSlider.value() self.isMuted = False else: volumeMutedIcon = QIcon() volumeMutedIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "volumeMutedIcon.svg")), QIcon.Normal, QIcon.Off) self.volumeBtn.setIcon(volumeMutedIcon) self.isMuted = True def volume_toggle(self): if self.isMuted == False: self.volumeSlider.setValue(0) self.isMuted = True elif self.isMuted == True: if self.previousVolume == 0: self.volumeSlider.setValue(10) else: self.volumeSlider.setValue(self.previousVolume) self.isMuted = False #=======================================================# def mousePressEvent(self, event): ''' remove the border around the buttons created by using tab key ''' focused_widget = QtWidgets.QApplication.focusWidget() try: focused_widget.clearFocus() except: pass QMainWindow.mousePressEvent(self, event) def player_state(self, event): ''' event handler that adjust the play/pause icon ''' if event == QMediaPlayer.PlayingState: pauseIcon = QIcon() pauseIcon.addPixmap( QPixmap(os.path.join(RES_PATH, "pauseIcon.svg")), QIcon.Normal, QIcon.Off) self.playBtn.setIcon(pauseIcon) elif event == QMediaPlayer.PausedState: playIcon = QIcon() playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg")), QIcon.Normal, QIcon.Off) self.playBtn.setIcon(playIcon) def closeEvent(self, event): ''' event handler that take window information and save it in config before the window close ''' # retrieve position xAxis = self.geometry().x() yAxis = self.geometry().y() self.data['last_position']['xPos'] = xAxis self.data['last_position']['yPos'] = yAxis # retrieve size width = self.width() height = self.height() self.data['last_window_size']['width'] = width self.data['last_window_size']['height'] = height # retrieve volume self.data['volume'] = self.mediaPlayer.volume() # retrieve user user = os.getlogin() self.data[ 'default_folder'] = f"C:\\Users\\{user}\\Desktop\\sputofy_songs" yaml_dump(self.data) def info_handle(self): info = "Sputofy\n1.0.0\n©2020 "+\ "Sputofy is a free audio player based on the converted youtube songs made by a_str0\n\n"+\ "Sputofy is written using python 3.x and PyQt5 modules" msg = QMessageBox.about(self, "About", info)
class Start(QMainWindow): def __init__(self): super(Start, self).__init__() self.titles = "Media Player" self.left = 500 self.top = 300 self.width = 400 self.height = 200 self.window_main() self.adding_menus() def openMultipleFile(self): dialogs = QFileDialog(self) self.fnames, _ = dialogs.getOpenFileNames( self, 'Open Media Files', QDir.homePath(), "Videos (*.mp4 *.mkv *.3pg)") if self.fnames != '': self.playlist = QMediaPlaylist(self) self.fnamelist = [] for playlst in self.fnames: self.fnamelist.append( QMediaContent(QUrl.fromLocalFile(playlst))) self.playlist.addMedia(self.fnamelist) self.playlist.setCurrentIndex(1) self.videoWidget = QVideoWidget(self) self.mediaPlayer.setVideoOutput(self.videoWidget) # self.videoWidget.setAspectRatioMode(60, 60,Qt.KeepAspectRatioByExpanding) self.mediaPlayer.setPlaylist(self.playlist) self.playlist.currentIndexChanged.connect(self.mediaNameChange) self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.setEnabled(True) self.stop.setEnabled(True) self.loop.setEnabled(True) if (len(self.fnamelist) > 1): self.forw.setEnabled(True) self.shuffl.setEnabled(True) self.l1.setText("00:00") mediaName = self.fnames[0].rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) self.mediaPlayer.durationChanged.connect(self.sliderDuration) def openFile(self): self.fname, _ = QFileDialog.getOpenFileName( self, 'Open Media Files', QDir.homePath(), "Videos (*.mp4 *.mkv *.3pg)") if self.fname != '': mediaName = self.fname.rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) self.playlist = QMediaPlaylist(self) self.playlist.addMedia( QMediaContent(QUrl.fromLocalFile(self.fname))) self.playlist.setCurrentIndex(1) self.mediaPlayer.setPlaylist(self.playlist) self.playlist.currentIndexChanged.connect(self.mediaNameChange) self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.setEnabled(True) self.stop.setEnabled(True) self.loop.setEnabled(True) self.l1.setText("00:00") self.mediaPlayer.durationChanged.connect(self.sliderDuration) def window_main(self): self.setWindowTitle(self.titles) qw = QWidget() self.setGeometry(self.left, self.top, qw.maximumWidth(), qw.maximumHeight()) self.setMinimumSize(540, 0) self.setWindowIcon(QIcon("mediaplayer.png")) self.video() self.show() def sliderChanged(self, position): pos = position * 1000 self.mediaPlayer.setPosition(pos) self.slider.setValue(position) def adding_menus(self): menu = Allmenu(self) def volumeChange(self, vol): self.mediaPlayer.setVolume(vol) def sliderDuration(self, duratn): milisec = self.mediaPlayer.duration() sec = int(milisec / 1000) hour = int(sec / 3600) min = int((sec / 60) - (hour * 60)) secs = int(sec - (min * 60) - (hour * 60 * 60)) self.l2.setText(str(hour) + ":" + str(min) + ":" + str(secs)) self.slider.setMaximum(sec) def sliderDuration2(self, duratn): second = int(duratn / 1000) self.slider.setValue(second) hour = int(second / 3600) min = int((second / 60) - (hour * 60)) secs = int(second - (min * 60) - (hour * 60 * 60)) if (min < 10): min = "0" + str(min) else: min = str(min) if (secs < 10): secs = "0" + str(secs) else: secs = str(secs) if (hour == 0): self.l1.setText(min + ":" + secs) else: self.l1.setText(str(hour) + ":" + min + ":" + secs) def mediaNameChange(self, index): mediaName = self.fnames[index].rsplit('/', 1)[-1] self.fulltitle = mediaName + " - " + self.titles self.setWindowTitle(self.fulltitle) if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) else: if ((index + 1) == self.playlist.mediaCount()): self.forw.setEnabled(False) self.back.setEnabled(True) else: self.back.setEnabled(True) def video(self): self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.positionChanged.connect(self.sliderDuration2) self.mediaPlayer.setVolume(10) videoWidget = QVideoWidget() layout = QVBoxLayout() wid = QWidget(self) self.play = QPushButton() self.play.setEnabled(False) self.play.setFixedWidth(40) self.play.setFixedHeight(30) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.play.setIconSize(QSize(20, 20)) self.play.clicked.connect(self.playAction) self.play.setShortcut(QKeySequence("Space")) self.back = QPushButton() self.back.setEnabled(False) self.back.setFixedWidth(40) self.back.setFixedHeight(25) self.back.setStyleSheet("margin-left: 10px") self.back.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekBackward)) self.back.setIconSize(QSize(14, 14)) self.back.clicked.connect(self.prevAction) self.back.setShortcut(QKeySequence("Ctrl+b")) self.stop = QPushButton() self.stop.setEnabled(False) self.stop.setFixedWidth(40) self.stop.setFixedHeight(25) self.stop.setStyleSheet("margin-left: 0px") self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stop.setIconSize(QSize(14, 14)) self.stop.clicked.connect(self.stopAction) self.stop.setShortcut(QKeySequence("s")) self.forw = QPushButton() self.forw.setEnabled(False) self.forw.setFixedWidth(40) self.forw.setFixedHeight(25) self.forw.setStyleSheet("margin-left: 0px") self.forw.setIcon(self.style().standardIcon( QStyle.SP_MediaSeekForward)) self.forw.setIconSize(QSize(14, 14)) self.forw.clicked.connect(self.forwAction) self.forw.setShortcut(QKeySequence("Ctrl+f")) self.loop = QPushButton() self.loop.setEnabled(False) self.loop.setFixedWidth(40) self.loop.setFixedHeight(25) self.loop.setStyleSheet("margin-left: 10px") self.loop.setIcon(QIcon(QPixmap("loop.svg"))) self.loop.setIconSize(QSize(14, 14)) self.loop.clicked.connect(self.loopAction) self.loop.setShortcut(QKeySequence("Ctrl+l")) self.shuffl = QPushButton() self.shuffl.setEnabled(False) self.shuffl.setFixedHeight(25) self.shuffl.setStyleSheet("margin-left: 0px") self.shuffl.setFixedWidth(40) self.shuffl.setFixedHeight(25) self.shuffl.setStyleSheet("margin-left: 0px") self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) self.shuffl.setIconSize(QSize(14, 14)) self.shuffl.clicked.connect(self.shufflAction) self.shuffl.setShortcut(QKeySequence("Ctrl+shift+s")) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.volume = QDial() self.volume.setFixedWidth(40) self.volume.setFixedHeight(40) self.volume.setMaximum(100) self.volume.setMinimum(0) self.volume.setToolTip("Volume") self.volume.valueChanged.connect(self.volumeChange) hlayout = QHBoxLayout() hlayout.addWidget(self.play) hlayout.addWidget(self.back) hlayout.addWidget(self.stop) hlayout.addWidget(self.forw) hlayout.addWidget(self.loop) hlayout.addWidget(self.shuffl) hlayout.addItem(spacer) hlayout.addWidget(self.volume) hslayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(0) self.l1 = QLabel() self.l1.setText("--:--:--") self.l2 = QLabel() self.l2.setText("--:--:--") self.slider.sliderMoved.connect(self.sliderChanged) hslayout.addWidget(self.l1) hslayout.addWidget(self.slider) hslayout.addWidget(self.l2) layout.addWidget(videoWidget) layout.addLayout(hslayout) layout.addLayout(hlayout) wid.setLayout(layout) self.setCentralWidget(wid) self.mediaPlayer.setVideoOutput(videoWidget) def playAction(self): if (self.mediaPlayer.state() == 1): self.mediaPlayer.pause() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) elif (self.mediaPlayer.state() == 2): self.mediaPlayer.play() self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) else: self.back.setEnabled(False) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) def stopAction(self): self.mediaPlayer.stop() self.play.setEnabled(False) self.play.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.setWindowTitle(self.titles) self.l1.setText("--:--:--") self.l2.setText("--:--:--") def forwAction(self): if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) indexes = random.randint(0, (self.playlist.mediaCount() - 1)) self.playlist.setCurrentIndex(indexes) elif (self.playlist.playbackMode() == 1): self.playlist.next() else: print(self.playlist.currentIndex()) if ((self.playlist.currentIndex() + 2) == self.playlist.mediaCount()): self.forw.setEnabled(False) self.playlist.next() self.back.setEnabled(True) else: self.playlist.next() self.back.setEnabled(True) def prevAction(self): if (self.playlist.playbackMode() == 4): self.forw.setEnabled(True) self.back.setEnabled(True) indexes = random.randint(0, (self.playlist.mediaCount() - 1)) self.playlist.setCurrentIndex(indexes) elif (self.playlist.playbackMode() == 1): self.playlist.previous() else: if (self.playlist.currentIndex() == 1): self.forw.setEnabled(True) self.playlist.previous() self.back.setEnabled(False) else: self.playlist.previous() self.forw.setEnabled(True) def loopAction(self): if (self.playlist.playbackMode() != 1): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) self.loop.setIcon(QIcon(QPixmap("greenloop.svg"))) self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.loop.setIcon(QIcon(QPixmap("loop.svg"))) def shufflAction(self): if (self.playlist.playbackMode() != 4): self.playlist.setPlaybackMode(QMediaPlaylist.Random) self.shuffl.setIcon(QIcon(QPixmap("greenshuffl.svg"))) self.loop.setIcon(QIcon(QPixmap("loop.svg"))) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.shuffl.setIcon(QIcon(QPixmap("shuffl.svg"))) def close(self): sys.exit(1)
class Demo(QWidget): def __init__(self): super(Demo, self).__init__() self.time_label = QLabel(self) self.volume_slider = QSlider(self) self.progress_slider = QSlider(self) self.sound_btn = QPushButton(self) self.previous_btn = QPushButton(self) self.play_pause_btn = QPushButton(self) self.next_btn = QPushButton(self) self.mode_btn = QPushButton(self) self.list_btn = QPushButton(self) self.list_widget = QListWidget(self) self.h1_layout = QHBoxLayout() self.h2_layout = QHBoxLayout() self.all_v_layout = QVBoxLayout() self.playlist = QMediaPlaylist(self) self.player = QMediaPlayer(self) self.widget_init() self.layout_init() self.signal_init() def widget_init(self): self.time_label.setText('--/--') self.volume_slider.setRange(0, 100) self.volume_slider.setValue(100) self.volume_slider.setOrientation(Qt.Horizontal) self.progress_slider.setEnabled(False) self.progress_slider.setOrientation(Qt.Horizontal) self.sound_btn.setIcon(QIcon('images/sound_on.png')) self.previous_btn.setIcon(QIcon('images/previous.png')) self.play_pause_btn.setIcon(QIcon('images/play.png')) self.next_btn.setIcon(QIcon('images/next.png')) self.mode_btn.setIcon(QIcon('images/list_loop.png')) self.list_btn.setIcon(QIcon('images/show.png')) self.player.setPlaylist(self.playlist) self.media_list = ['/Users/louis/Downloads/music1.mp3', '/Users/louis/Downloads/music2.mp4', '/Users/louis/Downloads/music3.mp3'] for m in self.media_list: self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(m))) self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.list_widget.addItems([m.split('/')[-1] for m in self.media_list]) def layout_init(self): self.h1_layout.addWidget(self.progress_slider) self.h1_layout.addWidget(self.time_label) self.h2_layout.addWidget(self.volume_slider) self.h2_layout.addWidget(self.sound_btn) self.h2_layout.addWidget(self.previous_btn) self.h2_layout.addWidget(self.play_pause_btn) self.h2_layout.addWidget(self.next_btn) self.h2_layout.addWidget(self.mode_btn) self.h2_layout.addWidget(self.list_btn) self.all_v_layout.addLayout(self.h1_layout) self.all_v_layout.addLayout(self.h2_layout) self.all_v_layout.addWidget(self.list_widget) self.all_v_layout.setSizeConstraint(QVBoxLayout.SetFixedSize) self.setLayout(self.all_v_layout) def signal_init(self): self.sound_btn.clicked.connect(lambda: self.btn_func(self.sound_btn)) self.previous_btn.clicked.connect(lambda: self.btn_func(self.previous_btn)) self.play_pause_btn.clicked.connect(lambda: self.btn_func(self.play_pause_btn)) self.next_btn.clicked.connect(lambda: self.btn_func(self.next_btn)) self.mode_btn.clicked.connect(lambda: self.btn_func(self.mode_btn)) self.list_btn.clicked.connect(lambda: self.btn_func(self.list_btn)) self.volume_slider.valueChanged.connect(self.volume_slider_func) self.list_widget.doubleClicked.connect(self.list_play_func) self.player.durationChanged.connect(self.get_duration_func) self.player.positionChanged.connect(self.get_position_func) self.progress_slider.sliderMoved.connect(self.update_position_func) def btn_func(self, btn): if btn == self.sound_btn: if self.player.isMuted(): self.player.setMuted(False) self.sound_btn.setIcon(QIcon('images/sound_on')) else: self.player.setMuted(True) self.sound_btn.setIcon(QIcon('images/sound_off')) elif btn == self.previous_btn: if self.playlist.currentIndex() == 0: self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1) else: self.playlist.previous() elif btn == self.play_pause_btn: if self.player.state() == 1: self.player.pause() self.play_pause_btn.setIcon(QIcon('images/play.png')) else: self.player.play() self.play_pause_btn.setIcon(QIcon('images/pause.png')) elif btn == self.next_btn: if self.playlist.currentIndex() == self.playlist.mediaCount() - 1: self.playlist.setCurrentIndex(0) else: self.playlist.next() elif btn == self.mode_btn: if self.playlist.playbackMode() == 2: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.mode_btn.setIcon(QIcon('images/item_loop.png')) elif self.playlist.playbackMode() == 3: self.playlist.setPlaybackMode(QMediaPlaylist.Random) self.mode_btn.setIcon(QIcon('images/random.png')) elif self.playlist.playbackMode() == 4: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) self.mode_btn.setIcon(QIcon('images/list_loop.png')) elif btn == self.list_btn: if self.list_widget.isHidden(): self.list_widget.show() self.list_btn.setIcon(QIcon('images/show.png')) else: self.list_widget.hide() self.list_btn.setIcon(QIcon('images/hide.png')) def volume_slider_func(self, value): self.player.setVolume(value) if value == 0: self.sound_btn.setIcon(QIcon('images/sound_off.png')) else: self.sound_btn.setIcon(QIcon('images/sound_on.png')) def list_play_func(self): self.playlist.setCurrentIndex(self.list_widget.currentRow()) self.player.play() self.play_pause_btn.setIcon(QIcon('images/pause.png')) def get_duration_func(self, d): self.progress_slider.setRange(0, d) self.progress_slider.setEnabled(True) self.get_time_func(d) def get_time_func(self, d): seconds = int(d / 1000) minutes = int(seconds / 60) seconds -= minutes * 60 if minutes == 0 and seconds == 0: self.time_label.setText('--/--') self.play_pause_btn.setIcon(QIcon('images/play.png')) else: self.time_label.setText('{}:{}'.format(minutes, seconds)) def get_position_func(self, p): self.progress_slider.setValue(p) def update_position_func(self, v): self.player.setPosition(v) d = self.progress_slider.maximum() - v self.get_time_func(d)
class MyWidget(QMainWindow): def __init__(self): super().__init__() # !Костыль # Запрещаю менять размер окна, т.к. не хочу работать с layout`ами self.setFixedSize(656, 532) self.setWindowIcon(QIcon('icons/icon.ico')) # Добавляем эквалайзер громкости self.equalizer = QVolumeEq((255, 255, 102), (255, 26, 10), bg_color=(0, 0, 0, 20)) self.equalizer.setParent(self) self.equalizer.move(20, 391) self.equalizer.resize(341, 31) uic.loadUi('icons/djap.ui', self) self.lightThemeAction.triggered.connect(self.change_theme) self.darkThemeAction.triggered.connect(self.change_theme) # Создаём организатор плейлистов self.playlist_handler = QPlaylistHandler() self.playlist_handler.setParent(self) self.playlist_handler.move(380, 40) # Настраиваем меню self.saveOption.triggered.connect(self.playlist_handler.save_playlist) self.saveAsOption.triggered.connect(self.playlist_handler.save_playlist_as) self.deleteOption.triggered.connect(self.playlist_handler.delete_playlist) self.aboutOption.triggered.connect(self.about) self.helpOption.triggered.connect(self.help) self.repeatModeOption.triggered.connect(self.playlist_handler.change_playmode) self.oneModeOption.triggered.connect(self.playlist_handler.change_playmode) self.randomModeOption.triggered.connect(self.playlist_handler.change_playmode) # Реализация проигрывателя и основного плейлиста self.player = QMediaPlayer() self.player.durationChanged.connect(self.update_song) self.player.setVolume(25) self.player.positionChanged.connect(self.update_timeline_position) self.queue = QMediaPlaylist(self.player) self.player.setPlaylist(self.queue) self.queue.setPlaybackMode(QMediaPlaylist.Loop) self.is_looped_queue = True # Загрузка музыки из плейлиста self.load_songs_from_playlist() # Подключаем кнопки к их функциям self.is_playing = False self.playBtn.clicked.connect(self.play_or_pause) self.queue.currentMediaChanged.connect(self.check_to_stop) self.nextBtn.clicked.connect(self.next_audio) self.prevBtn.clicked.connect(self.prev_audio) self.is_looped_current_track = False self.loopBtn.clicked.connect(self.loop_or_unloop_current_track) # Настройка слайдера звука self.volumeSlider.hide() self.volumeSlider.setValue(25) self.equalizer.setValue(25) self.volumeSlider.sliderReleased.connect(self.volumeSlider.hide) self.volumeSlider.valueChanged.connect(self.change_volume) self.volumeBtn.clicked.connect(self.change_volume) # Настройка таймлайна self.is_timeline_dragged = False self.timeline.sliderReleased.connect(self.timeline_changed) self.timeline.sliderPressed.connect(self.timeline_is_dragged) # !Костыль # Имитируем запуск аудиодорожки, чтобы подгрузить данные self.play_or_pause() self.play_or_pause() self.icon_changed() def palette(self): """Функция для создания темы""" con = sqlite3.connect('user_data.sqlite') cur = con.cursor() if int(cur.execute('SELECT * FROM theme').fetchone()[0]): palette = QPalette() palette.setColor(QPalette.Window, QColor(240, 240, 240)) palette.setColor(QPalette.WindowText, Qt.black) palette.setColor(QPalette.Base, Qt.white) palette.setColor(QPalette.AlternateBase, QColor(246, 246, 246)) palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 240)) palette.setColor(QPalette.ToolTipText, Qt.black) palette.setColor(QPalette.Text, Qt.black) palette.setColor(QPalette.Button, QColor(240, 240, 240)) palette.setColor(QPalette.ButtonText, Qt.black) palette.setColor(QPalette.BrightText, Qt.white) palette.setColor(QPalette.Highlight, QColor(0, 120, 215).lighter()) palette.setColor(QPalette.HighlightedText, Qt.white) else: palette = QPalette() palette.setColor(QPalette.Window, QColor(53, 53, 53)) palette.setColor(QPalette.WindowText, Qt.white) palette.setColor(QPalette.Base, QColor(15, 15, 15)) 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.Highlight, QColor(142, 45, 197).lighter()) palette.setColor(QPalette.HighlightedText, Qt.black) return palette def change_theme(self): """Функция для смены темы""" con = sqlite3.connect('user_data.sqlite') cur = con.cursor() if self.sender() == self.lightThemeAction: cur.execute('UPDATE theme SET isit = 1') else: cur.execute('UPDATE theme SET isit = 0') con.commit() QMessageBox.warning(self, 'DJust Audio Player', 'Чтобы изменения вступили в силу, ' 'перезапустите приложение.', QMessageBox.Ok) def help(self): """Функция для показа формы справки""" self.help = QHelp() def about(self): """Функция для показа формы О программе""" self.about = QAbout() def delete_song_from_mediaplayer(self, index): """Удалить трек из медиаплеера""" self.queue.removeMedia(index) def add_song_to_mediaplayer(self, url): """Добавить трек в медиаплеер""" self.queue.addMedia(QMediaContent(QUrl(url))) def change_track_by_click(self, row): """Функция для смены трека по нажатию в списке""" self.queue.setCurrentIndex(row) def check_to_stop(self): """Проверяем, чтобы плеер не играл с пустым плейлистом""" if self.queue.isEmpty() and self.is_playing: self.play_or_pause() def load_songs_from_playlist(self): """Загрузка музыки из БД в плейлист""" self.queue.clear() for url in self.playlist_handler.urls(): self.queue.addMedia(QMediaContent(QUrl(url))) def icon_changed(self): """Функция для вывода обложки трека""" def noicon(): """В случае отсутствия обложки эта функция ставить свою заглушку""" try: pixmap = QPixmap() if pixmap.load('icons/noicon.png'): self.audioPic.setPixmap(pixmap) except Exception as e: print(e.__class__.__name__, ': ', e, sep='') try: # Читаем метаданные трека n = self.queue.currentIndex() url = self.playlist_handler.urls()[n if n > -1 else 0] file = File(url) for i in file.tags.keys(): if 'APIC:' in i: artwork = file.tags[i].data break else: raise KeyError # Переводим их в байтовый массив ba = QByteArray(artwork) # И загружаем на форму, если это возможно pixmap = QPixmap() if pixmap.loadFromData(ba): self.audioPic.setPixmap(pixmap.scaled(341, 341, Qt.IgnoreAspectRatio)) else: raise KeyError except Exception as e: # print(e.__class__.__name__, ': ', e, sep='') noicon() def timeline_is_dragged(self): """Мини-функция для изменения переменной""" # При вызове этой функции мы понимаем, что пользователь # взаимодействует с таймлайном трека self.is_timeline_dragged = True def timeline_changed(self): """Функция для пользовательской перемотки данного трека""" # Перематываем позицию плеера self.player.setPosition(self.timeline.value() * 1000) # Пользователь отпустил язычок слайдера и больше не взаимодействует с таймлайном self.is_timeline_dragged = False # Вызываем обновление временной шкалы, т.к. произошла перемотка self.update_timeline_position() def update_song(self): """Изменение данных о треке""" # !Костыль # Проматываем несколько миллисекунд, чтобы избежать повреждённых треков self.player.setPosition(10) # Меняем обложку self.icon_changed() # Выделяем в списке новый трек self.playlist_handler.set_current_select(self.queue.currentIndex()) # Меняем название окна в соответствии с играющим треком title = self.queue.currentMedia().canonicalUrl().path().split('/')[-1] if title: self.setWindowTitle('DJust Audio Player | %s' % title) else: self.setWindowTitle('DJust Audio Player') # Изменяем длину таймлайна на длину трека self.timeline.setMaximum(self.player.duration() // 1000) # Выводим длину трека в минутах/секундах на экран minutes, seconds = self.player.duration() // 1000 // 60, self.player.duration() // 1000 % 60 self.endTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds)) def update_timeline_position(self): """Функция для обновления временной шкалы""" # Выводим текущее положение плеера в минутах/секундах minutes, seconds = self.player.position() // 1000 // 60, self.player.position() // 1000 % 60 self.currentTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds)) # Чтобы не "вырывать" язычок слайдера из рук пользователя, # проверяем, что пользователь НЕ взаимодейтсвует с таймлайном. if not self.is_timeline_dragged: self.timeline.setValue(minutes * 60 + seconds) def loop_or_unloop_current_track(self): """Мини-функция для зацикливания данного трека""" if not self.is_looped_current_track: # Зацикливаем self.is_looped_current_track = True self.queue.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) # Меняем картинку на перечёркнутый круг self.loopBtn.setStyleSheet('background-image: url(icons/unloop.png)') else: # убираем цикл self.is_looped_current_track = False self.queue.setPlaybackMode(self.playlist_handler.mode) self.loopBtn.setStyleSheet('background-image: url(icons/loop.png)') def next_audio(self): """Функция для перемотки на следующий в списке трек""" if self.queue.mediaCount() - 1 == self.queue.currentIndex(): # Если трек ппоследний в списке, возвращаемся к первому self.queue.setCurrentIndex(0) else: # Иначе просто перемещаемся к следующему self.queue.next() def prev_audio(self): """Функция для перемотки на предыдущий в списке трек""" if 0 == self.queue.currentIndex(): # Если трек первый в списке, возвращаемся к последнему self.queue.setCurrentIndex(self.queue.mediaCount() - 1) else: # Иначе просто возвращаемся к предыдущему self.queue.previous() def play_or_pause(self): """Функция для запуска или остановки проигрывателя""" if self.queue.isEmpty(): # Меняем картинку на стрелочку (проигрывание) self.is_playing = False self.playBtn.setStyleSheet('background-image: url(icons/play.png)') # Ставим на паузу self.player.pause() return if self.is_playing: # Меняем картинку на стрелочку (проигрывание) self.is_playing = False self.playBtn.setStyleSheet('background-image: url(icons/play.png)') # Ставим на паузу self.player.pause() else: # Меняем картинку на 2 палочки (пауза) self.is_playing = True self.playBtn.setStyleSheet('background-image: url(icons/pause.png)') # Запускаем звук self.player.play() def change_volume(self): """Мини-Функция для передачи уровня громкости в плеер""" # Функцию использует несколько объектов сразу, проверяем вызывателя if self.sender() == self.volumeBtn: # Если функцию вызвала кнопка, то включаем/выключаем отображение слайдера if not self.volumeSlider.isHidden(): self.volumeSlider.hide() else: self.volumeSlider.show() else: # Иначе функцию вызвал сам слайдер. Значит, меняем значение self.player.setVolume(self.volumeSlider.value()) self.equalizer.setValue(self.volumeSlider.value())
class play(QMainWindow, Ui_Form): def __init__(self): super(play, self).__init__() self.setupUi(self) self.setWindowTitle("VIP音乐播放器") self.m_filepath = 'E:/MusicMedia/MusicMedia/music/' # self.m_filepath = 'E:/ProgramData/PyUI/music' self.player = QMediaPlayer() self.PlayList = QMediaPlaylist() self.player.setPlaylist(self.PlayList) self.count = 0 #做一个计数器 def search(self): self.listWidget_2.clear() music = self.lineEdit.text() #地心 author = self.lineEdit_2.text() #汪峰 self.music = search_song(music, author) self.music.song.connect(self.get_music) # 启动线程 self.music.start() def get_music(self, data): if data != None: music = self.lineEdit.text() # 地心 self.listWidget_2.addItem("{} - {}".format(data[0], data[1])) #启动下载歌曲的线程 self.dowm = download_song(music, data[1], data[2]) # self.music.song.connect(self.music_dowm) #没有信号的发送这里也可以不用定义槽函数 self.dowm.start() else: music = self.lineEdit.text() # 地心 author = self.lineEdit_2.text() # 汪峰 # 启动下载歌曲的线程 self.Intel = download_song2(music, author) self.Intel.song.connect(self.Intelnet_song) self.Intel.start() def Intelnet_song(self, data): self.listWidget_2.addItem("{} - {}".format(data['title'], data['author'])) # 启动下载歌曲的线程 self.dowm = download_song(data['title'], data['author'], data['url']) self.dowm.start() def load_Local(self): if self.count == 0: self.PlayList.clear() # 便于网络歌曲加入 self.listWidget.clear() # 刷新播放列表 list = os.listdir(self.m_filepath) for cur_music in list: self.listWidget.addItem(cur_music[:-4]) self.PlayList.addMedia( QMediaContent( QUrl.fromLocalFile(self.m_filepath + cur_music))) self.count += 1 else: cur_music = self.listWidget_2.currentItem().text() row = self.listWidget.currentRow() self.listWidget.insertItem(row, cur_music) self.listWidget_2.clear() # 清空在线的列表,造成一种从左边移动到右边的视觉 self.PlayList.addMedia( QMediaContent( QUrl.fromLocalFile(self.m_filepath + cur_music + '.mp3'))) def custom_current_music(self): cur_music = self.listWidget.currentItem().text() #获取当前播放的歌曲的名字 item = self.listWidget.currentRow() self.PlayList.setCurrentIndex(item) self.player.play() # 开始播放当前指定的歌曲 def delete_song(self): cur_music = self.listWidget.currentItem().text() os.remove(self.m_filepath + cur_music + '.mp3') #从磁盘上删除 row = self.listWidget.currentRow() #获取当前鼠标所选行 self.listWidget.takeItem(row) #从列表上删除该行 self.PlayList.next() #歌曲列表顺势往下 self.player.play() #播放 # 重写窗口paintEvent函数 def paintEvent(self, event): painter = QPainter(self) painter.drawPixmap(self.rect(), QPixmap("image/back.jpg"))
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 ## self.setWindowTitle("Demo10_1,音乐播放器") self.player = QMediaPlayer(self) self.playlist = QMediaPlaylist(self) self.player.setPlaylist(self.playlist) self.playlist.setPlaybackMode(QMediaPlaylist.Loop) #循环模式 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) self.playlist.currentIndexChanged.connect(self.do_currentChanged) ## ==============自定义功能函数============ ## ===============event 处理函数========== def closeEvent(self, event): ##窗体关闭时 ## 窗口关闭时不能自动停止播放,需手动停止 if (self.player.state() == QMediaPlayer.PlayingState): self.player.stop() ## ==========由connectSlotsByName() 自动连接的槽函数================== # 播放列表管理 @pyqtSlot() ##添加文件 def on_btnAdd_clicked(self): ## curPath=os.getcwd() #获取系统当前目录 ## curPath=QDir.homePath() curPath = QDir.currentPath() dlgTitle = "选择音频文件" filt = "音频文件(*.mp3 *.wav *.wma);;所有文件(*.*)" fileList, flt = QFileDialog.getOpenFileNames(self, dlgTitle, curPath, filt) count = len(fileList) if count < 1: return filename = fileList[0] fileInfo = QFileInfo(filename) #文件信息 QDir.setCurrent(fileInfo.absolutePath()) #重设当前路径 for i in range(count): filename = fileList[i] fileInfo.setFile(filename) song = QMediaContent(QUrl.fromLocalFile(filename)) self.playlist.addMedia(song) #添加播放媒体 ## basename=os.path.basename(filename) #文件名和后缀 basename = fileInfo.baseName() self.ui.listWidget.addItem(basename) #添加到界面文件列表 if (self.player.state() != QMediaPlayer.PlayingState): self.playlist.setCurrentIndex(0) self.player.play() @pyqtSlot() ##移除一个文件 def on_btnRemove_clicked(self): pos = self.ui.listWidget.currentRow() item = self.ui.listWidget.takeItem(pos) #python会自动删除 if (self.playlist.currentIndex() == pos): #是当前播放的曲目 nextPos = 0 if pos >= 1: nextPos = pos - 1 self.playlist.removeMedia(pos) #从播放列表里移除 if self.ui.listWidget.count() > 0: #剩余个数 self.playlist.setCurrentIndex(nextPos) self.do_currentChanged(nextPos) #当前曲目变化 else: self.player.stop() self.ui.LabCurMedia.setText("无曲目") else: self.playlist.removeMedia(pos) @pyqtSlot() ##清空播放列表 def on_btnClear_clicked(self): self.playlist.clear() #清空播放列表 self.ui.listWidget.clear() self.player.stop() #停止播放 ## @pyqtSlot() ##双击时切换播放文件 def on_listWidget_doubleClicked(self, index): rowNo = index.row() #行号 self.playlist.setCurrentIndex(rowNo) self.player.play() # 播放控制 @pyqtSlot() ##播放 def on_btnPlay_clicked(self): if (self.playlist.currentIndex() < 0): self.playlist.setCurrentIndex(0) self.player.play() @pyqtSlot() ##暂停 def on_btnPause_clicked(self): self.player.pause() @pyqtSlot() ##停止 def on_btnStop_clicked(self): self.player.stop() @pyqtSlot() ##上一曲目 def on_btnPrevious_clicked(self): self.playlist.previous() @pyqtSlot() ##下一曲目 def on_btnNext_clicked(self): self.playlist.next() @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) ## =============自定义槽函数=============================== def do_stateChanged(self, state): ##播放器状态变化 self.ui.btnPlay.setEnabled(state != QMediaPlayer.PlayingState) self.ui.btnPause.setEnabled(state == QMediaPlayer.PlayingState) self.ui.btnStop.setEnabled(state == QMediaPlayer.PlayingState) 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) 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_currentChanged(self, position): ##playlist当前曲目变化 self.ui.listWidget.setCurrentRow(position) item = self.ui.listWidget.currentItem() #QListWidgetItem if (item != None): self.ui.LabCurMedia.setText(item.text())
class PMusic(QWidget): '''central widget''' DEFAULT_IMG = '/usr/share/pmusic/pMusic.png' def __init__(self, parent): '''initialize instance''' super().__init__(parent) self.player = QMediaPlayer() self.player.mediaStatusChanged.connect(self.onmedia_status_changed) self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(QMediaPlaylist.Loop) self.player.setVolume(100) self.resize(parent.width(), parent.height()) self.setContentsMargins(0, 0, 0, 0) self.current_albumart = '' pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label = PImage(self, pixmap) self.img_label.resize(self.width(), self.height()) self.img_label.clicked.connect(self.onclick_img_label) self.buttonbar = PButtonBar(self) self.buttonbar.hide() # position: at the bottom self.buttonbar.move(0, self.height() - self.buttonbar.height()) self.buttonbar.clicked_left.connect(self.onclick_prev) self.buttonbar.clicked_mid.connect(self.onclick_main) self.buttonbar.clicked_right.connect(self.onclick_next) # toggle button for shuffle self.shufflebutton = QPushButton(self) self.shufflebutton.hide() self.shufflebutton.setCheckable(True) self.shufflebutton.setText('S') # position: top left corner button_size = int(self.width() * 0.2) self.shufflebutton.setGeometry(0, 0, button_size, button_size) self.shufflebutton.clicked.connect(self.onclick_shuffle) self.quitbutton = QPushButton(self) self.quitbutton.hide() self.quitbutton.setStyleSheet('color: rgb(240, 0, 0)') # red self.quitbutton.setFont(QFont('webdings', 10)) self.quitbutton.setText('r') # cross # position: top right corner self.quitbutton.setGeometry(self.width() - button_size, 0, button_size, button_size) self.quitbutton.clicked.connect(self.onclick_quit) self.show() def enterEvent(self, event): '''on mouse enter, show the buttons''' super().enterEvent(event) self.buttonbar.show() self.shufflebutton.show() self.quitbutton.show() def leaveEvent(self, event): '''on mouse leave, hide the buttons''' super().leaveEvent(event) self.buttonbar.hide() self.shufflebutton.hide() self.quitbutton.hide() @pyqtSlot() def onclick_shuffle(self): '''shuffle button was toggled''' if self.shufflebutton.isChecked(): debug('shuffle: on') self.playlist.setPlaybackMode(QMediaPlaylist.Random) else: debug('shuffle: off') self.playlist.setPlaybackMode(QMediaPlaylist.Loop) @pyqtSlot() def onclick_quit(self): '''quit button was clicked''' debug('quit') self.stop() self.parent().close() @pyqtSlot() def onclick_img_label(self): '''image label was clicked''' debug('onclick_img_label') self.pause() @pyqtSlot() def onclick_prev(self): '''back button was pressed''' debug('onclick_prev') self.playlist.previous() if self.player.state() != QMediaPlayer.PlayingState: debug('player.state == {}'.format(self.player.state())) self.play() @pyqtSlot() def onclick_next(self): '''next button was pressed''' debug('onclick_next') self.playlist.next() if self.player.state() != QMediaPlayer.PlayingState: debug('player.state == {}'.format(self.player.state())) self.play() @pyqtSlot() def onclick_main(self): '''main button was pressed''' debug('onclick_main') # bring up directory selection dialog # have a preference for $HOME/Music/ try: homedir = os.environ['HOME'] if not os.path.isdir(homedir): homedir = os.path.curdir except KeyError: homedir = os.path.curdir music_dir = os.path.join(homedir, 'Music') if not os.path.isdir(music_dir): music_dir = os.path.curdir path = QFileDialog.getExistingDirectory(self, 'Select directory', music_dir, QFileDialog.ShowDirsOnly) debug('path == [{}]'.format(path)) if not path: # cancel return self.stop() self.load_playlist(path) self.play() def onmedia_status_changed(self): '''media changed; player switched to next song''' debug('onmedia_status_changed') debug('player.state == {}'.format(self.player.state())) debug('player.mediastate == {}'.format(self.player.mediaStatus())) # we want to load albumart if the song is in another directory # and display filename on stdout or console log # this is only relevant if the QMediaPlayer is now loading new media if self.player.mediaStatus() == QMediaPlayer.LoadingMedia: media = self.player.currentMedia() if media.isNull(): debug('media isNull') return filename = media.canonicalUrl().path() debug('current media == [{}]'.format(filename)) # make a short path for informational message short_path = filename try: homedir = os.environ['HOME'] + os.path.sep if short_path.startswith(homedir): short_path = filename[len(homedir):] except KeyError: pass if short_path.startswith('Music/'): short_path = short_path[len('Music/'):] print('now playing: {}'.format(short_path)) folder = os.path.dirname(filename) self.load_albumart(folder) elif self.player.mediaStatus() == QMediaPlayer.NoMedia: debug('no media present, change albumart to default image') # change to default image pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label.setPixmap(pixmap) self.current_albumart = '' def load_playlist(self, path): '''load new playlist''' debug('load playlist') self.playlist.clear() # Note: not actually sure these formats are all supported ... files = QDirIterator(path, ['*.mp3', '*.ogg', '*.wav', '*.flac'], flags=QDirIterator.Subdirectories) while files.hasNext(): filename = files.next() debug('+ {}'.format(filename)) url = QUrl.fromLocalFile(filename) if not self.playlist.addMedia(QMediaContent(url)): debug('addMedia() => False') self.player.setPlaylist(self.playlist) def load_albumart(self, path): '''load album art''' debug('load albumart, path == {}'.format(path)) # load album art found = False for name in ('cover.jpg', 'Folder.jpg', 'folder.jpg', 'cover.png', 'AlbumArt.jpg', 'AlbumArtSmall.jpg'): filename = os.path.join(path, name) if os.path.isfile(filename): found = True if filename == self.current_albumart: debug('same albumart, already loaded') break debug('loading albumart {}'.format(filename)) pixmap = QPixmap(filename) self.img_label.setPixmap(pixmap) self.current_albumart = filename break if not found: if not self.current_albumart: debug('no albumart found, keeping default image') else: # put default image debug('no albumart found, putting default image') pixmap = QPixmap(PMusic.DEFAULT_IMG) self.img_label.setPixmap(pixmap) self.current_albumart = '' def stop(self): '''stop playing''' debug('stop') self.player.stop() def play(self): '''start playing''' debug('play()') self.player.play() def pause(self): '''pause playing''' if self.player.state() == QMediaPlayer.PlayingState: debug('pause') self.player.pause() elif self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.player.play()
class BackWindow(QWidget): def __init__(self, parent=None): super(BackWindow, self).__init__(parent) self.init_ui() self.w = None self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.main_mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) # 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.main_mediaPlayer.positionChanged.connect(self.positionChanged) self.main_mediaPlayer.durationChanged.connect(self.durationChanged) self.main_mediaPlayer.error.connect(self.handleError) self._playlist = QMediaPlaylist() #self.addMedia("movie/movie1.wmv") self.init_play_list() self._stopped = True self.mediaPlayer.setVideoOutput(self.ui.videoWidget) self.mediaPlayer.setPlaylist(self._playlist) self.main_mediaPlayer.setPlaylist(self._playlist) def init_ui(self): ui_path = "ui/MediaPlayer.ui" print ui_path self.ui = loadUi(ui_path, self) self.ui.playButton.clicked.connect(self.play_movie) self.ui.nextButton.clicked.connect(self.next_movie) self.ui.launchButton.clicked.connect(self.launch_window) self.ui.positionSlider.setRange(0, 0) self.ui.positionSlider.sliderMoved.connect(self.setPosition) def init_play_list(self): movies = glob.glob(os.path.dirname("__file__") + "movie/*") #sort movies for movie in movies: self.addMedia(movie) self.ui.listWidget.addItem(movie) # プレイリストに動画を追加 def addMedia(self, media_file): media_content = QMediaContent(QUrl.fromLocalFile(media_file)) self._playlist.addMedia(media_content) """ def mousePressEvent(self, event): if self._stopped: self.play() else: self.mediaPlayer.pause() self._stopped = True """ def play_movie(self): if self._stopped: # self.mediaPlayer.setVideoOutput(self.ui.videoWidget) # self.mediaPlayer.setPlaylist(self._playlist) self.mediaPlayer.play() self.main_mediaPlayer.play() self._stopped = False self.ui.playButton.setText("pause") else: self.mediaPlayer.pause() self.main_mediaPlayer.pause() self._stopped = True self.ui.playButton.setText("play") def next_movie(self): self._playlist.next() def back_movie(self): pass def launch_window(self): print "aaaaaaaaa" self.w = MainWindow() #self.w.show() self.main_mediaPlayer.setVideoOutput(self.w.ui.videoWidget) def positionChanged(self, position): self.ui.positionSlider.setValue(position) def durationChanged(self, duration): self.ui.positionSlider.setRange(0, duration) def setPosition(self, position): self.mediaPlayer.setPosition(position) self.main_mediaPlayer.setPosition(position) def handleError(self): self.playButton.setEnabled(False) self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
class MusicPlayer(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) self.options = self.parent().options self.ffmpeg = self.options['paths']['ffmpeg_bin'] self.thumbnails = self.options['paths']['thumbnails'] self.thumb_width = self.options['thumbnail']['width'] self.thumb_height = self.options['thumbnail']['height'] self.jumping = False self.blocked = False self.durations = {} self.playback_value = 0 self.text = ["None", "Repeat", "Random"] self.playlist_list = [] self.values = [ QMediaPlaylist.Loop, QMediaPlaylist.CurrentItemInLoop, QMediaPlaylist.Random ] # Thumbnail widget self.image_label = QLabel() # Control widgets self.playButton = QToolButton(clicked=self.play) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.stopButton = QToolButton(clicked=self.stop) self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopButton.setEnabled(False) self.playbackButton = QToolButton(clicked=self.playback_mode) self.playbackButton.setText(self.text[0]) self.nextButton = QToolButton(clicked=self.next_song) self.nextButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.previousButton = QToolButton(clicked=self.previous_song) self.previousButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.muteButton = QToolButton(clicked=self.mute_clicked) self.muteButton.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) self.volumeSlider = QSlider(Qt.Horizontal, sliderMoved=self.change_volume) self.volumeSlider.setRange(0, 100) self.volumeSlider.setPageStep(1) self.volumeSlider.setValue(50) # Player and playlist setup self.player = QMediaPlayer() self.player.setVolume(50) self.player.stateChanged.connect(self.waveform) self.playlist = QMediaPlaylist() self.playlist.setPlaybackMode(self.values[0]) self.playlist.setCurrentIndex(1) self.player.setPlaylist(self.playlist) 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.playlistView.setContextMenuPolicy(Qt.CustomContextMenu) self.playlistView.customContextMenuRequested.connect( self.list_view_menu) self.playlist.currentIndexChanged.connect( lambda position: self.change_thumbnail(position)) song_search = QLineEdit() song_search.textChanged.connect(self.search) song_search.setClearButtonEnabled(True) # Playlist self.playlist_name = QComboBox() self.playlist_name.currentTextChanged.connect(self.switch_playlist) self.refresh_lists() self.up_button = QToolButton(clicked=self.move_up) self.up_button.setIcon(self.style().standardIcon(QStyle.SP_ArrowUp)) self.down_button = QToolButton(clicked=self.move_down) self.down_button.setIcon(self.style().standardIcon( QStyle.SP_ArrowDown)) # Sound wave widget self.wave_graphic = WaveGraphic(self) #self.wave_graphic.hide() # Testing slider again self.slider = QSlider(Qt.Horizontal) self.slider.setRange(0, self.player.duration() / 1000) self.slider.sliderMoved.connect(self.seek) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) # Shortcuts QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self, song_search.setFocus) # Layouts setup playlist_layout = QHBoxLayout() playlist_layout.addWidget(self.playlist_name) playlist_layout.addWidget(self.up_button) playlist_layout.addWidget(self.down_button) control_layout = QHBoxLayout() control_layout.setContentsMargins(0, 0, 0, 0) control_layout.addWidget(self.stopButton) control_layout.addWidget(self.previousButton) control_layout.addWidget(self.playButton) control_layout.addWidget(self.nextButton) control_layout.addWidget(self.muteButton) control_layout.addWidget(self.volumeSlider) control_layout.addWidget(self.playbackButton) display_layout = QVBoxLayout() display_layout.addWidget(song_search) display_layout.addWidget(self.playlistView) display_layout.addLayout(playlist_layout) music_layout = QVBoxLayout() music_layout.addWidget(self.image_label) music_layout.addWidget(self.slider) music_layout.addLayout(control_layout) main_layout = QHBoxLayout() main_layout.addLayout(music_layout) main_layout.addLayout(display_layout) main_2_layout = QVBoxLayout() main_2_layout.addLayout(main_layout) main_2_layout.addWidget(self.wave_graphic) self.setLayout(main_2_layout) def waveform(self, status): if status == QMediaPlayer.PlayingState: self.wave_graphic.start() elif status == QMediaPlayer.PausedState: self.wave_graphic.pause() else: self.wave_graphic.stop() def list_view_menu(self, point): menu = QMenu("Menu", self) recommend_action = QAction('&Recommend Songs', self) menu.addAction(recommend_action) # TODO: [FEATURE] add rename song recommend_action.triggered.connect( lambda: self.parent().call_download_manager(self.get_links())) rename_action = QAction('&Rename', self) menu.addAction(rename_action) # TODO: [FEATURE] add rename song rename_action.triggered.connect(lambda: print("rename")) # Show the context menu. menu.exec_(self.playlistView.mapToGlobal(point)) def get_links(self): title = self.playlistView.selectedIndexes()[0].data() link = getYoutubeURLFromSearch(title) if len(link) > 1: return youtube_recommendations(link) def move_up(self): index = self.playlistView.currentIndex().row() if index - 1 >= 0: item, above = self.playlist.media(index), self.playlist.media( index - 1) self.playlist.removeMedia(index) self.playlist.removeMedia(index - 1) self.playlist.insertMedia(index - 1, item) self.playlist.insertMedia(index, above) self.blocked = True self.playlistView.setCurrentIndex( self.playlistModel.index(index - 1, 0)) self.blocked = False self.stop() def move_down(self): index = self.playlistView.currentIndex().row() if index + 1 <= self.playlistModel.rowCount(): item, below = self.playlist.media(index), self.playlist.media( index + 1) self.playlist.removeMedia(index + 1) self.playlist.removeMedia(index) self.playlist.insertMedia(index, below) self.playlist.insertMedia(index + 1, item) self.blocked = True self.playlistView.setCurrentIndex( self.playlistModel.index(index + 1, 0)) self.blocked = False self.stop() def search(self, part_of_song): for index in range(self.playlistModel.rowCount()): item = self.playlistModel.data(self.playlistModel.index( index, 0)).lower() self.playlistView.setRowHidden(index, part_of_song.lower() not in item) def change_thumbnail(self, position=0): self.playlistView.setCurrentIndex(self.playlistModel.index( position, 0)) song = self.playlistView.selectedIndexes()[0].data() if self.wave_graphic.is_song_cached(song): self.wave_graphic.load_waves(song) else: wc_ = WaveConverter(song, self.wave_graphic.set_wav) wc_.convert() if self.playlistView.currentIndex().data() is None or self.blocked: return max_ratio = 0 img = None for item in listdir(self.thumbnails): if item.endswith('.jpg'): ratio = similar( item, self.playlistView.currentIndex().data().replace( '.mp3', '.jpg')) if ratio > max_ratio: max_ratio = ratio img = item if img: p = QPixmap(self.thumbnails + img) self.image_label.setPixmap( p.scaled(self.thumb_width, self.thumb_height, Qt.KeepAspectRatio)) def switch_playlist(self, current_text): self.playlist.clear() if current_text == "No Playlist": self.refresh() else: if read_playlist(current_text): songs = read_playlist(current_text).split('\n') for song in songs: self.playlist.addMedia( QMediaContent(QUrl.fromLocalFile(song))) def refresh(self): # Change it so it will go to same song. if self.playlist_name.currentText() != "No Playlist": return paths = fetch_options()['paths']['music_path'].split(';') current_songs = [ self.playlistModel.data(self.playlistModel.index(row, 0)) for row in range(self.playlistModel.rowCount()) ] for path in paths: if not path: continue for item in listdir(path): if isfile(join(path, item)) and item.endswith(".mp3") and ( item not in current_songs): self.playlist.addMedia( QMediaContent(QUrl.fromLocalFile(join(path, item)))) def refresh_lists(self): path = fetch_options()['paths']['playlist'] self.playlist_name.clear() self.playlist_list = ["No Playlist"] self.playlist_name.addItem("No Playlist") for item in listdir(path): if isfile(join(path, item)) and item.endswith(".lst"): self.playlist_list.append(item.split('.')[0]) self.playlist_name.addItem(item.split('.')[0]) def playback_mode(self): # Normal -> Loop -> Random def up_value(value, max_value=3): if value + 1 == max_value: return 0 return value + 1 self.playback_value = up_value(self.playback_value) self.playlist.setPlaybackMode(self.values[self.playback_value]) self.playbackButton.setText(self.text[self.playback_value]) def jump(self, index): if index.isValid() and not self.blocked: self.playlist.setCurrentIndex(index.row()) self.jumping = True self.play() def play(self): if self.blocked: return if self.player.state() != QMediaPlayer.PlayingState or self.jumping: self.player.play() self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.jumping = False else: self.player.pause() self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) self.stopButton.setEnabled(True) def change_volume(self, value): self.player.setVolume(value) def stop(self): if self.player.state() != QMediaPlayer.StoppedState: self.player.stop() self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.stopButton.setEnabled(False) def next_song(self): self.playlist.next() self.playlistView.setCurrentIndex( self.playlistModel.index(self.playlist.currentIndex(), 0)) def previous_song(self): self.playlist.previous() self.playlistView.setCurrentIndex( self.playlistModel.index(self.playlist.currentIndex(), 0)) def mute_clicked(self): self.player.setMuted(not self.player.isMuted()) self.muteButton.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume if not self.player.isMuted() else QStyle. SP_MediaVolumeMuted)) def durationChanged(self, duration): duration /= 1000 self.slider.setMaximum(duration) def positionChanged(self, progress): progress /= 1000 if not self.slider.isSliderDown(): self.slider.setValue(progress) def seek(self, seconds): self.player.setPosition(seconds * 1000)
class MainWindow(QWidget): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.playlistView = QListView() self.switch_status = 2 self.video_widget = QVideoWidget() self.playlist = QMediaPlaylist() self.model = PlaylistModel(self.playlist) self.titleBar = TitleBar(self) self.currentTimeLabel = QLabel() self.timeSlider = QSlider() self.totalTimeLabel = QLabel() self.mediaPlayer = QMediaPlayer() self.open_btn = QPushButton('Open File') self.play_btn = QPushButton() self.prev_btn = QPushButton() self.stop_btn = QPushButton() self.next_btn = QPushButton() self.switch_media_widgets_btn = QPushButton() self.pseudo_label = QLabel() self.vol_label = QLabel() self.volume_slider = Slider(Qt.Horizontal) self.gui() self.set_children_focus_policy(Qt.NoFocus) def gui(self): self.currentTimeLabel.setMinimumSize(QSize(80, 0)) self.currentTimeLabel.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.timeSlider.setOrientation(Qt.Horizontal) self.totalTimeLabel.setMinimumSize(QSize(80, 0)) self.totalTimeLabel.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignVCenter) self.playlistView.setAcceptDrops(True) self.playlistView.setProperty("showDropIndicator", True) self.playlistView.setDragDropMode(QAbstractItemView.DropOnly) self.playlistView.setAlternatingRowColors(True) self.playlistView.setUniformItemSizes(True) self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowTitle('Media Player') self.titleBar.label.setText('Media Player') self.setWindowIcon(QIcon('icon_png/media_player.png')) self.setGeometry(600, 200, 850, 600) self.timeSlider.setRange(0, 0) self.play_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.prev_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipBackward)) self.next_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipForward)) self.stop_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.switch_media_widgets_btn.setIcon(self.style().standardIcon(QStyle.SP_FileDialogDetailedView)) self.vol_label.setText("") self.vol_label.setPixmap(QPixmap("icon_png/speaker-volume.png")) self.currentTimeLabel.setText("00:00") self.totalTimeLabel.setText("00:00") self.volume_slider.setValue(self.mediaPlayer.volume()) self.mediaPlayer.setVideoOutput(self.video_widget) self.mediaPlayer.setPlaylist(self.playlist) self.playlistView.setModel(self.model) self.video_widget.hide() sizegrip = QSizeGrip(self) self.setAcceptDrops(True) inner_h_box = QHBoxLayout() inner_h_box.addWidget(self.prev_btn) inner_h_box.addWidget(self.stop_btn) inner_h_box.addWidget(self.next_btn) vol_h_box = QHBoxLayout() vol_h_box.addWidget(self.vol_label, 0) vol_h_box.addWidget(self.volume_slider, 1) h_box = QHBoxLayout() h_box.addWidget(self.open_btn) h_box.addWidget(self.play_btn, 0) h_box.addLayout(inner_h_box, 0) h_box.addWidget(self.switch_media_widgets_btn, 0) h_box.addWidget(self.pseudo_label, 1) h_box.addLayout(vol_h_box, 0) h_box.addWidget(sizegrip, 0, Qt.AlignBottom | Qt.AlignRight) video_slider_h_box = QHBoxLayout() video_slider_h_box.addWidget(self.currentTimeLabel) video_slider_h_box.addWidget(self.timeSlider) video_slider_h_box.addWidget(self.totalTimeLabel) v_box = QVBoxLayout() v_box.addWidget(self.titleBar, 0) v_box.addWidget(self.video_widget, 1) v_box.addWidget(self.playlistView, 1) v_box.addLayout(video_slider_h_box, 0) v_box.addLayout(h_box, 0) inner_h_box.setContentsMargins(20, 0, 10, 0) vol_h_box.setContentsMargins(0, 0, 20, 0) h_box.setContentsMargins(20, 0, 0, 0) v_box.setContentsMargins(0, 0, 0, 0) video_slider_h_box.setSpacing(10) h_box.setSpacing(0) v_box.setSpacing(0) self.setLayout(v_box) self.enabler() # connections self.open_btn.clicked.connect(self.open_file) self.play_btn.clicked.connect(self.play_media) self.stop_btn.clicked.connect(self.stop_media) self.prev_btn.pressed.connect(self.play_prev) self.next_btn.pressed.connect(self.play_next) self.switch_media_widgets_btn.pressed.connect(self.switch_media) self.playlist.currentIndexChanged.connect(self.playlist_position_changed) selection_model = self.playlistView.selectionModel() selection_model.selectionChanged.connect(self.playlist_selection_changed) self.mediaPlayer.durationChanged.connect(self.update_duration) self.mediaPlayer.positionChanged.connect(self.update_position) self.timeSlider.valueChanged.connect(self.mediaPlayer.setPosition) self.mediaPlayer.stateChanged.connect(self.media_state) self.mediaPlayer.volumeChanged.connect(self.volume_changed) self.volume_slider.valueChanged.connect(self.set_volume) def set_children_focus_policy(self, policy): def recursive_set_child_focus_policy(parent_q_widget): for childQWidget in parent_q_widget.findChildren(QWidget): childQWidget.setFocusPolicy(policy) recursive_set_child_focus_policy(childQWidget) recursive_set_child_focus_policy(self) def enabler(self, state=False): if state is False: self.play_btn.setEnabled(False) self.prev_btn.setEnabled(False) self.stop_btn.setEnabled(False) self.next_btn.setEnabled(False) else: self.play_btn.setEnabled(True) self.stop_btn.setEnabled(True) self.prev_btn.setEnabled(True) self.next_btn.setEnabled(True) def switch_media(self): if self.switch_status == 0: self.video_widget.hide() self.playlistView.show() self.switch_status = 1 self.switch_media_widgets_btn.setEnabled(True) elif self.switch_status == 1: self.video_widget.show() self.playlistView.hide() self.switch_status = 0 self.switch_media_widgets_btn.setEnabled(True) else: self.video_widget.hide() self.playlistView.show() self.switch_media_widgets_btn.setEnabled(False) def play_media(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() self.ui_handler() def ui_handler(self): if not self.playlist.isEmpty(): self.enabler(True) file_path = QFileInfo(self.mediaPlayer.currentMedia().canonicalUrl().toString()).fileName() ext = os.path.splitext(file_path)[-1].lower() audio_ext = ['.flac', '.mp3'] video_ext = ['.mp4', '.m4a', '.mov', '.flv', 'avi', '3gp', '.mkv', '.wmv'] if ext in audio_ext: self.switch_status = 2 self.switch_media() if self.isFullScreen(): self.fullscreen() elif ext in video_ext: self.switch_status = 1 self.switch_media() self.setWindowTitle(file_path + ' - Media Player') self.titleBar.label.setText(file_path + ' - Media Player') def stop_media(self): if self.mediaPlayer.state() != QMediaPlayer.StoppedState: self.mediaPlayer.stop() self.setWindowTitle('Media Player') self.titleBar.label.setText('Media Player') def fullscreen(self): if self.switch_status == 2 or self.isFullScreen(): self.titleBar.show() self.timeSlider.show() self.currentTimeLabel.show() self.totalTimeLabel.show() self.volume_slider.show() self.open_btn.show() self.play_btn.show() self.prev_btn.show() self.stop_btn.show() self.next_btn.show() self.switch_media_widgets_btn.show() self.pseudo_label.show() self.vol_label.show() self.showNormal() else: self.titleBar.hide() self.timeSlider.hide() self.currentTimeLabel.hide() self.totalTimeLabel.hide() self.volume_slider.hide() self.open_btn.hide() self.play_btn.hide() self.prev_btn.hide() self.stop_btn.hide() self.next_btn.hide() self.switch_media_widgets_btn.hide() self.pseudo_label.hide() self.vol_label.hide() self.showFullScreen() def mouseDoubleClickEvent(self, event: QMouseEvent): event.accept() if event.button() == Qt.LeftButton: self.fullscreen() def media_state(self): os_sleep = WindowsInhibitor() if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.play_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaPause)) if os.name == 'nt': os_sleep = WindowsInhibitor() os_sleep.inhibit() else: self.play_btn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) if os_sleep: os_sleep.uninhibit() def play_next(self): self.playlist.next() def media_seek(self, seek): if not self.playlist.isEmpty(): player = self.mediaPlayer if (player.duration() - seek) > player.position(): player.setPosition(player.position() + seek) def play_prev(self): self.playlist.previous() def dragEnterEvent(self, e): if e.mimeData().hasUrls(): e.acceptProposedAction() def dropEvent(self, e): for url in e.mimeData().urls(): ext = os.path.splitext(url.fileName())[-1].lower() allowed_ext = ['.flac', '.mp3', '.mp4', '.m4a', '.mov', '.flv', 'avi', '3gp', '.mkv', '.wmv'] if ext in allowed_ext: self.playlist.addMedia( QMediaContent(url) ) self.model.layoutChanged.emit() if self.mediaPlayer.state() != QMediaPlayer.PlayingState: i = self.playlist.mediaCount() - len(e.mimeData().urls()) self.playlist.setCurrentIndex(i) if not self.playlist.isEmpty(): self.play_media() def open_file(self): filter_files = "Media (*.mp3 *.mp4 *.mkv);; Videos files (*.mp4 *.mkv);; Music Files(*.mp3)" paths, _ = QFileDialog.getOpenFileNames(self, "Open file", "", filter_files) if paths: self.mediaPlayer.pause() for path in paths: self.playlist.addMedia( QMediaContent( QUrl.fromLocalFile(path) ) ) i = self.playlist.mediaCount() - len(paths) self.playlist.setCurrentIndex(i) self.play_media() self.model.layoutChanged.emit() def update_duration(self, duration): self.mediaPlayer.duration() self.timeSlider.setMaximum(duration) if duration >= 0: self.totalTimeLabel.setText(hhmmss(duration)) def update_position(self, position): if position >= 0: self.currentTimeLabel.setText(hhmmss(position)) self.timeSlider.blockSignals(True) self.timeSlider.setValue(position) self.timeSlider.blockSignals(False) def playlist_selection_changed(self, ix): i = ix.indexes()[0].row() self.playlist.setCurrentIndex(i) self.ui_handler() def playlist_position_changed(self, i): if i > -1: ix = self.model.index(i) self.playlistView.setCurrentIndex(ix) def set_volume(self, value): self.mediaPlayer.setVolume(value) def volume_changed(self, value): self.volume_slider.setValue(value) def keyPressEvent(self, event): key = event.key() modifiers = int(event.modifiers()) if (modifiers and modifiers & MOD_MASK == modifiers and key > 0 and key != Qt.Key_Shift and key != Qt.Key_Alt and key != Qt.Key_Control and key != Qt.Key_Meta): key_name = QKeySequence(modifiers + key).toString() if key_name == 'Ctrl+Right': self.media_seek(30000) elif key_name == 'Ctrl+Left': self.media_seek(-30000) elif key_name == 'Ctrl+Up': self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 5) elif key_name == 'Ctrl+Down': self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 5) elif key_name == 'Ctrl+O': self.open_file() else: if event.key() == Qt.Key_Space: self.play_media() elif event.key() == Qt.Key_MediaPlay: self.play_media() elif event.key() == Qt.Key_MediaNext: self.play_next() elif event.key() == Qt.Key_MediaPrevious: self.play_prev() elif event.key() == Qt.Key_Escape: self.close() elif event.key() == Qt.Key_F: self.fullscreen() elif event.key() == Qt.Key_Right: self.media_seek(5000) elif event.key() == Qt.Key_Left: self.media_seek(-5000)
class DPlayerCore(QWidget): def __init__(self): """Initialize player and load playlist if any.""" super().__init__() self.player = QMediaPlayer() self.playlist = QMediaPlaylist() self.player.setPlaylist(self.playlist) self.shuffling = False self.repeatingPlaylist = False self.repeatingSong = False self.musicOrder = [] self.loadPlaylist(QUrl( 'file://{}/lastListened.m3u'.format(os.getcwd()))) self.lyricsApi = 'http://api.musixmatch.com/ws/1.1/' self.lyricsApiKey = '4b364f0652e471aa50813a22cdf830ea' self.lastFMapi = 'http://ws.audioscrobbler.com/2.0/' self.lastFMapikey = '052c43a00a4fc294bb3c9e0c38bdf710' self.lastFMsecret = '14c66392fa9c6c142a41ccc2b0674e19' self.username = None self.password = None self.network = None self.error = 'Something went wrong! Try again later.' def play(self): """Start the player.""" self.player.play() def pause(self): """Pause the player.""" self.player.pause() def stop(self): """Stop the player.""" self.player.stop() def previous(self): """Play previous song.""" self.playlist.previous() def next(self): """Play next song.""" self.playlist.next() def mute(self): """Mute the player.""" self.player.setMuted(True) def unmute(self): """Unmute the player.""" self.player.setMuted(False) def setVolume(self, value): """Set player's volume to value.""" self.player.setVolume(value) def add(self, fileNames): """Add fileNames to the playlist.""" for name in fileNames: url = QUrl.fromLocalFile(QFileInfo(name).absoluteFilePath()) self.playlist.addMedia(QMediaContent(url)) self.musicOrder.append([name]) self.added(len(fileNames)) def added(self, added): """Saves music info in musicOrder.""" for name, index in zip( self.musicOrder[self.playlist.mediaCount() - added:], range(self.playlist.mediaCount() - added, len(self.musicOrder))): name = name[0] artist = self.getArtist(name)[0] title = self.getTitle(name)[0] album = self.getAlbum(name)[0] seconds = self.getDuration(name) duration = QTime(0, seconds // 60, seconds % 60) duration = duration.toString('mm:ss') self.musicOrder[index].extend( [artist, title, album, duration]) def remove(self, songIndexes): """Remove songIndexes from the playlist.""" for index in songIndexes: self.songChanged = True del self.musicOrder[index] self.playlist.removeMedia(index) self.songChanged = False def savePlaylist(self, path): """Save playlist to path.""" if path.toString()[len(path.toString()) - 4:] != '.m3u': path = QUrl('{}.m3u'.format(path.toString())) self.playlist.save(path, 'm3u') def loadPlaylist(self, path): """Load playlist form path.""" count = self.playlist.mediaCount() self.playlist.load(path) for index in range(count, self.playlist.mediaCount()): self.musicOrder.append( [self.playlist.media(index).canonicalUrl().path()]) self.added(self.playlist.mediaCount() - count) def clearPlaylist(self): """Delete all songs in the playlist.""" self.playlist.clear() self.musicOrder = [] def shuffle(self, value): """Shuffle playlist if value = True.""" self.shuffling = value if self.repeatingSong: return if self.shuffling: self.playlist.setPlaybackMode(QMediaPlaylist.Random) elif self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def repeatPlaylist(self, value): """Repeat playlist after the last song is finished if value = True.""" self.repeatingPlaylist = value if self.repeatingSong or self.shuffling: return if self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def repeatSong(self, value): """Repeat current song if value = True.""" self.repeatingSong = value if self.repeatingSong: self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) elif self.shuffling: self.playlist.setPlaybackMode(QMediaPlaylist.Random) elif self.repeatingPlaylist: self.playlist.setPlaybackMode(QMediaPlaylist.Loop) else: self.playlist.setPlaybackMode(QMediaPlaylist.Sequential) def sort(self, column, order): """Sort playlist by column in order.""" ordered = sorted(self.musicOrder, key=itemgetter(column + 1), reverse=order) self.clearPlaylist() for song in ordered: url = QUrl.fromLocalFile(QFileInfo(song[0]).absoluteFilePath()) self.playlist.addMedia(QMediaContent(url)) self.musicOrder = ordered def findLyrics(self, index): """Returns lyrics for song at index.""" if self.musicOrder[index][2] == 'Unknown': return 'Unknown song.' searchSong = '{}track.search?q_track={}'.format( self.lyricsApi, self.musicOrder[index][2].replace(' ', '%20')) if self.musicOrder[index][1] != 'Unknown': searchSong = '{}&q_artist={}'.format( searchSong, self.musicOrder[index][1].replace(' ', '%20')) searchSong = '{}&f_has_lyrics=1&apikey={}'.format( searchSong, self.lyricsApiKey) try: requestSong = requests.get(searchSong) except requests.ConnectionError: return self.error songJson = requestSong.json() if requestSong.status_code != 200 or \ songJson['message']['header']['available'] == 0: return self.error songId = songJson[ 'message']['body']['track_list'][0]["track"]["track_id"] searchLyrics = '{}track.lyrics.get?track_id={}&apikey={}'.format( self.lyricsApi, songId, self.lyricsApiKey) try: requestLyrics = requests.get(searchLyrics) except requests.ConnectionError: return self.error if requestLyrics.status_code != 200 or \ songJson['message']['header']['available'] == 0: return self.error return requestLyrics.json()[ 'message']['body']['lyrics']['lyrics_body'][:-58] # spam and bacon def findInfo(self, index): """Returns info about artist and album for index if any.""" info = [] if self.musicOrder[index][1] != 'Unknown': artist = self.artistInfo(self.musicOrder[index][1]) if artist != self.error: info += artist if self.musicOrder[index][1] != 'Unknown' and \ self.musicOrder[index][3] != 'Unknown': album = self.albumInfo(self.musicOrder[index][1], self.musicOrder[index][3]) if album != self.error: info += album if info: return info else: return ['Unknown artist and song!'] def artistInfo(self, artist): """Returns info about artist if any.""" try: response = requests.get( ('{}/?method=artist.getinfo&artist={}&api_key={}&' 'format=json&autocorrect=1').format( self.lastFMapi, artist, self.lastFMapikey)) except Exception: return self.error if response.status_code != 200: return self.error artist = 'Artist: {}'.format(response.json()['artist']['name']) bio = 'Bio: {}'.format( response.json()['artist']['bio']['summary'].replace('.', '.\n')) spam = bio.find('<a') bio = bio[:spam] return [artist, bio] def albumInfo(self, artist, album): """Returns info about album if any.""" try: response = requests.get( ('{}/?method=album.getinfo&artist={}&album={}&api_key={}&' 'format=json&autocorrect=1').format( self.lastFMapi, artist, album, self.lastFMapikey)) except Exception: return self.error if response.status_code != 200 or \ 'album' not in response.json().keys(): return self.error album = 'Album: {}'.format(response.json()['album']['name']) tracks = ['Tracks: '] t = response.json()['album']['tracks']['track'] for track, index in zip(t, range(len(t))): tracks.append('{}. {}'.format(index + 1, track['name'])) info = [album, '\n'.join(tracks)] if 'wiki' in response.json()['album'].keys(): wiki = response.json()['album']['wiki'] if 'published' in wiki.keys(): info.append('Published: {}'.format(wiki['published'])) if 'summary' in wiki.keys(): summary = wiki['summary'].replace('.', '.\n') spam = summary.find('<a') info.append('Summary: {}'.format(summary[:spam])) if 'Musical style' in wiki.keys(): info.append('Musical style: {}'.format(wiki['Musical style'])) return info def login(self, username, password): """Creates lastFM network.""" self.username = username self.password = pylast.md5(password) try: self.network = pylast.LastFMNetwork(api_key=self.lastFMapikey, api_secret=self.lastFMsecret, username=self.username, password_hash=self.password) except Exception: self.username = None self.password = None self.network = None return False return True def logout(self): """Destoys lastFM network and current user info.""" self.username = None self.password = None self.network = None def loveTrack(self, index): """Love track at index in lastFM.""" if self.network is None: return False track = self.network.get_track(self.musicOrder[index][1], self.musicOrder[index][2]) try: track.love() except Exception: return False return True def unloveTrack(self, index): """Unlove track at index in lastFM.""" if self.network is None: return False track = self.network.get_track(self.musicOrder[index][1], self.musicOrder[index][2]) try: track.unlove() except Exception: return False return True def isMuted(self): """Returns True if player is muted.""" return self.player.isMuted() def getArtist(self, song): """Returns the artist of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'artist' in obj.keys(): return obj['artist'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'artist' in obj.keys(): return [obj['artist']] elif 'ARTIST' in obj.keys(): return [obj['ARTIST']] else: return ['Unknown'] else: return ['Unknown'] def getTitle(self, song): """Returns the title of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'title' in obj.keys(): return obj['title'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'title' in obj.keys(): return [obj['title']] elif 'TITLE' in obj.keys(): return [obj['TITLE']] else: return ['Unknown'] else: return ['Unknown'] def getAlbum(self, song): """Returns the album of song.""" if song[-4:] == '.mp3': obj = EasyID3(song) if 'album' in obj.keys(): return obj['album'] elif 'TAG' in mediainfo(song).keys(): obj = mediainfo(song)['TAG'] if 'album' in obj.keys(): return [obj['album']] elif 'ALBUM' in obj.keys(): return [obj['ALBUM']] else: return ['Unknown'] else: return ['Unknown'] def getDuration(self, song): """Returns the duration of song.""" if song[-4:] == '.mp3': return MP3(song).info.length return int(float(mediainfo(song)['duration']))
class MediaPlayer(QWidget): # 初始化 def __init__(self): super(MediaPlayer, self).__init__() self.setWindowTitle('播放器') # 先注册一个媒体播放器 self.player = QMediaPlayer(self) # 注册其他控件 self.volume_slider = QSlider(self) self.volume_save = 0 self.player.setVolume(36) # 进度条 self.progress_slider = QSlider(self) self.time_stamp = QLabel(self) # 按钮(PushButton)有,播放(暂停) 上一首,下一首 ,播放模式 self.preview_btn = QPushButton(self) # 播放按钮要切换播放与暂停 self.play_pause_btn = QPushButton(self) self.next_btn = QPushButton(self) self.play_mode = QPushButton() self.get_music = QPushButton('云音乐') self.sound_btn = QPushButton(self) # 播放列表 self.mediaList = QMediaPlaylist(self) self.play_list = QListWidget(self) self.songs_list = [] self.songs_formats = ['mp3', 'm4a', 'flac', 'wav', 'ogg'] # 布局注册 self.h1_layout = QHBoxLayout() self.h2_layout = QHBoxLayout() self.all_v_layout = QVBoxLayout() self.widget_init() self.layout_init() self.signal_init() self.center() '''控件初始化''' def widget_init(self): self.time_stamp.setText('--/--') self.volume_slider.setRange(0, 100) self.volume_slider.setValue(36) self.volume_slider.setOrientation(Qt.Horizontal) self.progress_slider.setEnabled(False) self.progress_slider.setOrientation(Qt.Horizontal) self.sound_btn.setIcon(QIcon('../icon_font/sound_on.png')) self.next_btn.setIcon(QIcon(r'..\icon\next.png')) self.play_pause_btn.setIcon(QIcon(r'..\icon\play.png')) self.preview_btn.setIcon(QIcon(r'..\icon\prev.png')) self.play_mode.setIcon(QIcon('../icon_font/list_down.png')) self.sound_btn.setIcon(QIcon(r'..\icon_font\sound_on.png')) self.player.setPlaylist(self.mediaList) self.mediaList.setPlaybackMode(QMediaPlaylist.Sequential) # 布局初始化 def layout_init(self): self.h1_layout.addWidget(self.progress_slider) # 5 self.h1_layout.addWidget(self.time_stamp) self.h2_layout.addWidget(self.preview_btn) self.h2_layout.addWidget(self.play_pause_btn) self.h2_layout.addWidget(self.next_btn) self.h2_layout.addWidget(self.sound_btn) self.h2_layout.addWidget(self.volume_slider) self.h2_layout.addWidget(self.play_mode) self.h2_layout.addWidget(self.get_music) self.all_v_layout.addLayout(self.h1_layout) self.all_v_layout.addWidget(self.play_list) self.all_v_layout.addLayout(self.h2_layout) self.all_v_layout.setSizeConstraint(QVBoxLayout.SetFixedSize) # 6 self.setLayout(self.all_v_layout) # 创建信号函数,连接槽函数 def signal_init(self): # self.preview_btn.clicked.connect(lambda: self.slot_func(self.preview_btn)) self.play_pause_btn.clicked.connect(lambda: self.slot_func(self.play_pause_btn)) self.next_btn.clicked.connect(lambda: self.slot_func(self.next_btn)) self.play_mode.clicked.connect(lambda: self.slot_func(self.play_mode)) self.sound_btn.clicked.connect(lambda: self.slot_func(self.sound_btn)) # 获取云音乐函数 self.get_music.clicked.connect(self.get_music_func) # 播放器音量控制 self.volume_slider.valueChanged.connect(self.volume_slider_func) self.play_list.doubleClicked.connect(self.play_list_func) self.player.durationChanged.connect(self.get_progress_func) self.player.positionChanged.connect(self.get_position_func) self.progress_slider.sliderMoved.connect(self.update_position_func) # 建立槽函数 def slot_func(self, btn): if btn == self.play_pause_btn: if self.player.state() == 1: self.player.pause() self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\play.png')) else: self.player.play() self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png')) #下一首 elif btn == self.next_btn: # 如果点击下一个按钮时为最后一首歌 if self.mediaList.currentIndex() == self.mediaList.mediaCount() - 1: self.mediaList.setCurrentIndex(0) self.play_list.setCurrentRow(0) else: # print(self.player.state()) if self.player.state() == 1: self.play_list.setCurrentRow(self.mediaList.currentIndex() + 1) self.mediaList.next() self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png')) # 上一首 elif btn == self.preview_btn: if self.mediaList.currentIndex() == 0: self.mediaList.setCurrentIndex(self.mediaList.mediaCount() -1) else: if self.player.state() == 1: self.mediaList.previous() self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png')) # 播放模式 elif btn == self.play_mode: # 根据播放模式切换 if self.mediaList.playbackMode() == 2: self.mediaList.setPlaybackMode(QMediaPlaylist.Loop) self.play_mode.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\loop.png')) elif self.mediaList.playbackMode() == 3: self.mediaList.setPlaybackMode(QMediaPlaylist.Random) self.play_mode.setIcon(QIcon(r'..\icon_font\random.png')) elif self.mediaList.playbackMode() == 4: self.mediaList.setPlaybackMode(QMediaPlaylist.Sequential) self.play_mode.setIcon(QIcon(r'..\icon_font\list_loop.png')) # 声音按钮控制 elif btn == self.sound_btn: if self.player.isMuted(): # self.sound_btn.setIcon('') print("1", self.player.isMuted()) self.volume_slider.setValue(self.volume_save) self.player.setMuted(False) self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\sound_on.png')) else: print("2", self.player.isMuted()) self.player.setMuted(True) self.volume_save = self.volume_slider.value() self.volume_slider.setValue(0) self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\sound_off.png')) # 窗口居中 def center(self): qr = self.frameGeometry() # 获得主窗口的一个矩形特定几何图形。这包含了窗口的框架。 cp = QDesktopWidget().availableGeometry().center() # 算出相对于显示器的绝对值。 # 并且从这个绝对值中,我们获得了屏幕中心点。 qr.moveCenter(cp) # 矩形已经设置好了它的宽和高。现在我们把矩形的中心设置到屏幕的中间去。 # 矩形的大小并不会改变。 self.move(qr.topLeft()) # 移动了应用窗口的左上方的点到qr矩形的左上方的点,因此居中显示在我们的屏幕上。 # 获取音乐槽函数 def get_music_func(self): self.mediaList.clear() url = 'http://47.108.93.231:8000/cloudMusic' response = request.urlopen(url).read() # print(json.loads(response), type(json.loads(response))) # 读取数据库信息 # print(json.loads(response)) msg = json.loads(response)['msg'] for song in msg: if song['url'].split('.')[-1] in self.songs_formats: # self.songs_list.append([song, song['url']]) self.mediaList.addMedia(QMediaContent(QUrl(song['url']))) self.play_list.addItem(song['name']) self.play_list.setCurrentRow(0) # print(self.mediaList.mediaCount()) if self.songs_list: self.cur_playing_song = self.songs_list[self.play_list.currentRow()][-1] def volume_slider_func(self, val): self.player.setVolume(val) # if val == 0: # self.sound_btn.setICon(QIcon(r'G:\python3\PyQt_Study\icon\sound.png')) # else: # self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\sound.png')) # 播放列表双击函数 def play_list_func(self): self.mediaList.setCurrentIndex(self.play_list.currentRow()) self.player.play() self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png')) def get_progress_func(self, d): # 连接的函数,传入参数的d为毫秒。所以做一个时间变换 self.progress_slider.setRange(0, d) self.progress_slider.setEnabled(True) self.get_time_func(d) # 时间控制函数,每次调用改变滑条位置,以及时间减少 def get_time_func(self, d): seconds = int(d / 1000) minutes = int(seconds / 60) seconds -= minutes * 60 # print("%s分" %minutes, "%s秒" %seconds) if minutes == 0 and seconds == 0: self.time_stamp.setText("--/--") self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\play.png')) else: self.time_stamp.setText("{}:{}".format(minutes, seconds)) def get_position_func(self, p): self.progress_slider.setValue(p) self.get_time_func(self.progress_slider.maximum() - self.progress_slider.value()) # 当且仅当用户手动改变滑条位置时 def update_position_func(self, v): self.player.setPosition(v) d = self.progress_slider.maximum() - v self.get_time_func(d)
class CPlayer: def __init__(self, parent): # 윈도우 객체 self.parent = parent self.player = QMediaPlayer() self.player.currentMediaChanged.connect(self.mediaChanged) self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.playlist = QMediaPlaylist() def play(self, playlists, startRow=0, option=QMediaPlaylist.Sequential): if self.player.state() == QMediaPlayer.PausedState: self.player.play() else: self.createPlaylist(playlists, startRow, option) self.player.setPlaylist(self.playlist) self.playlist.setCurrentIndex(startRow) self.player.play() def pause(self): self.player.pause() def stop(self): self.player.stop() def prev(self): self.playlist.previous() def next(self): self.playlist.next() def createPlaylist(self, playlists, startRow=0, option=QMediaPlaylist.Sequential): self.playlist.clear() for path in playlists: url = QUrl.fromLocalFile(path) self.playlist.addMedia(QMediaContent(url)) #QMediaContent(url) ##내가 추가한 부분 self.filename = QMediaContent(url).canonicalUrl().fileName() ##내추부 끝 self.playlist.setPlaybackMode(option) def updatePlayMode(self, option): self.playlist.setPlaybackMode(option) def upateVolume(self, vol): self.player.setVolume(vol) def mediaChanged(self, e): self.parent.updateMediaChanged(self.playlist.currentIndex()) def durationChanged(self, msec): if msec > 0: self.parent.updateDurationChanged(self.playlist.currentIndex(), msec) def positionChanged(self, msec): if msec > 0: self.parent.updatePositionChanged(self.playlist.currentIndex(), msec)
class MediaPlayerTab(GalacteekTab): statePlaying = QMediaPlayer.PlayingState statePaused = QMediaPlayer.PausedState stateStopped = QMediaPlayer.StoppedState def __init__(self, *args, **kw): super(MediaPlayerTab, self).__init__(*args, **kw) self.playlistIpfsPath = None self.playlist = QMediaPlaylist() self.model = ListModel(self.playlist) self.playlistsMenu = QMenu(self) self.playlistsMenu.triggered.connect(self.onPlaylistsMenu) self.pListWidget = QWidget(self) self.uipList = ui_mediaplaylist.Ui_MediaPlaylist() self.uipList.setupUi(self.pListWidget) self.uipList.savePlaylistButton.clicked.connect(self.onSavePlaylist) self.uipList.savePlaylistButton.setEnabled(False) self.uipList.loadPlaylistButton.setPopupMode(QToolButton.InstantPopup) self.uipList.loadPlaylistButton.setMenu(self.playlistsMenu) self.clipMenu = QMenu(self) self.copyPathAction = QAction(getIconIpfsIce(), iCopyPlaylistPath(), self, triggered=self.onCopyPlaylistPath) self.loadPathAction = QAction(getIconIpfsIce(), iLoadPlaylistFromPath(), self, triggered=self.onLoadPlaylistPath) self.copyPathAction.setEnabled(False) self.clipMenu.addAction(self.copyPathAction) self.clipMenu.addAction(self.loadPathAction) self.uipList.clipPlaylistButton.setPopupMode(QToolButton.InstantPopup) self.uipList.clipPlaylistButton.setMenu(self.clipMenu) self.uipList.clearButton.clicked.connect(self.onClearPlaylist) self.uipList.nextButton.clicked.connect(self.onPlaylistNext) self.uipList.previousButton.clicked.connect(self.onPlaylistPrevious) self.uipList.nextButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipForward)) self.uipList.previousButton.setIcon(self.style().standardIcon( QStyle.SP_MediaSkipBackward)) self.pListView = self.uipList.listView self.pListView.mousePressEvent = self.playlistMousePressEvent self.pListView.setModel(self.model) self.pListView.setResizeMode(QListView.Adjust) self.pListView.setMinimumWidth(self.width() / 2) self.duration = None self.playerState = None self.player = QMediaPlayer(self) self.player.setPlaylist(self.playlist) self.videoWidget = MPlayerVideoWidget(self.player, self) self.useUpdates(True) self.videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.player.setVideoOutput(self.videoWidget) self.player.error.connect(self.onError) self.player.stateChanged.connect(self.onStateChanged) self.player.metaDataChanged.connect(self.onMetaData) self.player.durationChanged.connect(self.mediaDurationChanged) self.player.positionChanged.connect(self.mediaPositionChanged) self.player.videoAvailableChanged.connect(self.onVideoAvailable) self.pListView.activated.connect(self.onListActivated) self.playlist.currentIndexChanged.connect(self.playlistPositionChanged) self.playlist.currentMediaChanged.connect(self.playlistMediaChanged) self.playlist.mediaInserted.connect(self.playlistMediaInserted) self.playlist.mediaRemoved.connect(self.playlistMediaRemoved) self.togglePList = QToolButton(self) self.togglePList.setIcon(self.style().standardIcon( QStyle.SP_ArrowRight)) self.togglePList.setFixedSize(32, 128) self.togglePList.clicked.connect(self.onTogglePlaylist) self.clipboardMediaItem = None self.clipboardButton = QToolButton(clicked=self.onClipboardClicked) self.clipboardButton.setIcon(getIconClipboard()) self.clipboardButton.setEnabled(False) self.clipboardButton.setToolTip('Load media from clipboard') self.pinButton = QToolButton(clicked=self.onPinMediaClicked) self.pinButton.setIcon(getIcon('pin.png')) self.processClipboardItem(self.app.clipTracker.current, force=True) self.app.clipTracker.currentItemChanged.connect(self.onClipItemChange) self.playButton = QToolButton(clicked=self.onPlayClicked) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.pauseButton = QToolButton(clicked=self.onPauseClicked) self.pauseButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) self.pauseButton.setEnabled(False) self.stopButton = QToolButton(clicked=self.onStopClicked) self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) self.stopButton.setEnabled(False) self.fullscreenButton = QToolButton(clicked=self.onFullScreen) self.fullscreenButton.setIcon(getIcon('fullscreen.png')) self.fullscreenButton.setToolTip(iFullScreen()) self.seekSlider = QSlider(Qt.Horizontal, sliderMoved=self.onSeek) self.seekSlider.sliderReleased.connect(self.onSliderReleased) self.seekSlider.setObjectName('mediaPlayerSlider') self.durationLabel = QLabel() vLayout = QVBoxLayout() hLayoutControls = QHBoxLayout() hLayoutControls.setContentsMargins(0, 0, 0, 0) hLayoutControls.addWidget(self.clipboardButton) hLayoutControls.addWidget(self.pinButton) hLayoutControls.addWidget(self.playButton) hLayoutControls.addWidget(self.pauseButton) hLayoutControls.addWidget(self.stopButton) hLayoutControls.addWidget(self.seekSlider) hLayoutControls.addWidget(self.durationLabel) hLayoutControls.addWidget(self.fullscreenButton) vLayout.addWidget(self.videoWidget) vLayout.addLayout(hLayoutControls) hLayout = QHBoxLayout() hLayout.addLayout(vLayout) hLayout.addWidget(self.pListWidget) hLayout.addWidget(self.togglePList) self.pListWidget.hide() self.vLayout.addLayout(hLayout) self.update() self.videoWidget.changeFocus() @property def isPlaying(self): return self.playerState == self.statePlaying @property def isPaused(self): return self.playerState == self.statePaused @property def isStopped(self): return self.playerState == self.stateStopped def useUpdates(self, updates=True): # Enable widget updates or not on the video widget self.videoWidget.setUpdatesEnabled(updates) def update(self): self.app.task(self.updatePlaylistsMenu) def onFullScreen(self): self.videoWidget.viewFullScreen(True) def onClearPlaylist(self): self.copyPathAction.setEnabled(False) self.player.stop() self.clearPlaylist() def onLoadPlaylistPath(self): current = self.app.clipTracker.getCurrent() if current: self.app.task(self.loadPlaylistFromPath, current.path) def onCopyPlaylistPath(self): if self.playlistIpfsPath: self.app.setClipboardText(self.playlistIpfsPath) def onPinMediaClicked(self): currentMedia = self.playlist.currentMedia() if currentMedia.isNull(): return messageBox(iNoMediaInPlaylist()) ensure(self.pinMedia(currentMedia)) @ipfsOp async def pinMedia(self, ipfsop, media): mediaUrl = qurlPercentDecode(media.canonicalUrl()) path = IPFSPath(mediaUrl, autoCidConv=True) if path.valid: await ipfsop.ctx.pin(str(path), qname='mediaplayer') @ipfsOp async def updatePlaylistsMenu(self, ipfsop): currentList = [ action.text() for action in self.playlistsMenu.actions() ] listing = await ipfsop.filesList(self.profile.pathPlaylists) for entry in listing: if entry['Name'] in currentList: continue action = QAction(entry['Name'], self) action.setData(entry) self.playlistsMenu.addAction(action) def playlistShowContextMenu(self, event): selModel = self.pListView.selectionModel() idx = self.pListView.indexAt(event.pos()) if not idx.isValid(): return path = self.model.data(idx) if path: selModel.reset() selModel.select(idx, QItemSelectionModel.Select) menu = QMenu(self) menu.addAction(getIcon('clear-all.png'), iPlaylistRemoveMedia(), functools.partial(self.onRemoveMediaFromIndex, idx)) menu.exec_(event.globalPos()) def onRemoveMediaFromIndex(self, idx): self.playlist.removeMedia(idx.row()) def playlistMousePressEvent(self, event): if event.button() == Qt.RightButton: self.pListView.selectionModel().reset() self.playlistShowContextMenu(event) else: if not self.pListView.indexAt(event.pos()).isValid(): self.deselectPlaylistItems() QListView.mousePressEvent(self.pListView, event) def onPlaylistsMenu(self, action): entry = action.data() self.app.task(self.loadPlaylistFromPath, joinIpfs(entry['Hash'])) def onSavePlaylist(self): paths = self.playlistGetPaths() listName = inputText(title=iPlaylistName(), label=iPlaylistName()) if not listName: return obj = JSONPlaylistV1(listName=listName, itemPaths=paths) self.app.task(self.savePlaylist, obj, listName) @ipfsOp async def savePlaylist(self, ipfsop, obj, name): objPath = os.path.join(self.profile.pathPlaylists, name) exists = await ipfsop.filesStat(objPath) if exists: await ipfsop.filesRm(objPath) ent = await ipfsop.client.core.add_json(obj.root) if ent: await ipfsop.filesLinkFp(ent, objPath) self.playlistIpfsPath = joinIpfs(ent['Hash']) self.copyPathAction.setEnabled(True) self.update() @ipfsOp async def loadPlaylistFromPath(self, ipfsop, path): try: obj = await ipfsop.jsonLoad(path) except Exception: return messageBox(iCannotLoadPlaylist()) if obj is None: return messageBox(iCannotLoadPlaylist()) try: # Assume v1 format for now, when the format evolves we'll just # use json validation pList = JSONPlaylistV1(data=obj) self.clearPlaylist() for item in pList.items(): self.queueFromPath(item['path']) self.playlistIpfsPath = path self.copyPathAction.setEnabled(True) except Exception: return messageBox(iCannotLoadPlaylist()) def playlistMediaInserted(self, start, end): self.uipList.savePlaylistButton.setEnabled( self.playlist.mediaCount() > 0) def playlistMediaRemoved(self, start, end): self.uipList.savePlaylistButton.setEnabled( self.playlist.mediaCount() > 0) self.model.modelReset.emit() def playlistGetPaths(self): return [u.path() for u in self.playlistGetUrls()] def playlistGetUrls(self): urls = [] for idx in range(0, self.playlist.mediaCount()): media = self.playlist.media(idx) urls.append(media.canonicalUrl()) return urls def onClipItemChange(self, item): self.processClipboardItem(item) def processClipboardItem(self, item, force=False): if not item: return def analyzeMimeType(cItem): if cItem.mimeCategory in ['audio', 'video', 'image']: self.clipboardMediaItem = cItem self.clipboardButton.setEnabled(True) self.clipboardButton.setToolTip(cItem.path) else: self.clipboardButton.setEnabled(False) self.clipboardButton.setToolTip(iClipboardEmpty()) if force: analyzeMimeType(item) else: item.mimeTypeAvailable.connect(lambda mType: analyzeMimeType(item)) def onClipboardClicked(self): if self.clipboardMediaItem: self.playFromPath(self.clipboardMediaItem.path) else: messageBox('Not a multimedia resource') def onSliderReleased(self): pass def onPlaylistNext(self): self.playlist.next() def onPlaylistPrevious(self): self.playlist.previous() def onPlayClicked(self): self.player.play() def onPauseClicked(self): if self.isPlaying: self.player.pause() elif self.isPaused: self.player.play() def onStopClicked(self): self.player.stop() self.player.setPosition(0) self.seekSlider.setValue(0) self.seekSlider.setRange(0, 0) def onSeek(self, seconds): if self.player.isSeekable(): self.player.setPosition(seconds * 1000) def onTogglePlaylist(self): self.pListWidget.setVisible(self.pListWidget.isHidden()) def onError(self, error): messageBox(iPlayerError(error)) def onStateChanged(self, state): self.playerState = state self.updateControls(state) def updateControls(self, state): if self.isStopped: self.stopButton.setEnabled(False) self.pauseButton.setEnabled(False) self.playButton.setEnabled(True) self.seekSlider.setEnabled(False) self.duration = None elif self.isPlaying: self.seekSlider.setRange(0, self.player.duration() / 1000) self.seekSlider.setEnabled(True) self.pauseButton.setEnabled(True) self.playButton.setEnabled(False) self.stopButton.setEnabled(True) def onListActivated(self, index): if index.isValid(): self.playlist.setCurrentIndex(index.row()) self.player.play() def onMetaData(self): # Unfinished if self.player.isMetaDataAvailable(): availableKeys = self.player.availableMetaData() for key in availableKeys: self.player.metaData(key) def playFromUrl(self, url, mediaName=None): if self.isPlaying: self.player.stop() cUrls = self.playlistGetUrls() for u in cUrls: if u.toString() == url.toString(): return messageBox(iAlreadyInPlaylist()) media = QMediaContent(url) if self.playlist.addMedia(media): count = self.model.rowCount() if count > 0: self.playlist.setCurrentIndex(count - 1) self.player.play() def playFromPath(self, path, mediaName=None): mediaUrl = self.app.subUrl(path) self.playFromUrl(mediaUrl) def queueFromPath(self, path, playLast=False, mediaName=None): mediaUrl = self.app.subUrl(path) self.playlist.addMedia(QMediaContent(mediaUrl)) if playLast: count = self.playlist.mediaCount() if count > 0: self.player.stop() self.playlist.setCurrentIndex(count - 1) self.player.play() def clearPlaylist(self): self.playlist.clear() self.pListView.reset() def playlistPositionChanged(self, position): self.pListView.setCurrentIndex(self.model.index(position, 0)) def deselectPlaylistItems(self): self.pListView.selectionModel().reset() def playlistMediaChanged(self, media): selModel = self.pListView.selectionModel() self.deselectPlaylistItems() self.model.modelReset.emit() idx = self.model.index(self.playlist.currentIndex(), 0) if idx.isValid(): selModel.select(idx, QItemSelectionModel.Select) def onVideoAvailable(self, available): if available: if self.isPlaying: self.useUpdates(False) elif self.isStopped or self.isPaused: self.useUpdates(True) else: self.useUpdates(True) def mediaDurationChanged(self, duration): self.duration = duration / 1000 self.seekSlider.setMaximum(self.duration) def mediaPositionChanged(self, progress): progress /= 1000 if self.duration: cTime = durationConvert(progress) tTime = durationConvert(self.duration) self.durationLabel.setText('{0} ({1})'.format( cTime.toString(), tTime.toString())) if not self.seekSlider.isSliderDown(): self.seekSlider.setValue(progress) async def onClose(self): self.player.stop() self.player.setMedia(QMediaContent(None)) return True def playerAvailable(self): return mediaPlayerAvailable(player=self.player)
class Main(QWidget): def __init__(self): super().__init__() self.List = [ 'stay-PostMalon', '잠이 오질 않네요-장범준', 'STAY-BLACKPINK', 'Piano-melody_1', 'Piano-melody_3' ] self.showplaylist = QDialog() self.currentidx = 0 self.playlist = QMediaPlaylist() Qurlmusic = [] for name in self.List: k = "music/" + name + ".wav" Qurlmusic.append(QUrl.fromLocalFile(k)) #print(Qurlmusic[-1]) self.playlist.addMedia(QMediaContent(Qurlmusic[-1])) self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.bartimer = 0 self.Play() self.check = True def Play(self): #button,screen ... self.screen = QGroupBox() eq = QLabel("Equalizer", self) eq.move(25, 10) eq.resize(100, 50) self.label = QLabel(self.screen) self.screen.setStyleSheet("background:rgb(255,255,255)") self.label = QLabel(self.screen) self.label.move(200, 80) self.movie = QtGui.QMovie("icon/loading2.gif") self.label.setMovie(self.movie) self.label.setScaledContents(True) self.movie.start() self.title = QLineEdit('') #title self.title.setReadOnly(True) self.title.setMaxLength(1000) self.title.setFont(QtGui.QFont("Arial", 20, QtGui.QFont.Bold)) # repeat button self.replaybutton = QPushButton() self.replaybutton.setIcon(QtGui.QIcon('icon/repeatone.png')) self.replaybutton.setIconSize(QtCore.QSize(35, 35)) self.replaybutton.clicked.connect(self.currretloop) # random button self.randombutton = QPushButton() self.randombutton.setIcon(QtGui.QIcon('icon/repeat.png')) self.randombutton.setIconSize(QtCore.QSize(35, 35)) self.randombutton.clicked.connect(self.loop) # playbar self.positionSlider = QSlider(Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.player.positionChanged.connect(self.positionChanged) self.player.durationChanged.connect(self.durationChanged) #playbutton self.playbutton = QPushButton() self.playbutton.setIcon(QtGui.QIcon('icon/play.png')) self.playbutton.setIconSize(QtCore.QSize(60, 60)) self.playbutton.clicked.connect(self.playClicked) #next button self.nextbutton = QPushButton() self.nextbutton.setIcon(QtGui.QIcon('icon/next.png')) self.nextbutton.setIconSize(QtCore.QSize(80, 60)) self.nextbutton.clicked.connect(self.nextClicked) self.nextbutton.clicked.connect(self.openequalizer) #back button self.backbutton = QPushButton() self.backbutton.setIcon(QtGui.QIcon('icon/back.png')) self.backbutton.setIconSize(QtCore.QSize(80, 60)) self.backbutton.clicked.connect(self.prevClicked) self.backbutton.clicked.connect(self.openequalizer) #out button outbutton = QPushButton() outbutton.setIcon(QtGui.QIcon('icon/out.png')) outbutton.setIconSize(QtCore.QSize(50, 50)) outbutton.clicked.connect(self.Out) # volume self.volume = QSlider(QtCore.Qt.Vertical) style = SliderProxyStyle(self.volume.style()) self.volume.setStyle(style) self.volume.setStyleSheet("QSlider::handle:vertical{" "background:rgb(0,0,0)}") self.volume.setRange(0, 100) self.volume.setValue(50) self.volume.valueChanged[int].connect(self.volumeChanged) # lyricsbutton self.lyricsbutton = QPushButton() self.lyricsbutton.setIcon(QtGui.QIcon('icon/lyrics.png')) self.lyricsbutton.setIconSize(QtCore.QSize(50, 50)) self.lyricsbutton.clicked.connect(self.ShowPLayList) #layout vv1box = QVBoxLayout() vv2box = QVBoxLayout() vv1_v1box = QVBoxLayout() vv1_h1box = QHBoxLayout() vv1_h2box = QHBoxLayout() vv1_h3box = QHBoxLayout() #screen 띄우는 위치 vv1box.addLayout(vv1_v1box) vv1_v1box.addWidget(self.screen) #곡제목 위치 vv1box.addLayout(vv1_h1box) vv1_h1box.addWidget(self.replaybutton) vv1_h1box.addWidget(self.title) vv1_h1box.addWidget(self.randombutton) #replay, playbar, random 버튼 위치 vv1box.addLayout(vv1_h2box) vv1_h2box.addWidget(self.positionSlider) #back,play,next 버튼 vv1box.addLayout(vv1_h3box) vv1_h3box.addStretch(1) vv1_h3box.addWidget(self.backbutton) vv1_h3box.addWidget(self.playbutton) self.playbutton.clicked.connect(self.openequalizer) vv1_h3box.addWidget(self.nextbutton) vv1_h3box.addStretch(1) #out, volume, lyrics 버튼 vv2box.addWidget(outbutton) vv2box.addWidget(self.volume) vv2box.addWidget(self.lyricsbutton) Mainlayout = QHBoxLayout() Mainlayout.addLayout(vv1box) Mainlayout.addLayout(vv2box) self.setLayout(Mainlayout) self.setWindowTitle('main') self.setGeometry(500, 200, 1000, 700) self.show() def Out(self): self.close() def TTitle(self, idx): self.title.setText('{}'.format(self.List[idx])) def playClicked(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() self.playbutton.setIcon(QtGui.QIcon('icon/play.png')) self.playbutton.setIconSize(QtCore.QSize(60, 60)) self.check = True else: self.player.play() self.playbutton.setIcon(QtGui.QIcon('icon/stop.png')) self.playbutton.setIconSize(QtCore.QSize(60, 60)) self.TTitle(self.currentidx) self.check = False def nextClicked(self): self.step = 0 self.currentidx += 1 self.TTitle(self.currentidx) self.playlist.next() def prevClicked(self): self.step = 0 self.currentidx -= 1 self.TTitle(self.currentidx) self.playlist.previous() def volumeChanged(self): self.player.setVolume(self.volume.value()) def ShowPLayList(self): for (i, j) in zip(self.List, range(10, 110, 20)): a = QLabel(i, self.showplaylist) a.move(10, j) label = QLabel(self.showplaylist) label.move(0, 110) label.resize(100, 100) self.showplaylist.setWindowTitle('PlayLIst') self.showplaylist.setWindowModality(Qt.ApplicationModal) self.showplaylist.setGeometry(1500, 400, 300, 200) self.showplaylist.show() def positionChanged(self, position): self.positionSlider.setValue(position) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) def setPosition(self, position): self.player.setPosition(position) def closed(self, state): self.label.setVisible(state != Qt.Unchecked) def currretloop(self): self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) def loop(self): self.playList.setPlaybackMode(QMediaPlaylist.Loop) def openequalizer(self): if (self.check == False): self.w = Window() self.w.show() else: self.w.hide()
class Ui_MainWindow(object): # for stylizing progress bar progress_styleSheet = """ QSlider::groove:horizontal { background: dark; height: 40px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #07406a, stop: 1 #696969); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #696969, stop: 1 #07406a); height: 40px; } QSlider::add-page:horizontal { background: #696969; height: 40px; } QSlider::handle:horizontal { background: #aaa; border: 0px; width: 5px; margin-top: 0px; margin-bottom: 0px; border-radius: 0px; } """ def setupUi(self, MainWindow): MainWindow.setObjectName("Music Player") MainWindow.resize(640, 480) MainWindow.setAcceptDrops(True) self.playlist = QMediaPlaylist() self.player = QMediaPlayer() self.player.setPlaylist(self.playlist) self.player.setVolume(20) self.player.setPlaybackRate(jdata['playback']) self.playlist.setPlaybackMode(jdata['curr_playstyle']) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setObjectName("gridLayout_2") self.progress = QtWidgets.QSlider(self.centralwidget) self.progress.setOrientation(QtCore.Qt.Horizontal) self.progress.setStyleSheet(self.progress_styleSheet) self.progress.setObjectName("progress") self.progress.setSingleStep(1) self.progress.setPageStep(1) self.gridLayout_2.addWidget(self.progress, 1, 0, 1, 3) self.stop_but = QtWidgets.QPushButton(self.centralwidget) self.stop_but.setObjectName("stop_but") self.gridLayout_2.addWidget(self.stop_but, 0, 2, 1, 1) self.backward_b = QtWidgets.QPushButton(self.centralwidget) self.backward_b.setObjectName("backward") self.gridLayout_2.addWidget(self.backward_b, 0, 0, 1, 1) self.cont_pau = QtWidgets.QPushButton(self.centralwidget) self.cont_pau.setObjectName("cont_pau") self.gridLayout_2.addWidget(self.cont_pau, 0, 1, 1, 1) self.playstyle = QtWidgets.QPushButton(self.centralwidget) self.playstyle.setObjectName("playstyle") self.playstyle.setText("Loop") self.gridLayout_2.addWidget(self.playstyle, 0, 4, 1, 1) self.forward_b = QtWidgets.QPushButton(self.centralwidget) self.forward_b.setObjectName("forward") self.gridLayout_2.addWidget(self.forward_b, 0, 3, 1, 1) self.time_remain = QtWidgets.QLabel(self.centralwidget) self.time_remain.setObjectName("time_remain") self.gridLayout_2.addWidget(self.time_remain, 1, 3, 1, 1) self.verticalLayout_2 = QtWidgets.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.volume = QtWidgets.QLabel(self.centralwidget) self.volume.setAlignment(QtCore.Qt.AlignCenter) self.volume.setObjectName("volume") self.verticalLayout_2.addWidget(self.volume) self.volume_ctrl = QtWidgets.QSlider(self.centralwidget) self.volume_ctrl.setOrientation(QtCore.Qt.Horizontal) self.volume_ctrl.setObjectName("volume_ctrl") self.volume_ctrl.setValue(jdata["volume"]) self.volume_ctrl.setRange(-1, 101) self.volume_ctrl.setSingleStep(1) self.volume_ctrl.setPageStep(1) self.verticalLayout_2.addWidget(self.volume_ctrl) self.gridLayout_2.addLayout(self.verticalLayout_2, 1, 4, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 1, 0, 1, 1) self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.playing = QtWidgets.QLabel(self.centralwidget) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) self.playing.setFont(font) self.playing.setAlignment(QtCore.Qt.AlignCenter) self.playing.setObjectName("playing") self.playing.setScaledContents(True) self.playing.setWordWrap(True) self.verticalLayout.addWidget(self.playing) self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) self.verticalLayout_3 = QtWidgets.QVBoxLayout() self.verticalLayout_3.setObjectName("verticalLayout_3") self.song_list = ListWidget(self.centralwidget) self.song_list.setMinimumSize(QtCore.QSize(183, 0)) self.song_list.setAcceptDrops(True) self.song_list.setDragDropMode( QtWidgets.QAbstractItemView.InternalMove) self.song_list.setObjectName("song_list") self.song_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.song_list.setWordWrap(True) self.verticalLayout_3.addWidget(self.song_list) self.gridLayout.addLayout(self.verticalLayout_3, 0, 1, 2, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 632, 25)) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile.setObjectName("menuFile") self.menuAbout = QtWidgets.QMenu(self.menubar) self.menuAbout.setObjectName("menuAbout") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionOpen = QtWidgets.QAction(MainWindow) self.actionOpen.setObjectName("actionOpen") self.actionLisence_Information = QtWidgets.QAction(MainWindow) self.actionLisence_Information.setObjectName( "actionLisence_Information") self.menuFile.addAction(self.actionOpen) self.menuAbout.addAction(self.actionLisence_Information) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuAbout.menuAction()) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout_2.addItem(spacerItem, 0, 5, 1, 1) self.gridLayout.addLayout(self.gridLayout_2, 1, 0, 1, 1) self.info = QMessageBox() self.info.setWindowTitle("License Information") self.info.setText("MIT License\n\nCopyright (c) 2021 Marganotvke") self.err = QMessageBox() self.err.setWindowTitle("Error Loading File") self.err.setText("Error Loading File!\n\nPlease check file type!") self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) self.actionOpen.triggered.connect(lambda: self.open_trig()) self.actionLisence_Information.triggered.connect( lambda: self.info.exec_()) self.cont_pau.clicked.connect(lambda: self.cur_playing()) self.volume_ctrl.sliderMoved.connect(lambda: self.change_vol()) self.stop_but.clicked.connect(lambda: self.stop_playing()) self.forward_b.clicked.connect(lambda: self.forward()) self.backward_b.clicked.connect(lambda: self.backward()) self.playstyle.clicked.connect(lambda: self.playlist_style()) self.song_list.dropped.connect(lambda e: self.start_play(e)) self.song_list.itemDoubleClicked.connect( lambda: self.jump_start(self.song_list.currentRow())) self.song_list.model().rowsAboutToBeMoved.connect( lambda e, f, g, h, i: self.re_arr(f, i)) self.song_list.dele.connect(lambda e: self.delete_q(e)) self.player.metaDataAvailableChanged.connect(lambda: self.set_meta()) self.player.stateChanged.connect(lambda e: self.set_state(e)) self.player.positionChanged.connect(lambda e: self.set_pos(e)) self.progress.sliderMoved.connect(lambda e: self.skip_to(e)) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "Music Player")) self.stop_but.setText(_translate("MainWindow", "Stop")) self.backward_b.setText(_translate("MainWindow", "Backward")) self.cont_pau.setText(_translate("MainWindow", "Load Song")) self.playstyle.setText( _translate("MainWindow", f"{playstyles[jdata['curr_playstyle']]}")) self.forward_b.setText(_translate("MainWindow", "Forward")) self.time_remain.setText(_translate("MainWindow", "--/--")) self.volume.setText( _translate("MainWindow", f"Volume: {jdata['volume']}%")) self.playing.setText( _translate("MainWindow", "Currently playing: None")) self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuAbout.setTitle(_translate("MainWindow", "About")) self.actionOpen.setText(_translate("MainWindow", "Open")) self.actionLisence_Information.setText( _translate("MainWindow", "License Information")) self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O")) def re_arr(self, e=None, f=None): f -= 1 if self.song_list.count() == f else 0 media = self.playlist.media(e) self.playlist.removeMedia(e) self.playlist.insertMedia(f, media) def jump_start(self, index=None): if self.playlist.currentIndex() != index: self.playlist.setCurrentIndex(index) self.player.stop() self.start_play() def start_play(self, url=None): if url: print("Emitted from drop event:", url) threading.Thread(target=self.open_file(url)).start() self.player.play() def stop_playing(self): self.player.stop() def cur_playing(self): if self.playlist.isEmpty(): self.open_trig() else: if self.player.state() == 1: self.player.pause() self.cont_pau.setText("Play") else: self.player.play() self.cont_pau.setText("Pause") def forward(self): self.playlist.next() def backward(self): if round(self.player.position() / 1000) >= 5: self.player.setPosition(0) if not self.player.state(): self.start_play() else: self.playlist.previous() def open_trig(self): filename = QFileDialog.getOpenFileName( None, 'Open File', filter= "MPEG-2 (*.mp3);;WAVE Audio (*.wav,*.aif,*.aiff);;MPEG-1/DD/ACC (*.aac);;MIDI (*.mid,*.midi);;Windows Media Audio (*.wma);;Xiph.Org OGG Vorbis (*.ogg);;NeXT SouND (*.snd);;FLAC (*.flac);;All files(*)" ) threading.Thread(target=self.open_file(filename[0])).start() def open_file(self, file_url): url = QUrl.fromLocalFile(file_url) avai = ('.mp3', '.wav', 'ogg', '.aac', '.aif', '.aiff', '.mid', '.midi', '.wma', '.snd', '.flac') if url.url() != '' and not url.fileName().lower().endswith(avai): self.err.exec_() elif url.fileName().lower().endswith(avai): song_name = url.fileName().split(".")[0] self.song_list.addItem(song_name) if self.playlist.isEmpty(): self.playlist.addMedia(QMediaContent(url)) self.cont_pau.setText("Pause") self.start_play() else: self.playlist.addMedia(QMediaContent(url)) def delete_q(self, i): self.playlist.removeMedia(i) self.song_list.takeItem(i) def playlist_style(self): i = self.playlist.playbackMode() i += 1 i *= (i < 5) self.playlist.setPlaybackMode(i) self.playstyle.setText(f"{playstyles[self.playlist.playbackMode()]}") jdata["curr_playstyle"] = self.playlist.playbackMode() print(playstyles[self.playlist.playbackMode()]) def change_vol(self): vol = self.volume_ctrl.value() self.player.setVolume(vol) self.volume.setText(f"Volume: {vol}%") jdata["volume"] = vol def set_pos(self, e): if self.player.isMetaDataAvailable(): t = self.player.duration() dt = datetime.datetime.fromtimestamp( round(self.player.duration() / 1000)).strftime('%M:%S') dt_ct = datetime.datetime.fromtimestamp(round( e / 1000)).strftime('%M:%S') self.thread = threading.Thread( target=self.progress.setValue(round((e / t) * 100))) self.thread.start() self.time_remain.setText(f"{dt_ct}/{dt}") def set_meta(self): if self.player.isMetaDataAvailable(): self.duraiton = self.player.duration() self.progress.setRange(0, 100) self.playing.setText( f"Currently playing: {self.player.currentMedia().canonicalUrl().fileName().split('.')[0]}" ) else: if self.playlist.isEmpty(): self.cont_pau.setText("Load Song") self.time_remain.setText("--/--") def set_state(self, e): if not e: self.playing.setText("Currently playing: None") if self.playlist.isEmpty(): self.cont_pau.setText("Load Song") else: self.cont_pau.setText("Play") else: if self.player.isMetaDataAvailable(): self.playing.setText( f"Currently playing: {self.player.currentMedia().canonicalUrl().fileName().split('.')[0]}" ) def skip_to(self, e): self.player.setPosition(round((e / 100) * self.player.duration()))