Exemplo n.º 1
0
class chirpyPlayer(QMediaPlayer):
	def __init__(self):
		super().__init__()
		self._prevSong=0
		self._skipped=False
		self._playlist=QMediaPlaylist(self)
		self.setPlaylist(self._playlist)
		self.currentMediaChanged.connect(self.unsetSkipped)
	def replacePlaylist(self,plist):
		self._playlist.clear()
		for i in range (plist.rowCount()):
			self._playlist.addMedia(QMediaContent(QUrl.fromLocalFile(
				plist.data(plist.index(i,0),Qt.UserRole))))
	def setSkipped(self):
		self._skipped=True
	def unsetSkipped(self):
		self._skipped=False
	@pyqtProperty(bool)
	def skipped(self):
		return self._skipped
	@skipped.setter
	def skipped(self, val):
		self._skipped = bool(val)
	@pyqtProperty(int)
	def previousId(self):
		return self._prevSong
	@previousId.setter
	def previousId(self, id):
		self._prevSong=id
Exemplo n.º 2
0
class SoundPlayerWorker(QObject):
    def __init__(self, args=(), kwargs=None):
        super().__init__()
        self.media_player = QMediaPlayer(flags=QMediaPlayer.LowLatency)
        self.playlist = QMediaPlaylist()
        self.media_player.setPlaylist(self.playlist)
        self._priority = 0

    def play_sound(self, file="", priority=0, override=False):
        """
        Method to add a new sound to play
        :param file: str
        :param override:
        :return:
        """

        # logging.info(f"file: {file}, priority: {priority}, self._priority: {self._priority}")

        if priority > self._priority:
            self.media_player.stop()
            self.playlist.clear()
            self._priority = priority

        # if override:
        #     self.media_player.stop()
        #     self.playlist.clear()

        # logging.info(f"request to play: {file}, override set to: {override}, mediaCount: {self.playlist.mediaCount()}")

        self.playlist.addMedia(QMediaContent(QUrl(file)))

        # logging.info(f"request to play, after adding file: {file}, override set to: {override}, mediaCount: {self.playlist.mediaCount()}")

        if self.media_player.state() == 0:
            self.media_player.play()

    def state_changed(self):
        """
        Method called when the media_player state is changed
        :return: 
        """
        if self.media_player.state() == 0:
            self._priority = 0

    def check_playlist_index(self):
        """
        Method to check to see if we've reached the end of the playlist or not
        :return:
        """
        if self.playlist.currentIndex() == -1:
            self.playlist.clear()

    def stop(self):
        """
        Method to stop the sound from playing any further
        :return:
        """
        self.media_player.stop()
Exemplo n.º 3
0
class SoundPlayer:
    def __init__(self, parent):
        self.parent = parent

        self.player = QMediaPlayer()
        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 createPlaylist(self,
                       playlists,
                       startRow=0,
                       option=QMediaPlaylist.Sequential):
        self.playlist.clear()

        for path in playlists:
            url = QUrl.fromLocalFile(path)
            self.playlist.addMedia(QMediaContent(url))

        self.playlist.setPlaybackMode(option)

    def upateVolume(self, vol):
        self.player.setVolume(vol)
Exemplo n.º 4
0
class BasicVideoWidget(QVideoWidget):
    def __init__(self, *args, **kwargs):
        super(BasicVideoWidget, self).__init__(*args, **kwargs)
        self.mediaPlayer = QMediaPlayer(parent=self)
        self.setMediaObject(self.mediaPlayer)

        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        self.mediaPlayer.setPlaylist(self.playlist)

        self.mediaPlayer.positionChanged.connect(self._positionChanged)
        self.mediaPlayer.mutedChanged.connect(self.mutedChanged)
        self.mediaPlayer.durationChanged.connect(self._durationChanged)
        self.mediaPlayer.stateChanged.connect(self.stateChanged)
        self.mediaPlayer.seekableChanged.connect(self.seekableChanged)

    def loadUrl(self, url):
        mc = QMediaContent(url)
        self.playlist.clear()
        self.playlist.addMedia(mc)

    def load(self, path):
        self.loadUrl(QUrl.fromLocalFile(os.path.abspath(path)))

    @Slot()
    def play(self):
        self.mediaPlayer.play()

    @Slot()
    def pause(self):
        self.mediaPlayer.pause()

    @Slot()
    def stop(self):
        self.mediaPlayer.stop()

    @Slot(bool)
    def setMuted(self, b):
        self.mediaPlayer.setMuted(b)

    mutedChanged = Signal(bool)

    @Slot()
    def playPause(self):
        if self.mediaPlayer.state() != QMediaPlayer.PlayingState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def state(self):
        return self.mediaPlayer.state()

    stateChanged = Signal(QMediaPlayer.State)

    def duration(self):
        return self.mediaPlayer.duration()

    durationChanged = Signal(int)

    @Slot(int)
    def setPosition(self, p):
        self.mediaPlayer.setPosition(p)

    def position(self):
        return self.mediaPlayer.position()

    @Slot('qint64')
    def _positionChanged(self, p):
        self.positionChanged.emit(p)

    positionChanged = Signal(int)

    @Slot('qint64')
    def _durationChanged(self, p):
        self.durationChanged.emit(p)

    seekableChanged = Signal(bool)

    def isSeekable(self):
        return self.mediaPlayer.isSeekable()
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.title = 'Personal audio player v2.3'
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 150
        self.color = 0  # 0- toggle to dark 1- toggle to light
        self.userAction = -1  # 0- stopped, 1- playing 2-paused
        self.duration = 0
        #self.getRecommendedPlaylist()
        self.initUI()

    def initUI(self):
        # Add file menu
        menubar = self.menuBar()
        filemenu = menubar.addMenu('File')
        windowmenu = menubar.addMenu('Window')
        connectTo = menubar.addMenu('Connect to...')

        fileAct = QAction('Open File', self)
        folderAct = QAction('Open Folder', self)
        themeAct = QAction('Toggle light/dark theme', self)
        yandexMusic = QAction('Yandex Music', self)
        deezer = QAction('Deezer', self)
        spotify = QAction('Spotify', self)
        pandora = QAction('Pandora', self)
        mixcloud = QAction('Pandora', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')
        themeAct.setShortcut('Ctrl+T')


        filemenu.addAction(fileAct)
        filemenu.addAction(folderAct)
        windowmenu.addAction(themeAct)
        connectTo.addAction(yandexMusic)
        connectTo.addAction(deezer)
        connectTo.addAction(pandora)
        connectTo.addAction(mixcloud)
        connectTo.addAction(spotify)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)
        themeAct.triggered.connect(self.toggleColors)
        yandexMusic.triggered.connect(self.connectYandexMusic)
        deezer.triggered.connect(self.connectYandexMusic)
        pandora.triggered.connect(self.connectYandexMusic)
        mixcloud.triggered.connect(self.connectYandexMusic)
        spotify.triggered.connect(self.connectYandexMusic)

        self.addControls()

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.toggleColors()
        self.show()

    def downloadTrack(self, name):
        page = requests.get("http://zaycev.net/search.html?query_search=" + name).text
        parser = fromstring(page)
        fileJSON = parser.xpath('//div/@data-url')
        resp = requests.get("http://zaycev.net" + fileJSON[1])
        data = resp.json()
        with open("track.json", 'w') as outfile:
            json.dump(data, outfile)
        connection_file = open("track.json", 'r')
        conn_string = json.load(connection_file)

        track = requests.get(conn_string['url'].rsplit('?')[0])
        try:
            os.makedirs('./tracks')
        except OSError:
            pass

        out = open("./tracks/" + name.strip() + ".mp3", 'wb')
        out.write(track.content)
        out.close()
        QMessageBox.about(self, "Track added!", name.strip() + " was added")

    def playRecommend(self):
        try:
            similarTracks = open("playlist.txt", 'r')
            i = 0
            for line in similarTracks.readlines():
                if i == 5:
                    break
                else:
                    i = i+1
                print(line)
                self.downloadTrack(line)
                self.openFileRec("./tracks/" + line.strip() + ".mp3")

        except:
            QMessageBox.about(self, "Play error!", "Unknown error!")

    def getRecommendedPlaylist(self, song):
        try:
            audio = ID3(song[0])
            title = ''.join(audio['TIT2'].text[0].rsplit('(')[0])
            if title[-1] == ' ':
                title = title[0:-1]
            artist = audio['TPE1'].text[0]
            if artist[-1] == ' ':
                artist = artist[0:-1]
            print(artist + " " + title)
            resp = requests.get("http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=" + artist + "&track=" + title +
                                "&api_key=API_key&format=json")
            data = resp.json()
            with open("playlist" + artist + "-" + title + ".json", 'w') as outfile:
                json.dump(data, outfile)
            connection_file = open("playlist" + artist + "-" + title + ".json", 'r')
            conn_string = json.load(connection_file)

            with open("playlist.txt", 'a') as playlistFile:
                for track in conn_string['similartracks']['track']:
                    playlistFile.write(track['artist']['name'] + " " + track['name'] + "\n")
            playlistFile.close()
        except:
            QMessageBox.about(self, "Error!", "Some trouble with export title or artist name, try other track")

    def getRecommendedPlaylistFolder(self, song):
        audio = ID3(song)
        title = ''.join(audio['TIT2'].text[0].rsplit('(')[0])
        if title[-1] == ' ':
            title = title[0:-1]
        artist = audio['TPE1'].text[0]
        if artist[-1] == ' ':
            artist = artist[0:-1]
        print(artist + " " + title)
        resp = requests.get("http://ws.audioscrobbler.com/2.0/?method=track.getsimilar&artist=" + artist + "&track=" + title +
                            "&api_key=API_key&format=json")
        data = resp.json()
        with open("playlist" + artist + "-" + title + ".json", 'w') as outfile:
            json.dump(data, outfile)
            connection_file = open("playlist" + artist + "-" + title + ".json", 'r')
        conn_string = json.load(connection_file)
        with open("playlist.txt", 'a') as playlistFile:
            for track in conn_string['similartracks']['track']:
                playlistFile.write(track['artist']['name'] + " " + track['name'] + "\n")
        playlistFile.close()

    def addControls(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)
        # Add song controls
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(50)

        sldPosition = QSlider(Qt.Horizontal, self)
        sldPosition.setMinimum(0)
        sldPosition.setFocusPolicy(Qt.NoFocus)
        #sldPosition.valueChanged.connect(self.player.setPosition)
        self.player.positionChanged.connect(sldPosition.setValue)
        sldPosition.setMaximum(180000)

        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        stopBtn = QPushButton('Stop')  # stop button
        # Add playlist controls
        prevBtn = QPushButton('Prev')
        shuffleBtn = QPushButton('Shuffle')
        nextBtn = QPushButton('Next')
        playRecommendedBtn = QPushButton('Play Recommended Playlist')
        like = QPushButton('Like')
        dislike = QPushButton('DisLike')

        # Add button layouts
        controlArea = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()
        playRec = QHBoxLayout()
        ld = QHBoxLayout()

        # Add buttons to song controls layout
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)
        # Add buttons to playlist controls layout
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(shuffleBtn)
        playlistCtrlLayout.addWidget(nextBtn)
        playRec.addWidget(playRecommendedBtn)
        ld.addWidget(like)
        ld.addWidget(dislike)
        # Add to vertical layout
        controlArea.addWidget(sldPosition)
        controlArea.addWidget(volumeslider)
        controlArea.addLayout(controls)
        controlArea.addLayout(playlistCtrlLayout)
        controlArea.addLayout(playRec)
        controlArea.addLayout(ld)
        wid.setLayout(controlArea)
        # Connect each signal to their appropriate function
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        shuffleBtn.clicked.connect(self.shufflelist)
        nextBtn.clicked.connect(self.nextSong)

        playRecommendedBtn.clicked.connect(self.playRecommend)

        like.clicked.connect(self.like)
        dislike.clicked.connect(self.dislike)

        self.statusBar()

        self.playlist.currentMediaChanged.connect(self.songChanged)

    def like(self, text):
        QMessageBox.about(self, "Attention!", "You have Liked track!")

    def dislike(self, text):
        QMessageBox.about(self, "Attention!", "You have DisLiked track!")

    def connectYandexMusic(self):
        apple = LoginWindow()
        apple.exec_()

    def openFile(self):
        print("File button clicked!")
        song = QFileDialog.getOpenFileName(self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        print(song[0])

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())
            self.getRecommendedPlaylist(song)

    def openFileRec(self, path):
        song = path

        if song != '':
            url = QUrl.fromLocalFile(song)
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())

    def addFiles(self):
        print("Folder button clicked!")
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
            print(self.playlist.mediaCount())
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1

    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, 'Open Music Folder', '~')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    print(it.filePath(), fInfo.suffix())
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        print('added file', fInfo.fileName())
                        self.getRecommendedPlaylistFolder(it.filePath())
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                print(it.filePath(), fInfo.suffix())
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    print('added file', fInfo.fileName())
                    self.getRecommendedPlaylistFolder(it.filePath())
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))

    def playhandler(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1

    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    def stophandler(self):
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()
        print("Playlist cleared!")
        self.statusBar().showMessage("Stopped and cleared playlist")

    def changeVolume(self, value):
        self.player.setVolume(value)

    def changePosition(self, value):
        self.player.setPosition(value)

    def prevSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().previous()

    def shufflelist(self):
        self.playlist.shuffle()
        print("Shuffled playlist!")

    def nextSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().next()

    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.statusBar().showMessage(url.fileName())

    def toggleColors(self):

        app.setStyle("Fusion")
        palette = QPalette()
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.white)
            palette.setColor(QPalette.Button, QColor(53, 53, 53))
            palette.setColor(QPalette.ButtonText, Qt.white)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0
