In our imports add
from PyQt5.QtGui import QPixmap
Add the class
class Data:
def __init__(self):
pass
def data(self, player):
info = {}
info['artist'] = player.metaData(QMediaMetaData.AlbumArtist)
info['album'] = player.metaData(QMediaMetaData.AlbumTitle)
info['track'] = player.metaData(QMediaMetaData.Title)
info['release'] = player.metaData(QMediaMetaData.Year)
info['genre'] = player.metaData(QMediaMetaData.Genre)
info['coverart'] = player.metaData(QMediaMetaData.CoverArtImage)
return info
In the window class in this section
# Empty labels used as place holders. Text will show when a track is playing
self.artist = QLabel()
self.album = QLabel()
self._track = QLabel()
self.release = QLabel()
self.genre = QLabel()
self.art = QLabel()
add
imgbox = QVBoxLayout()
img_frame = QFrame()
img_frame.setFixedSize(400,350)
img_frame.setLayout(imgbox)
imgbox.addWidget(self.art)
In the info_container.add change to
info_container.addWidget(img_frame, 5, 0, 1, 2)
In the controller class added a new function
def meta(self):
if self.player.isMetaDataAvailable():
data = self.data.data(self.player)
self.window.artist.setText(data['artist'])
self.window.album.setText(self.truncate(data['album'].strip('(')))
self.window._track.setText(self.truncate(data['track'].strip('(')))
self.window.release.setText(str(data['release']))
self.window.genre.setText(data['genre'])
pixmap = QPixmap(data['coverart'])
pixmap = pixmap.scaled(380,320)
self.window.art.setPixmap(pixmap)
self.window.track.setText(f'Track: {self.truncate(data['track'])}')
Updated these two functions
# Update the state function to this
def state(self):
''' Method checks the state of the music player and append correct text
to the play button '''
if self.playlist.mediaCount() > 0:
if self.player.state() != QMediaPlayer.PlayingState:
self.window.play.setText('Paused')
self.window.status.setText('Status: Now Playing')
self.player.play()
else:
self.window.play.setText('Play')
self.window.status.setText('Status: Now Paused')
self.player.pause()
# Updated the clear function to this
def clear(self):
''' Method clears everthing. More will be added here later. '''
self.player.stop()
self.window.music_list.clear()
self.playlist.clear()
self.window.play.setText('Play')
self.window.artist.setText('')
self.window.album.setText('')
self.window._track.setText('')
self.window.release.setText('')
self.window.genre.setText('')
self.window.art.setPixmap(QPixmap())
In case I made any errors, here is the full code
# Do the imports
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout, QLabel,
QFrame, QHBoxLayout, QPushButton, QListWidget, QVBoxLayout, \
QDial, QFileDialog)
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtMultimedia import (QMediaPlayer, QMediaContent, QMediaPlaylist,
QMediaMetaData)
from PyQt5.QtGui import QPixmap
from mutagen.mp3 import MP3
class Data:
def __init__(self):
pass
def data(self, player):
info = {}
info['artist'] = player.metaData(QMediaMetaData.AlbumArtist)
info['album'] = player.metaData(QMediaMetaData.AlbumTitle)
info['track'] = player.metaData(QMediaMetaData.Title)
info['release'] = player.metaData(QMediaMetaData.Year)
info['genre'] = player.metaData(QMediaMetaData.Genre)
info['coverart'] = player.metaData(QMediaMetaData.CoverArtImage)
return info
class Window(QMainWindow):
''' Class will handle the display '''
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('My Music Player')
# Sets a fixed size for the window
self.setFixedSize(1280,720)
# Create a main container - will hold all other widgets and layouts
container = QGridLayout()
# Create a header label
header = QLabel('My Music Player')
header.setFrameShape(QFrame.Shape.Box)
header.setFrameShadow(QFrame.Shadow.Raised)
header.setLineWidth(3)
# Just like in css - set color and background color and the like. Is a bit limited.
header.setStyleSheet('font-size: 48px; color: gold; \
font-weight: bold; font-family: comic sans ms; \
background-color: seagreen; padding: 10px;')
# Aligning the text to the center
header.setAlignment(Qt.AlignmentFlag.AlignCenter)
# Set some common font styles
common_style = ''' font-weight: bold; font-size: 10pt; padding: 3px; '''
# Status Bars
self.status = QLabel('Status: Now Stopped')
self.status.setStyleSheet(common_style)
self.status.setFrameShape(QFrame.Shape.Box)
self.status.setFrameShadow(QFrame.Shadow.Sunken)
self.track = QLabel('Track: ')
self.track.setStyleSheet(common_style)
self.track.setFrameShape(QFrame.Shape.Box)
self.track.setFrameShadow(QFrame.Shadow.Sunken)
# To Buttons
btn_style = ''' QPushButton{background-color: skyblue;}
QPushButton:hover{background-color: lightskyblue; \
color: dodgetblue; font-weight: bold;}'''
self.file_button = QPushButton('Get Audio')
self.file_button.setStyleSheet(btn_style)
self.file_button.setCursor(Qt.CursorShape.PointingHandCursor)
self.clear_button = QPushButton('Clear List')
self.clear_button.setStyleSheet(btn_style)
self.clear_button.setCursor(Qt.CursorShape.PointingHandCursor)
# Continaer to hold top button
box1 = QHBoxLayout()
box1.addWidget(self.file_button)
box1.addWidget(self.clear_button)
# Info Containers
info_container = QGridLayout()
# Using a frame to get a border around the info_container
frame = QFrame()
frame.setFrameShape(QFrame.Shape.Box)
frame.setFrameShadow(QFrame.Shadow.Sunken)
frame.setLayout(info_container)
# Artist Labels Static
artist = QLabel('Artist:')
album = QLabel('Album:')
_track = QLabel('Track:')
release = QLabel('Album Release:')
genre = QLabel('Genre:')
# Empty labels used as place holders. Text will show when a track is playing
self.artist = QLabel()
self.album = QLabel()
self._track = QLabel()
self.release = QLabel()
self.genre = QLabel()
self.art = QLabel()
imgbox = QVBoxLayout()
img_frame = QFrame()
img_frame.setFixedSize(400,350)
img_frame.setLayout(imgbox)
imgbox.addWidget(self.art)
# Numers relate to a grid - row, column, occupy how many rows, how many columns
info_container.addWidget(artist, 0, 0, 1, 1)
info_container.addWidget(self.artist, 0, 1, 1, 1)
info_container.addWidget(album, 1, 0, 1, 1)
info_container.addWidget(self.album, 1, 1, 1, 1)
info_container.addWidget(_track, 2, 0, 1, 1)
info_container.addWidget(self._track, 2, 1, 1, 1)
info_container.addWidget(release, 3, 0, 1, 1)
info_container.addWidget(self.release, 3, 1, 1, 1)
info_container.addWidget(genre, 4, 0, 1, 1)
info_container.addWidget(self.genre, 4, 1, 1, 1)
info_container.addWidget(img_frame, 5, 0, 1, 2)
# Create a listbox to hold tracks
self.music_list = QListWidget()
# Container for buttons stop, play, next, back, and exit
btn_container = QHBoxLayout()
self.play = QPushButton('Play')
self.play.setStyleSheet(btn_style)
self.play.setCursor(Qt.CursorShape.PointingHandCursor)
self.prev = QPushButton('Prev')
self.prev.setStyleSheet(btn_style)
self.prev.setCursor(Qt.CursorShape.PointingHandCursor)
self._next = QPushButton('Next')
self._next.setStyleSheet(btn_style)
self._next.setCursor(Qt.CursorShape.PointingHandCursor)
self.stop = QPushButton('Stop')
self.stop.setCursor(Qt.CursorShape.PointingHandCursor)
self.stop.setStyleSheet(btn_style)
self._exit = QPushButton('Exit')
self._exit.setCursor(Qt.CursorShape.PointingHandCursor)
self._exit.setStyleSheet('QPushButton{background-color: firebrick;} \
QPushButton:hover{background-color: red; color: white; \
font-weight: bold;}')
# Add buttons to button container
btn_container.addWidget(self.play)
btn_container.addWidget(self.prev)
btn_container.addWidget(self._next)
btn_container.addWidget(self.stop)
btn_container.addWidget(self._exit)
# Placeholder
holder = QFrame()
holder.setFrameShape(QFrame.Shape.Box)
holder.setFrameShadow(QFrame.Shadow.Sunken)
# Volume Controller - Creating the box give the light gray square
dialbox = QVBoxLayout()
dialframe = QFrame()
dialframe.setFrameShape(QFrame.Shape.Box)
dialframe.setFrameShadow(QFrame.Shadow.Sunken)
dialframe.setLayout(dialbox)
# QDial creates the object, setRange - the range for volume
# setNotchesVisible - the ticks around the dial
# setSliderPosition sets the default volume
# setValues is used for passing variables
self.dial = QDial()
self.dial.setRange(0, 100)
self.dial.setNotchesVisible(True)
self.dial.setSliderPosition(50)
self.dial.setValue(50)
# The volume label in with the dial control
dialbox.addWidget(QLabel('Volume'))
dialbox.addWidget(self.dial)
# section for adding widgets to main container
container.addWidget(header, 0, 0, 1, 3, Qt.AlignmentFlag.AlignTop)
container.addWidget(self.status, 1, 0, 1, 1)
container.addWidget(self.track, 1, 1, 1, 1)
container.addLayout(box1, 1, 2, 1, 1)
container.addWidget(frame, 2, 0, 2, 1)
container.addWidget(self.music_list, 2, 1, 1, 2)
container.addLayout(btn_container, 3, 1, 1, 2)
container.addWidget(holder, 4, 0, 1, 2)
container.addWidget(dialframe, 4, 2, 1, 1)
# Sets main layout
widget = QWidget()
widget.setLayout(container)
self.setCentralWidget(widget)
class Controller:
def __init__(self, window, data):
self.window = window
self.data = data
# Set some variables for our player
self.url = QUrl
self.player = QMediaPlayer()
self.playlist = QMediaPlaylist(self.player)
self.player.setPlaylist(self.playlist)
# Button Commands
self.window.file_button.released.connect(self.getfiles)
self.window.clear_button.released.connect(self.clear)
self.window.play.released.connect(self.state)
self.window.prev.released.connect(self.prev)
self.window._next.released.connect(self._next)
self.window._exit.released.connect(sys.exit)
self.window.stop.released.connect(self.stop)
# Other commands
self.playlist.currentIndexChanged.connect(self.update)
self.window.music_list.itemDoubleClicked.connect(self.doubleclick)
self.window.dial.valueChanged.connect(self.volume, self.window.dial.value())
self.player.metaDataChanged.connect(self.meta)
def meta(self):
if self.player.isMetaDataAvailable():
data = self.data.data(self.player)
self.window.artist.setText(data['artist'])
self.window.album.setText(self.truncate(data['album'].strip('(')))
self.window._track.setText(self.truncate(data['track'].strip('(')))
self.window.release.setText(str(data['release']))
self.window.genre.setText(data['genre'])
pixmap = QPixmap(data['coverart'])
pixmap = pixmap.scaled(380,320)
self.window.art.setPixmap(pixmap)
self.window.track.setText(f'Track: {self.truncate(data['track'])}')
def volume(self, val=50):
self.player.setVolume(val)
def getfiles(self):
''' Method for getting our audio files - Can store multiple select ions '''
files = QFileDialog.getOpenFileNames(None, 'Get Audio Giles',
filter='Audio Files(*.mp3 *.ogg *.wav)')
# Loop through the files and add them to our playlist
for file in files[0]:
self.playlist.addMedia(QMediaContent(self.url.fromLocalFile(file)))
try:
track = MP3(file)
self.window.music_list.addItem(str(track['TIT2']))
except:
track = self.truncate(file.rpartition('/')[2].rpartition('.')[0])
# Adds the track title to our listbox
self.window.music_list.addItem(track)
# Set indexes in our playlist and listbox to 0
self.window.music_list.setCurrentRow(0)
self.playlist.setCurrentIndex(0)
def truncate(self, text, length=25):
# method shortens the text track a little
if text:
if len(text) <= length:
return text
else:
return f"{' '.join(text[:length+1].split( ' ')[0:-1])} ..."
def clear(self):
''' Method clears everthing. More will be added here later. '''
self.player.stop()
self.window.music_list.clear()
self.playlist.clear()
self.window.play.setText('Play')
self.window.artist.setText('')
self.window.album.setText('')
self.window._track.setText('')
self.window.release.setText('')
self.window.genre.setText('')
self.window.art.setPixmap(QPixmap())
def state(self):
''' Method checks the state of the music player and append correct text
to the play button '''
if self.playlist.mediaCount() > 0:
if self.player.state() != QMediaPlayer.PlayingState:
self.window.play.setText('Paused')
self.window.status.setText('Status: Now Playing')
self.player.play()
else:
self.window.play.setText('Play')
self.window.status.setText('Status: Now Paused')
self.player.pause()
def _next(self):
''' method for moving to next track '''
self.playlist.next()
if self.playlist.currentIndex() == -1:
self.playlist.setCurrentIndex(0)
self.player.play()
def prev(self):
''' Method for going to previous track '''
if self.playlist.previousIndex() == -1:
self.playlist.setCurrentIndex(self.playlist.mediaCount()-1)
else:
self.playlist.previous()
def stop(self):
''' method stops music player and resets indexes. '''
self.player.stop()
self.window.play.setText('Play')
self.playlist.setCurrentIndex(0)
self.window.music_list.setCurrentRow(0)
def update(self):
''' Method updates our list box highlight with the playlist '''
self.window.music_list.setCurrentRow(self.playlist.currentIndex())
if self.playlist.currentIndex() < 0:
self.window.music_list.setCurrentRow(0)
self.playlist.setCurrentIndex(0)
def doubleclick(self):
''' method plays a track that has been double clicked in the listbox .'''
self.playlist.setCurrentIndex(self.window.music_list.currentRow())
self.player.play()
if __name__ == '__main__':
app = QApplication([])
controller = Controller(Window(), Data())
controller.window.show()
sys.exit(app.exec())