import pygame
import os
from tkinter import *
from tkinter import filedialog
from tkinter import ttk  # Import the themed Tkinter module for better styling

# Initialize pygame and set the audio driver
pygame.init()
os.environ['SDL_AUDIODRIVER'] = 'sdl2'  # Use the appropriate audio driver for your system

# Create the main window
root = Tk()
root.title("MP3 Player")

# Create a style object for improved button appearance
style = ttk.Style()
style.configure("TButton", padding=(10, 5))

# Create a list to hold the paths of the selected songs
playlist = []

# Create a function to add songs to the playlist
def add_songs():
    songs = filedialog.askopenfilenames(filetypes=[("MP3 files", "*.mp3")])
    for song in songs:
        playlist.append(song)
        songs_listbox.insert(END, os.path.basename(song))

# Create a function to play the selected song
def play_song():
    global current_song
    current_song = playlistbox.curselection()[0]
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()

# Create a function to stop the current song
def stop_song():
    pygame.mixer.music.stop()

# Create a function to pause the current song
def pause_song():
    pygame.mixer.music.pause()

# Create a function to resume the current song
def resume_song():
    pygame.mixer.music.unpause()

# Create a function to play the next song
def next_song():
    global current_song
    current_song += 1
    if current_song >= len(playlist):
        current_song = 0
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()

# Create a function to play the previous song
def prev_song():
    global current_song
    current_song -= 1
    if current_song < 0:
        current_song = len(playlist) - 1
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()

# Create buttons with improved styling
add_button = ttk.Button(root, text="Add Songs", command=add_songs)
play_button = ttk.Button(root, text="Play", command=play_song)
stop_button = ttk.Button(root, text="Stop", command=stop_song)
pause_button = ttk.Button(root, text="Pause", command=pause_song)
resume_button = ttk.Button(root, text="Resume", command=resume_song)
next_button = ttk.Button(root, text="Next", command=next_song)
prev_button = ttk.Button(root, text="Previous", command=prev_song)

# Create a styled listbox
songs_listbox = Listbox(root, selectmode=SINGLE, selectbackground="gray")
songs_listbox.config(bg="black", fg="white", selectforeground="white", selectbackground="gray")

# Place the widgets using the grid layout manager for better alignment
add_button.grid(row=0, column=0, padx=10, pady=5)
play_button.grid(row=0, column=1, padx=10, pady=5)
stop_button.grid(row=0, column=2, padx=10, pady=5)
pause_button.grid(row=0, column=3, padx=10, pady=5)
resume_button.grid(row=0, column=4, padx=10, pady=5)
next_button.grid(row=0, column=5, padx=10, pady=5)
prev_button.grid(row=0, column=6, padx=10, pady=5)
songs_listbox.grid(row=1, column=0, columnspan=7, padx=10, pady=10)

root.mainloop()

import pygame
import os
from tkinter import *
from tkinter import filedialog
  • This first part of the code is just simply importing all the necessary tools such as the pygame library.
pygame.init()
os.environ['SDL_AUDIODRIVER'] = 'sdl2'
  • This intilializes the pygame library for audio operations.
  • sdl2 is the audio driver necessary in order to get audio. sdl2 can change based on what driver your system runs on.
root = Tk()
root.title("MP3 Player")
  • This creates the main window for the MP3 player and sets the title of the window.
playlist = []
  • This creates an empty list to store the paths of the songs.
def add_songs():
    songs = filedialog.askopenfilenames(filetypes=[("MP3 files", "*.mp3")])
    for song in songs:
        playlist.append(song)
        songs_listbox.insert(END, os.path.basename(song))

# Create a function to play the selected song
def play_song():
    global current_song
    current_song = playlistbox.curselection()[0]
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()

# Create a function to stop the current song
def stop_song():
    pygame.mixer.music.stop()

# Create a function to pause the current song
def pause_song():
    pygame.mixer.music.pause()

# Create a function to resume the current song
def resume_song():
    pygame.mixer.music.unpause()

# Create a function to play the next song
def next_song():
    global current_song
    current_song += 1
    if current_song >= len(playlist):
        current_song = 0
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()

# Create a function to play the previous song
def prev_song():
    global current_song
    current_song -= 1
    if current_song < 0:
        current_song = len(playlist) - 1
    pygame.mixer.music.load(playlist[current_song])
    pygame.mixer.music.play()
  • add_songs(): This function opens a file dialog to select the MP3 files you would like you and adds their path to playlist. It will also display the file chosen
  • play_song(): Plays the selected song from playlist
  • stop_song(): Stops the song currently playing
  • pause_song(): Pauses the currently playing song
  • resume_song(): Resumes the song if paused
  • next_song(): Skips to the next song in ‘playlist’ and plays it
  • prev_song(): Goes back to the previous song in ‘playlist’ and plays it
add_button = ttk.Button(root, text="Add Songs", command=add_songs)
play_button = ttk.Button(root, text="Play", command=play_song)

...

songs_listbox = Listbox(root, selectmode=SINGLE, selectbackground="gray")
songs_listbox.config(bg="black", fg="white", selectforeground="white", selectbackground="gray")
  • The various button widgets are created to be able to add, play, stop, resume, skip, and go back to the pervious song.
  • ‘Listbox’ widget creates a display list of selected songs.
add_button.grid(row=0, column=0, padx=10, pady=5)
play_button.grid(row=0, column=1, padx=10, pady=5)
stop_button.grid(row=0, column=2, padx=10, pady=5)
pause_button.grid(row=0, column=3, padx=10, pady=5)
resume_button.grid(row=0, column=4, padx=10, pady=5)
next_button.grid(row=0, column=5, padx=10, pady=5)
prev_button.grid(row=0, column=6, padx=10, pady=5)
songs_listbox.grid(row=1, column=0, columnspan=7, padx=10, pady=10)
---------------------------------------------------------------------------

TclError                                  Traceback (most recent call last)

/tmp/ipykernel_84340/1796873520.py in <module>
----> 1 add_button.grid(row=0, column=0, padx=10, pady=5)
      2 play_button.grid(row=0, column=1, padx=10, pady=5)
      3 stop_button.grid(row=0, column=2, padx=10, pady=5)
      4 pause_button.grid(row=0, column=3, padx=10, pady=5)
      5 resume_button.grid(row=0, column=4, padx=10, pady=5)


/usr/lib/python3.10/tkinter/__init__.py in grid_configure(self, cnf, **kw)
   2520                       widget stick to the cell boundary
   2521         """
-> 2522         self.tk.call(
   2523               ('grid', 'configure', self._w)
   2524               + self._options(cnf, kw))


TclError: can't invoke "grid" command: application has been destroyed
  • The widgets are placed using the grid layout manager for better alignment.
  • ‘song_listbox’ are packed into the main window and are organized in a vertical layout.
root.mainloop()
  • This final line of code starts the main event look which keeps the application running and responsive to user interactions.