Exemplo n.º 7
0
class UiForm(QWidget):  # QMainWindow

    def __init__(self):
        super(UiForm, self).__init__()  # ,QtCore.Qt.FramelessWindowHint

        self.initDrag()
        self.player_2_list_Mode = 1



        # 窗口初始化
        self.init_mainwindow()

        self.init_public()

    def init_mainwindow(self):
        self.setObjectName("Main")
        self.resize(app_width, app_height)
        # 窗体透明度设置
        self.setMouseTracking(True)
        # self.setWindowOpacity(0.8)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)

        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("{}/ico/b1.ico".format(here_dic)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.setWindowIcon(icon)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")

        self.tabWidget = QtWidgets.QTabWidget()
        # self.gridLayout.setSpacing(0)
        # 主窗口 》》》》》》》》》》》
        font = QtGui.QFont()
        font.setFamily("楷体")
        #font.setPointSize(10)
        self.tabWidget.setFont(font)
        #self.tabWidget.setFocusPolicy(QtCore.Qt.TabFocus)
        self.tabWidget.setObjectName("tabWidget")


        #self.tabWidget.setMouseTracking(True)

        # 自定义窗口关闭最大化最小化按钮
        self.btn_0_max = QtWidgets.QToolButton()
        self.btn_0_max.setObjectName('btn_0_max')
        self.gridLayout.addWidget(self.btn_0_max, 0, 10, 1, 1)
        self.btn_0_min = QtWidgets.QToolButton()
        self.btn_0_min.setObjectName('btn_0_min')
        self.gridLayout.addWidget(self.btn_0_min, 0, 9, 1, 1)
        self.btn_0_close = QtWidgets.QToolButton()
        self.btn_0_close.setObjectName('btn_0_close')
        self.gridLayout.addWidget(self.btn_0_close, 0, 11, 1, 1)
        self.btn_0_min.setFixedSize(QtCore.QSize(25, 25))
        self.btn_0_max.setFixedSize(QtCore.QSize(25, 25))
        self.btn_0_close.setFixedSize(QtCore.QSize(25, 25))
        ico_max = QIcon()
        ico_max.addPixmap(QPixmap('{}\ico\show_max1.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
        self.btn_0_max.setIcon(ico_max)
        ico_min = QIcon()
        ico_min.addPixmap(QPixmap('{}\ico\show_min.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
        self.btn_0_min.setIcon(ico_min)
        ico_close = QIcon()
        ico_close.addPixmap(QPixmap('{}\ico\show_close.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
        self.btn_0_close.setIcon(ico_close)

        # 标题图标
        self.label_0_title = QLabel()
        self.label_0_title.setObjectName('label_0_title')
        self.gridLayout.addWidget(self.label_0_title, 0, 0, 1, 1)
        self.label_0_title.setFixedSize(QtCore.QSize(25, 25))
        self.label_0_title.show()
        label_0_titie_img = QPixmap(r'{}\ico\a1.jpg'.format(here_dic)).scaled(self.label_0_title.width(),
                                                                              self.label_0_title.height())
        self.label_0_title.setPixmap(label_0_titie_img)
        self.label_0_title.show()

        # 链接
        self.btn_0_min.clicked.connect(self.showMinimized)
        self.btn_0_max.clicked.connect(self.showMaximized)
        self.btn_0_close.clicked.connect(self.closeEvent)












    def init_public(self):
        # 时间日期显示label   第一行 >>>>>>>
        self.time_show = QtCore.QTimer()
        self.time_show.start(100)
        self.time_show.timeout.connect(self.time_show_out)
        self.label_0_time = QLabel()
        self.setObjectName('label_0_time')
        self.label_0_time.setStyleSheet("QLabel{color: white ; background-color: 1}")
        self.label_0_time.setEnabled(False)
        font_time = QtGui.QFont()
        font_time.setFamily("楷体")
        font_time.setPointSize(10)
        self.label_0_time.setFont(font_time)
        self.label_0_time.setFixedSize(QtCore.QSize(180, 15))
        # self.gridLayout.addWidget(self.label_0_time, 0,2,1,1)
        #self.label_0_time.setEnabled(False)
        self.gridLayout.addWidget(self.label_0_time, 0, 5, 1, 1)

        # 公共音频接口
        self.play_common_list = QMediaPlaylist()
        self.play_common_player = QMediaPlayer()
        self.play_common_player.setPlaylist(self.play_common_list)
        self.play_common_player.stateChanged.connect(self.play_common_player_stateChanged)


        ## 主布局
        self.gridLayout.addWidget(self.tabWidget, 1, 0, 1, 12)
        self.setLayout(self.gridLayout)
        self.tabWidget.setCurrentIndex(0)








    def closeEvent(self, QCloseEvent):
        warn_close = QMessageBox.warning(self, '退出提示', '您确定要退出吗?', QMessageBox.Yes | QMessageBox.Cancel,QMessageBox.Cancel)
        if warn_close == 4194304:  # yes = 16384
            pass
        else:
            # sys.exit()
            quit(1000)



    def showMaximized(self):
        if self.isFullScreen():
            self.setGeometry((screen_width-app_width) / 2, (screen_height- app_height) / 2 , app_width, app_height)
            ico_max = QIcon()
            ico_max.addPixmap(QPixmap('{}\ico\show_max1.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
            self.btn_0_max.setIcon(ico_max)
            self.tabWidget.setVisible(True)
            self.gridLayout_5.addWidget(self.videowidget_5_video, 1, 1, 1, 13)

        else:
            self.showFullScreen()
            self.setGeometry(0, 0, 1920, 1080)
            ico_max = QIcon()
            ico_max.addPixmap(QPixmap('{}\ico\show_max2.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
            self.btn_0_max.setIcon(ico_max)
            if self.player_5_video.state() == 1:
                self.gridLayout.addWidget(self.videowidget_5_video, 1, 0, 10, 12)
                self.tabWidget.setVisible(False)
                self.videowidget_5_video.show()



    def initDrag(self):
        # 设置鼠标跟踪判断扳机默认值
        self.m_flag = False
        self._padding = 5
        self._top_drag = False
        self._left_drag = False
        self._corner_drag = False
        self._bottom_drag = False
        self._right_drag = False
        self._leftcorner_drag = False

    def resizeEvent_base(self, QResizeEvent):
        if not self.isFullScreen():
            ico_max = QIcon()
            ico_max.addPixmap(QPixmap('{}\ico\show_max1.png'.format(here_dic)), QIcon.Normal, QIcon.Off)
            self.btn_0_max.setIcon(ico_max)
            self.tabWidget.setVisible(True)
            self.gridLayout_5.addWidget(self.videowidget_5_video, 1, 1, 1, 13)
        self.right_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 2)
                           for y in range(10, self.height() - self._padding -5)]
        self.bottom_rect = [QPoint(x, y) for x in range(10, self.width() - self._padding - 5)
                            for y in range(self.height() - self._padding, self.height() + 2)]
        self.left_rect = [QPoint(x, y) for x in range(-2, self._padding)
                          for y in range(10, self.height() - self._padding -5)]
        self.top_rect = [QPoint(x, y) for x in range(10, self.width() - self._padding -5)
                         for y in range(-2, self._padding)]
        self.corner_rect = [QPoint(x, y) for x in range(self.width() - self._padding -5, self.width() + 2)
                            for y in range(self.height() - self._padding -5, self.height() + 2)]
        self.leftcprner_rect = [QPoint(x, y) for x in range(-2, self._padding +5)
                                for y in range(-2, self._padding +5)]
        self.move_rect = [QPoint(x,y) for x in range(0,self.width()) for y in range(0, 60)]

        # self.drawing_rect = [QPoint(x,y) for x in range(20, 20 + self.label_6_drawing.width())
        #                       for y in range(105, self.height())]
        # self.drawing_rect = [QPoint(x, y) for x in range(25, self.width())
        #                      for y in range(105, self.height())]


        if self.listwidget_2_additems_lrc_thread.isRunning():
            self.lrc_2_view()

    def mousePressEvent_base(self, event):
        if (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.corner_rect):
            # 鼠标左键点击右下角边界区域
            self._corner_drag = True
            event.accept()
        elif (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.right_rect):
            # 鼠标左键点击右侧边界区域
            self._right_drag = True
            event.accept()
        elif (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.bottom_rect):
            # 鼠标左键点击下侧边界区域
            self._bottom_drag = True
            event.accept()
        elif (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.left_rect):
            # 鼠标左键点击右侧边界区域
            self._left_drag = True
            event.accept()

        elif (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.top_rect):
            # 鼠标左键点击下侧边界区域
            self._top_drag = True
            event.accept()
        elif (event.button() == QtCore.Qt.LeftButton) and (event.pos() in self.leftcprner_rect):
            self._leftcorner_drag = True
            event.accept()

        # 移动
        elif (event.button() == QtCore.Qt.LeftButton or event.button() == QtCore.Qt.MidButton) and (event.pos() in self.move_rect):
            # if  self._top_drag == False and self._left_drag == False and self._corner_drag == False and self._bottom_drag == False and self._right_drag == False:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(QtCore.Qt.OpenHandCursor))  # 更改鼠标图标





    def mouseMoveEvent_base(self, QMouseEvent):
        if QMouseEvent.pos() in self.corner_rect:
            self.setCursor(QtCore.Qt.SizeFDiagCursor)
        elif QMouseEvent.pos() in self.bottom_rect:
            self.setCursor(QtCore.Qt.SizeVerCursor)
        elif QMouseEvent.pos() in self.right_rect:
            self.setCursor(QtCore.Qt.SizeHorCursor)
        elif QMouseEvent.pos() in self.top_rect:
            self.setCursor(QtCore.Qt.SizeVerCursor)
        elif QMouseEvent.pos() in self.left_rect:
            self.setCursor(QtCore.Qt.SizeHorCursor)
        elif QMouseEvent.pos() in self.leftcprner_rect:
            self.setCursor(QtCore.Qt.SizeFDiagCursor)
        elif self.m_flag:
            self.setCursor(QtCore.Qt.OpenHandCursor)


        else:
            self.setCursor(QtCore.Qt.ArrowCursor)

        if QtCore.Qt.LeftButton and self._right_drag:
            # 右侧调整窗口宽度
            self.resize(QMouseEvent.pos().x(), self.height())
            QMouseEvent.accept()
        elif QtCore.Qt.LeftButton and self._bottom_drag:
            # 下侧调整窗口高度
            self.resize(self.width(), QMouseEvent.pos().y())
            QMouseEvent.accept()
        elif QtCore.Qt.LeftButton and self._corner_drag:
            # 右下角同时调整高度和宽度
            self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y())
            QMouseEvent.accept()
        elif QtCore.Qt.LeftButton and self._top_drag:
            # 上侧侧调整窗口高度
            self.setGeometry(self.pos().x(), QMouseEvent.globalPos().y(), self.width(), (self.pos().y() + self.height() - QMouseEvent.globalPos().y()))
            # self.resize(self.width(), self.pos().y() + self.height() - QMouseEvent.globalPos().y())
            # self.move(self.pos().x(), QMouseEvent.globalPos().y())
            QMouseEvent.accept()
        elif QtCore.Qt.LeftButton and self._left_drag:
            # 左侧同时调整高度和宽度
            self.setGeometry(QMouseEvent.globalPos().x(), self.pos().y(), (self.pos().x() + self.width() - QMouseEvent.globalPos().x()), self.height())
            # self.resize(self.pos().x() + self.width() - QMouseEvent.globalPos().x(), self.height())
            # self.move(QMouseEvent.globalPos().x(), self.pos().y())
            QMouseEvent.accept()
        elif QtCore.Qt.LeftButton and self._leftcorner_drag:
            self.setGeometry(QMouseEvent.globalPos().x(), QMouseEvent.globalPos().y(),
                             (self.width() + self.pos().x() - QMouseEvent.globalPos().x()), (self.height() + self.pos().y() - QMouseEvent.globalPos().y()))
            QMouseEvent.accept()

        elif QtCore.Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()


    def wheelEvent_base(self, QWheelEvent):
        pass


    def mouseReleaseEvent_base(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(QtCore.Qt.ArrowCursor))
        # 鼠标释放后,各扳机复位
        self._top_drag = False
        self._left_drag = False
        self._corner_drag = False
        self._bottom_drag = False
        self._right_drag = False
        self._leftcorner_drag = False






    # 公共音频播放接口
    def play_common_play(self, file, f_type_int=1):
        '''
        f_type是文件类型, url = 1   file_audio = 2  file_video = 3
        '''
        self.play_common_player.stop()
        self.play_common_list.clear()
        if f_type_int == 1:
            self.play_common_list.addMedia(QMediaContent(QUrl(file)))
        elif f_type_int == 2:
            self.play_common_list.addMedia(QMediaContent(QUrl.fromLocalFile(file)))
        elif f_type_int == 3:
            self.play_common_list.addMedia(QMediaContent(QUrl.fromLocalFile(file)))
        self.play_common_player.play()

    def play_common_stop(self):
        if self.play_common_player.state() == 1:

            self.play_common_player.stop()
            self.play_common_list.clear()
        else:
            if self.listWidget_4_used_info.currentItem():
                self.listWidget_4_used_info_doubleclicked()

    def play_common_vol_control(self):
        self.play_common_player.setVolume(self.slider_4_vol.value())

    # 播放状态链接图标
    def play_common_player_stateChanged(self):
        if self.play_common_player.state() == 1:
            ico_4_vol_quit = QIcon()
            ico_4_vol_quit.addPixmap(QtGui.QPixmap('{}\ico\pause.ico'.format(here_dic)), QtGui.QIcon.Normal,
                                     QtGui.QIcon.Off)
            self.btn_4_quit_vol.setIcon(ico_4_vol_quit)
        else:
            ico_4_vol_quit = QIcon()
            ico_4_vol_quit.addPixmap(QtGui.QPixmap('{}\ico\play.ico'.format(here_dic)), QtGui.QIcon.Normal,
                                     QtGui.QIcon.Off)
            self.btn_4_quit_vol.setIcon(ico_4_vol_quit)
            self.play_common_player.stop()
            self.play_common_list.clear()

    def open_folder(self):
        os.system('start explorer D:\XiaoU\Download')

    def time_show_out(self):
        self.time_now = time.strftime('%Y-%m-%d %a %H:%M:%S', time.localtime())
        self.label_0_time.setText(self.time_now)
Exemplo n.º 8
0
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())
Exemplo n.º 9
0
class music_play(QtWidgets.QMainWindow, Ui_Form):
    #初始化一些操作
    def __init__(self):
        super(music_play, self).__init__()  #调用该类的父类的初始化函数,完成窗口布局操作
        self.setupUi(self)
        self.setWindowTitle("VIP音乐播放器")
        self.setWindowIcon(QIcon("format.ico"))
        #self.SaveData = db()
        self.m_filepath = 'E:/MusicMedia/MusicMedia/music/'
        self.player = QMediaPlayer()
        self.PlayList = QMediaPlaylist()
        self.player.setPlaylist(self.PlayList)

    #网络歌曲的搜索模块
    def start_search(self):
        music_name = self.SongName.text()
        musician_name = self.Musician.text()
        search = search_song(self.music_name, self.musician_name)
        search.song.connect(self.search_song2)
        search_song.start()

    def search_song2(self, music_data):
        #music_data = self.SaveData.get_data(musician_name,music_name)
        #在此处构建一个url实现在线播放
        print(music_data)
        file_url = music_data[2]
        file_name = "{} - {}".format(music_data[0], music_data[1])
        self.down_music(file_url, file_name)
        self.Internet.addItem(file_name)

    #当地歌曲的加载模块
    def Load_Song(self):
        self.PlayList.clear()  #便于网络歌曲加入
        self.Local.clear()  #刷新播放列表
        list = os.listdir(self.m_filepath)
        for cur_music in list:
            self.Local.addItem(cur_music)
            self.PlayList.addMedia(
                QMediaContent(QUrl.fromLocalFile(self.m_filepath + cur_music)))

    #在线歌曲下载模块
    def down_music(self, url, name):
        header = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
        }
        response = requests.get(url, headers=header)
        with open("{}/{}.mp3".format(self.m_filepath, name), "wb") as file:
            file.write(response.content)

    #用户自定义歌曲模块
    def custom_current_music(self):
        cur_music = self.Local.currentItem().text()
        self.CurMusic.setText(cur_music)
        item = self.Local.currentRow()
        self.PlayList.setCurrentIndex(item)
        self.player.stop()  #停止上一首歌
        self.player.play()  #开始播放当前指定的歌曲

    #设置音乐播放模式模块
    def music_Mode(self):
        self.PlayList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)  #单曲循环
        self.PlayList.setPlaybackMode(QMediaPlaylist.Random)  # 随机播放
        self.PlayList.setPlaybackMode(QMediaPlaylist.Sequential)  # 顺序播放

    #重写窗口paintEvent函数
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(self.rect(), QPixmap("image/background.jpg"))
Exemplo n.º 10
0
class MusicPlayer(QMainWindow):
    """MusicPlayer houses all of elements that directly interact with the main window."""
    def __init__(self, parent=None):
        """Initialize the QMainWindow widget.

        The window title, window icon, and window size are initialized here as well
        as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar,
        QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and
        QVBoxLayout. The connect signals for relavant widgets are also initialized.
        """
        super(MusicPlayer, self).__init__(parent)
        self.setWindowTitle('Mosaic')

        window_icon = utilities.resource_filename('mosaic.images', 'icon.png')
        self.setWindowIcon(QIcon(window_icon))
        self.resize(defaults.Settings().window_size,
                    defaults.Settings().window_size + 63)

        # Initiates Qt objects to be used by MusicPlayer
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist_location = defaults.Settings().playlist_path
        self.content = QMediaContent()
        self.menu = self.menuBar()
        self.toolbar = QToolBar()
        self.art = QLabel()
        self.pixmap = QPixmap()
        self.slider = QSlider(Qt.Horizontal)
        self.duration_label = QLabel()
        self.playlist_dock = QDockWidget('Playlist', self)
        self.library_dock = QDockWidget('Media Library', self)
        self.playlist_view = QListWidget()
        self.library_view = library.MediaLibraryView()
        self.library_model = library.MediaLibraryModel()
        self.preferences = configuration.PreferencesDialog()
        self.widget = QWidget()
        self.layout = QVBoxLayout(self.widget)
        self.duration = 0
        self.playlist_dock_state = None
        self.library_dock_state = None

        # Sets QWidget() as the central widget of the main window
        self.setCentralWidget(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # Initiates the playlist dock widget and the library dock widget
        self.addDockWidget(defaults.Settings().dock_position,
                           self.playlist_dock)
        self.playlist_dock.setWidget(self.playlist_view)
        self.playlist_dock.setVisible(defaults.Settings().playlist_on_start)
        self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable)

        self.addDockWidget(defaults.Settings().dock_position,
                           self.library_dock)
        self.library_dock.setWidget(self.library_view)
        self.library_dock.setVisible(
            defaults.Settings().media_library_on_start)
        self.library_dock.setFeatures(QDockWidget.DockWidgetClosable)
        self.tabifyDockWidget(self.playlist_dock, self.library_dock)

        # Sets the range of the playback slider and sets the playback mode as looping
        self.slider.setRange(0, self.player.duration() / 1000)
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        # OSX system menu bar causes conflicts with PyQt5 menu bar
        if sys.platform == 'darwin':
            self.menu.setNativeMenuBar(False)

        # Initiates Settings in the defaults module to give access to settings.toml
        defaults.Settings()

        # Signals that connect to other methods when they're called
        self.player.metaDataChanged.connect(self.display_meta_data)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.song_duration)
        self.player.positionChanged.connect(self.song_position)
        self.player.stateChanged.connect(self.set_state)
        self.playlist_view.itemActivated.connect(self.activate_playlist_item)
        self.library_view.activated.connect(self.open_media_library)
        self.playlist.currentIndexChanged.connect(self.change_index)
        self.playlist.mediaInserted.connect(self.initialize_playlist)
        self.playlist_dock.visibilityChanged.connect(
            self.dock_visiblity_change)
        self.library_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.preferences.dialog_media_library.media_library_line.textChanged.connect(
            self.change_media_library_path)
        self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(
            self.change_window_size)
        self.art.mousePressEvent = self.press_playback

        # Creating the menu controls, media controls, and window size of the music player
        self.menu_controls()
        self.media_controls()
        self.load_saved_playlist()

    def menu_controls(self):
        """Initiate the menu bar and add it to the QMainWindow widget."""
        self.file = self.menu.addMenu('File')
        self.edit = self.menu.addMenu('Edit')
        self.playback = self.menu.addMenu('Playback')
        self.view = self.menu.addMenu('View')
        self.help_ = self.menu.addMenu('Help')

        self.file_menu()
        self.edit_menu()
        self.playback_menu()
        self.view_menu()
        self.help_menu()

    def media_controls(self):
        """Create the bottom toolbar and controls used for media playback."""
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
        self.play_action = QAction(QIcon(play_icon), 'Play', self)
        self.play_action.triggered.connect(self.player.play)

        stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png')
        self.stop_action = QAction(QIcon(stop_icon), 'Stop', self)
        self.stop_action.triggered.connect(self.player.stop)

        previous_icon = utilities.resource_filename('mosaic.images',
                                                    'md_previous.png')
        self.previous_action = QAction(QIcon(previous_icon), 'Previous', self)
        self.previous_action.triggered.connect(self.previous)

        next_icon = utilities.resource_filename('mosaic.images', 'md_next.png')
        self.next_action = QAction(QIcon(next_icon), 'Next', self)
        self.next_action.triggered.connect(self.playlist.next)

        repeat_icon = utilities.resource_filename('mosaic.images',
                                                  'md_repeat_none.png')
        self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self)
        self.repeat_action.triggered.connect(self.repeat_song)

        self.toolbar.addAction(self.play_action)
        self.toolbar.addAction(self.stop_action)
        self.toolbar.addAction(self.previous_action)
        self.toolbar.addAction(self.next_action)
        self.toolbar.addAction(self.repeat_action)
        self.toolbar.addWidget(self.slider)
        self.toolbar.addWidget(self.duration_label)

    def file_menu(self):
        """Add a file menu to the menu bar.

        The file menu houses the Open File, Open Multiple Files, Open Playlist,
        Open Directory, and Exit Application menu items.
        """
        self.open_action = QAction('Open File', self)
        self.open_action.setShortcut('O')
        self.open_action.triggered.connect(self.open_file)

        self.open_multiple_files_action = QAction('Open Multiple Files', self)
        self.open_multiple_files_action.setShortcut('M')
        self.open_multiple_files_action.triggered.connect(
            self.open_multiple_files)

        self.open_playlist_action = QAction('Open Playlist', self)
        self.open_playlist_action.setShortcut('CTRL+P')
        self.open_playlist_action.triggered.connect(self.open_playlist)

        self.open_directory_action = QAction('Open Directory', self)
        self.open_directory_action.setShortcut('D')
        self.open_directory_action.triggered.connect(self.open_directory)

        self.save_playlist_action = QAction('Save Playlist', self)
        self.save_playlist_action.setShortcut('CTRL+S')
        self.save_playlist_action.triggered.connect(self.save_playlist)

        self.exit_action = QAction('Quit', self)
        self.exit_action.setShortcut('CTRL+Q')
        self.exit_action.triggered.connect(self.closeEvent)

        self.file.addAction(self.open_action)
        self.file.addAction(self.open_multiple_files_action)
        self.file.addAction(self.open_playlist_action)
        self.file.addAction(self.open_directory_action)
        self.file.addSeparator()
        self.file.addAction(self.save_playlist_action)
        self.file.addSeparator()
        self.file.addAction(self.exit_action)

    def edit_menu(self):
        """Add an edit menu to the menu bar.

        The edit menu houses the preferences item that opens a preferences dialog
        that allows the user to customize features of the music player.
        """
        self.preferences_action = QAction('Preferences', self)
        self.preferences_action.setShortcut('CTRL+SHIFT+P')
        self.preferences_action.triggered.connect(
            lambda: self.preferences.exec_())

        self.edit.addAction(self.preferences_action)

    def playback_menu(self):
        """Add a playback menu to the menu bar.

        The playback menu houses
        """
        self.play_playback_action = QAction('Play', self)
        self.play_playback_action.setShortcut('P')
        self.play_playback_action.triggered.connect(self.player.play)

        self.stop_playback_action = QAction('Stop', self)
        self.stop_playback_action.setShortcut('S')
        self.stop_playback_action.triggered.connect(self.player.stop)

        self.previous_playback_action = QAction('Previous', self)
        self.previous_playback_action.setShortcut('B')
        self.previous_playback_action.triggered.connect(self.previous)

        self.next_playback_action = QAction('Next', self)
        self.next_playback_action.setShortcut('N')
        self.next_playback_action.triggered.connect(self.playlist.next)

        self.playback.addAction(self.play_playback_action)
        self.playback.addAction(self.stop_playback_action)
        self.playback.addAction(self.previous_playback_action)
        self.playback.addAction(self.next_playback_action)

    def view_menu(self):
        """Add a view menu to the menu bar.

        The view menu houses the Playlist, Media Library, Minimalist View, and Media
        Information menu items. The Playlist item toggles the playlist dock into and
        out of view. The Media Library items toggles the media library dock into and
        out of view. The Minimalist View item resizes the window and shows only the
        menu bar and player controls. The Media Information item opens a dialog that
        shows information relevant to the currently playing song.
        """
        self.dock_action = self.playlist_dock.toggleViewAction()
        self.dock_action.setShortcut('CTRL+ALT+P')

        self.library_dock_action = self.library_dock.toggleViewAction()
        self.library_dock_action.setShortcut('CTRL+ALT+L')

        self.minimalist_view_action = QAction('Minimalist View', self)
        self.minimalist_view_action.setShortcut('CTRL+ALT+M')
        self.minimalist_view_action.setCheckable(True)
        self.minimalist_view_action.triggered.connect(self.minimalist_view)

        self.view_media_info_action = QAction('Media Information', self)
        self.view_media_info_action.setShortcut('CTRL+SHIFT+M')
        self.view_media_info_action.triggered.connect(
            self.media_information_dialog)

        self.view.addAction(self.dock_action)
        self.view.addAction(self.library_dock_action)
        self.view.addSeparator()
        self.view.addAction(self.minimalist_view_action)
        self.view.addSeparator()
        self.view.addAction(self.view_media_info_action)

    def help_menu(self):
        """Add a help menu to the menu bar.

        The help menu houses the about dialog that shows the user information
        related to the application.
        """
        self.about_action = QAction('About', self)
        self.about_action.setShortcut('H')
        self.about_action.triggered.connect(
            lambda: about.AboutDialog().exec_())

        self.help_.addAction(self.about_action)

    def open_file(self):
        """Open the selected file and add it to a new playlist."""
        filename, success = QFileDialog.getOpenFileName(
            self, 'Open File', '', 'Audio (*.mp3 *.flac)', '',
            QFileDialog.ReadOnly)

        if success:
            file_info = QFileInfo(filename).fileName()
            playlist_item = QListWidgetItem(file_info)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.addMedia(
                QMediaContent(QUrl().fromLocalFile(filename)))
            self.player.setPlaylist(self.playlist)
            playlist_item.setToolTip(file_info)
            self.playlist_view.addItem(playlist_item)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_multiple_files(self):
        """Open the selected files and add them to a new playlist."""
        filenames, success = QFileDialog.getOpenFileNames(
            self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '',
            QFileDialog.ReadOnly)

        if success:
            self.playlist.clear()
            self.playlist_view.clear()
            for file in natsort.natsorted(filenames, alg=natsort.ns.PATH):
                file_info = QFileInfo(file).fileName()
                playlist_item = QListWidgetItem(file_info)
                self.playlist.addMedia(
                    QMediaContent(QUrl().fromLocalFile(file)))
                self.player.setPlaylist(self.playlist)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)
                self.playlist_view.setCurrentRow(0)
                self.player.play()

    def open_playlist(self):
        """Load an M3U or PLS file into a new playlist."""
        playlist, success = QFileDialog.getOpenFileName(
            self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '',
            QFileDialog.ReadOnly)

        if success:
            playlist = QUrl.fromLocalFile(playlist)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(
                    song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def save_playlist(self):
        """Save the media in the playlist dock as a new M3U playlist."""
        playlist, success = QFileDialog.getSaveFileName(
            self, 'Save Playlist', '', 'Playlist (*.m3u)', '')
        if success:
            saved_playlist = "{}.m3u".format(playlist)
            self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u")

    def load_saved_playlist(self):
        """Load the saved playlist if user setting permits."""
        saved_playlist = "{}/.m3u".format(self.playlist_location)
        if os.path.exists(saved_playlist):
            playlist = QUrl().fromLocalFile(saved_playlist)
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(
                    song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)

    def open_directory(self):
        """Open the selected directory and add the files within to an empty playlist."""
        directory = QFileDialog.getExistingDirectory(self, 'Open Directory',
                                                     '', QFileDialog.ReadOnly)

        if directory:
            self.playlist.clear()
            self.playlist_view.clear()
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(
                            QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

            self.player.setPlaylist(self.playlist)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_media_library(self, index):
        """Open a directory or file from the media library into an empty playlist."""
        self.playlist.clear()
        self.playlist_view.clear()

        if self.library_model.fileName(index).endswith(('mp3', 'flac')):
            self.playlist.addMedia(
                QMediaContent(QUrl().fromLocalFile(
                    self.library_model.filePath(index))))
            self.playlist_view.addItem(self.library_model.fileName(index))

        elif self.library_model.isDir(index):
            directory = self.library_model.filePath(index)
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(
                            QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

        self.player.setPlaylist(self.playlist)
        self.player.play()

    def display_meta_data(self):
        """Display the current song's metadata in the main window.

        If the current song contains metadata, its cover art is extracted and shown in
        the main window while the track number, artist, album, and track title are shown
        in the window title.
        """
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
            (album, artist, title, track_number, *__,
             artwork) = metadata.metadata(file_path)

            try:
                self.pixmap.loadFromData(artwork)
            except TypeError:
                self.pixmap = QPixmap(artwork)

            meta_data = '{} - {} - {} - {}'.format(track_number, artist, album,
                                                   title)

            self.setWindowTitle(meta_data)
            self.art.setScaledContents(True)
            self.art.setPixmap(self.pixmap)
            self.layout.addWidget(self.art)

    def initialize_playlist(self, start):
        """Display playlist and reset playback mode when media inserted into playlist."""
        if start == 0:
            if self.library_dock.isVisible():
                self.playlist_dock.setVisible(True)
                self.playlist_dock.show()
                self.playlist_dock.raise_()

            if self.playlist.playbackMode() != QMediaPlaylist.Sequential:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                repeat_icon = utilities.resource_filename(
                    'mosaic.images', 'md_repeat_none.png')
                self.repeat_action.setIcon(QIcon(repeat_icon))

    def press_playback(self, event):
        """Change the playback of the player on cover art mouse event.

        When the cover art is clicked, the player will play the media if the player is
        either paused or stopped. If the media is playing, the media is set
        to pause.
        """
        if event.button() == 1 and configuration.Playback(
        ).cover_art_playback.isChecked():
            if (self.player.state() == QMediaPlayer.StoppedState
                    or self.player.state() == QMediaPlayer.PausedState):
                self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()

    def seek(self, seconds):
        """Set the position of the song to the position dragged to by the user."""
        self.player.setPosition(seconds * 1000)

    def song_duration(self, duration):
        """Set the slider to the duration of the currently played media."""
        duration /= 1000
        self.duration = duration
        self.slider.setMaximum(duration)

    def song_position(self, progress):
        """Move the horizontal slider in sync with the duration of the song.

        The progress is relayed to update_duration() in order
        to display the time label next to the slider.
        """
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.update_duration(progress)

    def update_duration(self, current_duration):
        """Calculate the time played and the length of the song.

        Both of these times are sent to duration_label() in order to display the
        times on the toolbar.
        """
        duration = self.duration

        if current_duration or duration:
            time_played = QTime(
                (current_duration / 3600) % 60, (current_duration / 60) % 60,
                (current_duration % 60), (current_duration * 1000) % 1000)
            song_length = QTime((duration / 3600) % 60, (duration / 60) % 60,
                                (duration % 60), (duration * 1000) % 1000)

            if duration > 3600:
                time_format = "hh:mm:ss"
            else:
                time_format = "mm:ss"

            time_display = "{} / {}".format(time_played.toString(time_format),
                                            song_length.toString(time_format))

        else:
            time_display = ""

        self.duration_label.setText(time_display)

    def set_state(self, state):
        """Change the icon in the toolbar in relation to the state of the player.

        The play icon changes to the pause icon when a song is playing and
        the pause icon changes back to the play icon when either paused or
        stopped.
        """
        if self.player.state() == QMediaPlayer.PlayingState:
            pause_icon = utilities.resource_filename('mosaic.images',
                                                     'md_pause.png')
            self.play_action.setIcon(QIcon(pause_icon))
            self.play_action.triggered.connect(self.player.pause)

        elif (self.player.state() == QMediaPlayer.PausedState
              or self.player.state() == QMediaPlayer.StoppedState):
            self.play_action.triggered.connect(self.player.play)
            play_icon = utilities.resource_filename('mosaic.images',
                                                    'md_play.png')
            self.play_action.setIcon(QIcon(play_icon))

    def previous(self):
        """Move to the previous song in the playlist.

        Moves to the previous song in the playlist if the current song is less
        than five seconds in. Otherwise, restarts the current song.
        """
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def repeat_song(self):
        """Set the current media to repeat and change the repeat icon accordingly.

        There are four playback modes: repeat none, repeat all, repeat once, and shuffle.
        Clicking the repeat button cycles through each playback mode.
        """
        if self.playlist.playbackMode() == QMediaPlaylist.Sequential:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
            repeat_on_icon = utilities.resource_filename(
                'mosaic.images', 'md_repeat_all.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Loop:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            repeat_on_icon = utilities.resource_filename(
                'mosaic.images', 'md_repeat_once.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
            repeat_icon = utilities.resource_filename('mosaic.images',
                                                      'md_shuffle.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Random:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            repeat_icon = utilities.resource_filename('mosaic.images',
                                                      'md_repeat_none.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

    def activate_playlist_item(self, item):
        """Set the active media to the playlist item dobule-clicked on by the user."""
        current_index = self.playlist_view.row(item)
        if self.playlist.currentIndex() != current_index:
            self.playlist.setCurrentIndex(current_index)

        if self.player.state() != QMediaPlayer.PlayingState:
            self.player.play()

    def change_index(self, row):
        """Highlight the row in the playlist of the active media."""
        self.playlist_view.setCurrentRow(row)

    def minimalist_view(self):
        """Resize the window to only show the menu bar and audio controls."""
        if self.minimalist_view_action.isChecked():

            if self.playlist_dock.isVisible():
                self.playlist_dock_state = True
            if self.library_dock.isVisible():
                self.library_dock_state = True

            self.library_dock.close()
            self.playlist_dock.close()

            QTimer.singleShot(10, lambda: self.resize(500, 0))

        else:
            self.resize(defaults.Settings().window_size,
                        defaults.Settings().window_size + 63)

            if self.library_dock_state:
                self.library_dock.setVisible(True)

            if self.playlist_dock_state:
                self.playlist_dock.setVisible(True)

    def dock_visiblity_change(self, visible):
        """Change the size of the main window when the docks are toggled."""
        if visible and self.playlist_dock.isVisible(
        ) and not self.library_dock.isVisible():
            self.resize(
                defaults.Settings().window_size + self.playlist_dock.width() +
                6, self.height())

        elif visible and not self.playlist_dock.isVisible(
        ) and self.library_dock.isVisible():
            self.resize(
                defaults.Settings().window_size + self.library_dock.width() +
                6, self.height())

        elif visible and self.playlist_dock.isVisible(
        ) and self.library_dock.isVisible():
            self.resize(
                defaults.Settings().window_size + self.library_dock.width() +
                6, self.height())

        elif (not visible and not self.playlist_dock.isVisible()
              and not self.library_dock.isVisible()):
            self.resize(defaults.Settings().window_size,
                        defaults.Settings().window_size + 63)

    def media_information_dialog(self):
        """Show a dialog of the current song's metadata."""
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
        else:
            file_path = None
        dialog = information.InformationDialog(file_path)
        dialog.exec_()

    def change_window_size(self):
        """Change the window size of the music player."""
        self.playlist_dock.close()
        self.library_dock.close()
        self.resize(defaults.Settings().window_size,
                    defaults.Settings().window_size + 63)

    def change_media_library_path(self, path):
        """Change the media library path to the new path selected in the preferences dialog."""
        self.library_model.setRootPath(path)
        self.library_view.setModel(self.library_model)
        self.library_view.setRootIndex(self.library_model.index(path))

    def closeEvent(self, event):
        """Override the PyQt close event in order to handle save playlist on close."""
        playlist = "{}/.m3u".format(self.playlist_location)
        if defaults.Settings().save_playlist_on_close:
            self.playlist.save(QUrl().fromLocalFile(playlist), "m3u")
        else:
            if os.path.exists(playlist):
                os.remove(playlist)
        QApplication.quit()
Exemplo n.º 11
0
class Window(QtWidgets.QDialog):

    def __init__(self):
        super().__init__()
        self.setGeometry(50, 50, 300, 400)
        self.setWindowTitle("Rolev Player")

# LIBRARY ROOT DIR FOLDER
        self.search_label = QtWidgets.QLabel("Select a music folder:", self)
        self.search_label.setGeometry(10, 5, 205, 10)

        self.btn_root_folder = QtWidgets.QPushButton("Browse", self)
        self.btn_root_folder.setGeometry(215, 20, 75, 25)

        # the text field of the currently selected root directory
        self.dir_text_field = QtWidgets.QLineEdit(self)
        self.dir_text_field.setGeometry(10, 20, 200, 25)

        self.btn_root_folder.clicked.connect(self.on_btn_root_folder)

# CURRENT MEDIA LABEL
        self.current_media_label = QtWidgets.QLabel("Now Playing: ", self)
        self.current_media_label.setGeometry(10, 260, 250, 15)

# CURRENT ALBUM COVER
        self.current_album_cover = QtWidgets.QLabel("Image", self)
        self.current_album_cover.setGeometry(10, 180, 75, 75)
        self.current_album_cover.setScaledContents(True)

# ARTIST DROP BOX
        self.artist_select_label = QtWidgets.QLabel("Artist", self)
        self.artist_select_label.setGeometry(10, 50, 250, 25)

        self.artist_select = QtWidgets.QComboBox(self)
        self.artist_select.setGeometry(10, 70, 250, 25)
        self.artist_select.activated[str].connect(self.on_artist_selection)

# ALBUMS DROP BOX
        self.album_select_label = QtWidgets.QLabel("Albums", self)
        self.album_select_label.setGeometry(10, 90, 250, 25)

        self.album_select = QtWidgets.QComboBox(self)
        self.album_select.setGeometry(10, 110, 250, 25)
        self.album_select.activated[str].connect(self.on_album_selection)

# SONGS DROP BOX
        self.song_select_label = QtWidgets.QLabel("Current Playlist", self)
        self.song_select_label.setGeometry(10, 130, 250, 25)

        self.song_select = QtWidgets.QComboBox(self)
        self.song_select.setGeometry(10, 150, 250, 25)
        self.song_select.activated[str].connect(self.on_song_selection)

# PLAYLIST
        self.playlist = QMediaPlaylist()
        self.playlist.currentIndexChanged.connect(self.meta_data_changed)

# MEDIA PLAYER
        self.player = QMediaPlayer()
        self.player.setPlaylist(self.playlist)
        self.player.playlist().setPlaybackMode(QMediaPlaylist.Loop)
        self.player.setVolume(50)

        self.player.durationChanged.connect(self.on_dur_change)
        self.player.positionChanged.connect(self.on_pos_change)

# VOLUME SLIDER
        self.slider_volume_label = QtWidgets.QLabel("Volume", self)
        self.slider_volume_label.setGeometry(10, 345, 50, 25)

        self.slider_volume = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.slider_volume.setGeometry(60, 350, 130, 20)
        self.slider_volume.setRange(0, 100)
        self.slider_volume.setValue(50)
        self.slider_volume.valueChanged.connect(self.volume_change)

# PROGRESS SLIDER
        self.slider_progress_label = QtWidgets.QLabel("Progress", self)
        self.slider_progress_label.setGeometry(10, 315, 50, 25)

        self.slider_progress = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
        self.slider_progress.setGeometry(60, 320, 130, 20)
        self.slider_progress.sliderMoved.connect(self.progress_change)

# LYRICS SEARCH
        self.btn_lyrics = QtWidgets.QPushButton("Search\n Lyrics", self)
        self.btn_lyrics.setGeometry(220, 310, 70, 80)
        self.btn_lyrics.clicked.connect(self.on_lyrics)

# ALBUM INFO SEARCH
        self.btn_album_info = QtWidgets.QPushButton(
            "Search\nAlbum\nInfo", self)
        self.btn_album_info.setGeometry(105, 180, 75, 75)
        self.btn_album_info.clicked.connect(self.on_album_info)

# ARTIST INFO SEARCH
        self.btn_artist_info = QtWidgets.QPushButton(
            "Search\nArtist\nInfo", self)
        self.btn_artist_info.setGeometry(200, 180, 75, 75)
        self.btn_artist_info.clicked.connect(self.on_artist_info)

# PREV SONG BUTTON
        self.btn_prev = QtWidgets.QPushButton("Prev", self)
        self.btn_prev.setGeometry(10, 280, 75, 25)
        self.btn_prev.clicked.connect(self.on_btn_prev)

# NEXT SONG BUTTON
        self.btn_next = QtWidgets.QPushButton("Next", self)
        self.btn_next.setGeometry(200, 280, 75, 25)
        self.btn_next.clicked.connect(self.on_btn_next)

# PLAY/PAUSE BUTTON
        self.btn_play_pause = QtWidgets.QPushButton("Play", self)
        self.btn_play_pause.setGeometry(105, 280, 75, 30)
        self.btn_play_pause.clicked.connect(self.on_btn_play_pause)

        self.show()

    def on_btn_root_folder(self):
        self.root_dir = QtWidgets.QFileDialog().getExistingDirectory()
        self.dir_text_field.setText(self.root_dir)
        self.library = LibraryLoader.load_music_from_dir(
            self.dir_text_field.text())

        self.artist_select.clear()
        self.album_select.clear()
        self.song_select.clear()
        self.playlist.clear()

        self.btn_play_pause.setText("Play")
        self.artist_select.addItem("All Artists")
        for artist in self.library:
            self.artist_select.addItem(artist)
            for album in self.library[artist]:
                self.album_select.addItem(album)
        self.load_all_songs()

    def on_artist_selection(self):
        current_artist = self.artist_select.currentText()

        self.album_select.clear()
        self.song_select.clear()
        self.playlist.clear()

        self.btn_play_pause.setText("Play")
        self.album_select.addItem("All Albums")
        if current_artist == "All Artists":
            for artist in self.library:
                for album in self.library[artist]:
                    self.album_select.addItem(album)
            self.load_all_songs()
        else:
            for album in self.library[current_artist]:
                self.album_select.addItem(album)
            self.load_all_from_artist(current_artist)

    def load_all_songs(self):
        for artist in self.library:
            for album in self.library[artist]:
                for song in self.library[artist][album]:
                    self.song_select.addItem(song[0])
                    self.playlist.addMedia(
                        QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def load_all_from_artist(self, artist):
        for album in self.library[artist]:
            for song in self.library[artist][album]:
                self.song_select.addItem(song[0])
                self.playlist.addMedia(
                    QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def on_album_selection(self):
        current_artist = self.artist_select.currentText()
        current_album = self.album_select.currentText()
        self.song_select.clear()
        self.playlist.clear()
        self.btn_play_pause.setText("Play")
        if current_album == "All Albums" and current_artist == "All Artists":
            self.load_all_songs()

        elif current_album == "All Albums":
            self.load_all_from_artist(current_artist)

        elif current_artist == "All Artists":
            for artist in self.library:
                for album in self.library[artist]:
                    if album == self.album_select.currentText():
                        for song in self.library[artist][album]:
                            self.song_select.addItem(song[0])
                            self.playlist.addMedia(
                                QMediaContent(
                                    QtCore.QUrl.fromLocalFile(song[1])))
        else:
            for song in self.library[current_artist][current_album]:
                self.song_select.addItem(song[0])
                self.playlist.addMedia(
                    QMediaContent(QtCore.QUrl.fromLocalFile(song[1])))

    def on_song_selection(self):
        index = self.song_select.currentIndex()
        self.playlist.setCurrentIndex(index)

# GETTING THE CURRENT SONG METADATA
    # Returns a SONG OBJECT and not the current song title
    # For the title of the currently playing song use get_current_title()
    def get_current_song(self):
        curr_url = self.playlist.currentMedia().canonicalUrl().toString()[8:]
        if curr_url:
            return LibraryLoader.create_song(curr_url)

    def get_current_artist(self):
        if self.get_current_song() is not None:
            return self.get_current_song().artist

    def get_current_album(self):
        if self.get_current_song() is not None:
            return self.get_current_song().album

    def get_current_path(self):
        if self.get_current_song() is not None:
            return self.get_current_song().path

    def get_current_album_path(self):
        if self.get_current_path() is not None:
            return self.get_current_path().rsplit("/", 1)[0]

    def get_current_title(self):
        if self.get_current_song() is not None:
            return self.get_current_song().name

    def on_lyrics(self):
        if self.get_current_song() is not None:
            curr_artist = self.get_current_artist()
            curr_song = self.get_current_title()

            found_lyrics = RequestLyrics.search_song_lyrics(
                curr_artist, curr_song)
            choice = QtWidgets.QMessageBox.question(
                self, "Lyrics", found_lyrics[0],
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
            if choice == QtWidgets.QMessageBox.Yes:
                webbrowser.open(found_lyrics[1])
        else:
            QtWidgets.QMessageBox.information(
                self, "Lyrics", "No lyrics found or no media is loaded!")

    def on_album_info(self):
        album = self.get_current_album()
        artist = self.get_current_artist()
        if (album is None) or (artist is None):
            print("Please, load a song first!")
        else:
            artist_info, album_info = AlbumArtwork.album_artist_info(
                artist, album)
            if album_info is not None:
                webbrowser.open(album_info)

    def on_artist_info(self):
        album = self.get_current_album()
        artist = self.get_current_artist()
        if (album is None) or (artist is None):
            print("Please, load a song first!")
        else:
            artist_info, album_info = AlbumArtwork.album_artist_info(
                artist, album)
            if artist_info is not None:
                webbrowser.open(artist_info)

    def on_btn_play_pause(self):
        if self.player.state() in (0, 2):
            self.player.play()
            if self.player.state() == 1:
                self.btn_play_pause.setText("Pause")
        else:
            self.player.pause()
            self.btn_play_pause.setText("Play")

    def on_btn_next(self):
        self.player.playlist().next()

    def on_btn_prev(self):
        self.player.playlist().previous()

    def on_dur_change(self, length):
        self.slider_progress.setMaximum(length)

    def on_pos_change(self, position):
        self.slider_progress.setValue(position)

    def volume_change(self):
        volume = self.slider_volume.value()
        self.player.setVolume(volume)

    def progress_change(self):
        position = self.slider_progress.value()
        self.player.setPosition(position)

    def meta_data_changed(self):

        now_playing = self.get_current_title()
        self.current_media_label.setText("Now Playing: " + now_playing)

        # Updating the currently playing album cover
        curr_album_path = self.get_current_album_path()
        curr_album = self.get_current_album()
        curr_artist = self.get_current_artist()
        cover_url = AlbumArtwork.album_cover(
            curr_album_path, curr_artist, curr_album)

        self.current_album_cover.setPixmap(QPixmap(cover_url))
        Scrobbler.scrobble(self.get_current_artist(), self.get_current_title())
Exemplo n.º 12
0
class MediaPlayerTab(GalacteekTab):
    statePlaying = QMediaPlayer.PlayingState
    statePaused = QMediaPlayer.PausedState
    stateStopped = QMediaPlayer.StoppedState

    def __init__(self, *args, **kw):
        super(MediaPlayerTab, self).__init__(*args, **kw)

        self.playlistIpfsPath = None
        self.playlist = QMediaPlaylist()
        self.model = ListModel(self.playlist)

        self.playlistsMenu = QMenu(self)
        self.playlistsMenu.triggered.connect(self.onPlaylistsMenu)

        self.pListWidget = QWidget(self)
        self.uipList = ui_mediaplaylist.Ui_MediaPlaylist()
        self.uipList.setupUi(self.pListWidget)
        self.uipList.savePlaylistButton.clicked.connect(self.onSavePlaylist)
        self.uipList.savePlaylistButton.setEnabled(False)
        self.uipList.loadPlaylistButton.setPopupMode(QToolButton.InstantPopup)
        self.uipList.loadPlaylistButton.setMenu(self.playlistsMenu)

        self.clipMenu = QMenu(self)
        self.copyPathAction = QAction(getIconIpfsIce(),
                                      iCopyPlaylistPath(),
                                      self,
                                      triggered=self.onCopyPlaylistPath)
        self.loadPathAction = QAction(getIconIpfsIce(),
                                      iLoadPlaylistFromPath(),
                                      self,
                                      triggered=self.onLoadPlaylistPath)

        self.copyPathAction.setEnabled(False)
        self.clipMenu.addAction(self.copyPathAction)
        self.clipMenu.addAction(self.loadPathAction)

        self.uipList.clipPlaylistButton.setPopupMode(QToolButton.InstantPopup)
        self.uipList.clipPlaylistButton.setMenu(self.clipMenu)
        self.uipList.clearButton.clicked.connect(self.onClearPlaylist)

        self.uipList.nextButton.clicked.connect(self.onPlaylistNext)
        self.uipList.previousButton.clicked.connect(self.onPlaylistPrevious)
        self.uipList.nextButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))
        self.uipList.previousButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipBackward))

        self.pListView = self.uipList.listView
        self.pListView.mousePressEvent = self.playlistMousePressEvent
        self.pListView.setModel(self.model)
        self.pListView.setResizeMode(QListView.Adjust)
        self.pListView.setMinimumWidth(self.width() / 2)

        self.duration = None
        self.playerState = None
        self.player = QMediaPlayer(self)
        self.player.setPlaylist(self.playlist)

        self.videoWidget = MPlayerVideoWidget(self.player, self)
        self.useUpdates(True)
        self.videoWidget.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        self.player.setVideoOutput(self.videoWidget)

        self.player.error.connect(self.onError)
        self.player.stateChanged.connect(self.onStateChanged)
        self.player.metaDataChanged.connect(self.onMetaData)
        self.player.durationChanged.connect(self.mediaDurationChanged)
        self.player.positionChanged.connect(self.mediaPositionChanged)
        self.player.videoAvailableChanged.connect(self.onVideoAvailable)

        self.pListView.activated.connect(self.onListActivated)
        self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.playlist.currentMediaChanged.connect(self.playlistMediaChanged)
        self.playlist.mediaInserted.connect(self.playlistMediaInserted)
        self.playlist.mediaRemoved.connect(self.playlistMediaRemoved)

        self.togglePList = QToolButton(self)
        self.togglePList.setIcon(self.style().standardIcon(
            QStyle.SP_ArrowRight))
        self.togglePList.setFixedSize(32, 128)
        self.togglePList.clicked.connect(self.onTogglePlaylist)

        self.clipboardMediaItem = None
        self.clipboardButton = QToolButton(clicked=self.onClipboardClicked)
        self.clipboardButton.setIcon(getIconClipboard())
        self.clipboardButton.setEnabled(False)
        self.clipboardButton.setToolTip('Load media from clipboard')

        self.pinButton = QToolButton(clicked=self.onPinMediaClicked)
        self.pinButton.setIcon(getIcon('pin.png'))

        self.processClipboardItem(self.app.clipTracker.current, force=True)
        self.app.clipTracker.currentItemChanged.connect(self.onClipItemChange)

        self.playButton = QToolButton(clicked=self.onPlayClicked)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

        self.pauseButton = QToolButton(clicked=self.onPauseClicked)
        self.pauseButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaPause))
        self.pauseButton.setEnabled(False)

        self.stopButton = QToolButton(clicked=self.onStopClicked)
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setEnabled(False)

        self.fullscreenButton = QToolButton(clicked=self.onFullScreen)
        self.fullscreenButton.setIcon(getIcon('fullscreen.png'))
        self.fullscreenButton.setToolTip(iFullScreen())

        self.seekSlider = QSlider(Qt.Horizontal, sliderMoved=self.onSeek)
        self.seekSlider.sliderReleased.connect(self.onSliderReleased)
        self.seekSlider.setObjectName('mediaPlayerSlider')
        self.durationLabel = QLabel()

        vLayout = QVBoxLayout()
        hLayoutControls = QHBoxLayout()
        hLayoutControls.setContentsMargins(0, 0, 0, 0)
        hLayoutControls.addWidget(self.clipboardButton)
        hLayoutControls.addWidget(self.pinButton)
        hLayoutControls.addWidget(self.playButton)
        hLayoutControls.addWidget(self.pauseButton)
        hLayoutControls.addWidget(self.stopButton)
        hLayoutControls.addWidget(self.seekSlider)
        hLayoutControls.addWidget(self.durationLabel)
        hLayoutControls.addWidget(self.fullscreenButton)
        vLayout.addWidget(self.videoWidget)
        vLayout.addLayout(hLayoutControls)

        hLayout = QHBoxLayout()
        hLayout.addLayout(vLayout)
        hLayout.addWidget(self.pListWidget)
        hLayout.addWidget(self.togglePList)

        self.pListWidget.hide()

        self.vLayout.addLayout(hLayout)
        self.update()
        self.videoWidget.changeFocus()

    @property
    def isPlaying(self):
        return self.playerState == self.statePlaying

    @property
    def isPaused(self):
        return self.playerState == self.statePaused

    @property
    def isStopped(self):
        return self.playerState == self.stateStopped

    def useUpdates(self, updates=True):
        # Enable widget updates or not on the video widget
        self.videoWidget.setUpdatesEnabled(updates)

    def update(self):
        self.app.task(self.updatePlaylistsMenu)

    def onFullScreen(self):
        self.videoWidget.viewFullScreen(True)

    def onClearPlaylist(self):
        self.copyPathAction.setEnabled(False)
        self.player.stop()
        self.clearPlaylist()

    def onLoadPlaylistPath(self):
        current = self.app.clipTracker.getCurrent()
        if current:
            self.app.task(self.loadPlaylistFromPath, current.path)

    def onCopyPlaylistPath(self):
        if self.playlistIpfsPath:
            self.app.setClipboardText(self.playlistIpfsPath)

    def onPinMediaClicked(self):
        currentMedia = self.playlist.currentMedia()
        if currentMedia.isNull():
            return messageBox(iNoMediaInPlaylist())

        ensure(self.pinMedia(currentMedia))

    @ipfsOp
    async def pinMedia(self, ipfsop, media):
        mediaUrl = qurlPercentDecode(media.canonicalUrl())
        path = IPFSPath(mediaUrl, autoCidConv=True)

        if path.valid:
            await ipfsop.ctx.pin(str(path), qname='mediaplayer')

    @ipfsOp
    async def updatePlaylistsMenu(self, ipfsop):
        currentList = [
            action.text() for action in self.playlistsMenu.actions()
        ]
        listing = await ipfsop.filesList(self.profile.pathPlaylists)
        for entry in listing:
            if entry['Name'] in currentList:
                continue
            action = QAction(entry['Name'], self)
            action.setData(entry)
            self.playlistsMenu.addAction(action)

    def playlistShowContextMenu(self, event):
        selModel = self.pListView.selectionModel()
        idx = self.pListView.indexAt(event.pos())
        if not idx.isValid():
            return

        path = self.model.data(idx)
        if path:
            selModel.reset()
            selModel.select(idx, QItemSelectionModel.Select)

            menu = QMenu(self)
            menu.addAction(getIcon('clear-all.png'), iPlaylistRemoveMedia(),
                           functools.partial(self.onRemoveMediaFromIndex, idx))
            menu.exec_(event.globalPos())

    def onRemoveMediaFromIndex(self, idx):
        self.playlist.removeMedia(idx.row())

    def playlistMousePressEvent(self, event):
        if event.button() == Qt.RightButton:
            self.pListView.selectionModel().reset()
            self.playlistShowContextMenu(event)
        else:
            if not self.pListView.indexAt(event.pos()).isValid():
                self.deselectPlaylistItems()

            QListView.mousePressEvent(self.pListView, event)

    def onPlaylistsMenu(self, action):
        entry = action.data()
        self.app.task(self.loadPlaylistFromPath, joinIpfs(entry['Hash']))

    def onSavePlaylist(self):
        paths = self.playlistGetPaths()
        listName = inputText(title=iPlaylistName(), label=iPlaylistName())
        if not listName:
            return

        obj = JSONPlaylistV1(listName=listName, itemPaths=paths)
        self.app.task(self.savePlaylist, obj, listName)

    @ipfsOp
    async def savePlaylist(self, ipfsop, obj, name):
        objPath = os.path.join(self.profile.pathPlaylists, name)
        exists = await ipfsop.filesStat(objPath)

        if exists:
            await ipfsop.filesRm(objPath)

        ent = await ipfsop.client.core.add_json(obj.root)

        if ent:
            await ipfsop.filesLinkFp(ent, objPath)
            self.playlistIpfsPath = joinIpfs(ent['Hash'])
            self.copyPathAction.setEnabled(True)

        self.update()

    @ipfsOp
    async def loadPlaylistFromPath(self, ipfsop, path):
        try:
            obj = await ipfsop.jsonLoad(path)
        except Exception:
            return messageBox(iCannotLoadPlaylist())

        if obj is None:
            return messageBox(iCannotLoadPlaylist())

        try:
            # Assume v1 format for now, when the format evolves we'll just
            # use json validation
            pList = JSONPlaylistV1(data=obj)
            self.clearPlaylist()

            for item in pList.items():
                self.queueFromPath(item['path'])

            self.playlistIpfsPath = path
            self.copyPathAction.setEnabled(True)
        except Exception:
            return messageBox(iCannotLoadPlaylist())

    def playlistMediaInserted(self, start, end):
        self.uipList.savePlaylistButton.setEnabled(
            self.playlist.mediaCount() > 0)

    def playlistMediaRemoved(self, start, end):
        self.uipList.savePlaylistButton.setEnabled(
            self.playlist.mediaCount() > 0)

        self.model.modelReset.emit()

    def playlistGetPaths(self):
        return [u.path() for u in self.playlistGetUrls()]

    def playlistGetUrls(self):
        urls = []
        for idx in range(0, self.playlist.mediaCount()):
            media = self.playlist.media(idx)
            urls.append(media.canonicalUrl())
        return urls

    def onClipItemChange(self, item):
        self.processClipboardItem(item)

    def processClipboardItem(self, item, force=False):
        if not item:
            return

        def analyzeMimeType(cItem):
            if cItem.mimeCategory in ['audio', 'video', 'image']:
                self.clipboardMediaItem = cItem
                self.clipboardButton.setEnabled(True)
                self.clipboardButton.setToolTip(cItem.path)
            else:
                self.clipboardButton.setEnabled(False)
                self.clipboardButton.setToolTip(iClipboardEmpty())

        if force:
            analyzeMimeType(item)
        else:
            item.mimeTypeAvailable.connect(lambda mType: analyzeMimeType(item))

    def onClipboardClicked(self):
        if self.clipboardMediaItem:
            self.playFromPath(self.clipboardMediaItem.path)
        else:
            messageBox('Not a multimedia resource')

    def onSliderReleased(self):
        pass

    def onPlaylistNext(self):
        self.playlist.next()

    def onPlaylistPrevious(self):
        self.playlist.previous()

    def onPlayClicked(self):
        self.player.play()

    def onPauseClicked(self):
        if self.isPlaying:
            self.player.pause()
        elif self.isPaused:
            self.player.play()

    def onStopClicked(self):
        self.player.stop()
        self.player.setPosition(0)
        self.seekSlider.setValue(0)
        self.seekSlider.setRange(0, 0)

    def onSeek(self, seconds):
        if self.player.isSeekable():
            self.player.setPosition(seconds * 1000)

    def onTogglePlaylist(self):
        self.pListWidget.setVisible(self.pListWidget.isHidden())

    def onError(self, error):
        messageBox(iPlayerError(error))

    def onStateChanged(self, state):
        self.playerState = state
        self.updateControls(state)

    def updateControls(self, state):
        if self.isStopped:
            self.stopButton.setEnabled(False)
            self.pauseButton.setEnabled(False)
            self.playButton.setEnabled(True)
            self.seekSlider.setEnabled(False)
            self.duration = None
        elif self.isPlaying:
            self.seekSlider.setRange(0, self.player.duration() / 1000)
            self.seekSlider.setEnabled(True)
            self.pauseButton.setEnabled(True)
            self.playButton.setEnabled(False)
            self.stopButton.setEnabled(True)

    def onListActivated(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def onMetaData(self):
        # Unfinished
        if self.player.isMetaDataAvailable():
            availableKeys = self.player.availableMetaData()

            for key in availableKeys:
                self.player.metaData(key)

    def playFromUrl(self, url, mediaName=None):
        if self.isPlaying:
            self.player.stop()

        cUrls = self.playlistGetUrls()
        for u in cUrls:
            if u.toString() == url.toString():
                return messageBox(iAlreadyInPlaylist())

        media = QMediaContent(url)
        if self.playlist.addMedia(media):
            count = self.model.rowCount()
            if count > 0:
                self.playlist.setCurrentIndex(count - 1)

        self.player.play()

    def playFromPath(self, path, mediaName=None):
        mediaUrl = self.app.subUrl(path)
        self.playFromUrl(mediaUrl)

    def queueFromPath(self, path, playLast=False, mediaName=None):
        mediaUrl = self.app.subUrl(path)
        self.playlist.addMedia(QMediaContent(mediaUrl))

        if playLast:
            count = self.playlist.mediaCount()

            if count > 0:
                self.player.stop()
                self.playlist.setCurrentIndex(count - 1)
                self.player.play()

    def clearPlaylist(self):
        self.playlist.clear()
        self.pListView.reset()

    def playlistPositionChanged(self, position):
        self.pListView.setCurrentIndex(self.model.index(position, 0))

    def deselectPlaylistItems(self):
        self.pListView.selectionModel().reset()

    def playlistMediaChanged(self, media):
        selModel = self.pListView.selectionModel()

        self.deselectPlaylistItems()

        self.model.modelReset.emit()
        idx = self.model.index(self.playlist.currentIndex(), 0)
        if idx.isValid():
            selModel.select(idx, QItemSelectionModel.Select)

    def onVideoAvailable(self, available):
        if available:
            if self.isPlaying:
                self.useUpdates(False)
            elif self.isStopped or self.isPaused:
                self.useUpdates(True)
        else:
            self.useUpdates(True)

    def mediaDurationChanged(self, duration):
        self.duration = duration / 1000
        self.seekSlider.setMaximum(self.duration)

    def mediaPositionChanged(self, progress):
        progress /= 1000

        if self.duration:
            cTime = durationConvert(progress)
            tTime = durationConvert(self.duration)
            self.durationLabel.setText('{0} ({1})'.format(
                cTime.toString(), tTime.toString()))

        if not self.seekSlider.isSliderDown():
            self.seekSlider.setValue(progress)

    async def onClose(self):
        self.player.stop()
        self.player.setMedia(QMediaContent(None))
        return True

    def playerAvailable(self):
        return mediaPlayerAvailable(player=self.player)
Exemplo n.º 13
0
class AlarmWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        # Флаг, чтобы функция вызова будильника не вызвыалась с каждым тиком
        self.flag_get_up = True
        # Нулевое время для сброса часов
        self.zero_time = QTime(0, 0)
        # Пустая ссылка
        self.url = QUrl()
        # Инициализируем плеер и плейлист, который после зацикливаем
        self.playlist = QMediaPlaylist(self)
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        self.player = QMediaPlayer()
        # Кнопка для выбора файла с музыкой
        self.btn_getfile = QPushButton('Выбрать файл', self)
        self.btn_getfile.setFont(QFont('Times', 10))
        self.btn_getfile.move(142.5, 25)
        self.btn_getfile.resize(215, 50)
        self.btn_getfile.setVisible(False)
        self.btn_getfile.clicked.connect(self.getfile)
        # Радио-кнопка для включения будильника
        self.radio_btn1 = QRadioButton('вкл', self)
        self.radio_btn1.move(0, 15)
        self.radio_btn1.setFont(QFont('Times', 10))
        self.radio_btn1.toggled.connect(self.on_off)
        # Радио-кнопка для выключения будильника
        self.radio_btn2 = QRadioButton('выкл', self)
        self.radio_btn2.move(0, 40)
        self.radio_btn2.setChecked(True)
        self.radio_btn2.setFont(QFont('Times', 10))
        self.radio_btn2.toggled.connect(self.on_off)
        # Значение будильника
        self.timer_edit = QTimeEdit(self)
        self.timer_edit.setDisplayFormat('hh:mm')
        self.timer_edit.move(200, 110)
        self.timer_edit.resize(100, 50)
        self.timer_edit.setFont(QFont('Times', 18, QFont.Bold))
        self.timer_edit.setVisible(False)
        # Бирка
        self.lbl = QLabel('Будильник:', self)
        self.lbl.move(0, 0)
        self.lbl.setFont(QFont('Times', 10))
        # Подсказка для кнопки выбора мелодии
        self.lbl2 = QLabel('Выберите мелодию для будильника:', self)
        self.lbl2.move(142.5, 0)
        self.lbl2.setVisible(False)
        self.lbl2.setFont(QFont('Times', 10))
        # Бирка
        self.lbl3 = QLabel('Будильник установлен на:', self)
        self.lbl3.move(175, 185)
        self.lbl3.setFont(QFont('Times', 10))
        self.lbl3.setVisible(False)
        # Бирка
        self.lbl4 = QLabel('Установите время будильника:', self)
        self.lbl4.move(150, 85)
        self.lbl4.setFont(QFont('Times', 10))
        self.lbl4.setVisible(False)
        # Кнопка выключения будильника, когда он сработает
        self.btn = QPushButton('Выключить\nбудильник', self)
        self.btn.clicked.connect(self.awake)
        self.btn.resize(100, 100)
        self.btn.move(200, 200)
        self.btn.setFont(QFont('Times', 11, QFont.ExtraBold))
        self.btn.setVisible(False)
        # Дисплей для вывода значения будильника
        self.dis2 = QLCDNumber(self)
        self.dis2.move(200, 210)
        self.dis2.resize(100, 50)
        self.dis2.setVisible(False)
        # Дисплей с текущим временем
        self.dis1 = QLCDNumber(self)
        self.dis1.move(375, 25)
        self.dis1.resize(100, 50)
        # Бирка
        self.lbl5 = QLabel('Сейчас:', self)
        self.lbl5.move(375, 0)
        self.lbl5.setFont(QFont('Times', 10))
        # Таймер
        self.nTimer = QTimer()
        self.nTimer.timeout.connect(self.repeatTime)
        self.nTimer.start()

    def initUI(self):
        self.setGeometry(100, 100, 500, 500)
        self.setWindowTitle('Будильник')

    def repeatTime(self):
        # Вытаскиваем системное время и преобразуем в строку
        self.time = QTime().currentTime()
        time_text = self.time.toString('hh:mm')
        # Вытаскиваем выставленное значение будильника и преобразуем в строку
        timer = self.timer_edit.time()
        timer_text = timer.toString('hh:mm')
        # Выводим значения будильника на дисплей
        self.dis2.display(timer_text)
        # Выводим текущее время
        self.dis1.display(time_text)
        # Проверяем условия срабатывания будильника
        if timer_text == time_text and self.flag_get_up and self.radio_btn1.isChecked(
        ):
            self.flag_get_up = False
            self.get_up()
        else:
            self.flag_get_up = True

    def awake(self):
        # Устанавливаем нулевое значение времени будильника
        self.timer_edit.setTime(self.zero_time)
        # Махинация с показом виджетов
        self.lbl.setVisible(True)
        self.lbl2.setVisible(True)
        self.lbl3.setVisible(True)
        self.lbl4.setVisible(True)
        self.radio_btn1.setVisible(True)
        self.radio_btn2.setVisible(True)
        self.btn_getfile.setVisible(True)
        self.dis2.setVisible(True)
        self.timer_edit.setVisible(True)
        self.btn.setVisible(False)
        # Останавливаем музыку
        self.player.stop()

    def get_up(self):
        # Махинации с показом виджетов
        self.lbl.setVisible(False)
        self.lbl2.setVisible(False)
        self.lbl3.setVisible(False)
        self.lbl4.setVisible(False)
        self.radio_btn1.setVisible(False)
        self.radio_btn2.setVisible(False)
        self.btn_getfile.setVisible(False)
        self.dis2.setVisible(False)
        self.timer_edit.setVisible(False)
        self.btn.setVisible(True)
        # Включаем музыку
        self.player.play()

    def getfile(self):
        # Достаем файл с мелодией и сохраняем её путь
        fname = QFileDialog.getOpenFileName(self, 'Open File', '/home',
                                            'Audio Files (*mp3 *wav)')
        self.url = QUrl.fromLocalFile(fname[0])
        # Устанавливаем музыку в плеер
        self.content = QMediaContent(self.url)
        self.playlist.clear()
        self.playlist.addMedia(self.content)
        self.player.setPlaylist(self.playlist)

    def on_off(self):
        # Включаем/выключаем будильник
        if self.radio_btn1.isChecked():
            self.btn_getfile.setVisible(True)
            self.timer_edit.setVisible(True)
            self.dis2.setVisible(True)
            self.lbl2.setVisible(True)
            self.lbl3.setVisible(True)
            self.lbl4.setVisible(True)
        else:
            self.btn_getfile.setVisible(False)
            self.timer_edit.setVisible(False)
            self.dis2.setVisible(False)
            self.lbl2.setVisible(False)
            self.lbl3.setVisible(False)
            self.lbl4.setVisible(False)
            self.timer_edit.setTime(self.zero_time)
            self.btn.setVisible(False)
            self.player.stop()
class SoundPlayerWorker(QObject):
    def __init__(self, args=(), kwargs=None):
        super().__init__()
        self.media_player = QMediaPlayer(flags=QMediaPlayer.LowLatency)
        self.playlist = QMediaPlaylist()
        self.media_player.setPlaylist(self.playlist)
        self._priority = 0
        # For play on non-Windows platforms:
        mixer.init()
        self.pygame_player = mixer.music

    def play_sound(self, file="", priority=0, override=False):
        """
        Method to add a new sound to play
        :param file: str
        :param override:
        :return:
        """

        # logging.info(f"file: {file}, priority: {priority}, self._priority: {self._priority}")

        if priority > self._priority:
            self.media_player.stop()
            self.playlist.clear()
            self._priority = priority

        if override:
            self.media_player.stop()
            self.playlist.clear()

        # logging.info(f"request to play: {file}, override set to: {override}, mediaCount: {self.playlist.mediaCount()}")

        if ObserverUtility.platform_is_windows():
            self.playlist.addMedia(QMediaContent(QUrl(file)))

            # logging.info(f"request to play, after adding file: {file}, override set to: {override}, mediaCount: {self.playlist.mediaCount()}")

            if self.media_player.state() == 0:
                self.media_player.play()
        else:
            # Note: Sound play on non-Windows is not using QMediaPlayer, which does not appear
            # to work on MacOS, at least not out of the box. Using python package pygame instead.
            self._pygame_play_sound(file)

    def _pygame_play_sound(self, sound_file):
        """ Play a WAV or MP3 sound file using the pygame python package. """
        self.pygame_player.load(sound_file)
        self.pygame_player.play()

        logging.info(f"Pygame: played sound file {sound_file}. ")

    def state_changed(self):
        """
        Method called when the media_player state is changed
        :return: 
        """
        if self.media_player.state() == 0:
            self._priority = 0

    def check_playlist_index(self):
        """
        Method to check to see if we've reached the end of the playlist or not
        :return:
        """
        if self.playlist.currentIndex() == -1:
            self.playlist.clear()

    def stop(self):
        """
        Method to stop the sound from playing any further
        :return:
        """
        self.media_player.stop()
Exemplo n.º 15
0
class MyWindow(QMainWindow):
    text_update = pyqtSignal(str)

    # Create main window
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.central = QWidget(self)

        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.inference = Inference()
        self.folder_chosen = False
        self.textbox = QTextEdit(self.central)
        self.textbox.setFont(TEXT_FONT)
        self.textbox.setMinimumSize(300, 100)
        self.text_update.connect(self.append_text)
        sys.stdout = self
        print("Camera number %u" % camera_num)
        print("Image size %u x %u" % IMG_SIZE)
        if DISP_SCALE > 1:
            print("Display scale %u:1" % DISP_SCALE)

        self.vlayout = QVBoxLayout()        # Window layout
        self.displays = QHBoxLayout()
        self.disp = ImageWidget(self)
        self.displays.addWidget(self.disp)
        self.vlayout.addLayout(self.displays)
        self.label = QLabel(self)
        self.vlayout.addWidget(self.label)
        self.vlayout.addWidget(self.textbox)

        # TODO provision for allowing song to play
        # DONE
        self.current_song_start_time = datetime.now()

        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(100)

        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        stopBtn = QPushButton('Stop')  # stop button

        # Add playlist controls
        prevBtn = QPushButton('Prev')
        shuffleBtn = QPushButton('Shuffle')
        nextBtn = QPushButton('Next')

        # Add button layouts
        #controlArea = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()

        # Add buttons to song controls layout
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)

        # Add buttons to playlist controls layout
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(shuffleBtn)
        playlistCtrlLayout.addWidget(nextBtn)

        # Add to vertical layout
        self.vlayout.addWidget(volumeslider)
        self.vlayout.addLayout(controls)
        self.vlayout.addLayout(playlistCtrlLayout)

        self.central.setLayout(self.vlayout)

        #self.central.setLayout(controlArea)

        self.setCentralWidget(self.central)

        # Connect each signal to their appropriate function
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        shuffleBtn.clicked.connect(self.shufflelist)
        nextBtn.clicked.connect(self.nextSong)

        self.statusBar()
        self.playlist.currentMediaChanged.connect(self.songChanged)

        self.mainMenu = self.menuBar()      # Menu bar
        exitAction = QAction('&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.triggered.connect(self.close)
        self.fileMenu = self.mainMenu.addMenu('&File')

        fileAct = QAction('Open File', self)
        folderAct = QAction('Open Folder', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')

        self.fileMenu.addAction(fileAct)
        self.fileMenu.addAction(folderAct)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)

        self.fileMenu.addAction(exitAction)


        #self.addControls()

    # Start image capture & display
    def start(self):
        self.timer = QTimer(self)           # Timer to trigger display
        self.timer.timeout.connect(lambda:
                    self.show_image(image_queue, self.disp, DISP_SCALE))
        self.timer.start(DISP_MSEC)
        self.capture_thread = threading.Thread(target=grab_images,
                    args=(camera_num, image_queue))
        self.capture_thread.start()         # Thread to grab images

    # Fetch camera image from queue, and display it
    def show_image(self, imageq, display, scale):
        if not imageq.empty():
            image = imageq.get()
            if image is not None and len(image) > 0:
                img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

                self.display_image(img, display, scale)

    # Display an image, reduce size if required
    def display_image(self, img, display, scale=1):
        disp_size = img.shape[1]//scale, img.shape[0]//scale
        disp_bpl = disp_size[0] * 3
        if scale > 1:
            img = cv2.resize(img, disp_size,
                             interpolation=cv2.INTER_CUBIC)

            global PREDICTION_STATUS
            if PREDICTION_STATUS != -1:
                # print(PREDICTION_STATUS)
                self.handle_inference(PREDICTION_STATUS)
            # img_try = cv2.imread('test_image.jpg')
            # img_try = cv2.cvtColor(img , cv2.COLOR_BGR2RGB)
            # self.inference.perform_inference(img)
            # if self.inference.network.wait() == 0 :
            #     result = self.inference.network.extract_output()
            #     pred = np.argmax(result[0, :])
            #     print(pred)
            #     self.handle_inference(  pred  )

        qimg = QImage(img.data, disp_size[0], disp_size[1],
                      disp_bpl, IMG_FORMAT)
        display.setImage(qimg)

    # Handle sys.stdout.write: update text display
    def write(self, text):
        self.text_update.emit(str(text))
    def flush(self):
        pass

    def check_song_is_playing(self):
        if  (datetime.now()  - self.current_song_start_time ).seconds >= 4:
            return False
        else:
            return True
    def handle_inference(self, result):
        if self.folder_chosen == True  and self.check_song_is_playing() == False:
            global PREDICTION_STATUS
            if result == 1:
                #self.pausehandler()

                PREDICTION_STATUS = -1
                pass
            elif result == 5:
                self.playhandler()
            elif result == 0:
                #self.stophandler()
                PREDICTION_STATUS = -1
                pass
            elif result == 4:
                PREDICTION_STATUS = -1
            elif result == 2:
                self.prevSong()
            elif result == 3:
                self.nextSong()

    # Append to text display
    def append_text(self, text):
        cur = self.textbox.textCursor()     # Move cursor to end of text
        cur.movePosition(QTextCursor.End)
        s = str(text)
        while s:
            head,sep,s = s.partition("\n")  # Split line at LF
            cur.insertText(head)            # Insert text at cursor
            if sep:                         # New line if LF
                cur.insertBlock()
        self.textbox.setTextCursor(cur)     # Update visible cursor

    # Window is closing: stop video capture
    def closeEvent(self, event):
        global capturing
        capturing = False
        self.capture_thread.join()

    def openFile(self):
        song = QFileDialog.getOpenFileName(self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()

            else:
                self.playlist.addMedia(QMediaContent(url))


    def addFiles(self):
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()

    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, 'Open Music Folder', '~')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                        self.folder_chosen = True
                it.next()
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)

            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                    self.folder_chosen = True



    def playhandler(self):

        if self.playlist.mediaCount() == 0:
            self.folder_chosen = False
            self.addFiles()

        elif self.playlist.mediaCount() != 0:
            self.player.play()
            self.current_song_start_time = datetime.now()
        global PREDICTION_STATUS
        PREDICTION_STATUS = -1




    def pausehandler(self):
        print('Stopped and cleared playlist')
        self.player.pause()
        global PREDICTION_STATUS
        PREDICTION_STATUS = -1

    def stophandler(self):
        self.folder_chosen = False
        self.player.stop()
        self.playlist.clear()
        print('Stopped and cleared playlist')
        self.statusBar().showMessage("Stopped and cleared playlist")
        global PREDICTION_STATUS
        PREDICTION_STATUS = -1

    def changeVolume(self, value):
        self.player.setVolume(value)

    def prevSong(self):
        print('playing previous song')
        if self.playlist.mediaCount() == 0:
            self.folder_chosen = False
            self.addFiles()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().previous()
            self.current_song_start_time = datetime.now()
        global PREDICTION_STATUS
        PREDICTION_STATUS = -1

    def shufflelist(self):
        self.playlist.shuffle()


    def nextSong(self):
        print('playing next song')
        if self.playlist.mediaCount() == 0:
            self.folder_chosen = False
            self.addFiles()

        elif self.playlist.mediaCount() != 0:
            self.player.playlist().next()
            self.current_song_start_time = datetime.now()
        global PREDICTION_STATUS
        PREDICTION_STATUS = -1

    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            print('Now playing  ' +url.fileName())
            self.statusBar().showMessage(url.fileName())
Exemplo n.º 16
0
class DirectoryPlaylist(Playlist):

    def __init__(self, parent=None):
        super(DirectoryPlaylist, self).__init__(parent)

        self._directories_urls = set()
        self._added_song_urls = set()
        self._tracks = []

        self._qPlaylist = QMediaPlaylist(parent)
        self._qPlaylist.mediaAboutToBeInserted.connect(
            lambda s, e: self.mediaAboutToBeInserted.emit(s, e))
        self._qPlaylist.mediaInserted.connect(
            lambda s, e: self.mediaInserted.emit(s, e))
        self._qPlaylist.mediaAboutToBeRemoved.connect(
            lambda s, e: self.mediaAboutToBeRemoved.emit(s, e))
        self._qPlaylist.mediaRemoved.connect(
            lambda s, e: self.mediaRemoved.emit(s, e))
        self._qPlaylist.mediaChanged.connect(
            lambda s, e: self.mediaChanged.emit(s, e))

    def songs(self):
        return self._tracks

    def albums_data(self):
        return self._albumsData

    def artists_data(self):
        return self._artistsData

    def __traverse_directory(self, url, func):
        songs = []
        for root, dirs, files in os.walk(url):
                for file in files:
                    abs_path = os.path.join(root, file)
                    song = func(abs_path)
                    if song:
                        songs.append(song)
        return songs

    def is_empty(self):
        return not self._tracks

    def add_song(self, abs_path):
        if abs_path not in self._added_song_urls:
            url = QtCore.QUrl.fromLocalFile(abs_path)
            song = MediaFactory.create_media(abs_path)
            if not song:
                return None
            added = self._qPlaylist.addMedia(QMediaContent(url))
            if not added:
                return None

            self._tracks.append(song)
            self._added_song_urls.add(abs_path)
            return song

    def remove_song(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None

        if self._qPlaylist.currentIndex() == row:
            if row < self.song_count():
                self._qPlaylist.setCurrentIndex(row + 1)
            else:
                self._qPlaylist.setCurrentIndex(row - 1)

        removed = self._qPlaylist.removeMedia(row)
        if not removed:
            return

        del self._tracks[row]
        url = self.get_song_abs_path(row)
        self._added_song_urls.discard(url)

    def add_directory(self, directory):
        if directory not in self._directories_urls:
            self._directories_urls.add(directory)
            songs = self.__traverse_directory(directory, self.add_song)
            return songs
        return None

    def add_directories(self, directories):
        songs = []
        for directory in directories:
            if directory not in self._directories_urls:
                current_songs = self.add_directory(directory)
                if current_songs:
                    songs.extend(current_songs)
        return songs

    def remove_directory(self, directory):
        if directory not in self._directories_urls:
            return False  # raise Error

        self.__traverse_directory(directory, self.remove_song)

    def setCurrentIndex(self, index):
        self._qPlaylist.setCurrentIndex(index)

    def getCurrentIndex(self):
        return self._qPlaylist.currentIndex()

    def getCurrentSong(self):
        return self._qPlaylist.currentMedia()

    def clear(self):
        self._tracks = []
        self._directories_urls = set()
        self._added_song_urls = set()
        self._qPlaylist.clear()

    @property
    def internalPlaylist(self):
        return self._qPlaylist

    def song_count(self):
        return len(self._tracks)

    def get_song_metadata(self, row, tags):
        if row < 0 or row > self.song_count() - 1:
            return None
        if not isinstance(tags, list):
            tags = [tags]
        return self._tracks[row].get_values(tags)

    def get_song(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None

        return self._tracks[row]

    def get_song_title(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None
        k, v = self.get_song_metadata(row, 'title').popitem()
        try:
            return v[0]
        except IndexError:
            return None

    def get_song_album(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None
        k, v = self.get_song_metadata(row, 'album').popitem()
        try:
            return v[0]
        except IndexError:
            return None

    def get_song_artist(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None

        k, v = self.get_song_metadata(row, 'artist').popitem()
        try:
            return v[0]
        except IndexError:
            return None

    def get_song_genre(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None

        k, v = self.get_song_metadata(row, 'genre').popitem()
        try:
            return v[0]
        except IndexError:
            return None

    def get_song_abs_path(self, row):
        if row < 0 or row > self.song_count() - 1:
            return None

        return self._tracks[row].get_abs_path()

    def getDirectories(self):
        return self._directories_urls

    def getAddedSongUrls(self):
        return self._added_song_urls

    def __str__(self):
        return str(self._tracks)

    def __eq__(self, other):
        return (isinstance(other, self.__class__) and
                self._directories_urls == other._directories_urls and
                self._added_song_urls == other._added_song_urls)
Exemplo n.º 17
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.title = 'JPR Reader GUI version2'
        self.left = 50
        self.top = 100
        self.width = 1200
        self.height = 800
        self.fileReady = False
        self.tableRow = 5
        self.tableCol = 15
        self.row = 2
        self.audiolist = []
        self.configFile = ".//configurationFile.xlsx"
        self.dict = {
            'num': None,
            'partner': None,
            'parcel': None,
            'exception': None,
            'box': None
        }
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # menu
        menubar = self.menuBar()
        filemenu = menubar.addMenu('File')
        fileAct = QAction('Open File', self)
        fileAct.setShortcut('Ctrl+O')
        filemenu.addAction(fileAct)
        fileAct.triggered.connect(self.openFileNameDialog)

        # status_bar
        self.statusbar = self.statusBar()

        # tabs
        self.tabs = QTabWidget()
        self.tab1 = QWidget(self)
        self.tab2 = QWidget(self)
        self.tabs.addTab(self.tab1, "조작")
        self.tabs.addTab(self.tab2, "설정")
        self.setCentralWidget(self.tabs)

        # tab1 gui
        self.ButtonGroupBox = self.createButtonGroupBox()
        self.createLogTable()
        self.tab1.layout = QVBoxLayout()
        self.tab1.layout.addWidget(self.ButtonGroupBox)
        self.tab1.layout.addWidget(self.logTable)
        self.tab1.setLayout(self.tab1.layout)

        # tab2 gui
        self.explanation = QLabel()
        self.explanation.setText("""<<< JPR reader 설정 테이블 >>>    
            이곳에서 JPR reader가 읽어주는 항목과 아이템을 설정할 수 있습니다.
            항목과 아이템의 설정 방법은 셀을 더블 클릭한 후 이름을 입력하는 방식으로진행됩니다.
            그 후 떠오른 파일 탐색기에서 지정할 mp3파일을 선택해 주세요.
            설정의 확인은 셀의 색으로 확인 가능합니다. 지정이 완료된 항목은 노란색, 아이템은 하늘색으로 표시됩니다.
            지정이 되지 않은 셀은 빨간색으로 표시됩니다. 행과 열 버튼으로 테이블의 크기를 조절할 수 있으며
            초기화시 모든 설정은 사라지며 테이블은 5by5로 초기화 됩니다.

            <<<주의사항>>>
            1. 첫번째 열은 반드시 항목을 입력해 주세요.
            2. 입력되는 이름은 엑셀파일에서 표현된 명칭과 완벽히 일치해야 합니다.(엔터나 스페이스, 오타 주의!)
            3. 초기화를 누르면 처음부터 모든 항목과 아이템을 지정해야 합니다.
            4. 엑셀 파일의 ()나 /을 통해 구분한 아이템은 따로 입력해 주세요.
            5. 사용하는 엑셀파일의 구조를 유지해 주세요. 변경시 프로그램의 수정이 필요할 수 있습니다.(예: '박스'항목은 항상 있을 것으로 간주됩니다.)

            제작자 정보: 김현우([email protected])""")
        self.explanation.setAlignment(Qt.AlignCenter)
        self.createConfigTable()
        self.createHorizontalButtons2()
        self.tab2.layout = QVBoxLayout()
        self.tab2.layout.addWidget(self.explanation)
        self.tab2.layout.addWidget(self.configTable)
        self.tab2.layout.addWidget(self.horizontalButtons2)
        self.tab2.setLayout(self.tab2.layout)

        # Show widget
        self.show()

    def openFileNameDialog(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open file", "",
                                                  "All Files (*)")
        if not fileName:
            self.statusbar.showMessage('Fail to load file...')

        else:
            self.wb = load_workbook(fileName.strip())
            self.ws = self.wb.active
            self.fileReady = True
            self.row = 2
            self.statusbar.showMessage('succeed to load file...')
            self.logTable.clear()

            # set logTable's horizontal header
            self.logTable.setHorizontalHeaderItem(0, QTableWidgetItem("포장순번"))
            self.logTable.setHorizontalHeaderItem(1, QTableWidgetItem("거래처명"))
            self.logTable.setHorizontalHeaderItem(2, QTableWidgetItem("배송센터"))
            self.logTable.setHorizontalHeaderItem(3, QTableWidgetItem("특이사항"))
            self.logTable.setHorizontalHeaderItem(4, QTableWidgetItem("박스"))

            # initialize dictionary
            self.dict = {
                'num': None,
                'partner': None,
                'parcel': None,
                'exception': None,
                'box': None
            }
            col = 6
            num = 0
            header = str(self.ws.cell(row=1, column=col + 1).value).strip()
            while header != 'None':
                self.dict[header] = None
                col = col + 1
                num = num + 1
                header = str(self.ws.cell(row=1, column=col + 1).value).strip()

            self.tableCol = 5 + num
            self.logTable.setColumnCount(self.tableCol)

            for c in range(5, self.tableCol):
                self.logTable.setHorizontalHeaderItem(
                    c, QTableWidgetItem(list(self.dict.keys())[c]))

    def createButtonGroupBox(self):
        buttonGroupBox = QGroupBox("Controller")
        vLayout = QVBoxLayout()

        pre_button = QPushButton('w', self)
        pre_button.clicked.connect(self.pre_click)
        pre_button.setIcon(QIcon('.\\img\\up-arrow.png'))
        pre_button.setIconSize(QSize(600, 100))
        pre_button.setShortcut('w')
        vLayout.addWidget(pre_button)

        hBottensWidget = self.createHButtons()
        vLayout.addWidget(hBottensWidget)

        next_button = QPushButton('x', self)
        next_button.clicked.connect(self.next_click)
        next_button.setIcon(QIcon('.\\img\\down-arrow.png'))
        next_button.setIconSize(QSize(600, 100))
        next_button.setShortcut('x')
        vLayout.addWidget(next_button)

        buttonGroupBox.setLayout(vLayout)

        return buttonGroupBox

    def createHButtons(self):
        hBottensWidget = QWidget()
        hLayout = QHBoxLayout()

        back_button = QPushButton('a', self)
        back_button.clicked.connect(self.back_click)
        back_button.setIcon(QIcon('.\\img\\left-arrow.png'))
        back_button.setIconSize(QSize(200, 150))
        back_button.setShortcut('a')
        hLayout.addWidget(back_button)

        cur_button = QPushButton('s', self)
        cur_button.clicked.connect(self.cur_click)
        cur_button.setIcon(QIcon('.\\img\\reload.png'))
        cur_button.setIconSize(QSize(200, 150))
        cur_button.setShortcut('s')
        hLayout.addWidget(cur_button)

        forward_button = QPushButton('d', self)
        forward_button.clicked.connect(self.forward_click)
        forward_button.setIcon(QIcon('.\\img\\right-arrow.png'))
        forward_button.setIconSize(QSize(200, 150))
        forward_button.setShortcut('d')
        hLayout.addWidget(forward_button)

        hBottensWidget.setLayout(hLayout)

        return hBottensWidget

    def createHorizontalButtons2(self):
        self.horizontalButtons2 = QGroupBox("설정 변경")
        layout = QHBoxLayout()

        plusRowButton = QPushButton('행+', self)
        plusRowButton.clicked.connect(self.plus_row)
        layout.addWidget(plusRowButton)

        plusColButton = QPushButton('열+', self)
        plusColButton.clicked.connect(self.plus_col)
        layout.addWidget(plusColButton)

        init_button = QPushButton('초기화', self)
        init_button.clicked.connect(self.initialize)
        layout.addWidget(init_button)

        self.horizontalButtons2.setLayout(layout)

    def createLogTable(self):
        # Create table
        self.logTable = QTableWidget()
        self.logTable.setRowCount(self.tableRow)
        self.logTable.setColumnCount(self.tableCol)
        self.logTable.move(0, 0)

    def createConfigTable(self):
        self.configTable = QTableWidget()

        try:
            # load configurationFile
            cwb = load_workbook(self.configFile.strip())
        except:
            # message box
            string = "설정파일을 불러올 수 없습니다."
            QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                 QMessageBox.Ok)

        else:
            # Get matadata
            cws = cwb.active
            self.crow = cws.cell(row=1, column=1).value
            self.ccol = cws.cell(row=1, column=2).value

            # Configure table
            self.configTable.setRowCount(self.crow)
            self.configTable.setColumnCount(self.ccol)
            self.configTable.move(0, 0)

            # Load data from configFile
            for i in range(self.crow):
                for j in range(self.ccol):
                    item = str(cws.cell(row=i + 2, column=j + 1).value).strip()
                    if item == 'None':
                        item = ''
                    self.configTable.setItem(i, j, QTableWidgetItem(item))

            # check if files exist
            arr = listdir('./audio_clips')
            for row in range(self.crow):
                for col in range(self.ccol):
                    # if 박스(0,0)
                    if row == 0 and col == 0:
                        continue

                    # reset backgound color
                    self.configTable.item(row,
                                          col).setBackground(QColor(255, 0, 0))

                    # if file exist, change background color
                    fname = str(row) + '_' + str(col) + '.mp3'
                    if fname in arr:
                        if row == 0:
                            self.configTable.item(row, col).setBackground(
                                QColor(255, 255, 0))
                        else:
                            self.configTable.item(row, col).setBackground(
                                QColor(0, 255, 255))

            # 박스(0,0)
            self.configTable.setItem(0, 0, QTableWidgetItem('박스'))
            self.configTable.item(0, 0).setBackground(QColor(255, 255, 255))

            # link the callback function
            self.configTable.itemDoubleClicked.connect(self.item_doubleClicked)
            self.configTable.itemChanged.connect(self.item_changed)

    def setLogTable(self):
        # shifting other rows
        for r in range(1, self.tableRow):
            for c in range(self.tableCol):
                try:
                    self.logTable.item(r,
                                       c).setBackground(QColor(255, 255, 255))
                    self.logTable.setItem(r - 1, c,
                                          self.logTable.item(r, c).clone())
                except:
                    pass

        # set current row
        for idx, key in enumerate(list(self.dict.keys())):
            if type(self.dict[key]) is list:
                self.logTable.setItem(
                    self.tableRow - 1, idx,
                    QTableWidgetItem(' '.join(self.dict[key])))
                self.logTable.item(self.tableRow - 1,
                                   idx).setBackground(QColor(255, 255, 0))
            else:
                self.logTable.setItem(self.tableRow - 1, idx,
                                      QTableWidgetItem(self.dict[key]))
                self.logTable.item(self.tableRow - 1,
                                   idx).setBackground(QColor(255, 255, 0))

    def read(self):

        # 포장 순번
        self.dict['num'] = str(self.ws.cell(row=self.row,
                                            column=3).value[2:]).strip()

        # 거래처명
        self.dict['partner'] = str(self.ws.cell(row=self.row,
                                                column=5).value).strip()

        # 배송센터
        self.dict['parcel'] = str(self.ws.cell(row=self.row,
                                               column=4).value).strip()

        # 특이사항
        self.dict['exception'] = str(
            self.ws.cell(row=self.row, column=6).value).strip()

        # 박스
        self.dict['box'] = str(self.ws.cell(row=self.row,
                                            column=2).value).strip()

        # left things
        print(len(self.dict))
        for i in range(5, len(self.dict)):
            header = str(self.ws.cell(row=1, column=i + 2).value).strip()
            self.dict[header] = str(
                self.ws.cell(row=self.row, column=i + 2).value).strip()
            self.parsing(header, self.dict[header])

        print(self.dict)
        self.setLogTable()

    def parsing(self, key, val):
        if val == 'None' or val == '':
            self.dict[key] = None

        else:
            if '(' in val or '/' in val:
                arr = re.split('[(/]', val)
                for i in range(len(arr)):
                    if ')' in arr[i]:
                        arr[i] = arr[i][:arr[i].index(')')]
                    arr[i] = arr[i].strip()
                self.dict[key] = arr

            else:
                self.dict[key] = val

    def itemFromKeyVal(self, key, val):
        items = self.configTable.findItems(val, Qt.MatchExactly)
        if len(items) <= 0:
            # Error
            string = '(' + key + ', ' + val + ') ' + '아이템을 찾을 수 없습니다.'
            QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                 QMessageBox.Ok)
        else:
            for item in items:
                if self.configTable.item(0, item.column()).data(0) == key:
                    return item

    def load_audiolist(self):
        for key, val in self.dict.items():

            # 포장순번
            if key == 'num':
                for i in range(len(self.dict['num'])):
                    self.audiolist.append('_' + val[i])

                # beep
                self.audiolist.append('_beep')

            # 택배발송
            elif key == 'parcel':
                if val == '택배발송':
                    self.audiolist.append('_택배발송')

                    # beep
                    self.audiolist.append('_beep')

            # 박스
            elif key == 'box':
                item = self.itemFromKeyVal('박스', val)
                if item:
                    self.audiolist.append(
                        str(item.row()) + '_' + str(item.column()))

                    # beep
                    self.audiolist.append('_beep')

            elif key in ['partner', 'exception']:
                pass

            # general case
            else:
                # The case(val == None) will be ignored
                if val == None:
                    pass

                # when val is list
                elif type(val) == list:
                    for idx, eachVal in enumerate(val):
                        item = self.itemFromKeyVal(key, eachVal)
                        if item:
                            if idx == 0:
                                self.audiolist.append(
                                    '0_' + str(item.column()))  # key
                            self.audiolist.append(
                                str(item.row()) + '_' +
                                str(item.column()))  # val

                    # beep
                    self.audiolist.append('_beep')

                # when val is not list
                else:
                    item = self.itemFromKeyVal(key, val)
                    if item:
                        if val == '1' or key == val:
                            self.audiolist.append('0_' +
                                                  str(item.column()))  # key
                        else:
                            self.audiolist.append('0_' +
                                                  str(item.column()))  # key
                            self.audiolist.append(
                                str(item.row()) + '_' +
                                str(item.column()))  # val

                        # beep
                        self.audiolist.append('_beep')

        print(self.audiolist)

    def speak(self):
        self.playlist.clear()
        for clip in self.audiolist:
            url = QUrl.fromLocalFile('./audio_clips/' + clip + '.mp3')
            #print(url)
            self.playlist.addMedia(QMediaContent(url))
        self.player.setPlaylist(self.playlist)
        self.player.play()

#----------------------- Control button callback -----------------------#

    @pyqtSlot()
    def pre_click(self):
        if not self.fileReady:
            self.cur_click()

        else:
            if self.row == 2:
                self.statusbar.showMessage("Can't be previous.")
            else:
                self.row -= 1

            self.dict = self.dict.fromkeys(self.dict, None)
            del self.audiolist[:]
            self.read()
            self.load_audiolist()
            self.speak()

    @pyqtSlot()
    def cur_click(self):
        if not self.fileReady:
            string = '파일이 준비되어 있지 않습니다.'
            QMessageBox.question(self, '경고', string, QMessageBox.Ok,
                                 QMessageBox.Ok)
            self.openFileNameDialog()
        else:

            self.dict = self.dict.fromkeys(self.dict, None)
            del self.audiolist[:]
            self.read()
            self.load_audiolist()
            self.speak()

    @pyqtSlot()
    def next_click(self):
        if not self.fileReady:
            self.cur_click()

        else:
            if self.row == self.ws.max_row:
                self.statusbar.showMessage("It's over.")
            else:
                self.row += 1

            self.dict = self.dict.fromkeys(self.dict, None)
            del self.audiolist[:]
            self.read()
            self.load_audiolist()
            self.speak()

    @pyqtSlot()
    def back_click(self):
        if self.playlist.mediaCount() == 0:
            self.cur_click()
        elif self.playlist.mediaCount() != 0:
            p = re.compile('.+_beep.+')
            cnt = 0
            for i in range(self.playlist.mediaCount()):
                # if it's start point, start at here
                if self.playlist.currentIndex() == 0:
                    break
                # go backward
                self.playlist.setCurrentIndex(self.playlist.previousIndex(1))

                # start at previous beep point
                if p.match(str(self.playlist.currentMedia().canonicalUrl())):
                    cnt = cnt + 1
                    if cnt == 2:
                        print(self.playlist.currentIndex())
                        if self.player.state() == QMediaPlayer.StoppedState:
                            self.player.play()
                        break

    @pyqtSlot()
    def forward_click(self):
        if self.playlist.mediaCount() == 0:
            self.cur_click()
        elif self.playlist.mediaCount() != 0:
            p = re.compile('.+_beep.+')
            for i in range(self.playlist.mediaCount()):
                # don't go further from end point
                if self.playlist.currentIndex() < 0:
                    break

                # go forward
                self.playlist.setCurrentIndex(self.playlist.nextIndex(1))

                # start at next beep point
                if p.match(str(self.playlist.currentMedia().canonicalUrl())):
                    print(self.playlist.currentIndex())
                    break

#----------------------- Configuration button callback -----------------------#

    @pyqtSlot()
    def plus_row(self):
        # change configTable
        self.crow = self.crow + 1
        self.configTable.setRowCount(self.crow)

        # fill the generated cell
        self.configTable.itemChanged.disconnect(self.item_changed)
        for col in range(self.ccol):
            self.configTable.setItem(self.crow - 1, col, QTableWidgetItem(''))
            self.configTable.item(self.crow - 1,
                                  col).setBackground(QColor(255, 0, 0))
        self.configTable.itemChanged.connect(self.item_changed)

    @pyqtSlot()
    def plus_col(self):
        # change configTable
        self.ccol = self.ccol + 1
        self.configTable.setColumnCount(self.ccol)

        # fill the generated cell
        self.configTable.itemChanged.disconnect(self.item_changed)
        for row in range(self.crow):
            self.configTable.setItem(row, self.ccol - 1, QTableWidgetItem(''))
            self.configTable.item(row, self.ccol - 1).setBackground(
                QColor(255, 0, 0))
        self.configTable.itemChanged.connect(self.item_changed)

    @pyqtSlot()
    def initialize(self):
        # remove configurable audio files
        arr = listdir('./audio_clips')
        p = re.compile('_.+')
        for file in arr:
            if p.match(file):
                continue
            remove('./audio_clips/' + file)

        # init configTable
        self.configTable.itemChanged.disconnect(self.item_changed)  # lock

        self.configTable.clear()
        self.crow = 5
        self.ccol = 5
        self.configTable.setRowCount(self.crow)
        self.configTable.setColumnCount(self.ccol)

        # reset configTable item
        for row in range(self.crow):
            for col in range(self.ccol):
                self.configTable.setItem(row, col, QTableWidgetItem(''))
                self.configTable.item(row,
                                      col).setBackground(QColor(255, 0, 0))
        self.configTable.setItem(0, 0, QTableWidgetItem('박스'))
        self.configTable.item(0, 0).setBackground(QColor(255, 255, 255))

        self.configTable.itemChanged.connect(self.item_changed)  # unlock

        # init configFile
        self.update_configFile()


#---------------------- ConfigTable signal callback ------------------------#

    def item_doubleClicked(self, item):
        self.previousItem = item.data(0)
        print(self.previousItem)

    def update_configFile(self):
        cwb_w = Workbook(write_only=True)
        cws_w = cwb_w.create_sheet()

        cws_w.append([self.crow, self.ccol])

        for row in range(self.crow):
            itemList = []
            for col in range(self.ccol):
                itemList.append(self.configTable.item(row, col).data(0))
            cws_w.append(itemList)
        try:
            cwb_w.save(self.configFile)
        except:
            string = """설정파일이 열려있을 수 있습니다.
                            설정파일을 닫은 후에 다시 시도하세요."""
            QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                 QMessageBox.Ok)

    def item_changed(self, item):
        self.configTable.itemChanged.disconnect(self.item_changed)  # lock

        if item.row() == 0 and item.column() == 0:
            string = "이 항목은 바꿀 수 없습니다."
            QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                 QMessageBox.Ok)
            self.configTable.setItem(item.row(), item.column(),
                                     QTableWidgetItem(self.previousItem))

        else:
            # get file name
            fileName, _ = QFileDialog.getOpenFileName(self, "Open file", "",
                                                      "All Files (*)")

            # count the number of key that has same name
            keys = self.configTable.findItems(item.data(0), Qt.MatchExactly)
            kcnt = 0
            for key in keys:
                if key.row() == 0:
                    kcnt = kcnt + 1

            # count the number of atribute that has same name
            atributes = self.configTable.findItems(item.data(0),
                                                   Qt.MatchExactly)
            acnt = 0
            for atribute in atributes:
                if atribute.row() == 0:
                    pass
                elif atribute.column() == item.column():
                    acnt = acnt + 1

            # change is accepted only in case of uniqueness and existence and it is not 박스(0,0)
            if kcnt >= 2:
                string = "항목명이 같을 수 없습니다."
                QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                     QMessageBox.Ok)
                self.configTable.setItem(item.row(), item.column(),
                                         QTableWidgetItem(self.previousItem))

            elif acnt >= 2:
                string = "같은 항목에 같은 이름의 아이템을 둘 수 없습니다."
                QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                     QMessageBox.Ok)
                self.configTable.setItem(item.row(), item.column(),
                                         QTableWidgetItem(self.previousItem))

            elif fileName:
                # copy file to local dir
                dst = "./audio_clips./" + str(item.row()) + '_' + str(
                    item.column()) + '.mp3'
                copyfile(fileName, dst)

                # change cell color
                if item.row() == 0:
                    self.configTable.item(item.row(),
                                          item.column()).setBackground(
                                              QColor(255, 255, 0))
                else:
                    self.configTable.item(item.row(),
                                          item.column()).setBackground(
                                              QColor(0, 255, 255))

                # update configFile
                self.update_configFile()

            else:
                string = "선택이 취소됨."
                QMessageBox.question(self, 'Error', string, QMessageBox.Ok,
                                     QMessageBox.Ok)
                self.configTable.setItem(item.row(), item.column(),
                                         QTableWidgetItem(self.previousItem))

        self.configTable.itemChanged.connect(self.item_changed)  # unlock
Exemplo n.º 18
0
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)
Exemplo n.º 19
0
class AudioPlayerPage(QWidget):
    about_play_audio = pyqtSignal(str)

    def __init__(self):
        super().__init__()

        self.audio_list_widget = QListWidget()
        self.audio_list_widget.installEventFilter(self)
        self.audio_list_widget.itemDoubleClicked.connect(self.play)

        # TODO: playlist объединить с audio_list_widget (см примеры работы с QMediaPlayer)
        self.playlist = QMediaPlaylist()
        self.playlist.currentIndexChanged.connect(
            lambda row: self.audio_list_widget.setCurrentRow(row))

        # TODO: обрабатывать сигналы плеера: http://doc.qt.io/qt-5/qmediaplayer.html#signals
        self.player = QMediaPlayer()
        self.player.setPlaylist(self.playlist)
        self.player.currentMediaChanged.connect(
            lambda media: self.about_play_audio.emit(self.audio_list_widget.
                                                     currentItem().text()))

        if not self.player.isAvailable():
            # TODO: перевод
            text = "The QMediaPlayer object does not have a valid service.\n" \
                   "Please check the media service plugins are installed."

            log.warning(text)
            QMessageBox.warning(self, "Service not available", text)

            quit()

        self.controls = PlayerControls(self.player)
        self.controls.set_state(self.player.state())
        self.controls.set_volume(self.player.volume())
        self.controls.set_muted(self.controls.is_muted())

        self.controls.play_signal.connect(self.play)
        self.controls.pause_signal.connect(self.player.pause)
        self.controls.stop_signal.connect(self.player.stop)
        self.controls.next_signal.connect(self.playlist.next)
        self.controls.previous_signal.connect(self.playlist.previous)
        self.controls.change_volume_signal.connect(self.player.setVolume)
        self.controls.change_muting_signal.connect(self.player.setMuted)

        self.progress = QProgressBar()
        self.progress.hide()

        layout = QVBoxLayout()
        layout.addWidget(self.controls)
        layout.addWidget(self.audio_list_widget)
        layout.addWidget(self.progress)

        self.setLayout(layout)

        self.thread = LoadAudioListThread()
        self.thread.about_add_audio.connect(self._add_audio)
        self.thread.about_progress.connect(self.progress.setValue)
        self.thread.about_range_progress.connect(self.progress.setRange)
        self.thread.started.connect(self._start)
        self.thread.finished.connect(self._finished)

    def _add_audio(self, title, url):
        item = QListWidgetItem(title)
        item.setData(Qt.UserRole, url)
        self.audio_list_widget.addItem(item)
        self.playlist.addMedia(QMediaContent(QUrl(url)))

        # При добавлении первой аудизаписи, вызываем воспроизведение
        if self.audio_list_widget.count() == 1:
            self.audio_list_widget.setCurrentRow(0)
            self.playlist.setCurrentIndex(0)
            self.play()

    def _start(self):
        self.audio_list_widget.clear()
        self.playlist.clear()

        self.progress.show()

    def _finished(self):
        self.progress.hide()

    def fill(self, vk):
        self.thread.vk = vk

        # Если поток запущен, останавливаем его, иначе -- запускаем
        if self.thread.isRunning():
            self.thread.exit()
        else:
            self.thread.start()

    def play(self):
        if self.playlist.currentIndex() != self.audio_list_widget.currentRow():
            self.playlist.setCurrentIndex(self.audio_list_widget.currentRow())

        self.player.play()

    def eventFilter(self, obj, event):
        # Воспроизведение видео при клике на кнопки Enter/Return в плейлисте
        if obj == self.audio_list_widget and event.type(
        ) == QKeyEvent.KeyPress:
            if self.audio_list_widget.hasFocus() and event.key(
            ) == Qt.Key_Return or event.key() == Qt.Key_Enter:
                item = self.audio_list_widget.currentItem()
                if item is not None:
                    self.play()

        return super().eventFilter(obj, event)
Exemplo n.º 20
0
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)
Exemplo n.º 21
0
class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer() # 播放器
        self.playlist = QMediaPlaylist() # 播放列表
        self.title = '音乐播放器'
        self.volumeHint = QLabel('音量: 99%')
        self.mInfo = {
            'cover': './default_cover.jpg', 
            'music': '', 
            'singer': '',
            'duration': 0
        }
        self.aboutWin = AboutWindow()
        self.cover = QLabel()
        self.listWid = QListWidget()

        # 设置主窗口位置
        self.left = 200
        self.top = 100
        self.width = 500
        self.height = 430

        self.font = QFont('SansSerif', 10.5)
        self.color = 1  # 0 - 黑色界面, 1 - 白色界面
        self.userAction = 0  # 0 - 停止中, 1 - 播放中 2 - 暂停中
        self.initUI()

    def initUI(self):
        # 添加文件菜单
        menubar = self.menuBar()
        menubar.setNativeMenuBar(False) # 不使用本地菜单栏以获得全平台统一的效果
        filemenu = menubar.addMenu('文件')
        windowmenu = menubar.addMenu('窗口')

        fileAct = QAction('打开文件', self)
        folderAct = QAction('打开文件夹', self)
        themeAct = QAction('切换[亮/暗]主题', self)
        aboutAct = QAction('关于', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')
        themeAct.setShortcut('Ctrl+T')
        aboutAct.setShortcut('Ctrl+H')

        filemenu.addAction(fileAct)
        filemenu.addAction(folderAct)
        windowmenu.addAction(themeAct)
        windowmenu.addAction(aboutAct)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)
        themeAct.triggered.connect(self.toggleColors)
        aboutAct.triggered.connect(self.viewAbout)
        self.listWid.itemDoubleClicked.connect(self.quickplayhandler)

        self.listWid.setFont(self.font)
        self.playlist.setPlaybackMode(2)
        self.setLayout()
        self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) # 禁用窗口最大化按钮
        self.setFont(self.font)
        self.setWindowTitle(self.title)
        self.setWindowIcon(QIcon('icon.ico'))
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setFixedSize(self.width, self.height)
        self.toggleColors()
        self.show()

    def setLayout(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # 添加音量控制
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(100)

        # 添加歌曲播放控制
        playBtn = QPushButton('播放')  # 播放
        pauseBtn = QPushButton('暂停')  # 暂停
        stopBtn = QPushButton('清空列表')  # 停止
        prevBtn = QPushButton('上一首') # 上一首
        playback = QComboBox() # 回放模式
        nextBtn = QPushButton('下一首') # 下一首

        playback.addItem('      单曲播放')
        playback.addItem('      单曲循环')
        playback.addItem('      列表播放')
        playback.addItem('      列表循环')
        playback.addItem('      列表随机')

        playback.setCurrentIndex(2)

        # 添加封面
        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)

        # 添加布局
        Area = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        showLayout = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()

        # 歌曲播放控制布局
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)

        # 播放列表控制布局
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(playback)
        playlistCtrlLayout.addWidget(nextBtn)

        # 显示布局
        showLayout.addWidget(self.cover)
        showLayout.addWidget(self.listWid)

        # 竖直排列
        Area.addStretch(1)
        Area.addLayout(showLayout)
        Area.addWidget(self.volumeHint)
        Area.addWidget(volumeslider)
        Area.addLayout(controls)
        Area.addLayout(playlistCtrlLayout)
        wid.setLayout(Area)

        # 事件绑定
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        playback.currentIndexChanged.connect(self.playbackhandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        nextBtn.clicked.connect(self.nextSong)

        self.statusBar().showMessage('文件-打开文件(夹)-选择-开始播放')
        self.playlist.currentMediaChanged.connect(self.songChanged)

    def openFile(self):
        print("点击了文件按钮")
        song = QFileDialog.getOpenFileName(self, "打开音频", "github-lkxed", "音频文件 (*.mp3 *.ogg *.wav *.m4a)")

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
                self.listWid.addItem(song[0].split('/')[-1].split('.')[0])
                print(self.playlist.mediaCount())
            else:
                self.playlist.addMedia(QMediaContent(url))
                print(self.playlist.mediaCount())

    def addFiles(self):
        print("点击了文件夹按钮")
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
            print(self.playlist.mediaCount())
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            print(self.playlist.mediaCount())
            self.userAction = 1
    
    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, '打开音频文件夹', '.')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    print(it.filePath(), fInfo.suffix())
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        print('added file', fInfo.fileName())
                        self.listWid.addItem(fInfo.fileName())
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                print(it.filePath(), fInfo.suffix())
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    print('added file', fInfo.fileName())
                    self.listWid.addItem(fInfo.fileName())
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))

            # 设置ListItem高度
            for x in range(self.listWid.count()):
                self.listWid.item(x).setSizeHint(QSize(100, 30))

    # 处理双击播放事件
    def quickplayhandler(self, item):
        # 若播放列表没有音频了就跳出打开文件对话框
        if self.playlist.mediaCount() == 0:
            self.openFile()
        # 若播放列表不为空则播放
        elif self.playlist.mediaCount() != 0:
            index = self.listWid.currentRow()
            self.player.playlist().setCurrentIndex(index)
            self.player.play()
            self.userAction = 1

    # 处理按钮播放事件
    def playhandler(self):
        if self.userAction == 2:
            self.player.play()
        elif self.userAction == 0:
            # 若播放列表没有音频了就跳出打开文件对话框
            if self.playlist.mediaCount() == 0:
                self.openFile()
            # 若播放列表不为空则播放
            elif self.playlist.mediaCount() != 0:
                index = self.listWid.currentRow()
                self.player.playlist().setCurrentIndex(index)
                self.player.play()
                self.userAction = 1
        else:
            self.statusBar().showMessage('已经在播放中!')

    # 处理暂停事件
    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    # 处理清空列表事件
    def stophandler(self):
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()
        self.listWid.clear()
        self.mInfo['cover'] = 'default_cover.jpg'
        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)
        print("Playlist cleared!")
        self.statusBar().showMessage("列表已清空")

    def changeVolume(self, value):
        text = '音量: ' + str(value) + '%'
        self.volumeHint.setText(text)
        self.player.setVolume(value)

    # 上一首事件
    def prevSong(self):
        if self.playlist.currentIndex() == 0:
            self.playlist.setCurrentIndex(self.playlist.mediaCount()-1)
        else:
            self.player.playlist().previous()
    
    # 随机播放事件
    def playbackhandler(self, index):
        self.playlist.setPlaybackMode(index)
        print(self.playlist.playbackMode())

    # 下一首事件
    def nextSong(self):
        if self.playlist.mediaCount() == self.playlist.currentIndex()+1:
            self.playlist.setCurrentIndex(0)
        else:
            self.player.playlist().next()
    
    # 音频切换事件
    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.showInfo(url)
            self.statusBar().showMessage(url.fileName())
            index = self.player.playlist().currentIndex()
            self.listWid.setCurrentRow(index)

    def showInfo(self, url):
        filepath = url.path()[1:]
        filename = url.fileName()[:-4]
        print(filename)
        if filepath[-3:] == 'm4a':
            file = mutagen.MP4(filepath)
            try:
                img = file.tags['covr'][0]
                self.mInfo['cover'] = './cover/'+filename+'.jpg'
                if not os.path.exists('./cover'):
                    os.mkdir('./cover')
                if not os.path.exists(self.mInfo['cover']):
                    with open(self.mInfo['cover'], 'wb') as f:
                        f.write(img)
            except:
                print('找不到封面')
                self.mInfo['cover'] = './default_cover.jpg'

        elif filepath[-3:] == 'mp3':
            file = mutagen.File(filepath)
            try:
                img = file.tags['APIC:'].data
                self.mInfo['cover'] = './cover/'+filename+'.jpg'
                if not os.path.exists('./cover'):
                    os.mkdir('./cover')
                if not os.path.exists(self.mInfo['cover']):
                    with open(self.mInfo['cover'], 'wb') as f:
                        f.write(img)
            except:
                print('找不到封面')
                self.mInfo['cover'] = './default_cover.jpg'
        else:
            print('音频文件不支持提取封面')
            self.mInfo['cover'] = './default_cover.jpg'

        jpg = QPixmap(self.mInfo['cover']).scaled(300, 300)
        self.cover.setPixmap(jpg)


    # 主题切换事件
    def toggleColors(self):

        app.setStyle("Fusion")
        palette = QPalette()

        # 明亮主题
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.white)
            palette.setColor(QPalette.Button, QColor(53, 53, 53))
            palette.setColor(QPalette.ButtonText, Qt.white)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1

        # 黑暗主题
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0

    def viewAbout(self):
        self.aboutWin.show()
