badge
Home Projects Basic About

Project-3

Music Player on tkinter

In this project, we can learn how to use pygame on playing .mp3 or wave files using filepicker.

In this image you can see how to play music

mplayer

Before run this code install both tkinter and pygame using command:-

pip install pygame

Tap this code and select "copy" button to copy this code.

Code - mplayer.py


import tkinter as tk
from tkinter import filedialog, ttk
import pygame
import os

pygame.mixer.init()

#      IMPORTANT NOTICE
#   install command in terminal-
#          pip install pygame
#           or install pygame
#      before run this program
root = tk.Tk()
root.title("Music Player")
root.geometry("1024x980")
root.configure(bg="#C0C0C0")  # Windows 2000 gray

# ---------- STATE ----------
playlist = []
paused = False
repeat = False
song_length = 0

# ---------- FUNCTIONS ----------

def format_time(sec):
    m = int(sec) // 60
    s = int(sec) % 60
    return f"{m:02}:{s:02}"

def load_folder():
    global playlist
    folder = filedialog.askdirectory(title="Select Music Folder")
    if not folder:
        return

    playlist.clear()
    combo["values"] = ()

    files = []
    for f in os.listdir(folder):
        if f.lower().endswith((".mp3", ".wav")):
            files.append(f)
            playlist.append(os.path.join(folder, f))

    combo["values"] = files
    if files:
        combo.current(0)
        play_selected()

def play_selected(event=None):
    global paused, song_length
    idx = combo.current()
    if idx == -1:
        return

    file = playlist[idx]
    pygame.mixer.music.load(file)
    pygame.mixer.music.play()
    paused = False
    title_lbl.config(text=os.path.basename(file))

    try:
        sound = pygame.mixer.Sound(file)
        song_length = int(sound.get_length())
        progress.config(to=song_length)
        time_lbl.config(text=f"00:00 / {format_time(song_length)}")
    except:
        song_length = 0

def play_music():
    global paused
    if paused:
        pygame.mixer.music.unpause()
        paused = False
    elif not pygame.mixer.music.get_busy():
        play_selected()

def pause_music():
    global paused
    pygame.mixer.music.pause()
    paused = True

def toggle_repeat():
    global repeat
    repeat = not repeat
    repeat_btn.config(text="Repeat: ON" if repeat else "Repeat: OFF")

def check_end():
    if not pygame.mixer.music.get_busy() and not paused and playlist:
        if repeat:
            play_selected()
    root.after(1000, check_end)

def set_volume(val):
    pygame.mixer.music.set_volume(float(val))

def update_progress():
    if pygame.mixer.music.get_busy() and not paused:
        pos = pygame.mixer.music.get_pos() / 1000
        progress.set(pos)
        time_lbl.config(
            text=f"{format_time(pos)} / {format_time(song_length)}"
        )
    root.after(500, update_progress)

# ---------- UI ----------

tk.Label(
    root, text="Music Player",
    font=("Tahoma", 11, "bold"),
    bg="#C0C0C0"
).pack(pady=5)

frame = tk.Frame(root, bg="#C0C0C0")
frame.pack(fill="both", expand=True, padx=10)

title_lbl = tk.Label(
    frame, text="No file loaded",
    font=("Tahoma", 9),
    bg="#C0C0C0",
    anchor="w"
)
title_lbl.pack(fill="x")

tk.Button(
    frame, text="Load Folder",
    font=("Tahoma", 9),
    command=load_folder
).pack(pady=5)

combo = ttk.Combobox(
    frame, state="readonly", width=50
)
combo.pack()
combo.bind("<>", play_selected)

controls = tk.Frame(frame, bg="#C0C0C0")
controls.pack(pady=8)

tk.Button(
    controls, text="Play",
    width=10,
    font=("Tahoma", 9),
    command=play_music
).pack(side="left", padx=4)

tk.Button(
    controls, text="Pause",
    width=10,
    font=("Tahoma", 9),
    command=pause_music
).pack(side="left", padx=4)

repeat_btn = tk.Button(
    controls, text="Repeat: OFF",
    width=12,
    font=("Tahoma", 9),
    command=toggle_repeat
)
repeat_btn.pack(side="left", padx=4)

progress = tk.Scale(
    frame,
    from_=0, to=100,
    orient="horizontal",
    length=500,
    showvalue=False,
    bg="#C0C0C0",
    highlightthickness=0
)
progress.pack(pady=4)

time_lbl = tk.Label(
    frame, text="00:00 / 00:00",
    font=("Tahoma", 9),
    bg="#C0C0C0"
)
time_lbl.pack()

volume = tk.Scale(
    frame,
    from_=0, to=1,
    resolution=0.01,
    orient="horizontal",
    length=200,
    label="Volume",
    bg="#C0C0C0",
    highlightthickness=0,
    command=set_volume
)
volume.set(0.7)
volume.pack(pady=5)

# ---------- LOOPS ----------
update_progress()
check_end()

root.mainloop()