Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PyQt5 Music Player
#5
The above code had issues with the prev/next buttons(worked when I posted). Anyhow I re-wrote the code and all is working now(fingers crossed).

from functools import partial
import os
import sys
from PyQt5.QtCore import Qt, QUrl, QDir
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QGridLayout, \
QFrame, QGraphicsDropShadowEffect, QGraphicsView, QGraphicsScene, QLabel, \
QPushButton, QHBoxLayout, QStyle, QListWidget, QFileDialog, QSlider, QVBoxLayout
from PyQt5.QtGui import QGradient, QFont, QColor, QCursor, QIcon, QPixmap
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist, \
QMediaMetaData


class Window(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle('PyQt5 Music Player')

        # Create a containers
        btn_box = QHBoxLayout()
        btn_box2 = QHBoxLayout()
        container = QGridLayout()
        info_container = QGridLayout()
        frame = QFrame()
        frame.setFrameShape(QFrame.Box)
        frame.setFrameShadow(QFrame.Sunken)
        frame.setLayout(info_container)




        # Create some variables
        self.dir = f'{QDir.currentPath()}'
        self.url = QUrl()
        self.player = QMediaPlayer()
        self.content = QMediaContent()
        self.playlist = QMediaPlaylist(self.player)
        self.player.setPlaylist(self.playlist)

        # Used to changed to notify self.update that the playlist index has changed.
        # Will update the highlighted line in the listbox
        self.playlist.currentIndexChanged.connect(self.update)

        # Signal that the metadate has changed
        self.player.metaDataChanged.connect(self.meta_data)

        # Labels for the track information
        self.artist = QLabel('Artist: ')
        self.album_title = QLabel('Album: ')
        self.track_title = QLabel('Track: ')
        self.released = QLabel('Released: ')
        self.genre = QLabel('Genre: ')
        self.art = QLabel()


        # Add track information to the info container
        info_container.addWidget(self.artist, 0, 0, 1, 1)
        info_container.addWidget(self.album_title, 1, 0, 1, 1)
        info_container.addWidget(self.track_title, 2, 0, 1, 1)
        info_container.addWidget(self.released, 3, 0, 1, 1)
        info_container.addWidget(self.genre, 4, 0, 1, 1)
        info_container.addWidget(self.art, 5, 0, 1, 1)

        # Create the status and track labels
        self.status = QLabel('Status: ')
        self.status.setFrameShape(QFrame.Box)
        self.status.setFrameShadow(QFrame.Sunken)

        self.track = QLabel('Track: ')
        self.track.setFrameShape(QFrame.Box)
        self.track.setFrameShadow(QFrame.Sunken)

        # Define and create the listbox
        self.musiclist = QListWidget()
        self.musiclist.setFrameShape(QFrame.Box)
        self.musiclist.setFrameShadow(QFrame.Sunken)
        self.musiclist.setStyleSheet('background-color: snow;')

        # Used for track play when double clicked
        self.musiclist.itemDoubleClicked.connect(self._doubleclick)

        # Create the control buttons & button styles
        btn_style = '''QPushButton{background-color: skyblue;}
                       QPushButton:hover{background-color: lightskyblue; color: dodgerblue; \
                       font-weight: bold;}'''

        # Create buttons for getting audio files and clearing playlist
        file_btn = QPushButton('Get Audio')
        file_btn.released.connect(self._files)
        file_btn.setCursor(Qt.PointingHandCursor)
        file_btn.setStyleSheet(btn_style)
        file_btn.setMaximumWidth(100)

        clear_btn = QPushButton('Clear List')
        clear_btn.released.connect(self._clear)
        clear_btn.setCursor(Qt.PointingHandCursor)
        clear_btn.setStyleSheet(btn_style)
        clear_btn.setMaximumWidth(100)

        # Create & style the control buttons
        self.play_btn = QPushButton('Play')
        self.play_btn.released.connect(self._state)
        self.play_btn.setCursor(Qt.PointingHandCursor)
        self.play_btn.setStyleSheet(btn_style)

        self.prev_btn = QPushButton('Prev')
        self.prev_btn.released.connect(self._prev)
        self.prev_btn.setCursor(Qt.PointingHandCursor)
        self.prev_btn.setStyleSheet(btn_style)

        self.next_btn = QPushButton('Next')
        self.next_btn.released.connect(self._next)
        self.next_btn.setCursor(Qt.PointingHandCursor)
        self.next_btn.setStyleSheet(btn_style)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.released.connect(self._stop)
        self.stop_btn.setCursor(Qt.PointingHandCursor)
        self.stop_btn.setStyleSheet(btn_style)

        self.exit_btn = QPushButton('Exit')
        self.exit_btn.released.connect(sys.exit)
        self.exit_btn.setCursor(Qt.PointingHandCursor)
        self.exit_btn.setStyleSheet('QPushButton{background-color: firebrick;} \
                                    QPushButton:hover{background-color: red; color: white; \
                                    font-weight: bold;}')


        # Add the buttons to layout
        btn_box.addWidget(file_btn)
        btn_box.addWidget(clear_btn)
        btn_box2.addWidget(self.play_btn)
        btn_box2.addWidget(self.prev_btn)
        btn_box2.addWidget(self.next_btn)
        btn_box2.addWidget(self.stop_btn)
        btn_box2.addWidget(self.exit_btn)


        # Add layouts to container layout
        container.addWidget(self._header_footer(100, 100, 40, 'PyQt5 Music Player'), 0, 0, 1, 3)
        container.addWidget(self.status, 1, 0, 1, 1)
        container.addWidget(self.track, 1, 1, 1, 1)
        container.addLayout(btn_box, 1, 2, 1, 1)
        container.addWidget(frame, 2, 0, 2, 1)
        container.addWidget(self.musiclist, 2, 1, 1, 2)
        container.addLayout(btn_box2, 3, 1, 1, 2)
        container.addWidget(self._header_footer(40, 40, 10, 'my-python.org - 10/16/2021'), 4, 0, 1, 3)

        # Create the widget and add the button box layout
        widget = QWidget()
        widget.setLayout(container)
        self.setCentralWidget(widget)

    # Get music metadata
    def meta_data(self):
        if self.player.isMetaDataAvailable():
            self.artist.setText(f'Artist: {self.player.metaData(QMediaMetaData.AlbumArtist)}')
            self.album_title.setText(f'Album: {self.player.metaData(QMediaMetaData.AlbumTitle)}')
            self.track_title.setText(f'Track: {self.player.metaData(QMediaMetaData.Title)}')
            self.released.setText(f'Released: {self.player.metaData(QMediaMetaData.Year)}')
            self.genre.setText(f'Genre: {self.player.metaData(QMediaMetaData.Genre)}')
            self.track.setText(f'Track: {self.player.metaData(QMediaMetaData.Title)}')
            pixmap = QPixmap(self.player.metaData(QMediaMetaData.CoverArtImage))
            pixmap = pixmap.scaled(int(pixmap.width()/3), int(pixmap.height()/3))
            self.art.setPixmap(pixmap)

    # Create the header
    def _header_footer(self, minheight, maxheight, fontsize, text):
        shadow = QGraphicsDropShadowEffect()
        shadow.setBlurRadius(3)
        shadow.setOffset(3, 3)

        scene = QGraphicsScene()

        view = QGraphicsView()
        view.setMinimumSize(800, minheight)
        view.setMaximumHeight(maxheight)
        view.setScene(scene)

        gradient = QGradient(QGradient.RichMetal)

        scene.setBackgroundBrush(gradient)

        font = QFont('comic sans ms', fontsize, QFont.Bold)

        text = scene.addText(text)
        text.setDefaultTextColor(QColor(250,250,250))
        text.setFont(font)

        text.setGraphicsEffect(shadow)

        return view

    # Method for double clicking a track and play
    def _doubleclick(self):
        self.playlist.setCurrentIndex(self.musiclist.currentRow())
        self.player.play()

    # Method for clearing the playlist and musiclist
    def _clear(self):
        self.player.stop()
        self.musiclist.clear()
        self.playlist.clear()
        self.play_btn.setText('Play')
        self.status.setText('Status: ')
        self.track.setText('Track: ')
        self.artist.setText('Artist: ')
        self.album_title.setText('Album: ')
        self.track_title.setText('Track: ')
        self.released.setText('Released: ')
        self.genre.setText('Genre: ')
        pixmap = QPixmap()
        self.art.setPixmap(pixmap)


    # Method for adding tracks to the playlist and musiclist
    def _files(self):
        files = QFileDialog.getOpenFileNames(None, 'Get Audio Files',
                                         filter='Audio Files (*.mp3 *.ogg *.wav)')

        for file in files[0]:
            self.playlist.addMedia(QMediaContent(self.url.fromLocalFile(file)))
            file = file.split('/')
            self.musiclist.addItem(f'{file[-1][:-4]}')

        self.musiclist.setCurrentRow(0)
        self.playlist.setCurrentIndex(0)

    # Methods for the control buttons
    def _prev(self):
        if self.playlist.previousIndex() == -1:
            self.playlist.setCurrentIndex(self.playlist.mediaCount()-1)
        else:
            self.playlist.previous()

    def _next(self):
        self.playlist.next()
        if self.playlist.currentIndex() == -1:
            self.playlist.setCurrentIndex(0)
            self.player.play()

    def _stop(self):
        self.player.stop()
        self.play_btn.setText('Play')
        self.playlist.setCurrentIndex(0)
        self.musiclist.setCurrentRow(0)
        self.status.setText('Status: Now Stopped')

    def _state(self):
        if self.playlist.mediaCount() > 0:
            if self.player.state() != QMediaPlayer.PlayingState:
                self.play_btn.setText('Pause')
                self.status.setText('Status: Now Playing')
                self.player.play()
            else:
                self.play_btn.setText('Play')
                self.player.pause()
                self.status.setText('Status: Now Paused')

        else:
            pass

    # Method for updating the listbox when the playlist updates
    def update(self):
        self.musiclist.setCurrentRow(self.playlist.currentIndex())
        if self.playlist.currentIndex() < 0:
            self.musiclist.setCurrentRow(0)
            self.playlist.setCurrentIndex(0)

def main():
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Messages In This Thread
PyQt5 Music Player - by menator01 - Oct-14-2021, 09:38 AM
RE: PyQt5 Music Player - by Larz60+ - Oct-14-2021, 08:49 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-14-2021, 09:16 PM
RE: PyQt5 Music Player - by menator01 - Oct-15-2021, 05:58 AM
RE: PyQt5 Music Player - by menator01 - Oct-16-2021, 09:44 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-16-2021, 10:49 PM
RE: PyQt5 Music Player - by menator01 - Oct-16-2021, 11:00 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-17-2021, 09:26 PM
RE: PyQt5 Music Player - by menator01 - Oct-17-2021, 10:03 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-18-2021, 04:09 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-18-2021, 05:12 PM
RE: PyQt5 Music Player - by menator01 - Oct-18-2021, 06:44 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Oct-19-2021, 05:21 PM
RE: PyQt5 Music Player - by menator01 - Oct-29-2021, 06:49 PM
RE: PyQt5 Music Player - by menator01 - Nov-02-2021, 09:34 AM
RE: PyQt5 Music Player - by Axel_Erfurt - Nov-02-2021, 08:04 PM
RE: PyQt5 Music Player - by menator01 - Nov-03-2021, 08:30 AM
RE: PyQt5 Music Player - by Axel_Erfurt - Nov-03-2021, 09:05 AM
RE: PyQt5 Music Player - by menator01 - Nov-03-2021, 09:06 AM
RE: PyQt5 Music Player - by Axel_Erfurt - Nov-03-2021, 09:11 AM
RE: PyQt5 Music Player - by menator01 - Nov-03-2021, 05:49 PM
RE: PyQt5 Music Player - by Axel_Erfurt - Nov-03-2021, 05:59 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Basic Music Player with tkinter menator01 4 5,007 Jul-31-2021, 04:27 AM
Last Post: ndc85430

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020