Exemplo n.º 22
0
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']))
Exemplo n.º 23
0
class Control:
    """A class that handles the logic behind the program by manipulating the GUI classes
    and calling their methods in response to received signals."""

    MAGIC = b"\x01\xff"

    def __init__(self, screens: list) -> None:
        self.player = QMediaPlayer()
        self.player.setAudioRole(QAudio.MusicRole)
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)
        self.mainWindow = MainWindow(self, screens)
        self.mainArea = self.mainWindow.centralWidget().upperBox.mainArea
        self.songList = self.mainWindow.centralWidget().upperBox.songList
        self.mediaControlArea = self.mainWindow.centralWidget(
        ).mediaControlArea
        self.mainWindow.show()
        self.library = None
        self.currentSong = None
        self.playing = False
        self.random = False
        self.repeat = 0
        self.volume = 50

        self.volumeChange(self.volume)
        self.mediaControlArea.volumeControl.setValue(self.volume)

        self.mainTimer = QTimer()
        self.mainTimer.setInterval(100)
        self.mainTimer.timeout.connect(self.updateSongProgress)
        self.mainTimer.start()

        self.libraryUpdateTimer = QTimer()
        self.libraryUpdateTimer.setInterval(15_000)
        self.libraryUpdateTimer.timeout.connect(self.updateLibrary)
        self.libraryUpdateTimer.start()

        self._connection = None
        self.connections()

        self.displayedType = None
        self.displayedName = None
        self.types = None
        self.songListWidth = None
        values = self.load()
        if values:
            self.mainWindow.setGeometry(*values)
            self.volumeChange(self.volume)
            self.mediaControlArea.volumeControl.setValue(self.volume)

        self.setUpTimer = QTimer()
        self.setUpTimer.setInterval(20)
        self.setUpTimer.setSingleShot(True)
        self.setUpTimer.timeout.connect(self.setAreas)
        self.setUpTimer.start()

    def connections(self):
        self.player.currentMediaChanged.connect(self.updateCurrentSong)
        self.player.durationChanged.connect(self.updateSongProgressRange)
        self.player.stateChanged.connect(self.playerStatusChanged)
        self.mediaControlArea.previousButton.click.connect(
            self.playlist.previous)
        self.mediaControlArea.repeatButton.click.connect(
            self.repeatButtonClick)
        self.mediaControlArea.stopButton.click.connect(self.stopButtonClick)
        self.mediaControlArea.playButton.click.connect(self.playButtonClick)
        self.mediaControlArea.randomButton.click.connect(
            self.randomButtonClick)
        self.mediaControlArea.nextButton.click.connect(self.playlist.next)
        self.mediaControlArea.muteButton.click.connect(self.mute)
        self.mediaControlArea.songProgress.sliderMoved.connect(
            self.songProgressMove)
        self.mediaControlArea.volumeControl.sliderMoved.connect(
            self.volumeChange)

    def setAreas(self) -> None:
        """Called after the GUI is created to provide user with a feedback
        that the program is running in case a larger amount of songs will be added
        when the Library class is initialized."""
        # TODO add a tooltip that will notify the user larger amount of songs is being loaded
        #  (freezes the program as the execution moves to the Library class.)
        self.library = library.Library()
        self.types = {
            "artist": self.library.getSongsForArtist,
            "album": self.library.getSongsForAlbum,
            "playlist": self.library.getSongsForPlaylist
        }
        self.mainArea.setAreas(self.library)
        self.setUpTimer.deleteLater()
        self.setUpTimer = None
        self.getSongs(self.displayedType, self.displayedName)
        if self.songListWidth is not None:
            songListGeometry = self.songList.geometry()
            self.songList.preferredWidth = songListGeometry.width(
            ) - self.songListWidth
            self.mainWindow.centralWidget().upperBox.line.resizeWidgets(
                songListGeometry.width() - self.songListWidth)

    def updateLibrary(self) -> None:
        self.library.update()
        self.mainArea.updateView(self.library)

    def updateCurrentSong(self) -> None:
        """Update all areas that may display information about the currently
        playing song - SongList, Now Playing tab, BottomBox"""
        media = self.player.currentMedia()
        self.currentSong = media.request().url().toLocalFile().replace(
            "/", "\\")
        if self.currentSong in self.library.library:
            self.songList.updateActiveSong(self.currentSong)
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            songEntry = self.library.library[self.currentSong]
            self.mediaControlArea.updateSongInfo(
                f"{songEntry[ARTIST]} - {songEntry[NAME]}")

    def updateSongProgressRange(self) -> None:
        """Updates the range of the slider that represents the song position."""
        self.mediaControlArea.updateSongProgressRange(self.player.duration())

    def playerStatusChanged(self) -> None:
        """Used to properly update the player look after the current playlist has finished."""
        index = self.playlist.currentIndex()
        if index == -1:
            self.stopButtonClick()

    def getSongs(self, isType: str, name: str) -> None:
        """Retrieves the songs for a given artist, album or playlist based on type
        and passes the resulting list to the SongList class."""
        if isType is None:
            isType = self.displayedType
        if name is None:
            name = self.displayedName
        orderBy = self.songList.buttonOrderBy.text()
        reverse = True if self.songList.buttonOrderReverse.text() == chr(
            0x25bc) else False
        listForType = self.types[isType](name, orderBy, reverse)
        playlist = None
        if isType == "playlist":
            playlist = name
        if len(listForType) == 0:
            artists = self.library.artists
            if len(artists):
                listForType = self.library.getSongsForArtist(artists[0])
        self.songList.updateSongList(listForType, self.library.library,
                                     self.currentSong, playlist, isType)
        self.displayedType = isType
        self.displayedName = name

    def playSongList(self, song: str = None) -> None:
        """Called when user double-clicks on an artist/album/playlist widget or a song
        in right-hand side panel."""
        self.playlist.clear()
        index = 0
        loopIndex = 0
        for songPath in self.songList.garbageProtector:
            if song == songPath:
                index = loopIndex
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
            loopIndex += 1
        if self.playlist.isEmpty():
            return
        self.player.play()
        if index > 0:
            self.playlist.setCurrentIndex(index)
        self.playing = True
        self.mediaControlArea.playButton.updatePictures(
            bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playSongWidget(self,
                       songPath: str,
                       afterCurrent: bool = False) -> None:
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            self.playlist.insertMedia(
                index, QMediaContent(QUrl.fromLocalFile(songPath)))
        else:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())
        self.playing = True

    def removeFromNowPlaying(self, widget) -> None:
        if self.playlist.mediaCount() > 1:
            for row in range(self.mainArea.nowPlayingLayout.rowCount()):
                for column in range(
                        self.mainArea.nowPlayingLayout.columnCount()):
                    if self.mainArea.nowPlayingLayout.itemAtPosition(
                            row, column).widget() is widget:
                        self.playlist.removeMedia(row - 1)
                        break
                else:
                    continue
                break
        else:
            self.stopButtonClick()
            self.playlist.clear()
        self.mainArea.setNowPlayingArea(self.library)
        if self.playing:
            self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playMediaWidget(self, isType: str, target: str, startOver: bool,
                        afterCurrent: bool) -> None:
        """Called from MediaWidget - plays all songs for MediaWidget's type and name."""
        if startOver:
            self.playlist.clear()
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            for songPath in self.types[isType](target):
                self.playlist.insertMedia(
                    index, QMediaContent(QUrl.fromLocalFile(songPath)))
                index += 1
        else:
            for songPath in self.types[isType](target):
                self.playlist.addMedia(
                    QMediaContent(QUrl.fromLocalFile(songPath)))
        if startOver:
            self.player.play()
            self.playing = True
            self.mediaControlArea.playButton.updatePictures(
                bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playFromNowPlaying(self, song: str) -> None:
        """Called when user double-clicks on a song in the Now Playing tab."""
        for n in range(self.playlist.mediaCount()):
            media = self.playlist.media(n)
            if song == media.request().url().toLocalFile().replace("/", "\\"):
                self.playlist.setCurrentIndex(n)
                if not self.playing:
                    self.player.play()
                    self.playing = True
                return

    def createPlaylist(self, playlistName: str) -> None:
        self.library.createPlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)

    def addToExistingPlaylist(self, playlist: str, songOrWidget: str,
                              isType: str) -> None:
        if isType in self.types:
            for song in self.types[isType](songOrWidget):
                self.library.addToPlaylist(playlist, song)
        else:
            self.library.addToPlaylist(playlist, songOrWidget)
        self.library.update()

    def removeFromPlaylist(self, playlist: str, song: str) -> None:
        self.library.deleteFromPlaylist(playlist, song)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()
        self.getSongs("playlist", playlist)

    def renamePlaylist(self, playlistName: str, newPlaylistName: str) -> None:
        self.library.renamePlaylist(playlistName, newPlaylistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def deletePlaylist(self, playlistName: str) -> None:
        self.library.deletePlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def addWatchedFolder(self, folder: str) -> None:
        """Adds a folder to the Library class. all mp3 files within the folder
        and its sub-folders will be added to the library and accessible to the player."""
        self.library.addFolder(folder.replace("/", "\\"))
        self.mainArea.updateView(self.library)

    def removeWatchedFolder(self, folder: str) -> None:
        """Removes folder from the library, updates view and stops playback if
        the current song was in the now-removed folder."""
        self.library.deleteFolder(folder)
        self.mainArea.updateView(self.library)
        if self.currentSong not in self.library.library:
            self.songList.updateSongList([], [], "", "")
            self.player.stop()
            self.playlist.clear()
            self.mediaControlArea.updateSongInfo("")
            self.songList.nowPlayingSong = None
            self.mainArea.nowPlayingSong = None
            self.playing = False
            self.mediaControlArea.updatePlayButton(self.playing, False)

    def playButtonClick(self, passMove: bool = True) -> None:
        if not self.playing:
            if self.playlist.isEmpty():
                self.playSongList()
                return
            self.playing = True
            self.player.play()
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            self.songList.updateActiveSong(self.currentSong)
        else:
            self.playing = False
            self.player.pause()
        self.mediaControlArea.updatePlayButton(self.playing, passMove)

    def repeatButtonClick(self) -> None:
        if self.repeat == 0:
            self.repeat = 1
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        elif self.repeat == 1:
            self.repeat = 2
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        elif self.repeat == 2:
            self.repeat = 0
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRepeatButton(self.repeat)

    def randomButtonClick(self) -> None:
        if not self.random:
            self.random = True
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        else:
            self.random = False
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRandomButton(self.random)

    def stopButtonClick(self) -> None:
        self.playing = False
        self.player.stop()
        if self.songList.nowPlayingSong is not None:
            self.songList.nowPlayingSong.clear()
        if self.mainArea.nowPlayingSong is not None:
            self.mainArea.nowPlayingSong.clear()
        self.mediaControlArea.updatePlayButton(self.playing, False)

    def mute(self) -> None:
        if not self.player.isMuted():
            self.player.setMuted(True)
            self.mediaControlArea.showMute()
        else:
            self.player.setMuted(False)
            self.volumeChange(self.volume)

    def volumeChange(self, volume: int) -> None:
        logVolume = QAudio.convertVolume(volume / 100,
                                         QAudio.LogarithmicVolumeScale,
                                         QAudio.LinearVolumeScale) * 100
        self.player.setVolume(logVolume)
        self.volume = volume
        self.mediaControlArea.updateVolumeBar(volume)

    def songProgressMove(self, position: int) -> None:
        self.player.setPosition(position)

    def updateSongProgress(self) -> None:
        position = self.player.position()
        if 0 <= position < 2_000_000_000:
            if self.player.state() > 0:
                self.mediaControlArea.updateSongProgress(position)
                if self.playing:
                    self.songList.activeSongPixmap()
                    self.mainArea.activeSongPixmap()
            else:
                self.mediaControlArea.updateSongProgress(0)

    def disconnect(self):
        self.player.currentMediaChanged.disconnect()
        self.player.durationChanged.disconnect()
        self.player.stateChanged.disconnect()
        self.mediaControlArea.previousButton.click.disconnect()
        self.mediaControlArea.repeatButton.click.disconnect()
        self.mediaControlArea.stopButton.click.disconnect()
        self.mediaControlArea.playButton.click.disconnect()
        self.mediaControlArea.randomButton.click.disconnect()
        self.mediaControlArea.nextButton.click.disconnect()
        self.mediaControlArea.muteButton.click.disconnect()
        self.mediaControlArea.songProgress.sliderMoved.disconnect()
        self.mediaControlArea.volumeControl.sliderMoved.disconnect()

    def close(self) -> None:
        self.disconnect()
        self.player.stop()
        self.mainTimer.stop()
        self.save()

    def save(self) -> None:
        """Called on exit, saves current view, geometry and volume."""
        with gzip.open(r"musicplayer\mpdata", "wb") as fh:
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedType.encode())}s",
                                      len(self.displayedType.encode()),
                                      self.displayedType.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedName.encode())}s",
                                      len(self.displayedName.encode()),
                                      self.displayedName.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            geo = self.mainWindow.geometry()
            toBeWritten = struct.pack("<4h", geo.x(), geo.y(), geo.width(),
                                      geo.height())
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.volume)
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.songList.width())
            fh.write(toBeWritten)

    def load(self) -> [bool, tuple]:
        """Called on startup, loads view, geometry and volume saved on previous run."""
        try:
            with gzip.open(r"musicplayer\mpdata", "rb") as fh:
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedType = fh.read(length)
                displayedType = struct.unpack(f"<{length}s",
                                              displayedType)[0].decode("utf8")
                if displayedType in ["artist", "album", "playlist"]:
                    self.displayedType = displayedType
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedName = fh.read(length)
                displayedName = struct.unpack(f"<{length}s",
                                              displayedName)[0].decode("utf8")
                if not fh.read(2) == self.MAGIC:
                    return False
                self.displayedName = displayedName
                variables = []
                for n in range(6):
                    var = fh.read(2)
                    var = struct.unpack("<h", var)[0]
                    variables.append(var)
                x, y, width, height, volume, songListWidth = variables
                self.volume = volume
                self.songListWidth = songListWidth
                return x, y, width, height
        except Exception:
            return False
