Buttons:
- Get Audio - Used to get our music file
- Clear List - Clear the playlist
- Play/Pause - Will play or pause our music player
- Prev - Go back to previous track
- Next - Go to nest track
- Stop - Stop the music player
- Exit - Exit the music player
- Add volume control to dial
In our Controller Class add these lines
# 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())
Now we need to define some functions:
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')
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.player.play()
else:
self.window.play.setText('Play')
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()
And now our music.py should be looking something like this.
# 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 mutagen.mp3 import MP3
class Data:
pass
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()
img_frame = QFrame()
img_frame.setFrameShape(QFrame.Shape.Box)
img_frame.setFrameShadow(QFrame.Shadow.Sunken)
img_frame.setFixedSize(400,300)
# 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(self.art, 5, 0, 1, 2)
info_container.addWidget(img_frame, 6, 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):
self.window = window
# 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())
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')
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.player.play()
else:
self.window.play.setText('Play')
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())
controller.window.show()
sys.exit(app.exec())
We now should have a working music player. In the next tutorial we will be adding some display data to our music player.