Sonore: Modern Music Player Project
Sonore: Modern Music Player Project
2. Our Project
3. Functions Used
4. Modules Used
5. Tables Created
6. System Requirements
7. Source Code
8. Output
9. Conclusions
10. Bibliography
INDEX
Introduction to Python
and SQL
Python:
Python is a versatile high-level programming
language known for its user-friendliness and
adaptability. It’s an ideal choice for beginners and
finds applications in diverse fields, including web
development and data analysis.
Python’s open-source nature fosters a strong
community of developers who readily share
resources and provide support. This collaboration
and sharing of knowledge are at the core of
Python’s success.
My SQL:
SQL (Structured Query Language) is a fundamental
tool for data management in relational databases.
It provides a standardized way to interact with
databases, facilitating data retrieval, manipulation,
and maintenance.
SQL’s simplicity and universality make it
indispensable for various applications, including
web development and data analysis, ensuring
efficient data handling.
OUR PROJECT
Our project, Sonore, is a modern and minimalistic
music player system designed to provide users
with a seamless and distraction-free listening
experience.
The device runs a custom-built application that
supports local storage and playback of audio
files. Users can browse through their music
library, create playlists, and control playback
using simple and intuitive controls. The interface
focuses on simplicity and elegance, ensuring that
users can access their favourite tracks quickly
and easily.
The main goal of Sonore is to create a dedicated
environment for pure music enjoyment,
eliminating the distractions commonly found in
smartphones and streaming apps. Through this
project, we aim to highlight the importance of
mindful listening and focus on delivering an
immersive and clutter-free musical experience.
FUNCTIONS USED
[Link]() – main function that runs the whole
Sonore music player app
2.load_icon() – loads an icon image from file and
converts it to CTkImage
3.load_cover_icon() – loads a circular cropped version of
a cover image for playlists
4.make_circle_image() – creates a circular colored
CTkImage (used as placeholders or defaults)
5.update_player_info() – updates song details, cover
images, and starts playing the selected song
6.update_progress() – updates the progress bar as the
current song plays
7.show_popup() – displays a small popup message
window
8.show_create_playlist() – opens a popup to create a
new playlist in the database
9.refresh_playlists() – refreshes and displays all
available playlists in the sidebar
10.load_and_play_playlist() – loads songs from a
selected playlist and starts playback
11.on_search() – searches for a song by name and
plays it if found
12.play_song_command() – plays a song when selected
from the main song grid
13.add_song_to_playlist() – adds the currently playing
song to a selected playlist
14.show_add_to_playlist_popup() – opens a popup to
choose a playlist to add the current song
15.on_prev() – plays the previous song in the current
queue
16.on_play_pause() – toggles between play and pause
for the current song
17.on_next() – plays the next song in the current queue
18.user_id() – fetches and returns the user ID for a
given username and password from the database
[Link]() – launches the main Sonore app
interface for a logged-in user
[Link]() – provides admin control panel for
managing users and songs
[Link]() – displays all users and optionally allows
searching by user ID
22.add_song() – inserts a new song entry into the song
table
23.delete_song() – deletes a song from the song table
by name
24.search_user() – searches for a specific user by ID
and displays their data
[Link]() – deletes a user and optionally their
playlists from the database
MODULES USED
1. [Link] : To connect MySQL
database with Python
2. pwinput : To securely take hidden
password input from the user
3. customtkinter : To design and create
a modern GUI (graphical user interface)
4. PIL (Pillow) : To handle image loading,
resizing, and manipulation
5. os : To handle file and directory
operations
6. math : To perform mathematical
calculations where needed
7. pygame : To play and control audio
(used for music playback)
8. admin : Custom module to manage
users and songs (admin control panel)
9. app (application) : Custom module
that runs the main Sonore music player
interface
TABLES CREATED
[Link]
[Link]
[Link]
SYSTEM REQUIREMENT
1. CPU: Intel(R) CPU 3825U @ 1.90
GHz,1901 Mhz, 2 Core(s), 4 Logical
Processor(s) SYSTEM REQUIREMENTS
2. Installed RAM: 4.00 GB
3. Motherboard: HP 80C1 96.42
4. Keyboard and mouse
5. Printer SOFTWARE REQUIREMENTS:
Windows OS
“Python”
MySQL
SOURCE CODE
[Link]:
from app import application
import [Link] as m
import admin
import pwinput
mydb=[Link](host="localhost",user="root",password="1234",databa
se="SONORE")
c=[Link]()
while a==1:
name=input("ENTER YOUR NAME: ")
password=[Link]("ENTER YOUR PASSWORD: ")
password1=[Link]("ENTER YOUR PASSWORD AGAIN: ")
id1=user_id(name,password)
dict_user[id1]=name
print("YOUR ACCOUNT HAS BEEN CREATED")
application(dict_user)
break
except:
[Link]()
else:
print("ERROR")
while a==2:
name=input("ENTER YOUR NAME: ")
password=[Link]("ENTER YOUR PASSWORD: ")
id1=user_id(name,password)
if id1==None: #checks if user already exists
print("WRONG USERNAME/PASSWORD")
else: #loggin in
dict_user={}
dict_user[id1]=name
if id1==1: #if user is admin
[Link]()
else: #normal user
application(dict_user)
break
[Link]()
[Link]()
[Link]:
import [Link] as m
mydb=[Link](host="localhost",user="root",password="1234",databa
se="SONORE")
c=[Link]()
def user_id(name,password):
[Link]("select user_id from user where name='{}' and
password='{}'".format(name,password))
user_id=[Link]()
if user_id==None:
return user_id
else:
return user_id[0]
def admin():
ans="yes"
while [Link]()=="yes":
def viewusers():
[Link]("SELECT * FROM USER")
f=[Link]()
for i in f:
print(i)
viewuser1=input("DO YOU WANT TO SEARCH?yes/no:")
if [Link]()=="yes":
d=int(input("ENTER THE ID TO BE SEARCHED:"))
for j in f:
if j[0]==d:
print(j)
def add_song():
N=input("ENTER NAME OF THE SONG: ")
P=input("ENTER PATH OF THE SONG: ")
A=input("ENTER NAME OF THE ARTIST: ")
D=input("ENTER DESCRIPTION IF ANY: ")
L=input("ENTER THE PATH OF THE LOGO: ")
[Link]("insert into song values(%s,%s,%s,%s,%s,)"%
(N,P,A,D,L,))
def delete_song():
S=input('ENTER SONG NAME TO BE DELETED')
[Link]("delete from song where name=%s"%(S,))
def search_user():
def delete():
[Link]:
import customtkinter as ctk
from PIL import Image, ImageTk, ImageOps, ImageDraw
import os
import [Link] as m
import math
[Link]['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame
[Link]()
current_song_index = -1
current_playing_queue = []
all_songs_data = []
is_playing = False
now_playing_title_label = None
now_playing_artist_label = None
now_playing_img_label = None
player_title_label = None
player_artist_label = None
player_img_widget = None
play_btn = None
progress = None
app = None
pause_icon = None
play_icon = None
search_bar = None
playlist_scroll = None
current_song_length = 0
def application(dict_user):
keys_list = list(dict_user.keys())
id1=keys_list[0]
global now_playing_title_label, now_playing_artist_label,
now_playing_img_label
global player_title_label, player_artist_label, player_img_widget,
play_btn, progress
global is_playing, current_playing_queue, app, pause_icon, play_icon,
search_bar, playlist_scroll, all_songs_data
# Color variables
MAIN_BG = "#151515"
SECTION_BG = "#1f1f1f"
BLUE = "#A3BCF9"
WINDOW_W, WINDOW_H = 1280, 720
ICON_DIR = "icons"
player_title_label.configure(text=name)
player_artist_label.configure(text=artist)
try:
if logo_path and [Link](logo_path):
pil_img = [Link](logo_path).convert("RGBA")
pil_img_side = [Link](pil_img, (240, 240))
pil_img_bottom = [Link](pil_img, (56, 56))
now_playing_img_label.configure(image=[Link](pil_img_side,
size=(240, 240)))
player_img_widget.configure(image=[Link](pil_img_bottom,
size=(56, 56)))
else:
default_img = make_circle_image(240, 240)
now_playing_img_label.configure(image=default_img)
player_img_widget.configure(image=make_circle_image(56,
56))
except Exception as e:
print(f"Error updating image: {e}")
default_img = make_circle_image(240, 240)
now_playing_img_label.configure(image=default_img)
player_img_widget.configure(image=make_circle_image(56, 56))
try:
[Link](song_path)
[Link]()
is_playing = True
if pause_icon:
play_btn.configure(image=pause_icon)
snd = [Link](song_path)
current_song_length = snd.get_length()
def show_create_playlist():
popup = [Link](app)
[Link]("Create Playlist")
[Link]("400x200")
[Link](app)
popup.grab_set()
x = app.winfo_x() + (WINDOW_W // 2) - 200
y = app.winfo_y() + (WINDOW_H // 2) - 100
[Link](f"400x200+{x}+{y}")
[Link](fg_color=MAIN_BG)
[Link](
popup,
text="Enter Playlist Name",
text_color="white",
font=("Manjari", 24, "bold")
).pack(pady=15)
playlist_name_entry = [Link](
popup,
placeholder_text="Playlist Name",
width=250,
fg_color=SECTION_BG,
text_color="white"
)
playlist_name_entry.pack(pady=10)
def confirm_playlist():
name = playlist_name_entry.get().strip()
if name:
[Link](
f"create table `{name}`(user_id INT(3), name VARCHAR(30),
path VARCHAR(100), artist VARCHAR(15), description VARCHAR(30), logo
VARCHAR(100))"
)
[Link]()
[Link]()
show_popup("Success", f"Playlist '{name}' created
successfully!")
refresh_playlists()
confirm_btn = [Link](
popup,
text="Confirm",
fg_color=BLUE,
text_color="black",
command=confirm_playlist
)
confirm_btn.pack(pady=15)
def refresh_playlists():
for widget in playlist_scroll.winfo_children():
[Link]()
[Link](
'SELECT table_name FROM information_schema.tables '
'WHERE table_schema = "SONORE" AND table_name NOT IN
("user", "song");'
)
playlist_data = [Link]()
icon = None
if logo_data and logo_data[0] and [Link](logo_data[0]):
icon = load_cover_icon(logo_data[0], (44, 44))
if icon:
btn = [Link](
playlist_scroll,
image=icon,
text="",
width=44,
height=44,
fg_color=SECTION_BG,
corner_radius=20,
command=lambda name=playlist_name:
load_and_play_playlist(name)
)
else:
btn = [Link](
playlist_scroll,
text=playlist_name[:3].upper(),
width=44,
height=44,
fg_color=BLUE,
corner_radius=20,
text_color="black",
font=("Manjari", 16, "bold"),
command=lambda name=playlist_name:
load_and_play_playlist(name)
)
[Link](pady=12)
def load_and_play_playlist(playlist_name):
global current_playing_queue, current_song_index
try:
[Link](f"SELECT name, artist, logo, path FROM
`{playlist_name}`")
playlist_songs = [Link]()
if not playlist_songs:
show_popup("Playlist Empty", "This playlist does not contain any
songs.")
return
song_path, song_info =
current_playing_queue[current_song_index]
update_player_info(song_info)
if not query:
show_popup("Search Error", "Please enter a song name to
search.")
return
current_playing_queue = []
for i, row in enumerate(fetched_output):
current_playing_queue.append((row[3], (row[0], row[1], row[2],
row[3])))
name, artist, logo, path = row
if [Link]() == [Link]():
found_song_info = (name, artist, logo, path)
current_song_index = i
if found_song_info:
print(f"Playing song: {found_song_info[0]}")
update_player_info(found_song_info)
else:
show_popup("Song Not Found", f"No song found with the name
'{query}'")
current_playing_queue = [] # Clear queue if not found
search_bar.delete(0, "end")
search_bar = [Link](
app,
placeholder_text="Search",
width=350,
height=36,
corner_radius=20,
fg_color=SECTION_BG,
placeholder_text_color="#fff",
border_width=0,
text_color="white",
font=("Manjari", 18, 'bold'),
)
search_bar.place(x=(WINDOW_W - 350) // 2, y=18)
search_bar.bind("<Return>", on_search)
playlist_scroll = [Link](
sidebar, width=55, height=WINDOW_H - 188 - 80,
fg_color=SECTION_BG
)
playlist_scroll.place(x=8, y=80)
refresh_playlists()
[Link](
main_frame,
text="Music Displayed",
text_color="white",
font=("Manjari", 28, "bold")
).pack(pady=(10, 20), anchor="w", padx=20)
def play_song_command(index):
global current_song_index, current_playing_queue
current_playing_queue = [(row[3], (row[0], row[1], row[2], row[3]))
for row in all_songs_data] # Reset queue to all songs
current_song_index = index
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
for r in range(rows):
row_frame = [Link](main_frame, fg_color=SECTION_BG)
row_frame.pack(pady=(0, gap_y - thumb_h), anchor='w')
for c in range(cols):
if index >= len(all_songs_data):
break
song_name, song_artist, song_logo, song_path =
all_songs_data[index]
try:
if song_logo and [Link](song_logo):
pil_img = [Link](song_logo).convert("RGBA")
pil_img = [Link](pil_img, (thumb_w, thumb_h))
logo_ctk = [Link](pil_img, size=(thumb_w, thumb_h))
tile_btn = [Link](
row_frame,
image=logo_ctk,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=SECTION_BG,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
else:
tile_btn = [Link](
row_frame,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=BLUE,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
tile_btn.grid(row=0, column=c, padx=(gap_x / 2, 0))
except Exception as e:
print("Error loading logo:", e)
tile_btn = [Link](
row_frame,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=BLUE,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
tile_btn.grid(row=0, column=c, padx=(gap_x / 2, gap_x / 2))
[Link](
row_frame, text=song_name, text_color="white",
font=("Manjari", 17, "bold")
).grid(row=1, column=c, pady=(5, 0))
[Link](
row_frame, text=song_artist, text_color="#fff", font=("Manjari",
14)
).grid(row=2, column=c)
index += 1
try:
song_info = current_playing_queue[current_song_index][1]
song_name, artist, logo_path, song_path = song_info
[Link](insert_query, song_data)
[Link]()
show_popup("Success", f"Song '{song_name}' added to playlist
'{playlist_name}'.")
except Exception as e:
show_popup("Error", f"Failed to add song to playlist: {e}")
def show_add_to_playlist_popup():
if current_song_index == -1:
show_popup("Error", "No song is currently playing. Please select a
song first.")
return
popup = [Link](app)
[Link]("Add to Playlist")
[Link]("350x400")
[Link](app)
popup.grab_set()
x = app.winfo_x() + (app.winfo_width() // 2) - 175
y = app.winfo_y() + (app.winfo_height() // 2) - 200
[Link](f"+{x}+{y}")
[Link](fg_color=MAIN_BG)
[Link](
popup,
text="Select a Playlist",
text_color="white",
font=("Manjari", 20, "bold")
).pack(pady=10)
playlist_frame = [Link](popup,
fg_color=SECTION_BG, corner_radius=10)
playlist_frame.pack(fill="both", expand=True, padx=20, pady=10)
[Link](
'SELECT table_name FROM information_schema.tables '
'WHERE table_schema = "SONORE" AND table_name NOT IN
("user", "song");'
)
playlists = [Link]()
if not playlists:
[Link](playlist_frame, text="No playlists found.",
text_color="white").pack(pady=20)
else:
for playlist in playlists:
playlist_name = playlist[0]
[Link](
playlist_frame,
text=playlist_name,
fg_color=BLUE,
text_color="black",
font=("Manjari", 16, "bold"),
command=lambda name=playlist_name:
add_song_to_playlist(name)
).pack(pady=5, padx=10, fill="x")
right_frame = [Link](
app, fg_color=SECTION_BG, width=315, height=WINDOW_H - 188,
corner_radius=20
)
right_frame.place(x=953, y=70)
[Link](
right_frame,
text="Now Playing",
text_color="white",
font=("Manjari", 22, "bold")
).place(x=20, y=14)
now_playing_img_label = [Link](right_frame,
image=make_circle_image(240, 240), text="")
now_playing_img_label.place(x=30, y=70)
now_playing_title_label = [Link](
right_frame,
text="Song Title - Artist",
text_color="white",
font=("Manjari", 20, "bold")
)
now_playing_title_label.place(x=20, y=322)
now_playing_artist_label = [Link](
right_frame,
text="Album • Year",
text_color="#cfcfcf",
font=("Manjari", 18)
)
now_playing_artist_label.place(x=20, y=348)
player_img_widget = [Link](
player_frame, image=make_circle_image(56, 56), text=""
)
player_img_widget.place(x=12, y=20)
player_title_label = [Link](
player_frame,
text="Song Title",
text_color="white",
font=("Manjari", 20, "bold")
)
player_title_label.place(x=80, y=22)
player_artist_label = [Link](
player_frame,
text="Artist Name",
text_color="#cfcfcf",
font=("Manjari", 18)
)
player_artist_label.place(x=80, y=50)
control_x_center = WINDOW_W // 2
start_x = control_x_center - 70
def on_prev():
global current_song_index
if not current_playing_queue: return
current_song_index = (current_song_index - 1 +
len(current_playing_queue)) % len(current_playing_queue)
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
def on_play_pause():
global is_playing
if not current_playing_queue or current_song_index == -1: return
if is_playing:
[Link]()
is_playing = False
if play_icon:
play_btn.configure(image=play_icon)
else:
[Link]()
is_playing = True
if pause_icon:
play_btn.configure(image=pause_icon)
def on_next():
global current_song_index
if not current_playing_queue: return
current_song_index = (current_song_index + 1) %
len(current_playing_queue)
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
if prev_icon:
prev_btn = [Link](
player_frame, image=prev_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_prev, text_color="#151515"
)
else:
prev_btn = [Link](player_frame, text="⏮", width=30,
height=40, fg_color=BLUE,
corner_radius=20, command=on_prev, text_color="#151515"
)
prev_btn.place(x=start_x, y=24)
if play_icon:
play_btn = [Link](
player_frame, image=play_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_play_pause,
text_color="#151515"
)
else:
play_btn = [Link](
player_frame, text="▶", width=30, height=40, fg_color=BLUE,
corner_radius=20, command=on_play_pause,
text_color="#151515"
)
play_btn.place(x=start_x + 70, y=24)
if next_icon:
next_btn = [Link](
player_frame, image=next_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_next, text_color="#151515"
)
else:
next_btn = [Link](
player_frame, text="⏭", width=30, height=40, fg_color=BLUE,
corner_radius=20, command=on_next, text_color="#151515"
)
next_btn.place(x=start_x + 140, y=24)
[Link]()
import customtkinter as ctk
from PIL import Image, ImageTk, ImageOps, ImageDraw
import os
import [Link] as m
import math
[Link]['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame
[Link]()
current_song_index = -1
current_playing_queue = []
all_songs_data = []
is_playing = False
now_playing_title_label = None
now_playing_artist_label = None
now_playing_img_label = None
player_title_label = None
player_artist_label = None
player_img_widget = None
play_btn = None
progress = None
app = None
pause_icon = None
play_icon = None
search_bar = None
playlist_scroll = None
current_song_length = 0
def application(dict_user):
keys_list = list(dict_user.keys())
id1=keys_list[0]
global now_playing_title_label, now_playing_artist_label,
now_playing_img_label
global player_title_label, player_artist_label, player_img_widget,
play_btn, progress
global is_playing, current_playing_queue, app, pause_icon, play_icon,
search_bar, playlist_scroll, all_songs_data
# Color variables
MAIN_BG = "#151515"
SECTION_BG = "#1f1f1f"
BLUE = "#A3BCF9"
WINDOW_W, WINDOW_H = 1280, 720
ICON_DIR = "icons"
now_playing_title_label.configure(text=name)
now_playing_artist_label.configure(text=artist)
player_title_label.configure(text=name)
player_artist_label.configure(text=artist)
try:
if logo_path and [Link](logo_path):
pil_img = [Link](logo_path).convert("RGBA")
pil_img_side = [Link](pil_img, (240, 240))
pil_img_bottom = [Link](pil_img, (56, 56))
now_playing_img_label.configure(image=[Link](pil_img_side,
size=(240, 240)))
player_img_widget.configure(image=[Link](pil_img_bottom,
size=(56, 56)))
else:
default_img = make_circle_image(240, 240)
now_playing_img_label.configure(image=default_img)
player_img_widget.configure(image=make_circle_image(56,
56))
except Exception as e:
print(f"Error updating image: {e}")
default_img = make_circle_image(240, 240)
now_playing_img_label.configure(image=default_img)
player_img_widget.configure(image=make_circle_image(56, 56))
try:
[Link](song_path)
[Link]()
is_playing = True
if pause_icon:
play_btn.configure(image=pause_icon)
snd = [Link](song_path)
current_song_length = snd.get_length()
def show_create_playlist():
popup = [Link](app)
[Link]("Create Playlist")
[Link]("400x200")
[Link](app)
popup.grab_set()
x = app.winfo_x() + (WINDOW_W // 2) - 200
y = app.winfo_y() + (WINDOW_H // 2) - 100
[Link](f"400x200+{x}+{y}")
[Link](fg_color=MAIN_BG)
[Link](
popup,
text="Enter Playlist Name",
text_color="white",
font=("Manjari", 24, "bold")
).pack(pady=15)
playlist_name_entry = [Link](
popup,
placeholder_text="Playlist Name",
width=250,
fg_color=SECTION_BG,
text_color="white"
)
playlist_name_entry.pack(pady=10)
def confirm_playlist():
name = playlist_name_entry.get().strip()
if name:
[Link](
f"create table `{name}`(user_id INT(3), name VARCHAR(30),
path VARCHAR(100), artist VARCHAR(15), description VARCHAR(30), logo
VARCHAR(100))"
)
[Link]()
[Link]()
show_popup("Success", f"Playlist '{name}' created
successfully!")
refresh_playlists()
confirm_btn = [Link](
popup,
text="Confirm",
fg_color=BLUE,
text_color="black",
command=confirm_playlist
)
confirm_btn.pack(pady=15)
def refresh_playlists():
for widget in playlist_scroll.winfo_children():
[Link]()
[Link](
'SELECT table_name FROM information_schema.tables '
'WHERE table_schema = "SONORE" AND table_name NOT IN
("user", "song");'
)
playlist_data = [Link]()
if icon:
btn = [Link](
playlist_scroll,
image=icon,
text="",
width=44,
height=44,
fg_color=SECTION_BG,
corner_radius=20,
command=lambda name=playlist_name:
load_and_play_playlist(name)
)
else:
btn = [Link](
playlist_scroll,
text=playlist_name[:3].upper(),
width=44,
height=44,
fg_color=BLUE,
corner_radius=20,
text_color="black",
font=("Manjari", 16, "bold"),
command=lambda name=playlist_name:
load_and_play_playlist(name)
)
[Link](pady=12)
def load_and_play_playlist(playlist_name):
global current_playing_queue, current_song_index
try:
[Link](f"SELECT name, artist, logo, path FROM
`{playlist_name}`")
playlist_songs = [Link]()
if not playlist_songs:
show_popup("Playlist Empty", "This playlist does not contain any
songs.")
return
current_playing_queue = [(row[3], (row[0], row[1], row[2], row[3]))
for row in playlist_songs]
current_song_index = 0
song_path, song_info =
current_playing_queue[current_song_index]
update_player_info(song_info)
if not query:
show_popup("Search Error", "Please enter a song name to
search.")
return
current_playing_queue = []
for i, row in enumerate(fetched_output):
current_playing_queue.append((row[3], (row[0], row[1], row[2],
row[3])))
name, artist, logo, path = row
if [Link]() == [Link]():
found_song_info = (name, artist, logo, path)
current_song_index = i
if found_song_info:
print(f"Playing song: {found_song_info[0]}")
update_player_info(found_song_info)
else:
show_popup("Song Not Found", f"No song found with the name
'{query}'")
current_playing_queue = [] # Clear queue if not found
search_bar.delete(0, "end")
search_bar = [Link](
app,
placeholder_text="Search",
width=350,
height=36,
corner_radius=20,
fg_color=SECTION_BG,
placeholder_text_color="#fff",
border_width=0,
text_color="white",
font=("Manjari", 18, 'bold'),
)
search_bar.place(x=(WINDOW_W - 350) // 2, y=18)
search_bar.bind("<Return>", on_search)
playlist_scroll = [Link](
sidebar, width=55, height=WINDOW_H - 188 - 80,
fg_color=SECTION_BG
)
playlist_scroll.place(x=8, y=80)
refresh_playlists()
[Link](
main_frame,
text="Music Displayed",
text_color="white",
font=("Manjari", 28, "bold")
).pack(pady=(10, 20), anchor="w", padx=20)
def play_song_command(index):
global current_song_index, current_playing_queue
current_playing_queue = [(row[3], (row[0], row[1], row[2], row[3]))
for row in all_songs_data] # Reset queue to all songs
current_song_index = index
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
for r in range(rows):
row_frame = [Link](main_frame, fg_color=SECTION_BG)
row_frame.pack(pady=(0, gap_y - thumb_h), anchor='w')
for c in range(cols):
if index >= len(all_songs_data):
break
song_name, song_artist, song_logo, song_path =
all_songs_data[index]
try:
if song_logo and [Link](song_logo):
pil_img = [Link](song_logo).convert("RGBA")
pil_img = [Link](pil_img, (thumb_w, thumb_h))
logo_ctk = [Link](pil_img, size=(thumb_w, thumb_h))
tile_btn = [Link](
row_frame,
image=logo_ctk,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=SECTION_BG,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
else:
tile_btn = [Link](
row_frame,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=BLUE,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
tile_btn.grid(row=0, column=c, padx=(gap_x / 2, 0))
except Exception as e:
print("Error loading logo:", e)
tile_btn = [Link](
row_frame,
text="",
width=thumb_w,
height=thumb_h,
corner_radius=8,
fg_color=BLUE,
hover_color="#333",
command=lambda idx=index: play_song_command(idx)
)
tile_btn.grid(row=0, column=c, padx=(gap_x / 2, gap_x / 2))
[Link](
row_frame, text=song_name, text_color="white",
font=("Manjari", 17, "bold")
).grid(row=1, column=c, pady=(5, 0))
[Link](
row_frame, text=song_artist, text_color="#fff", font=("Manjari",
14)
).grid(row=2, column=c)
index += 1
try:
song_info = current_playing_queue[current_song_index][1]
song_name, artist, logo_path, song_path = song_info
[Link](insert_query, song_data)
[Link]()
show_popup("Success", f"Song '{song_name}' added to playlist
'{playlist_name}'.")
except Exception as e:
show_popup("Error", f"Failed to add song to playlist: {e}")
def show_add_to_playlist_popup():
if current_song_index == -1:
show_popup("Error", "No song is currently playing. Please select a
song first.")
return
popup = [Link](app)
[Link]("Add to Playlist")
[Link]("350x400")
[Link](app)
popup.grab_set()
x = app.winfo_x() + (app.winfo_width() // 2) - 175
y = app.winfo_y() + (app.winfo_height() // 2) - 200
[Link](f"+{x}+{y}")
[Link](fg_color=MAIN_BG)
[Link](
popup,
text="Select a Playlist",
text_color="white",
font=("Manjari", 20, "bold")
).pack(pady=10)
playlist_frame = [Link](popup,
fg_color=SECTION_BG, corner_radius=10)
playlist_frame.pack(fill="both", expand=True, padx=20, pady=10)
[Link](
'SELECT table_name FROM information_schema.tables '
'WHERE table_schema = "SONORE" AND table_name NOT IN
("user", "song");'
)
playlists = [Link]()
if not playlists:
[Link](playlist_frame, text="No playlists found.",
text_color="white").pack(pady=20)
else:
for playlist in playlists:
playlist_name = playlist[0]
[Link](
playlist_frame,
text=playlist_name,
fg_color=BLUE,
text_color="black",
font=("Manjari", 16, "bold"),
command=lambda name=playlist_name:
add_song_to_playlist(name)
).pack(pady=5, padx=10, fill="x")
right_frame = [Link](
app, fg_color=SECTION_BG, width=315, height=WINDOW_H - 188,
corner_radius=20
)
right_frame.place(x=953, y=70)
[Link](
right_frame,
text="Now Playing",
text_color="white",
font=("Manjari", 22, "bold")
).place(x=20, y=14)
now_playing_img_label = [Link](right_frame,
image=make_circle_image(240, 240), text="")
now_playing_img_label.place(x=30, y=70)
now_playing_title_label = [Link](
right_frame,
text="Song Title - Artist",
text_color="white",
font=("Manjari", 20, "bold")
)
now_playing_title_label.place(x=20, y=322)
now_playing_artist_label = [Link](
right_frame,
text="Album • Year",
text_color="#cfcfcf",
font=("Manjari", 18)
)
now_playing_artist_label.place(x=20, y=348)
player_img_widget = [Link](
player_frame, image=make_circle_image(56, 56), text=""
)
player_img_widget.place(x=12, y=20)
player_title_label = [Link](
player_frame,
text="Song Title",
text_color="white",
font=("Manjari", 20, "bold")
)
player_title_label.place(x=80, y=22)
player_artist_label = [Link](
player_frame,
text="Artist Name",
text_color="#cfcfcf",
font=("Manjari", 18)
)
player_artist_label.place(x=80, y=50)
control_x_center = WINDOW_W // 2
start_x = control_x_center - 70
def on_prev():
global current_song_index
if not current_playing_queue: return
current_song_index = (current_song_index - 1 +
len(current_playing_queue)) % len(current_playing_queue)
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
def on_play_pause():
global is_playing
if not current_playing_queue or current_song_index == -1: return
if is_playing:
[Link]()
is_playing = False
if play_icon:
play_btn.configure(image=play_icon)
else:
[Link]()
is_playing = True
if pause_icon:
play_btn.configure(image=pause_icon)
def on_next():
global current_song_index
if not current_playing_queue: return
current_song_index = (current_song_index + 1) %
len(current_playing_queue)
song_path, song_info = current_playing_queue[current_song_index]
update_player_info(song_info)
if prev_icon:
prev_btn = [Link](
player_frame, image=prev_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_prev, text_color="#151515"
)
else:
prev_btn = [Link](player_frame, text="⏮", width=30,
height=40, fg_color=BLUE,
corner_radius=20, command=on_prev, text_color="#151515"
)
prev_btn.place(x=start_x, y=24)
if play_icon:
play_btn = [Link](
player_frame, image=play_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_play_pause,
text_color="#151515"
)
else:
play_btn = [Link](
player_frame, text="▶", width=30, height=40, fg_color=BLUE,
corner_radius=20, command=on_play_pause,
text_color="#151515"
)
play_btn.place(x=start_x + 70, y=24)
if next_icon:
next_btn = [Link](
player_frame, image=next_icon, text="", width=30, height=40,
fg_color=BLUE,
corner_radius=20, command=on_next, text_color="#151515"
)
else:
next_btn = [Link](
player_frame, text="⏭", width=30, height=40, fg_color=BLUE,
corner_radius=20, command=on_next, text_color="#151515"
)
next_btn.place(x=start_x + 140, y=24)
[Link](player_frame, text="00:00", text_color="white",
font=("Manjari", 10)).place(x=start_x - 150, y=64)
progress = [Link](player_frame, width=380, height=6,
progress_color=BLUE)
[Link](x=start_x - 110, y=74)
[Link](0)
[Link](player_frame, text="03:45", text_color="white",
font=("Manjari", 10)).place(x=start_x + 290, y=64)
[Link]()
OUTPUT
CONCLUSION
3. [Link]
python/introduction-to-python-tabulate-
library/