Exemplo n.º 24
0
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())
Exemplo n.º 25
0
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()
Exemplo n.º 26
0
class Player(QWidget):
    audio_path = "audio"
    lyrics_path = "lyrics"
    timings_path = os.path.join("lyrics", "timing")
    settings_path = "settings.json"

    fullScreenChanged = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(Player, self).__init__(parent)

        self.setWindowTitle("SongScreen")

        self.setFocusPolicy(Qt.StrongFocus)

        self.colorDialog = None
        self.trackInfo = ""
        self.statusInfo = ""
        self.duration = 0

        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        # self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
        self.player.error.connect(self.displayErrorMessage)

        # self.videoWidget = VideoWidget()
        # self.player.setVideoOutput(self.videoWidget)

        self.slider = MediaProgressWidget()  # QSlider(Qt.Horizontal)
        self.markers = []

        self.songtext_widget = SongTextWidget()
        self.songtext_widget.show()

        # self.playlistModel = PlaylistModel()
        # self.playlistModel.setPlaylist(self.playlist)
        #
        # self.playlistView = QListView()
        # self.playlistView.setModel(self.playlistModel)
        # self.playlistView.setCurrentIndex(
        #     self.playlistModel.index(self.playlist.currentIndex(), 0))
        #
        # self.playlistView.activated.connect(self.jump)

        self.slider.setRange(0, self.player.duration() / 1000)

        self.labelDuration = QLabel()
        self.slider.sliderMoved.connect(self.seek)

        # openButton = QPushButton("Open", clicked=self.open)

        controls = PlayerControlsWidget()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        # controls.setMuted(controls.isMuted())

        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.stop_clicked)
        # controls.stop.connect(self.videoWidget.update)
        # controls.next.connect(self.playlist.next)
        # controls.previous.connect(self.previousClicked)
        controls.changeVolume.connect(self.player.setVolume)
        # controls.changeMuting.connect(self.player.setMuted)
        # controls.changeRate.connect(self.player.setPlaybackRate)

        self.player.stateChanged.connect(controls.setState)
        self.player.stateChanged.connect(self.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        # self.player.mutedChanged.connect(controls.setMuted)

        # self.fullScreenButton = QPushButton("FullScreen")
        # self.fullScreenButton.setCheckable(True)
        #
        # self.colorButton = QPushButton("Color Options...")
        # self.colorButton.setEnabled(False)
        # self.colorButton.clicked.connect(self.showColorDialog)

        displayLayout = QHBoxLayout()
        # displayLayout.addWidget(self.videoWidget, 2)
        # displayLayout.addWidget(self.songtext_widget)
        # displayLayout.addWidget(self.playlistView)

        self.song_select_widget = SongSelectWidget()
        self.song_select_widget.song_selected.connect(self.load_song)

        self.screen_select_widget = ScreenSelectWidget()
        self.screen_select_widget.screen_selected.connect(self.display_lyrics_on_screen)
        self.screen_select_widget.active_screen = QApplication.desktop().screenNumber(self.songtext_widget)

        self.settings_button = QPushButton()
        self.settings_button.setText(self.tr("Settings..."))
        self.settings_button.clicked.connect(self.show_settings)

        sidebarLayout = QVBoxLayout()
        sidebarLayout.setContentsMargins(10, 1, 0, 1);

        sidebarLayout.addWidget(self.settings_button)
        sidebarLayout.addStretch(1);
        sidebarLayout.addWidget(self.screen_select_widget)

        displayLayout.addWidget(self.song_select_widget)
        displayLayout.addLayout(sidebarLayout)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        # controlLayout.addWidget(openButton)
        # controlLayout.addStretch(1)
        controlLayout.addWidget(controls)
        controlLayout.addStretch(1)
        controlLayout.addWidget(self.labelDuration)
        # controlLayout.addWidget(self.fullScreenButton)
        # controlLayout.addWidget(self.colorButton)

        layout = QVBoxLayout()
        layout.addLayout(displayLayout)
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.slider)
        # hLayout.addWidget(self.labelDuration)
        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        if not self.player.isAvailable():
            QMessageBox.warning(self, "Service not available",
                                "The QMediaPlayer object does not have a valid service.\n"
                                "Please check the media service plugins are installed.")

            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            # openButton.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self._loading_audio = False
        self._finished_song = False
        self._lyrics_fading = False

        self._song_number = -1

        self.settings = {
            'font_size': 40,
            'line_increment': 2,
            'lyrics_language': '',
        }
        self._load_settings()

        self.settings_widget = SettingsWidget(self.settings, self.lyrics_path)
        self.settings_widget.font_size_changed.connect(self.songtext_widget.set_font_size)
        self.settings_widget.line_increment_changed.connect(self.songtext_widget.set_line_increment)
        self.settings_widget.language_changed.connect(self._language_changed)

        self.song_select_widget.reset(self.available_song_numbers)

    @property
    def lyrics_language_path(self):
        path = QStandardPaths.locate(QStandardPaths.AppDataLocation, self.lyrics_path, QStandardPaths.LocateDirectory)
        return os.path.join(path, self.settings['lyrics_language'])

    @property
    def available_song_numbers(self):
        audios = set(
            [int(os.path.splitext(filename)[0]) for filename in os.listdir(self.audio_path) if filename[0] != '.'])
        try:
            lyrics = set(
                [int(os.path.splitext(filename)[0])
                 for filename in os.listdir(self.lyrics_language_path)
                 if filename[0] != '.']
            )
        except (ValueError, FileNotFoundError):
            lyrics = set()

        return sorted(list(audios.intersection(lyrics)))

    def show_settings(self):
        self.settings_widget.hide()
        self.settings_widget.show()

    def display_lyrics_on_screen(self, screen_number):
        desktop = QApplication.desktop()

        if screen_number >= desktop.screenCount():
            screen_number = desktop.screenNumber(self)

        rect = desktop.availableGeometry(screen_number)

        for _ in range(3):
            if screen_number != desktop.screenNumber(self):
                self.songtext_widget.setWindowFlags(Qt.FramelessWindowHint)
                self.songtext_widget.hide()
                self.songtext_widget.move(rect.x(), rect.y())
                self.songtext_widget.resize(rect.width(), rect.height())
                self.songtext_widget.showFullScreen()
            else:
                self.songtext_widget.setWindowFlags(Qt.WindowTitleHint)
                self.songtext_widget.hide()
                self.songtext_widget.move(rect.x(), rect.y())
                self.songtext_widget.resize(self.songtext_widget.minimumSize())
                self.songtext_widget.show()

        self.screen_select_widget.active_screen = screen_number

        self.activateWindow()

    def load_song(self, song_number):
        if self._song_number == song_number:
            self.seek(0)
        else:
            if self._song_number > 0:
                self._save_timings()

            self._song_number = song_number
            self.slider.dirty = False
            self._load_audio()
            self._load_lyrics()

            # self.player.play()

    def _load_audio(self):
        filename = os.path.join(self.audio_path, "{:03}.mp3".format(self._song_number))
        self.playlist.clear()
        fileInfo = QFileInfo(filename)
        if fileInfo.exists():
            url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
            if fileInfo.suffix().lower() == 'm3u':
                self.playlist.load(url)
            else:
                self.playlist.addMedia(QMediaContent(url))
                self._loading_audio = True

            self.player.play()

    def _load_lyrics(self):
        with open(os.path.join(self.lyrics_language_path, "{}.json".format(self._song_number)), 'r') as f:
            song_markers = json.load(f)

            self.markers = []

            for m in song_markers['markers']:
                marker = MediaMarker(self.slider, m['name'])
                marker.text = m['text']
                marker.progress = 0.0
                self.markers.append(marker)

            self.songtext_widget.title = "{}  {}".format(self._song_number, song_markers['title'])
            self.songtext_widget.markers = self.markers
            self.songtext_widget.fade_in()

        try:
            with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'r') as f:
                timings = json.load(f)
                for m, t in zip(self.markers, timings):
                    m.progress = t
        except FileNotFoundError:
            pass

        self.slider.markers = self.markers

    def _language_changed(self, _):
        available_song_numbers = self.available_song_numbers
        self.song_select_widget.reset(available_song_numbers)
        if self._song_number in available_song_numbers:
            self._load_lyrics()

    # def open(self):
    #     fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files")
    #     self.addToPlaylist(fileNames)
    #
    # def addToPlaylist(self, fileNames):
    #     for name in fileNames:
    #         fileInfo = QFileInfo(name)
    #         if fileInfo.exists():
    #             url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
    #             if fileInfo.suffix().lower() == 'm3u':
    #                 self.playlist.load(url)
    #             else:
    #                 self.playlist.addMedia(QMediaContent(url))
    #         else:
    #             url = QUrl(name)
    #             if url.isValid():
    #                 self.playlist.addMedia(QMediaContent(url))

    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

        if self._loading_audio:
            self._loading_audio = False

            line_total = 0
            for marker in self.markers:
                line_total += marker.linecount - 1

            silence_ratio = 5.0 / self.duration
            offset = 1.8 / line_total

            linecount = 0
            for marker in self.markers:
                if marker.progress == 0.0:
                    marker.progress = offset + (1 - offset) * (1 - silence_ratio) * linecount / line_total
                linecount += marker.linecount - 1

            self.player.pause()

    @property
    def _should_fade_out(self):
        return self.player.position() / 1000 >= self.duration - 5

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.updateDurationInfo(progress)

        if self.duration > 0:
            # if self.player.state() == QMediaPlayer.PlayingState:
            self.songtext_widget.progress = progress / self.duration

            if self._should_fade_out:
                self._fade_out_lyrics()

    def _fade_out_lyrics(self):
        if not self._lyrics_fading:
            self._lyrics_fading = True
            self.songtext_widget.fade_out()

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo("%s - %s" % (
                self.player.metaData(QMediaMetaData.AlbumArtist),
                self.player.metaData(QMediaMetaData.Title)))

    def previousClicked(self):
        # Go to the previous track if we are within the first 5 seconds of
        # playback.  Otherwise, seek to the beginning.
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def setState(self, status):

        if status == QMediaPlayer.StoppedState:
            self._finished_song = True

        elif status == QMediaPlayer.PlayingState:
            if self._finished_song or (self._lyrics_fading and not self._should_fade_out):
                self._finished_song = False
                self._lyrics_fading = False
                self.songtext_widget.fade_in()

    def stop_clicked(self):
        self.player.stop()
        self._fade_out_lyrics()

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo("Loading...")
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo("Media Stalled")
        elif status == QMediaPlayer.EndOfMedia:
            QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo("")

    def handleCursor(self, status):
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def bufferingProgress(self, progress):
        self.setStatusInfo("Buffering %d%" % progress)

    def videoAvailableChanged(self, available):
        if available:
            self.fullScreenButton.clicked.connect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.connect(
                self.fullScreenButton.setChecked)

            if self.fullScreenButton.isChecked():
                self.videoWidget.setFullScreen(True)
        else:
            self.fullScreenButton.clicked.disconnect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.disconnect(
                self.fullScreenButton.setChecked)

            self.videoWidget.setFullScreen(False)

        self.colorButton.setEnabled(available)

    def setTrackInfo(self, info):
        self.trackInfo = info

        # if self.statusInfo != "":
        #     self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        # else:
        #     self.setWindowTitle(self.trackInfo)

    def setStatusInfo(self, info):
        self.statusInfo = info

        # if self.statusInfo != "":
        #     self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        # else:
        #     self.setWindowTitle(self.trackInfo)

    def displayErrorMessage(self):
        self.setStatusInfo(self.player.errorString())

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60,
                                currentInfo % 60, (currentInfo * 1000) % 1000)
            totalTime = QTime((duration / 3600) % 60, (duration / 60) % 60,
                              duration % 60, (duration * 1000) % 1000);

            format = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format) + " / " + totalTime.toString(format)
        else:
            tStr = ""

        self.labelDuration.setText(tStr)

    def showColorDialog(self):
        if self.colorDialog is None:
            brightnessSlider = QSlider(Qt.Horizontal)
            brightnessSlider.setRange(-100, 100)
            brightnessSlider.setValue(self.videoWidget.brightness())
            brightnessSlider.sliderMoved.connect(
                self.videoWidget.setBrightness)
            self.videoWidget.brightnessChanged.connect(
                brightnessSlider.setValue)

            contrastSlider = QSlider(Qt.Horizontal)
            contrastSlider.setRange(-100, 100)
            contrastSlider.setValue(self.videoWidget.contrast())
            contrastSlider.sliderMoved.connect(self.videoWidget.setContrast)
            self.videoWidget.contrastChanged.connect(contrastSlider.setValue)

            hueSlider = QSlider(Qt.Horizontal)
            hueSlider.setRange(-100, 100)
            hueSlider.setValue(self.videoWidget.hue())
            hueSlider.sliderMoved.connect(self.videoWidget.setHue)
            self.videoWidget.hueChanged.connect(hueSlider.setValue)

            saturationSlider = QSlider(Qt.Horizontal)
            saturationSlider.setRange(-100, 100)
            saturationSlider.setValue(self.videoWidget.saturation())
            saturationSlider.sliderMoved.connect(
                self.videoWidget.setSaturation)
            self.videoWidget.saturationChanged.connect(
                saturationSlider.setValue)

            layout = QFormLayout()
            layout.addRow("Brightness", brightnessSlider)
            layout.addRow("Contrast", contrastSlider)
            layout.addRow("Hue", hueSlider)
            layout.addRow("Saturation", saturationSlider)

            button = QPushButton("Close")
            layout.addRow(button)

            self.colorDialog = QDialog(self)
            self.colorDialog.setWindowTitle("Color Options")
            self.colorDialog.setLayout(layout)

            button.clicked.connect(self.colorDialog.close)

        self.colorDialog.show()

    def closeEvent(self, close_event):
        self._save_timings()
        self._save_settings()
        self.songtext_widget.close()
        self.settings_widget.close()

    def keyPressEvent(self, key_event):
        if key_event.key() == Qt.Key_Space:
            key_event.accept()
            if self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()
            elif self.player.state() in [QMediaPlayer.PausedState, QMediaPlayer.StoppedState]:
                self.player.play()
        elif key_event.key() == Qt.Key_M:
            key_event.accept()
            self.slider.set_closest_marker_to_current_progress()

    def _save_timings(self):
        if self.slider.dirty:
            with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'w') as f:
                json.dump([marker.progress for marker in self.markers], f, indent=2)

    def _save_settings(self):
        # TODO : refactor and use QSettings directly

        # with open(self.settings_path, 'w') as f:
        self.settings.update({
            'lyrics_screen': QApplication.desktop().screenNumber(self.songtext_widget),
            'control_window_position': self.pos(),
        })

        # json.dump(self.settings, f, indent=2)

        settings = QSettings("Maccesch", "SongScreen")

        for key, value in self.settings.items():
            settings.setValue(key, value)

    def _load_settings(self):
        # try:
        #     with open(self.settings_path, 'r') as f:
        #         settings = json.load(f)
        settings = QSettings("Maccesch", "SongScreen")

        if settings.contains('lyrics_screen'):
            self.display_lyrics_on_screen(settings.value('lyrics_screen'))

        if settings.contains('control_window_position'):
            self.move(settings.value('control_window_position'))

        for key in settings.allKeys():
            self.settings[key] = settings.value(key)

        # self.settings.update(settings)

        self.songtext_widget.set_font_size(self.settings['font_size'])
        self.songtext_widget.set_line_increment(self.settings['line_increment'])

        # except (FileNotFoundError, ValueError):
        #     pass

        if not os.path.exists(self.lyrics_language_path) or not self.settings['lyrics_language']:
            languages = list(
                filter(lambda p: os.path.isdir(os.path.join(self.lyrics_path, p)) and p != "timings",
                       os.listdir(self.lyrics_path))
            )
            self.settings['lyrics_language'] = languages[0] if languages else ""
Exemplo n.º 27
0
class MusicPlayer(QMainWindow):
    """MusicPlayer houses all of elements that directly interact with the main window."""

    def __init__(self, parent=None):
        """Initialize the QMainWindow widget.

        The window title, window icon, and window size are initialized here as well
        as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar,
        QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and
        QVBoxLayout. The connect signals for relavant widgets are also initialized.
        """
        super(MusicPlayer, self).__init__(parent)
        self.setWindowTitle('Mosaic')

        window_icon = utilities.resource_filename('mosaic.images', 'icon.png')
        self.setWindowIcon(QIcon(window_icon))
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

        # Initiates Qt objects to be used by MusicPlayer
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist_location = defaults.Settings().playlist_path
        self.content = QMediaContent()
        self.menu = self.menuBar()
        self.toolbar = QToolBar()
        self.art = QLabel()
        self.pixmap = QPixmap()
        self.slider = QSlider(Qt.Horizontal)
        self.duration_label = QLabel()
        self.playlist_dock = QDockWidget('Playlist', self)
        self.library_dock = QDockWidget('Media Library', self)
        self.playlist_view = QListWidget()
        self.library_view = library.MediaLibraryView()
        self.library_model = library.MediaLibraryModel()
        self.preferences = configuration.PreferencesDialog()
        self.widget = QWidget()
        self.layout = QVBoxLayout(self.widget)
        self.duration = 0
        self.playlist_dock_state = None
        self.library_dock_state = None

        # Sets QWidget() as the central widget of the main window
        self.setCentralWidget(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # Initiates the playlist dock widget and the library dock widget
        self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock)
        self.playlist_dock.setWidget(self.playlist_view)
        self.playlist_dock.setVisible(defaults.Settings().playlist_on_start)
        self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable)

        self.addDockWidget(defaults.Settings().dock_position, self.library_dock)
        self.library_dock.setWidget(self.library_view)
        self.library_dock.setVisible(defaults.Settings().media_library_on_start)
        self.library_dock.setFeatures(QDockWidget.DockWidgetClosable)
        self.tabifyDockWidget(self.playlist_dock, self.library_dock)

        # Sets the range of the playback slider and sets the playback mode as looping
        self.slider.setRange(0, self.player.duration() / 1000)
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        # OSX system menu bar causes conflicts with PyQt5 menu bar
        if sys.platform == 'darwin':
            self.menu.setNativeMenuBar(False)

        # Initiates Settings in the defaults module to give access to settings.toml
        defaults.Settings()

        # Signals that connect to other methods when they're called
        self.player.metaDataChanged.connect(self.display_meta_data)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.song_duration)
        self.player.positionChanged.connect(self.song_position)
        self.player.stateChanged.connect(self.set_state)
        self.playlist_view.itemActivated.connect(self.activate_playlist_item)
        self.library_view.activated.connect(self.open_media_library)
        self.playlist.currentIndexChanged.connect(self.change_index)
        self.playlist.mediaInserted.connect(self.initialize_playlist)
        self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.library_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path)
        self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size)
        self.art.mousePressEvent = self.press_playback

        # Creating the menu controls, media controls, and window size of the music player
        self.menu_controls()
        self.media_controls()
        self.load_saved_playlist()

    def menu_controls(self):
        """Initiate the menu bar and add it to the QMainWindow widget."""
        self.file = self.menu.addMenu('File')
        self.edit = self.menu.addMenu('Edit')
        self.playback = self.menu.addMenu('Playback')
        self.view = self.menu.addMenu('View')
        self.help_ = self.menu.addMenu('Help')

        self.file_menu()
        self.edit_menu()
        self.playback_menu()
        self.view_menu()
        self.help_menu()

    def media_controls(self):
        """Create the bottom toolbar and controls used for media playback."""
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
        self.play_action = QAction(QIcon(play_icon), 'Play', self)
        self.play_action.triggered.connect(self.player.play)

        stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png')
        self.stop_action = QAction(QIcon(stop_icon), 'Stop', self)
        self.stop_action.triggered.connect(self.player.stop)

        previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png')
        self.previous_action = QAction(QIcon(previous_icon), 'Previous', self)
        self.previous_action.triggered.connect(self.previous)

        next_icon = utilities.resource_filename('mosaic.images', 'md_next.png')
        self.next_action = QAction(QIcon(next_icon), 'Next', self)
        self.next_action.triggered.connect(self.playlist.next)

        repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
        self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self)
        self.repeat_action.setShortcut('R')
        self.repeat_action.triggered.connect(self.repeat_song)

        self.toolbar.addAction(self.play_action)
        self.toolbar.addAction(self.stop_action)
        self.toolbar.addAction(self.previous_action)
        self.toolbar.addAction(self.next_action)
        self.toolbar.addAction(self.repeat_action)
        self.toolbar.addWidget(self.slider)
        self.toolbar.addWidget(self.duration_label)

    def file_menu(self):
        """Add a file menu to the menu bar.

        The file menu houses the Open File, Open Multiple Files, Open Playlist,
        Open Directory, and Exit Application menu items.
        """
        self.open_action = QAction('Open File', self)
        self.open_action.setShortcut('O')
        self.open_action.triggered.connect(self.open_file)

        self.open_multiple_files_action = QAction('Open Multiple Files', self)
        self.open_multiple_files_action.setShortcut('M')
        self.open_multiple_files_action.triggered.connect(self.open_multiple_files)

        self.open_playlist_action = QAction('Open Playlist', self)
        self.open_playlist_action.setShortcut('CTRL+P')
        self.open_playlist_action.triggered.connect(self.open_playlist)

        self.open_directory_action = QAction('Open Directory', self)
        self.open_directory_action.setShortcut('D')
        self.open_directory_action.triggered.connect(self.open_directory)

        self.save_playlist_action = QAction('Save Playlist', self)
        self.save_playlist_action.setShortcut('CTRL+S')
        self.save_playlist_action.triggered.connect(self.save_playlist)

        self.exit_action = QAction('Quit', self)
        self.exit_action.setShortcut('CTRL+Q')
        self.exit_action.triggered.connect(self.closeEvent)

        self.file.addAction(self.open_action)
        self.file.addAction(self.open_multiple_files_action)
        self.file.addAction(self.open_playlist_action)
        self.file.addAction(self.open_directory_action)
        self.file.addSeparator()
        self.file.addAction(self.save_playlist_action)
        self.file.addSeparator()
        self.file.addAction(self.exit_action)

    def edit_menu(self):
        """Add an edit menu to the menu bar.

        The edit menu houses the preferences item that opens a preferences dialog
        that allows the user to customize features of the music player.
        """
        self.preferences_action = QAction('Preferences', self)
        self.preferences_action.setShortcut('CTRL+SHIFT+P')
        self.preferences_action.triggered.connect(lambda: self.preferences.exec_())

        self.edit.addAction(self.preferences_action)

    def playback_menu(self):
        """Add a playback menu to the menu bar.

        The playback menu houses
        """
        self.play_playback_action = QAction('Play', self)
        self.play_playback_action.setShortcut('P')
        self.play_playback_action.triggered.connect(self.player.play)

        self.stop_playback_action = QAction('Stop', self)
        self.stop_playback_action.setShortcut('S')
        self.stop_playback_action.triggered.connect(self.player.stop)

        self.previous_playback_action = QAction('Previous', self)
        self.previous_playback_action.setShortcut('B')
        self.previous_playback_action.triggered.connect(self.previous)

        self.next_playback_action = QAction('Next', self)
        self.next_playback_action.setShortcut('N')
        self.next_playback_action.triggered.connect(self.playlist.next)

        self.playback.addAction(self.play_playback_action)
        self.playback.addAction(self.stop_playback_action)
        self.playback.addAction(self.previous_playback_action)
        self.playback.addAction(self.next_playback_action)

    def view_menu(self):
        """Add a view menu to the menu bar.

        The view menu houses the Playlist, Media Library, Minimalist View, and Media
        Information menu items. The Playlist item toggles the playlist dock into and
        out of view. The Media Library items toggles the media library dock into and
        out of view. The Minimalist View item resizes the window and shows only the
        menu bar and player controls. The Media Information item opens a dialog that
        shows information relevant to the currently playing song.
        """
        self.dock_action = self.playlist_dock.toggleViewAction()
        self.dock_action.setShortcut('CTRL+ALT+P')

        self.library_dock_action = self.library_dock.toggleViewAction()
        self.library_dock_action.setShortcut('CTRL+ALT+L')

        self.minimalist_view_action = QAction('Minimalist View', self)
        self.minimalist_view_action.setShortcut('CTRL+ALT+M')
        self.minimalist_view_action.setCheckable(True)
        self.minimalist_view_action.triggered.connect(self.minimalist_view)

        self.view_media_info_action = QAction('Media Information', self)
        self.view_media_info_action.setShortcut('CTRL+SHIFT+M')
        self.view_media_info_action.triggered.connect(self.media_information_dialog)

        self.view.addAction(self.dock_action)
        self.view.addAction(self.library_dock_action)
        self.view.addSeparator()
        self.view.addAction(self.minimalist_view_action)
        self.view.addSeparator()
        self.view.addAction(self.view_media_info_action)

    def help_menu(self):
        """Add a help menu to the menu bar.

        The help menu houses the about dialog that shows the user information
        related to the application.
        """
        self.about_action = QAction('About', self)
        self.about_action.setShortcut('H')
        self.about_action.triggered.connect(lambda: about.AboutDialog().exec_())

        self.help_.addAction(self.about_action)

    def open_file(self):
        """Open the selected file and add it to a new playlist."""
        filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            file_info = QFileInfo(filename).fileName()
            playlist_item = QListWidgetItem(file_info)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename)))
            self.player.setPlaylist(self.playlist)
            playlist_item.setToolTip(file_info)
            self.playlist_view.addItem(playlist_item)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_multiple_files(self):
        """Open the selected files and add them to a new playlist."""
        filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            self.playlist.clear()
            self.playlist_view.clear()
            for file in natsort.natsorted(filenames, alg=natsort.ns.PATH):
                file_info = QFileInfo(file).fileName()
                playlist_item = QListWidgetItem(file_info)
                self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                self.player.setPlaylist(self.playlist)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)
                self.playlist_view.setCurrentRow(0)
                self.player.play()

    def open_playlist(self):
        """Load an M3U or PLS file into a new playlist."""
        playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly)

        if success:
            playlist = QUrl.fromLocalFile(playlist)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def save_playlist(self):
        """Save the media in the playlist dock as a new M3U playlist."""
        playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '')
        if success:
            saved_playlist = "{}.m3u" .format(playlist)
            self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u")

    def load_saved_playlist(self):
        """Load the saved playlist if user setting permits."""
        saved_playlist = "{}/.m3u" .format(self.playlist_location)
        if os.path.exists(saved_playlist):
            playlist = QUrl().fromLocalFile(saved_playlist)
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)

    def open_directory(self):
        """Open the selected directory and add the files within to an empty playlist."""
        directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly)

        if directory:
            self.playlist.clear()
            self.playlist_view.clear()
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

            self.player.setPlaylist(self.playlist)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_media_library(self, index):
        """Open a directory or file from the media library into an empty playlist."""
        self.playlist.clear()
        self.playlist_view.clear()

        if self.library_model.fileName(index).endswith(('mp3', 'flac')):
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index))))
            self.playlist_view.addItem(self.library_model.fileName(index))

        elif self.library_model.isDir(index):
            directory = self.library_model.filePath(index)
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

        self.player.setPlaylist(self.playlist)
        self.player.play()

    def display_meta_data(self):
        """Display the current song's metadata in the main window.

        If the current song contains metadata, its cover art is extracted and shown in
        the main window while the track number, artist, album, and track title are shown
        in the window title.
        """
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
            (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path)

            try:
                self.pixmap.loadFromData(artwork)
            except TypeError:
                self.pixmap = QPixmap(artwork)

            meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title)

            self.setWindowTitle(meta_data)
            self.art.setScaledContents(True)
            self.art.setPixmap(self.pixmap)
            self.layout.addWidget(self.art)

    def initialize_playlist(self, start):
        """Display playlist and reset playback mode when media inserted into playlist."""
        if start == 0:
            if self.library_dock.isVisible():
                self.playlist_dock.setVisible(True)
                self.playlist_dock.show()
                self.playlist_dock.raise_()

            if self.playlist.playbackMode() != QMediaPlaylist.Sequential:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
                self.repeat_action.setIcon(QIcon(repeat_icon))

    def press_playback(self, event):
        """Change the playback of the player on cover art mouse event.

        When the cover art is clicked, the player will play the media if the player is
        either paused or stopped. If the media is playing, the media is set
        to pause.
        """
        if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked():
            if (self.player.state() == QMediaPlayer.StoppedState or
                    self.player.state() == QMediaPlayer.PausedState):
                self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()

    def seek(self, seconds):
        """Set the position of the song to the position dragged to by the user."""
        self.player.setPosition(seconds * 1000)

    def song_duration(self, duration):
        """Set the slider to the duration of the currently played media."""
        duration /= 1000
        self.duration = duration
        self.slider.setMaximum(duration)

    def song_position(self, progress):
        """Move the horizontal slider in sync with the duration of the song.

        The progress is relayed to update_duration() in order
        to display the time label next to the slider.
        """
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.update_duration(progress)

    def update_duration(self, current_duration):
        """Calculate the time played and the length of the song.

        Both of these times are sent to duration_label() in order to display the
        times on the toolbar.
        """
        duration = self.duration

        if current_duration or duration:
            time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60,
                                (current_duration % 60), (current_duration * 1000) % 1000)
            song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60),
                                (duration * 1000) % 1000)

            if duration > 3600:
                time_format = "hh:mm:ss"
            else:
                time_format = "mm:ss"

            time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format))

        else:
            time_display = ""

        self.duration_label.setText(time_display)

    def set_state(self, state):
        """Change the icon in the toolbar in relation to the state of the player.

        The play icon changes to the pause icon when a song is playing and
        the pause icon changes back to the play icon when either paused or
        stopped.
        """
        if self.player.state() == QMediaPlayer.PlayingState:
            pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png')
            self.play_action.setIcon(QIcon(pause_icon))
            self.play_action.triggered.connect(self.player.pause)

        elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState):
            self.play_action.triggered.connect(self.player.play)
            play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
            self.play_action.setIcon(QIcon(play_icon))

    def previous(self):
        """Move to the previous song in the playlist.

        Moves to the previous song in the playlist if the current song is less
        than five seconds in. Otherwise, restarts the current song.
        """
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def repeat_song(self):
        """Set the current media to repeat and change the repeat icon accordingly.

        There are four playback modes: repeat none, repeat all, repeat once, and shuffle.
        Clicking the repeat button cycles through each playback mode.
        """
        if self.playlist.playbackMode() == QMediaPlaylist.Sequential:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Loop:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Random:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

    def activate_playlist_item(self, item):
        """Set the active media to the playlist item dobule-clicked on by the user."""
        current_index = self.playlist_view.row(item)
        if self.playlist.currentIndex() != current_index:
            self.playlist.setCurrentIndex(current_index)

        if self.player.state() != QMediaPlayer.PlayingState:
            self.player.play()

    def change_index(self, row):
        """Highlight the row in the playlist of the active media."""
        self.playlist_view.setCurrentRow(row)

    def minimalist_view(self):
        """Resize the window to only show the menu bar and audio controls."""
        if self.minimalist_view_action.isChecked():

            if self.playlist_dock.isVisible():
                self.playlist_dock_state = True
            if self.library_dock.isVisible():
                self.library_dock_state = True

            self.library_dock.close()
            self.playlist_dock.close()

            QTimer.singleShot(10, lambda: self.resize(500, 0))

        else:
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

            if self.library_dock_state:
                self.library_dock.setVisible(True)

            if self.playlist_dock_state:
                self.playlist_dock.setVisible(True)

    def dock_visiblity_change(self, visible):
        """Change the size of the main window when the docks are toggled."""
        if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6,
                        self.height())

        elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif (not visible and not self.playlist_dock.isVisible() and not
                self.library_dock.isVisible()):
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def media_information_dialog(self):
        """Show a dialog of the current song's metadata."""
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
        else:
            file_path = None
        dialog = information.InformationDialog(file_path)
        dialog.exec_()

    def change_window_size(self):
        """Change the window size of the music player."""
        self.playlist_dock.close()
        self.library_dock.close()
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def change_media_library_path(self, path):
        """Change the media library path to the new path selected in the preferences dialog."""
        self.library_model.setRootPath(path)
        self.library_view.setModel(self.library_model)
        self.library_view.setRootIndex(self.library_model.index(path))

    def closeEvent(self, event):
        """Override the PyQt close event in order to handle save playlist on close."""
        playlist = "{}/.m3u" .format(self.playlist_location)
        if defaults.Settings().save_playlist_on_close:
            self.playlist.save(QUrl().fromLocalFile(playlist), "m3u")
        else:
            if os.path.exists(playlist):
                os.remove(playlist)
        QApplication.quit()
Exemplo n.º 28
0
class Music_App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'Music Player'
        self.left = 20
        self.top = 30
        self.width = 600
        self.height = 400
        self.root_Gui()
        self.song_path = ""
        self.q_path = ""
        #initializing playlist and player

        self.Playlist = QMediaPlaylist()
        self.Player = QMediaPlayer()

        self.button_stat = -1
        #self.sp_st_cam= -1

    def root_Gui(self):
        #base of GUI

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.menu()
        self.main_buttons()
        self.status_bar()
        self.show()

    def menu(self):
        #menu of GUI

        main_menu = self.menuBar()
        file_menu = main_menu.addMenu('File')
        tools_menu = main_menu.addMenu('Tools')
        help__menu = main_menu.addMenu('Help')
        exit_ = main_menu.addMenu('Exit')

        file_menu.addAction(self.open_file())
        file_menu.addAction(self.exit_button())
        exit_.addAction(self.exit_button())

    def main_buttons(self):
        #different button available in GUI

        play_button = QPushButton('Play', self)
        play_button.setToolTip("To play the song click it.")
        play_button.move(100, 80)
        play_button.clicked.connect(self.play_button)

        pause_button = QPushButton('Pause', self)
        pause_button.setToolTip("To pause the song click it.")
        pause_button.move(200, 80)
        pause_button.clicked.connect(self.pause_button)

        next_button = QPushButton('Next', self)
        next_button.setToolTip('Play Next Song')
        next_button.move(300, 80)
        next_button.clicked.connect(self.next_button)

        prev_button = QPushButton('Prev', self)
        prev_button.setToolTip('Play Previous Song')
        prev_button.move(400, 80)
        prev_button.clicked.connect(self.prev_button)

        plusV_button = QPushButton('+ Vol', self)
        plusV_button.setToolTip('Increase Volume')
        plusV_button.move(100, 110)
        plusV_button.clicked.connect(self.plusV_button)

        minsV_button = QPushButton('- Vol', self)
        minsV_button.setToolTip('Decrease Volume')
        minsV_button.move(200, 110)
        minsV_button.clicked.connect(self.minsV_button)

        stop_button = QPushButton('Stop', self)
        stop_button.setToolTip('Stop Song')
        stop_button.move(300, 110)
        stop_button.clicked.connect(self.stop_button)

        info_button = QPushButton('Song Details', self)
        info_button.setToolTip('Get Song Details')
        info_button.move(400, 110)
        info_button.clicked.connect(self.info_button)

    #play button handler
    def play_button(self):
        print("Playing Music")
        if self.Playlist.mediaCount() == 0:
            self.file_dialog()
        elif self.Playlist.mediaCount() != 0:
            self.button_stat = 1
            self.Player.play()

    #pause button handler
    def pause_button(self):
        print("Pause Music")
        self.button_stat = 2
        self.Player.pause()

    #prev button handler
    def prev_button(self):
        print("Next Song")
        if self.Playlist.mediaCount() == 0:
            self.file_dialog()
        elif self.Playlist.mediaCount != 0:
            self.Player.playlist().previous()

    #next button handler
    def next_button(self):
        print("Prev Song")
        if self.Playlist.mediaCount() == 0:
            self.file_dialog()
        elif self.Playlist.mediaCount() != 0:
            self.Player.playlist().next()

    #info button handler

    def info_button(self):
        print("\n  info button")
        song = eyed3.load(self.song_path)
        artist = song.tag.artist
        album = song.tag.album
        title = song.tag.title

        s_detail = 'Artist : ' + artist + '\n\tAlbum : ' + album + '\n\tTitle : ' + title

        song_det = QMessageBox(self)
        song_det.setWindowTitle('Song Details')
        song_det.setText(s_detail)
        song_det.show()

    #volume button handler
    def plusV_button(self):
        print("Plus Volume")
        vol_ = self.Player.volume()
        vol_ = min(100, vol_ + 5)
        self.Player.setVolume(vol_)

    def minsV_button(self):
        print("Minus Volume")
        vol_ = self.Player.volume()
        vol_ = max(100, vol_ - 5)
        self.Player.setVolume(vol_)

    #stop button handler
    def stop_button(self):
        print("Stopping Music")
        self.button_stat = 3
        self.Player.stop()
        self.Playlist.clear()
        self.statusBar().showMessage("Music Stopped")

    #open file dialog

    def open_file(self):
        fopen_button = QAction('Open File', self)
        #fopen_button.setShortcut('CTRL+O')
        fopen_button.setStatusTip('Open Music File')
        fopen_button.triggered.connect(self.file_dialog)
        return fopen_button

    #EXIT button handler

    def exit_button(self):
        exit_Button = QAction('Exit', self)
        #exit_Button.setShortcut('CTRL+Q')
        exit_Button.setStatusTip('Exit Application')
        exit_Button.triggered.connect(self.close_msg)
        return exit_Button

    def show_qoute(self, q_path):

        q_img = Image.open(q_path)
        q_img.show()

    def song_play(self, song_path):
        self.button_stat = 1
        self.Playlist.addMedia(
            QMediaContent(QUrl.fromLocalFile(self.song_path)))
        self.Player.setPlaylist(self.Playlist)
        self.Player.setVolume(50)
        self.Player.play()

    #file dialog handler
    def file_dialog(self):
        fName = QFileDialog.getOpenFileName(
            self, "Select A Song", "~", "All Files (*) ;;  Mp3 Files(*.mp3)")

        if fName[0] == '':
            print("No file Selected")

        elif self.Playlist.mediaCount() == 0:
            #print(QUrl(fName[0]))

            self.song_path = fName[0]
            self.button_stat = 1
            self.Playlist.addMedia(QMediaContent(QUrl.fromLocalFile(fName[0])))
            self.Player.setPlaylist(self.Playlist)
            self.Player.setVolume(50)
            self.Player.play()

        else:

            self.Playlist.addMedia(QMediaContent(QUrl(fName[0])))

    #close/exit handler
    def close_msg(self):
        msg = QMessageBox.question(self, 'Close Msg', 'Click Yes to Close',
                                   QMessageBox.Yes, QMessageBox.No)

        if msg == QMessageBox.Yes:
            self._obj.change_f(1)
            self.close()
            print('Closing App')
        else:
            print('Not Closing')

    #status  handler
    def status_bar(self):
        self.statusBar().showMessage('ViAna Music Player')
Exemplo n.º 29
0
class Ui_Dialog(QMainWindow):

    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.palette = QPalette()
        self.VerticalLayout = QVBoxLayout()
        self.userAction = -1  # 0- stopped, 1- playing 2-paused
        self.width = 550
        self.height = 700
        self.PlayerIsActive = 0 # 0 - not active, 1 - active
        self.nameFont = 'Plug_2.png'

        self.msgBox = QMessageBox()

    def setupUi(self, Dialog):
        Dialog.resize(self.width, self.height)
        Dialog.setWindowTitle('MyPlayer')
        Dialog.setWindowIcon(QIcon(self.nameFont))


        # Add MainMenu
        self.mainMenu = QMenuBar(Dialog)
        self.fileMenu = self.mainMenu.addMenu('File')
        self.ChangeThemeMenu = self.mainMenu.addMenu('Change')
        self.DataBaseSongs = self.mainMenu.addMenu('Recommend')
        self.helpMenu = self.mainMenu.addMenu('About')


        # Add In Menu Actions
        self.openAction = QAction('Open File')
        self.openAction.setShortcut('Ctrl+O')
        self.openActions = QAction('Open Directory')
        self.exitAction = QAction('Exit')
        self.exitAction.setShortcut('Ctrl+Q')

        self.loadBackgroung = QAction('Load my background')
        self.changeBlack = QAction('Change Black')
        self.changeWhite = QAction('Change white')

        self.RecommendedDataBase = QAction('Recommended data base of songs')

        self.Developer = QAction('About Developer')
        self.Program = QAction('About Program')
        self.Help_ = QAction('Help')


        # Add to Menus Actions
        self.fileMenu.addAction(self.openAction)
        self.fileMenu.addAction(self.openActions)
        self.fileMenu.addAction(self.exitAction)
        self.ChangeThemeMenu.addAction(self.changeBlack)
        self.ChangeThemeMenu.addAction(self.changeWhite)
        self.ChangeThemeMenu.addAction(self.loadBackgroung)
        self.DataBaseSongs.addAction(self.RecommendedDataBase)
        self.helpMenu.addAction(self.Developer)
        self.helpMenu.addAction(self.Program)
        self.helpMenu.addAction(self.Help_)


        # Create Slider Volume
        self.volumeslider = QSlider(Qt.Horizontal, Dialog)
        self.volumeslider.setFocusPolicy(Qt.NoFocus)
        self.volumeslider.setGeometry(420, 650, 120, 30)
        self.volumeslider.setValue(100)
        self.volumeslider.setTickInterval(20)
        self.volumeslider.setTickPosition(QSlider.TicksBelow)
        self.volumeslider.valueChanged[int].connect(self.changeVolume)

        #Create Slider Status of song
        self.songSlider = QSlider(Qt.Horizontal, Dialog)
        self.songSlider.setGeometry(17, 602, 521, 15)
        self.songSlider.setRange(0, 0)
        self.songSlider.sliderMoved.connect(self.set_position)



        # Add labels
        self.timeInStart = QLabel(Dialog)
        self.timeInStart.setGeometry(10, 612, 70, 25)
        self.AllTimeSong = QLabel(Dialog)
        self.AllTimeSong.setGeometry(500, 610, 70, 25)
        self.PictureAlbum = QLabel(Dialog)
        self.PictureAlbum.setGeometry(20, 170, 300, 300)
        self.showInfoToMusic_1 = QLabel(Dialog)
        self.showInfoToMusic_2 = QLabel(Dialog)
        self.showInfoToMusic_3 = QLabel(Dialog)
        self.showInfoToMusic_4 = QLabel(Dialog)

        # Add labals in Vertical layout widget
        self.verticalLayoutWidget = QtWidgets.QWidget(Dialog)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(350, 230, 200, 200))
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.showInfoToMusic_1 = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.verticalLayout.addWidget(self.showInfoToMusic_1)
        self.showInfoToMusic_1.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
        self.showInfoToMusic_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.verticalLayout.addWidget(self.showInfoToMusic_2)
        self.showInfoToMusic_2.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
        self.showInfoToMusic_3 = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.verticalLayout.addWidget(self.showInfoToMusic_3)
        self.showInfoToMusic_3.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))
        self.showInfoToMusic_4 = QtWidgets.QLabel(self.verticalLayoutWidget)
        self.verticalLayout.addWidget(self.showInfoToMusic_4)
        self.showInfoToMusic_4.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold))


        #Create buttons
            #initialization
        self.PlayBtn = QPushButton(Dialog)
        self.StopBtn = QPushButton(Dialog)
        self.BreakBtn = QPushButton(Dialog)
        self.NextBtn = QPushButton(Dialog)
        self.PrevBtn = QPushButton(Dialog)
        self.shuffleBtn = QPushButton(Dialog)


            #Show buttons
        self.PlayBtn.setGeometry(QtCore.QRect(245, 630, 60, 60))
        self.PlayBtn.setStyleSheet('''background: transparent;
                                         border-image: url(Play.png) ''')

        self.StopBtn.setGeometry(QtCore.QRect(190, 635, 55, 55))
        self.StopBtn.setStyleSheet('''background: transparent;
                                         border-image: url(Stop.png)''')


        self.BreakBtn.setGeometry(QtCore.QRect(305, 635, 55, 55))
        self.BreakBtn.setStyleSheet('''background: transparent;
                                         border-image: url(Break.png) ''')

        self.NextBtn.setGeometry(QtCore.QRect(355, 635, 55, 55))
        self.NextBtn.setStyleSheet('''background: transparent;
                                         border-image: url(Next_song.png) ''')

        self.PrevBtn.setGeometry(QtCore.QRect(140, 635, 55, 55))
        self.PrevBtn.setStyleSheet('''background: transparent;
                                         border-image: url(Prev_song.png) ''')

        self.shuffleBtn.setGeometry(QtCore.QRect(90, 635, 55, 55))
        self.shuffleBtn.setStyleSheet('''background: transparent;
                                            border-image: url(Shuffle_.png) ''')



        # Events
        self.player.positionChanged.connect(self.position_changed)
        self.player.durationChanged.connect(self.duration_changed)
        self.RecommendedDataBase.triggered.connect(self.connect_list)

        self.exitAction.triggered.connect(self.quit_trigger)
        self.openAction.triggered.connect(self.file_open)
        self.openActions.triggered.connect(self.addFiles)

        self.PlayBtn.clicked.connect(self.playMusic)
        self.BreakBtn.clicked.connect(self.stopMusic)
        self.StopBtn.clicked.connect(self.pauseMusic)

        self.PrevBtn.clicked.connect(self.prevSong)
        self.shuffleBtn.clicked.connect(self.shufflelist)
        self.NextBtn.clicked.connect(self.nextSong)

        self.loadBackgroung.triggered.connect(self.LoadYourBackground)
        self.changeBlack.triggered.connect(self.ChangeBlackTheme)
        self.changeWhite.triggered.connect(self.ChangeWhiteTheme)

        self.Developer.triggered.connect(self.AboutDeveloper)
        self.Program.triggered.connect(self.AboutProgram)
        self.Help_.triggered.connect(self.Help)

        self.ChangeBlackTheme()

        QtCore.QMetaObject.connectSlotsByName(Dialog)


    # Triggered function
    def AboutDeveloper(self):
        textOnDev = open('Developer.txt').read()
        self.msgBox.setStyleSheet('QMessageBox {background-image: url(BlackFont.png)}')
        self.msgBox.setText('About Developer')
        self.msgBox.setInformativeText(textOnDev)
        self.msgBox.setStandardButtons(QMessageBox.Close)
        self.msgBox.show()

    def AboutProgram(self):
        TextOnDev = open('Program.txt').read()
        self.msgBox.setStyleSheet('QMessageBox {background-image: url(BlackFont.png)}')
        self.msgBox.setText('About Program')
        self.msgBox.setInformativeText(TextOnDev)
        self.msgBox.setStandardButtons(QMessageBox.Close)
        self.msgBox.show()

    def Help(self):
        TextOnDev = open('Help.txt').read()
        self.msgBox.setStyleSheet('QMessageBox {background-image: url(BlackFont.png)}')
        self.msgBox.setText('Help')
        self.msgBox.setInformativeText(TextOnDev)
        self.msgBox.setStandardButtons(QMessageBox.Close)
        self.msgBox.show()

    def connect_list(self):
        self.w2 = Window2()
        dic_music = MusicParser.parse()
        x = 550
        y = 50
        for i, j in dic_music.items():
            #h = QLabel(self.w2)
            #h.setGeometry(10,0, x,y)
            verticalLayoutWidget = QtWidgets.QWidget(self.w2)
            verticalLayoutWidget.setGeometry(QtCore.QRect(10, 0, x, y))
            verticalLayout = QtWidgets.QVBoxLayout(verticalLayoutWidget)
            verticalLayout.setContentsMargins(0, 0, 0, 0)
            left_label = QLabel(verticalLayoutWidget)
            verticalLayout.addWidget(left_label)
            left_label.setFont(QtGui.QFont("Times", 9, QtGui.QFont.Bold))
            left_label.setText(i + ' - ' + j)
            y += 60

        self.w2.show()

    def position_changed(self, position):
        self.songSlider.setValue(position)
        self.timeInStart.setText(str(time.strftime("%M:%S", time.gmtime(position / 1000))))

    def duration_changed(self, duration):
        self.songSlider.setRange(0, duration)

    def set_position(self, position):
        self.player.setPosition(position)

    def quit_trigger(self):
        qApp.quit()

    def file_open(self):
        self.song = QFileDialog.getOpenFileName(self, "Open Song", "", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")
        if self.song[0] != '':
            self.PlayerIsActive = 1
            url = QUrl.fromLocalFile(self.song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1

            else:
                self.playlist.addMedia(QMediaContent(url))

        if self.PlayerIsActive == 1:
            self.showImage()
            self.ShowInfoAboutSong()
            self.showSlider()

    def showSlider(self):
        self.songSlider.setMaximum(self.long)

    def showImage(self):
        self.audioFile = mutagen.File(self.song[0])
        pixmap_1 = QPixmap('Plug_2.png').scaled(300, 300)
        try:
            photo = self.audioFile.tags.getall('APIC')[0].data
            pixmap = QPixmap()
            pixmap.loadFromData(photo)
            pixmap.scaled(300, 300)
            self.PictureAlbum.setPixmap(pixmap)
        except IndexError:
            self.PictureAlbum.setPixmap(pixmap_1)


    def ShowInfoAboutSong(self):
        #Open song in mutagen
        audioFile = mutagen.File(self.song[0])
        #Create time label (all time song)
        self.long = audioFile.info.length

        #Open all info about song and editing
        singer = audioFile.tags.getall('TPE1')
        song_title = audioFile.tags.getall('TIT2')
        YearOfSong = audioFile.tags.getall('TDRC')
        Bitrate = (audioFile.info.bitrate) // 1000
        singer = str(singer[0])
        song_title = str(song_title[0])

        #show all info on labels
        try:
            self.AllTimeSong.setText(str(time.strftime("%M:%S", time.gmtime(round(self.long)))))
            self.showInfoToMusic_1.setToolTip(singer.encode('latin1').decode('cp1251'))
            self.showInfoToMusic_2.setToolTip(song_title.encode('latin1').decode('cp1251'))
            self.showInfoToMusic_1.setText(singer.encode('latin1').decode('cp1251'))
            self.showInfoToMusic_2.setWordWrap(True)
            self.showInfoToMusic_2.setText(song_title.encode('latin1').decode('cp1251'))
            self.showInfoToMusic_2.setWordWrap(True)
            self.showInfoToMusic_3.setText(str(YearOfSong[0]))
            self.showInfoToMusic_4.setText(str(Bitrate) + ' kbps')

        except IndexError:
            self.showInfoToMusic.setText('')
        except UnicodeEncodeError:
            self.showInfoToMusic_2.setText(song_title)
            self.showInfoToMusic_1.setText(singer)


    def show_more_music(self):
        try:
            self.audioFile = mutagen.File(self.sp_songs[self.playlist.currentIndex()])
            pixmap_1 = QPixmap('Plug_2.png').scaled(300, 300)
            try:
                photo = self.audioFile.tags.getall('APIC')[0].data
                pixmap = QPixmap()
                pixmap.loadFromData(photo)
                pixmap.scaled(300, 300)
                self.PictureAlbum.setPixmap(pixmap)
            except IndexError:
                self.PictureAlbum.setPixmap(pixmap_1)

        except IndexError:
            pass
        try:
            self.index = 0
            audioFile = mutagen.File(self.sp_songs[self.playlist.currentIndex()])
            self.long = audioFile.info.length
            singer = audioFile.tags.getall('TPE1')
            song_title = audioFile.tags.getall('TIT2')
            YearOfSong = audioFile.tags.getall('TDRC')
            Bitrate = (audioFile.info.bitrate) // 1000
            singer = str(singer[0])
            song_title = str(song_title[0])
            try:
                self.AllTimeSong.setText(str(time.strftime("%M:%S", time.gmtime(round(self.long)))))
                self.showInfoToMusic_1.setToolTip(singer.encode('latin1').decode('cp1251'))
                self.showInfoToMusic_2.setToolTip(song_title.encode('latin1').decode('cp1251'))
                self.showInfoToMusic_1.setText(singer.encode('latin1').decode('cp1251'))
                self.showInfoToMusic_2.setWordWrap(True)
                self.showInfoToMusic_2.setText(song_title.encode('latin1').decode('cp1251'))
                self.showInfoToMusic_2.setWordWrap(True)
                self.showInfoToMusic_3.setText(str(YearOfSong[0]))
                self.showInfoToMusic_4.setText(str(Bitrate) + ' kbps')
            except IndexError:
                self.showInfoToMusic.setText('')
            except UnicodeEncodeError:
                self.showInfoToMusic_2.setText(song_title)
                self.showInfoToMusic_1.setText(singer)
        except IndexError:
            pass

    def addFiles(self):
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            self.userAction = 1
            self.PlayerIsActive = 1
            self.show_more_music()
            self.playlist.currentIndexChanged.connect(self.show_more_music)


    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(self, 'Open Music Folder', '')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            self.sp_songs = []
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        self.sp_songs.append(it.filePath())
                        self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                self.sp_songs.append(it.filePath())
                fInfo = it.fileInfo()
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(it.filePath())))


    def ChangeBlackTheme(self):
        oImage = QImage("BlackFont.png")
        sImage = oImage.scaled(QtCore.QSize(self.width, self.height))
        self.palette.setBrush(QPalette.Window, QBrush(sImage))
        self.palette.setColor(QPalette.Text, Qt.white)
        self.palette.setColor(QPalette.WindowText, Qt.white)
        self.palette.setColor(QPalette.ToolTipText, Qt.white)
        QApplication.setPalette(self.palette)


    def ChangeWhiteTheme(self):
        oImage = QImage("WhiteFont_.jpg")
        sImage = oImage.scaled(QtCore.QSize(self.width, self.height))
        self.palette.setBrush(QPalette.Window, QBrush(sImage))
        self.palette.setColor(QPalette.Text, Qt.black)
        self.palette.setColor(QPalette.WindowText, Qt.black)
        self.palette.setColor(QPalette.ToolTipText, Qt.black)
        QApplication.setPalette(self.palette)


    def LoadYourBackground(self):
        font = QFileDialog.getOpenFileName(self, "Open Image", "", "Image Files (*.png *.jpg *.JPEG )")
        oImage = QImage(font[0])
        sImage = oImage.scaled(QtCore.QSize(self.width, self.height))
        self.palette.setBrush(QPalette.Window, QBrush(sImage))
        self.palette.setColor(QPalette.Text, Qt.white)
        self.palette.setColor(QPalette.WindowText, Qt.white)
        self.palette.setColor(QPalette.ToolTipText, Qt.white)
        QApplication.setPalette(self.palette)


    def playMusic(self):
        if self.playlist.mediaCount() == 0:
            self.file_open()

        elif self.playlist.mediaCount() != 0:
            self.player.play()
            self.userAction = 1
            self.PlayerIsActive = 1

    def pauseMusic(self):
        self.userAction = 2
        self.player.pause()
        self.PlayerIsActive = 0

    def stopMusic(self):
        self.PlayerIsActive = 0
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()

    def changeVolume(self, value):
        self.player.setVolume(value)

    def prevSong(self):
        if self.playlist.mediaCount() == 0:
            self.file_open()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().previous()
            try:
                self.show_more_music()
            except AttributeError:
                pass

    def shufflelist(self):
        if self.playlist.mediaCount() == 0:
            self.file_open()
        elif self.playlist.mediaCount() != 0:
            try:
                self.show_more_music()
                self.playlist.shuffle()
            except AttributeError:
                pass

    def nextSong(self):
        if self.playlist.mediaCount() == 0:
            self.file_open()
        elif self.playlist.mediaCount() != 0:
            try:
                self.player.playlist().next()
                self.show_more_music()
            except AttributeError:
                pass
Exemplo n.º 30
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.title = 'PyTunes'
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 150
        self.color = 0  # 0- toggle to dark 1- toggle to light
        self.userAction = -1  # 0- stopped, 1- playing 2-paused
        self.initUI()

    def initUI(self):
        # Add file menu
        menubar = self.menuBar()
        filemenu = menubar.addMenu('File')
        windowmenu = menubar.addMenu('Window')

        fileAct = QAction('Open File', self)
        folderAct = QAction('Open Folder', self)
        themeAct = QAction('Toggle light/dark theme', self)

        fileAct.setShortcut('Ctrl+O')
        folderAct.setShortcut('Ctrl+D')
        themeAct.setShortcut('Ctrl+T')

        filemenu.addAction(fileAct)
        filemenu.addAction(folderAct)
        windowmenu.addAction(themeAct)

        fileAct.triggered.connect(self.openFile)
        folderAct.triggered.connect(self.addFiles)
        themeAct.triggered.connect(self.toggleColors)

        self.addControls()

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.toggleColors()
        self.show()

    def addControls(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)
        # Add song controls
        volumeslider = QSlider(Qt.Horizontal, self)
        volumeslider.setFocusPolicy(Qt.NoFocus)
        volumeslider.valueChanged[int].connect(self.changeVolume)
        volumeslider.setValue(100)
        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        stopBtn = QPushButton('Stop')  # stop button
        # Add playlist controls
        prevBtn = QPushButton('Prev')
        shuffleBtn = QPushButton('Shuffle')
        nextBtn = QPushButton('Next')
        # Add button layouts
        controlArea = QVBoxLayout()  # centralWidget
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()
        # Add buttons to song controls layout
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)
        # Add buttons to playlist controls layout
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(shuffleBtn)
        playlistCtrlLayout.addWidget(nextBtn)
        # Add to vertical layout
        controlArea.addWidget(volumeslider)
        controlArea.addLayout(controls)
        controlArea.addLayout(playlistCtrlLayout)
        wid.setLayout(controlArea)
        # Connect each signal to their appropriate function
        playBtn.clicked.connect(self.playhandler)
        pauseBtn.clicked.connect(self.pausehandler)
        stopBtn.clicked.connect(self.stophandler)

        prevBtn.clicked.connect(self.prevSong)
        shuffleBtn.clicked.connect(self.shufflelist)
        nextBtn.clicked.connect(self.nextSong)

        self.statusBar()
        self.playlist.currentMediaChanged.connect(self.songChanged)

    def openFile(self):
        song = QFileDialog.getOpenFileName(
            self, "Open Song", "~", "Sound Files (*.mp3 *.ogg *.wav *.m4a)")

        if song[0] != '':
            url = QUrl.fromLocalFile(song[0])
            if self.playlist.mediaCount() == 0:
                self.playlist.addMedia(QMediaContent(url))
                self.player.setPlaylist(self.playlist)
                self.player.play()
                self.userAction = 1
            else:
                self.playlist.addMedia(QMediaContent(url))

    def addFiles(self):
        if self.playlist.mediaCount() != 0:
            self.folderIterator()
        else:
            self.folderIterator()
            self.player.setPlaylist(self.playlist)
            self.player.playlist().setCurrentIndex(0)
            self.player.play()
            self.userAction = 1

    def folderIterator(self):
        folderChosen = QFileDialog.getExistingDirectory(
            self, 'Open Music Folder', '~')
        if folderChosen != None:
            it = QDirIterator(folderChosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                        self.playlist.addMedia(
                            QMediaContent(QUrl.fromLocalFile(it.filePath())))
                it.next()
            if it.fileInfo().isDir() == False and it.filePath() != '.':
                fInfo = it.fileInfo()
                if fInfo.suffix() in ('mp3', 'ogg', 'wav', 'm4a'):
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(it.filePath())))

    def playhandler(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.play()
            self.userAction = 1

    def pausehandler(self):
        self.userAction = 2
        self.player.pause()

    def stophandler(self):
        self.userAction = 0
        self.player.stop()
        self.playlist.clear()
        self.statusBar().showMessage("Stopped and cleared playlist")

    def changeVolume(self, value):
        self.player.setVolume(value)

    def prevSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().previous()

    def shufflelist(self):
        self.playlist.shuffle()

    def nextSong(self):
        if self.playlist.mediaCount() == 0:
            self.openFile()
        elif self.playlist.mediaCount() != 0:
            self.player.playlist().next()

    def songChanged(self, media):
        if not media.isNull():
            url = media.canonicalUrl()
            self.statusBar().showMessage(url.fileName())

    def toggleColors(self):

        app.setStyle("Fusion")
        palette = QPalette()
        if self.color == 0:
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(25, 25, 25))
            palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.white)
            palette.setColor(QPalette.Button, QColor(53, 53, 53))
            palette.setColor(QPalette.ButtonText, Qt.white)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(235, 101, 54))
            palette.setColor(QPalette.Highlight, QColor(235, 101, 54))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 1
        elif self.color == 1:
            palette.setColor(QPalette.Window, Qt.white)
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, QColor(240, 240, 240))
            palette.setColor(QPalette.AlternateBase, Qt.white)
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, Qt.white)
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Link, QColor(66, 155, 248))
            palette.setColor(QPalette.Highlight, QColor(66, 155, 248))
            palette.setColor(QPalette.HighlightedText, Qt.black)
            app.setPalette(palette)
            self.color = 0
Exemplo n.º 31
0
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"))
Exemplo n.º 32
0
class MainWindow(QWidget):
    """Main player window"""
    def __init__(self):
        super().__init__()
        # UI
        self.ui = uic.loadUi("nobs_ui.ui", self)
        self.ui.setWindowTitle("NOBS Player")
        self.settings_dialog = SettingsDialog(self)
        self.settings = self.settings_dialog.settings
        # Variables
        self.sort_ascending = False
        # Library object
        self.lib = LibGrabber()
        self.lib.load_lib()
        # Player object
        self.player = QMediaPlayer()
        self.main_playlist = QMediaPlaylist()
        # Setup
        self.connect_slots()
        self.populate_podcast_list()
        self.view_all_episodes()
        # Go!
        self.show()

    def connect_slots(self):
        """Connect controls and events to functions"""
        # Events
        self.player.positionChanged.connect(self.show_position)
        self.player.stateChanged.connect(self.state_changed)
        self.player.mediaStatusChanged.connect(self.media_status_changed)
        self.ui.lstSubs.itemDoubleClicked.connect(self.view_episodes)
        self.ui.lstEps.itemDoubleClicked.connect(self.play_episode)
        self.ui.lstAllEps.itemDoubleClicked.connect(self.play_episode)
        # Controls
        self.ui.sldVolume.sliderMoved.connect(self.volume_changed)
        self.sldProgress.sliderMoved.connect(self.seek)
        self.btnPlayPause.clicked.connect(self.play_pause)
        self.btnFwd.clicked.connect(self.fwd)
        self.btnRwd.clicked.connect(self.rwd)
        self.btnSortEps.clicked.connect(self.sort_episodes)
        self.ui.btnSettings.clicked.connect(self.settings_dialog.show)
        self.ui.btnAddRss.clicked.connect(self.add_rss)
        self.ui.txtSubFilter.textChanged.connect(lambda: self.filter_sub(self.ui.lstSubs, self.ui.txtSubFilter.text()))
        self.ui.txtEpFilter.textChanged.connect(lambda: self.filter_sub(self.ui.lstEps, self.ui.txtEpFilter.text()))
        self.ui.txtAllEpFilter.textChanged.connect(lambda: self.filter_sub(self.ui.lstAllEps, self.ui.txtAllEpFilter.text()))

    def filter_sub(self, lst, filter_text):
        for i in range(lst.count()):
            item = lst.item(i)
            if filter_text:
                item.setHidden(not filter_text.lower() in item.text().lower())
            else:
                item.setHidden(False)

    # Media Buffering doesn't seem to want to play.
    def media_status_changed(self, media_status):
        pass
        # if media_status == QMediaPlayer.bufferStatusChanged():
        #     self.ui.lblBuffering.setText("Buffering")
        # else:
        #     self.ui.lblBuffering.setText("")

    def add_rss(self, _):
        url = self.ui.txtRssUrl.text()
        print(url)
        pass

    def sort_episodes(self):
        """Switch episode listing between ascending and descending list sort - is this even useful?"""
        # Current setting
        if self.sort_ascending:
            self.lstEps.sortItems(Qt.DescendingOrder)
            # toggle both the sort flag and the sort button icon
            self.sort_ascending = False
            self.btnSortEps.setIcon(QIcon(os.path.join("ui", "sort-ascending.png")))
        else:
            self.lstEps.sortItems(Qt.AscendingOrder)
            # toggle both the sort flag and the sort button icon
            self.sort_ascending = True
            self.btnSortEps.setIcon(QIcon(os.path.join("ui", "sort-descending.png")))

    def volume_changed(self, value):
        """Set volume and UI effects when volume slider is moved"""
        # Set player volume accordingly
        self.player.setVolume(value)
        # Set label to display volume level text
        self.ui.lblVolValue.setText(str(value))
        # Alter volume label image according to volume level
        if value == 0:
            self.ui.lblVolume.setPixmap(QPixmap(os.path.join('ui', 'mute_red.png')))
        elif 0 < value <= 33:
            self.ui.lblVolume.setPixmap(QPixmap(os.path.join('ui', 'volume1.png')))
        elif 33 < value <= 66:
            self.ui.lblVolume.setPixmap(QPixmap(os.path.join('ui', 'volume2.png')))
        elif 66 < value:
            self.ui.lblVolume.setPixmap(QPixmap(os.path.join('ui', 'volume3.png')))

    def populate_podcast_list(self):
        """List the podcasts themselves"""
        for feed in self.lib.feeds:
            if len(self.lib.raw_data[feed.pid]['episodes']) > 0:
                # Create new item with feed as data
                item = QListWidgetItem(self.ui.lstSubs)
                item.setData(Qt.UserRole, feed)
                item.setText(feed.title)
                # Add item to list
                self.ui.lstSubs.addItem(item)
                self.ui.lstSubs.update()
                self.ui.lstSubs.sortItems(Qt.AscendingOrder)

    def view_episodes(self, feed_item, clear: bool = True):
        """List the episodes associated with the current podcast item"""
        # Look up podcast dictionary in read JSON data
        print("Getting episode listing...")
        episodes = self.lib.raw_data[feed_item.data(Qt.UserRole).pid]['episodes']
        print("...done")
        print("Getting podcast title...")
        podcast_title = self.lib.raw_data[feed_item.data(Qt.UserRole).pid]['details'].get('title', "None")
        print("...done")
        # Switch to episode tab, display podcast title
        self.ui.tabWidget.setCurrentWidget(self.ui.tabEps)
        self.ui.lblCurrentShowTitle.setText(podcast_title)
        # Clear list for displaying one feed only
        if clear:
            self.ui.lstEps.clear()
        # Check how many to list (EPF = -1 means no restriction)
        if len(episodes) == 0:
            return

        eps_per_feed = self.settings['eps_per_feed']
        if eps_per_feed != -1:
            max_count = eps_per_feed
        print("set eps per feed")
        # Loop to max episode count OR to end of episode list
        ep_count = 0
        while ep_count < max_count:
            print(f"Count: {ep_count}")
            # Create new list item
            item = QListWidgetItem(self.ui.lstEps)
            item.setFlags(item.flags()|Qt.ItemIsUserCheckable)
            # Grab episode data
            episode = episodes[ep_count]
            title = episode.get('title', None)
            url = episode.get('link', None)
            published = episode.get('published', None)
            summary = episode.get('summary', None)
            # Parse date
            dt = self.extract_date(published) if published else None
            if dt:
                item.setText(
                    f"{dt.year}/{dt.month:02}/{dt.day:02} {dt.hour:02}:{dt.minute:02} | {episode.get('title', None)}")
            else:
                item.setText(episode.get("title", None))
            # Store data in named tuple, set as item data
            details = EpisodeDetails(podcast_title, title, url, summary, published, 0, 0)
            item.setData(Qt.UserRole, details)
            # Add item to list
            fp = os.path.join("imgs", self.lib.filename_friendly(podcast_title)+".png")
            self.ui.lstEps.addItem(item)
            ep_count += 1
        # Finally sort the items
        self.ui.lstEps.sortItems(Qt.DescendingOrder)

    @staticmethod
    def extract_date(date_string: str) -> datetime:
        """This was a pain in the hole"""
        # Anticipatory list of possible date formats to parse
        format_strings = ["%a, %d %b %Y %H:%M:%S %z",  # Tue, 22 Sep 2009 17:32:28 -0000
                          "%a, %d %b %Y %H:%M:%S %Z",  # Tue, 22 Sep 2009 17:32:28 GMT
                          "%d %b %Y %H:%M:%S %z",  # 22 Sep 2009 17:32:28 -0000
                          "%d %b %Y %H:%M:%S %Z",  # 22 Sep 2009 17:32:28 GMT
                          "%a, %d %b %Y %H:%M:%S",  # Tue, 22 Sep 2009 17:32:28
                          "%d %b %Y %H:%M:%S"]  # 22 Sep 2009 17:32:28
        # Attempt date parsing (I should really pay more attention to the exceptions)
        dt = None
        for format_string in format_strings:
            try:
                dt = datetime.strptime(date_string, format_string)
            except Exception as e:
                print(f"Error  parsing date:\n{date_string}\nError: {e}\n")
            if dt:
                return dt

    def view_all_episodes(self):  # Not up to date - rewrite to match code in view_episodes()
        """Populate the 'all episodes' tab.  This may end up being the only episodes tab"""
        for podcast in self.lib.feeds:
            podcast_title = self.lib.raw_data[podcast.pid]['details']['title']
            for episode in self.lib.raw_data[podcast.pid]['episodes']:
                # Create item
                item = QListWidgetItem(self.ui.lstAllEps)
                # Grab details
                title = episode.get('title', None)
                url = episode.get('link', None)
                published = episode.get('published', None)
                summary = episode.get('summary', None)
                # Date
                dt = self.extract_date(published) if published else None
                if dt:
                    item.setText(
                        f"{dt.year}/{dt.month:02}/{dt.day:02} {dt.hour:02}:{dt.minute:02} \
                        | {podcast_title} - {episode.get('title', None)}")
                else:
                    item.setText(f"0 -NO DATE- | {podcast_title} - {episode.get('title', None)}")
                # Store details in named tuple, set as item data
                details = EpisodeDetails(podcast.title, title, url, summary, published, 0, 0)
                item.setData(Qt.UserRole, details)
                # Add item to list
                self.ui.lstEps.addItem(item)
        self.ui.lstAllEps.sortItems(Qt.DescendingOrder)

    def play_episode(self, item):
        """Load file into media object, put it in a playlist object, send it around the world..."""
        # Load the track info named tuple from the item
        data = item.data(Qt.UserRole)
        # Create media object from URL
        track = QMediaContent(QUrl(data.url))
        # Get relevant date-time info
        date_string = " ".join(data.datetime.split()[:4])
        # Display track info
        self.ui.lblDate.setText(f"Published: {date_string}")
        self.ui.lblCurrentPodTitle.setText(data.podcast)
        self.ui.lblCurrentEpTitle.setText(data.title)
        # Actually play the thing
        self.main_playlist.clear()
        self.main_playlist.addMedia(track)
        self.player.setPlaylist(self.main_playlist)
        self.player.play()

    def show_position(self, position):
        """Displays values of track duration and progress, advances progress slider"""
        duration = self.player.duration()
        if duration == 0:
            self.ui.lblDuration.setText("Duration: please wait...")
        elif duration > 0:
            self.ui.sldProgress.setMaximum(duration)
            self.ui.sldProgress.setValue(position)
            # Calculate hours
            position_hours = (position // 3600000) % 60
            duration_hours = (duration // 3600000) % 60
            # minutes
            duration_minutes = (duration // 60000) % 60
            position_minutes = (position // 60000) % 60
            # and seconds
            position_seconds = (position // 1000) % 60
            duration_seconds = (duration // 1000) % 60
            # Assemble display strings
            position_string = f"{position_hours:02}:{position_minutes:02}:{position_seconds:02}"
            duration_string = f"{duration_hours:02}:{duration_minutes:02}:{duration_seconds:02}"
            # Display values
            self.ui.lblProgress.setText(f"{position_string}")
            self.ui.lblDuration.setText(f"Duration: {duration_string}")

    def state_changed(self, state):
        """Displays playing/paused/stopped state"""
        if state == QMediaPlayer.PlayingState:
            self.ui.btnPlayPause.setIcon(QIcon(os.path.join('ui', 'pause.png')))
            self.ui.lblPlayerState.setText('Playing')
        elif state == QMediaPlayer.PausedState:
            self.ui.btnPlayPause.setIcon(QIcon(os.path.join('ui', 'play.png')))
            self.ui.lblPlayerState.setText('Paused')
        elif state == QMediaPlayer.StoppedState:
            self.ui.lblPlayerState.setText('Stopped')

    def seek(self, position):
        """Seeks track to given position"""
        self.player.setPosition(position)

    def play_pause(self, _):
        """Toggle play/pause state"""
        if self.player.state() == self.player.PlayingState:
            self.player.pause()
        elif self.player.state() == self.player.PausedState:
            self.player.play()

    def fwd(self):
        """Skip forward by set amount (default 15 seconds)"""
        if self.player.state() == self.player.PlayingState:
            self.player.setPosition(self.player.position() + self.settings['skip_amount'])
            self.player.play()

    def rwd(self):
        """Skip backward by set amount"""
        if self.player.state() == self.player.PlayingState:
            self.player.setPosition(self.player.position() - self.settings['skip_amount'])
            self.player.play()
Exemplo n.º 33
0
class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()

        uic.loadUi('ui/alarm_clock_form.ui', self)
        self.initUI()

        self.alarm_clock_list = []

        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        self.player.setPlaylist(self.playlist)

    def initUI(self):
        self.digital_clock = DigitalClock(self.clockWidget)
        self.digital_clock.time_tick.connect(self.time_tick)

        clock_widget_layout = QHBoxLayout()
        clock_widget_layout.addWidget(self.digital_clock)
        self.clockWidget.setLayout(clock_widget_layout)

        self.addAlarmClockButton.clicked.connect(self.add_alarm_clock)

    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Выход',
                                     "Вы уверены что хотите выйти? Будильники перестанут работать", 
                                     QMessageBox.Yes | QMessageBox.No, 
                                     QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def add_alarm_clock(self):
        dialog = NewAlarmClockDialog()
        dialog_result = dialog.exec_()

        if (dialog_result == QDialog.Accepted):
            widget_item = QListWidgetItem(self.listWidget);

            alarm_clock_item = AlarmClockItem(dialog.nameLineEdit.text(), 
                                            dialog.timeEdit.time(),
                                            dialog.filePathLineEdit.text())
            alarm_clock_item.alarm.connect(self.alarm)
            self.alarm_clock_list.append(alarm_clock_item)

            alarm_clock_item_widget = AlarmClockItemWidget(alarm_clock_item, widget_item, self)
            alarm_clock_item_widget.alarm_clock_remove.connect(self.alarm_clock_remove)
            
            widget_item.setSizeHint(alarm_clock_item_widget.sizeHint());
            self.listWidget.setItemWidget(widget_item, alarm_clock_item_widget);
        
        dialog.deleteLater()

    def alarm_clock_remove(self):
        self.listWidget.takeItem(self.listWidget.row(self.sender().list_widget_item))
        self.alarm_clock_list.remove(self.sender().alarm_clock)

    def time_tick(self):
        for alarm_clock in self.alarm_clock_list:
            if alarm_clock.is_active:
                alarm_clock.tick()

    def alarm(self):
        alarm_clock = self.sender()

        self.play_sound(alarm_clock.alarm_sound)

        QMessageBox.information(self, 'Будильник',
                                     'Будильник "' + alarm_clock.title + '"', 
                                     QMessageBox.Ok)
        alarm_clock.is_alarm = False
        self.stop_sound()

    def play_sound(self, sound):
        if len(sound):
            self.player.stop()
            self.playlist.clear()

            media_content = QMediaContent(QUrl.fromLocalFile(sound))
            self.playlist.addMedia(media_content)
            self.player.play()

    def stop_sound(self):
        self.player.stop()
Exemplo n.º 34
0
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)
Exemplo n.º 35
0
class Player(QMediaPlayer):

    player = None  # 播放器
    playList = None  # 播放列表
    source = None  # 音频路径
    content = None  # 音频内容
    musicSource = []  # 音频路劲列表
    MUSIC_PATH = './BackgroundMusic'

    def __init__(self, parent=None):
        super(Player, self).__init__(parent)

        self.getMusicSource()
        self.initPlayer()
        self.createPlayList()
        self.player.play()

    def getMusicSource(self):
        """获取音乐文件路径"""
        for src in os.listdir(self.MUSIC_PATH):
            self.musicSource.append('{}/{}'.format(self.MUSIC_PATH, src))

    def initPlayer(self):
        """初始化播放器"""
        self.player = QMediaPlayer(self)  # 创建播放器
        self.playList = QMediaPlaylist(self.player)  # 播放列表
        self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)  # 播放模式
        """
        QMediaPlaylist.CurrentItemOnce       0->播放一次
        QMediaPlaylist.CurrentItemInLoop     1->单曲循环
        QMediaPlaylist.Sequential            2->顺序播放
        QMediaPlaylist.Loop                  3->列表循环
        QMediaPlaylist.Random                4->随机播放
        """

    def createPlayList(self):
        """创建播放列表"""
        self.playList.clear()
        for path in self.musicSource:
            self.content = QMediaContent(QUrl.fromLocalFile(path))
            self.playList.addMedia(self.content)
        self.player.setPlaylist(self.playList)  # 创建播放列表
        # print(self.player.currentMedia().canonicalUrl().path())  # 输出音乐文件路径

    def nextMusic(self):
        """播放下一首音乐"""
        if self.playList.currentIndex() == len(self.musicSource) - 1:
            index = 0
        else:
            index = self.playList.currentIndex() + 1

        self.playList.setCurrentIndex(index)
        self.player.play()

    def previousMusic(self):
        """播放前一首音乐"""
        if self.playList.currentIndex() == 0:
            index = len(self.musicSource) - 1
        else:
            index = self.playList.currentIndex() - 1

        self.playList.setCurrentIndex(index)
        self.player.play()

    def mute(self):
        """静音"""
        self.player.setMuted(True)

    def cancelMute(self):
        """取消静音"""
        self.player.setMuted(False)
Exemplo n.º 36
0
class App(QMainWindow):
 
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.title = 'JPR Reader GUI version1'
        self.left = 50
        self.top = 100
        self.width = 1050
        self.height = 550
        self.fileReady = False
        self.tableRow = 5
        self.tableCol = 10
        self.row = 2
        self.words = []
        self.couple = []
        self.audiolist = []
        self.initUI()
 
    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        
        # menu
        menubar = self.menuBar()
        filemenu = menubar.addMenu('File')
        fileAct = QAction('Open File', self)
        fileAct.setShortcut('Ctrl+O')
        filemenu.addAction(fileAct)
        fileAct.triggered.connect(self.openFileNameDialog)

        # status_bar
        self.statusbar = self.statusBar()
 
        # gui object
        self.wid = QWidget(self)
        self.setCentralWidget(self.wid)
        self.createHL()
        self.createTable()
 
        # layout
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.horizontalGroupBox) 
        self.layout.addWidget(self.tableWidget) 
        self.wid.setLayout(self.layout) 
 
        # Show widget
        self.show()

    def openFileNameDialog(self):    
        fileName, _ = QFileDialog.getOpenFileName(self,"Open file", "", "XML files (*.xml, *.xlsx)")
        if fileName:
            self.wb = openpyxl.load_workbook(fileName.strip())
            self.ws = self.wb.active
            self.fileReady = True
            self.statusbar.showMessage('succeed to load file...')
            self.row = 2
            self.tableWidget.clearContents()
        else:
            self.statusbar.showMessage('Fail to load file...')
        

    def createHL(self):
        self.horizontalGroupBox = QGroupBox("Controller")
        layout = QHBoxLayout()
 
        pre_button = QPushButton('', self)
        pre_button.clicked.connect(self.pre_click)
        pre_button.setIcon(QIcon('.\\img\\pre.png'))
        pre_button.setIconSize(QSize(250,250))
        layout.addWidget(pre_button) 
 
        cur_button = QPushButton('', self)
        cur_button.clicked.connect(self.cur_click)
        cur_button.setIcon(QIcon('.\\img\\cur.png'))
        cur_button.setIconSize(QSize(250,250))
        layout.addWidget(cur_button) 
 
        next_button = QPushButton('', self)
        next_button.clicked.connect(self.next_click)
        next_button.setIcon(QIcon('.\\img\\next.png'))
        next_button.setIconSize(QSize(250,250))
        layout.addWidget(next_button) 
 
        self.horizontalGroupBox.setLayout(layout)
 
    def createTable(self):
       # Create table
        self.tableWidget = QTableWidget()
        self.tableWidget.setRowCount(self.tableRow)
        self.tableWidget.setColumnCount(self.tableCol)

        # Horizontal header
        self.tableWidget.setHorizontalHeaderItem(0, QTableWidgetItem("포장순번"))
        self.tableWidget.setHorizontalHeaderItem(1, QTableWidgetItem("거래처명"))
        self.tableWidget.setHorizontalHeaderItem(2, QTableWidgetItem("배송센터"))
        self.tableWidget.setHorizontalHeaderItem(3, QTableWidgetItem("박스"))
        self.tableWidget.setHorizontalHeaderItem(4, QTableWidgetItem("깔개"))
        self.tableWidget.setHorizontalHeaderItem(5, QTableWidgetItem("상부"))
        self.tableWidget.setHorizontalHeaderItem(6, QTableWidgetItem("하부"))
        self.tableWidget.setHorizontalHeaderItem(7, QTableWidgetItem("행잉"))
        self.tableWidget.setHorizontalHeaderItem(8, QTableWidgetItem("평대"))
        self.tableWidget.setHorizontalHeaderItem(9, QTableWidgetItem("배너"))

        self.tableWidget.move(0,0)

    def setTable(self):
        # shifting other rows
        for r in range(1, self.tableRow):
            for c in range(self.tableCol):
                try:
                    self.tableWidget.item(r,c).setBackground(QColor(255,255,255))
                    self.tableWidget.setItem(r-1 , c, self.tableWidget.item(r,c).clone())
                except:
                    pass

        # set current row
        self.tableWidget.setItem(self.tableRow - 1, 0, QTableWidgetItem(self.num))
        self.tableWidget.setItem(self.tableRow - 1, 1, QTableWidgetItem(self.partner))
        self.tableWidget.setItem(self.tableRow - 1, 2, QTableWidgetItem(self.parcel))
        self.tableWidget.setItem(self.tableRow - 1, 3, QTableWidgetItem(self.box))
        self.tableWidget.setItem(self.tableRow - 1, 4, QTableWidgetItem(self.kkar))
        self.tableWidget.setItem(self.tableRow - 1, 5, QTableWidgetItem(self.sang))
        self.tableWidget.setItem(self.tableRow - 1, 6, QTableWidgetItem(self.ha))
        self.tableWidget.setItem(self.tableRow - 1, 7, QTableWidgetItem(self.hang))
        self.tableWidget.setItem(self.tableRow - 1, 8, QTableWidgetItem(self.pyeng))
        self.tableWidget.setItem(self.tableRow - 1, 9, QTableWidgetItem(self.ban))

        for c in range(self.tableCol):
            self.tableWidget.item(self.tableRow - 1, c).setBackground(QColor(255,255,0))

    def read(self):
        if not self.fileReady:
            self.openFileNameDialog()

        #포장 순번
        self.num = str(self.ws.cell(row = self.row, column = 3).value[2:]).strip()
        print('<<<', self.num, '>>>', end = ' / ')
        self.couple.append('포장순번')
        self.parsing(self.num)

        #거래처명
        self.partner = str(self.ws.cell(row = self.row, column = 5).value).strip()
        print('거래처:', self.partner, end = ' / ')

        #택배발송
        self.parcel = str(self.ws.cell(row = self.row, column = 4).value).strip()
        print('배송센터:', self.parcel, end = ' / ')
        self.couple.append('배송센터')
        self.parsing(self.parcel)

        #박스
        self.box = str(self.ws.cell(row = self.row, column = 2).value).strip()
        print('박스:', self.box, end =' / ')
        self.couple.append('박스')
        self.parsing(self.box)


        #깔개
        self.kkar = str(self.ws.cell(row = self.row, column = 7).value).strip()
        print('깔개:', self.kkar, end =' / ')
        self.couple.append('깔개')
        self.parsing(self.kkar)


        #상부
        self.sang = str(self.ws.cell(row = self.row, column = 8).value).strip()
        print('상부:', self.sang, end =' / ')
        self.couple.append('상부')
        self.parsing(self.sang)


        #하부
        self.ha = str(self.ws.cell(row = self.row, column = 9).value).strip()
        print('하부:', self.ha, end =' / ')
        self.couple.append('하부')
        self.parsing(self.ha)


        #행잉
        self.hang = str(self.ws.cell(row = self.row, column = 10).value).strip()
        print('행잉:', self.hang, end =' / ')
        self.couple.append('행잉')
        self.parsing(self.hang)


        #평대
        self.pyeng = str(self.ws.cell(row = self.row, column = 11).value).strip()
        print('평대:', self.pyeng, end =' / ')
        self.couple.append('평대')
        self.parsing(self.pyeng)


        #배너
        self.ban = str(self.ws.cell(row = self.row, column = 12).value).strip()
        print('배너:', self.ban)
        self.couple.append('배너')
        self.parsing(self.ban)


        self.setTable()
        print(self.words)

    def parsing(self, val):
        if val == 'None' or val == '':
            self.couple.append('없음')

        else:
            if '(' in val or '/' in val:
                arr = re.split('[(/]',val)
                for i in range(len(arr)):
                    if ')' in arr[i]:
                        arr[i] = arr[i][:arr[i].index(')')]
                self.couple.append(arr)

            else:
                self.couple.append(val)

        self.words.append(self.couple)
        self.couple = [] 

    def load_audiolist(self):
        for item, value in self.words:
            if item == '배송센터':
                if value == '택배발송':
                    self.audiolist.append('택배발송')
            else:
                self.audiolist.append(item.strip())
                # 포장순번
                if item == '포장순번':
                    for i in range(3):
                        self.audiolist.append('_' + value[i])

                # in / or () case
                elif isinstance(value, list):
                    for name in value:
                        # '2개' case
                        if '2' in name:
                            self.audiolist.append('2')
                        else:
                            self.audiolist.append(name.strip())
                else:
                    self.audiolist.append(value.strip())

            # beep
            self.audiolist.append('beep')

    def speak(self):
        self.playlist.clear()
        for clip in self.audiolist:
            url = QUrl.fromLocalFile('.\\audio_clips\\' + clip + '.mp3')
            #print(url)
            self.playlist.addMedia(QMediaContent(url))
        self.player.setPlaylist(self.playlist)
        self.player.play()
            

    @pyqtSlot()
    def pre_click(self):
        if not self.fileReady:
            pass
        
        else:
            if self.row == 2:
                self.statusbar.showMessage("Can't be previous.")
            else:
                self.row -= 1

        del self.words[:]
        del self.audiolist[:]
        self.read()
        self.load_audiolist()
        self.speak()


    @pyqtSlot()
    def cur_click(self):
        del self.words[:]
        del self.audiolist[:]
        self.read()
        self.load_audiolist()
        self.speak()


    @pyqtSlot()
    def next_click(self):
        if not self.fileReady:
            pass

        else:
            if self.row == self.ws.max_row:
                self.statusbar.showMessage("It's over.")
            else:
                self.row += 1

        del self.words[:]
        del self.audiolist[:]
        self.read()
        self.load_audiolist()
        self.speak()