Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import sqlite3
- import tempfile
- from tkinter import *
- from tkinter import filedialog, messagebox, ttk
- import vlc
- from PIL import Image, ImageTk, ImageSequence
- import sys
- import configparser
- import hashlib
- import base64
- #================ADD-IMAGE-ICON=================
- import sys
- def resource_path(relative_path):
- """ Get the absolute path to the resource, works for PyInstaller. """
- if getattr(sys, '_MEIPASS', False):
- return os.path.join(sys._MEIPASS, relative_path)
- return os.path.join(os.path.abspath("."), relative_path)
- # Use this function to load files:
- #splash_image = resource_path("splash-1.png")
- icon_path = resource_path("M.ico")
- #-------------------------------------------
- def resource_path(relative_path):
- """ Get absolute path to resource, works for dev and for PyInstaller """
- try:
- # PyInstaller creates a temp folder and stores path in _MEIPASS
- base_path = sys._MEIPASS
- except Exception:
- base_path = os.path.abspath(".")
- return os.path.join(base_path, relative_path)
- #================ADD-IMAGE-ICON=================
- class Mp3PlayerApp:
- def __init__(self, root):
- self.root = root
- self.root.title("Najeeb Advanced MP3 Player")
- self.root.geometry("1200x700")
- self.root.config(bg="#f0f0f0")
- #self.root.configure(bg="#2c3e50")
- self.root.iconbitmap(icon_path)
- # Initialize VLC
- self.vlc_instance = vlc.Instance()
- self.media_player = self.vlc_instance.media_player_new()
- # Security
- self.secure_mode = False
- self.password_hash = self.load_password_hash()
- # DB Setup
- self.db_path = "M-DATA.db"
- self.connect_database()
- # Stream data
- self.streams = {}
- self.current_streams = {}
- # Temp files list
- self.temp_files = []
- # UI Setup
- self.setup_theme()
- self.create_menu()
- self.create_notebook()
- self.create_media_controls()
- self.create_status_bar()
- self.load_gif("MP3.gif")
- self.load_mp3s_from_database()
- def setup_theme(self):
- style = ttk.Style()
- style.theme_use('clam')
- style.configure("TButton", padding=6, relief="flat", background="#4CAF50")
- style.configure("TFrame", background="#f0f0f0")
- style.configure("Treeview", background="#ffffff", fieldbackground="#f0f0f0")
- style.configure("TNotebook.Tab", padding=[10, 5], background="#e0e0e0")
- self.root.option_add("*Font", "Helvetica 10")
- self.root.option_add("*Background", "#f0f0f0")
- self.root.option_add("*Button.Background", "#4CAF50")
- self.root.option_add("*Button.Foreground", "white")
- def create_menu(self):
- menubar = Menu(self.root)
- filemenu = Menu(menubar, tearoff=0)
- filemenu.add_command(label="Open MP3 Database", command=self.select_database)
- filemenu.add_command(label="Open Streams File", command=self.select_streams_file)
- filemenu.add_separator()
- filemenu.add_command(label="Exit", command=self.root.quit)
- menubar.add_cascade(label="File", menu=filemenu)
- securitymenu = Menu(menubar, tearoff=0)
- securitymenu.add_command(label="Set Password", command=self.set_password)
- securitymenu.add_command(label="Lock Application", command=self.lock_application)
- securitymenu.add_checkbutton(label="Secure Mode", variable=IntVar(value=1), command=self.toggle_secure_mode)
- menubar.add_cascade(label="Security", menu=securitymenu)
- self.root.config(menu=menubar)
- def create_notebook(self):
- self.notebook = ttk.Notebook(self.root)
- self.notebook.pack(fill=BOTH, expand=True, padx=10, pady=10)
- # Music Tab
- music_tab = ttk.Frame(self.notebook)
- self.notebook.add(music_tab, text='Music Library')
- self.create_music_ui(music_tab)
- # Radio Tab
- radio_tab = ttk.Frame(self.notebook)
- self.notebook.add(radio_tab, text='Live Radio')
- self.create_radio_ui(radio_tab)
- # Settings Tab
- settings_tab = ttk.Frame(self.notebook)
- self.notebook.add(settings_tab, text='Settings')
- self.create_settings_ui(settings_tab)
- def create_music_ui(self, parent):
- main_frame = ttk.Frame(parent)
- main_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
- button_frame = ttk.Frame(main_frame)
- button_frame.pack(fill=X, pady=5)
- Button(button_frame, text="Browse Folder", command=self.browse_folder).pack(side=LEFT, padx=5)
- Button(button_frame, text="Add MP3", command=self.add_mp3_file).pack(side=LEFT, padx=5)
- Button(button_frame, text="Delete MP3", command=self.delete_mp3_file).pack(side=LEFT, padx=5)
- Button(button_frame, text="Save MP3", command=self.save_mp3_to_database).pack(side=LEFT, padx=5)
- Button(button_frame, text="Delete Temp", command=self.delete_temp_files).pack(side=LEFT, padx=5)
- list_frame = ttk.Frame(main_frame)
- list_frame.pack(fill=BOTH, expand=True)
- self.listbox = Listbox(list_frame, width=50, height=10)
- self.listbox.pack(side=LEFT, fill=BOTH, expand=True)
- self.listbox.bind("<<ListboxSelect>>", self.play_selected_song)
- scrollbar = Scrollbar(list_frame)
- scrollbar.pack(side=RIGHT, fill=Y)
- self.listbox.config(yscrollcommand=scrollbar.set)
- scrollbar.config(command=self.listbox.yview)
- def create_radio_ui(self, parent):
- radio_frame = ttk.Frame(parent)
- radio_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
- Label(radio_frame, text="Select Category:", font=("Helvetica", 10, "bold")).pack(anchor=W, pady=5)
- self.category_var = StringVar()
- self.category_combo = ttk.Combobox(radio_frame, textvariable=self.category_var, state="readonly", width=30)
- self.category_combo.pack(pady=5)
- self.category_combo.bind("<<ComboboxSelected>>", self.update_stations)
- Label(radio_frame, text="Select Station:", font=("Helvetica", 10, "bold")).pack(anchor=W, pady=5)
- self.station_list = Listbox(radio_frame, width=50, height=10)
- self.station_list.pack(fill=BOTH, expand=True)
- self.station_list.bind("<Double-1>", self.play_selected_station)
- self.stream_info = Label(radio_frame, text="Double-click a station to play", fg="blue", cursor="hand2")
- self.stream_info.pack(pady=5)
- self.stream_info.bind("<Button-1>", lambda e: self.open_stream_url())
- def create_settings_ui(self, parent):
- settings_frame = ttk.Frame(parent)
- settings_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
- Label(settings_frame, text="Security Settings", font=("Helvetica", 12, "bold")).pack(anchor=W, pady=5)
- self.secure_mode_var = IntVar(value=1)
- Checkbutton(settings_frame, text="Enable Secure Mode", variable=self.secure_mode_var, command=self.toggle_secure_mode).pack(anchor=W)
- Button(settings_frame, text="Set Password", command=self.set_password).pack(anchor=W, pady=5)
- Button(settings_frame, text="Lock Application", command=self.lock_application).pack(anchor=W)
- Label(settings_frame, text="About", font=("Helvetica", 12, "bold")).pack(anchor=W, pady=5)
- Label(settings_frame, text="MP3 Player v3.0\nDeveloped by Najeeb Shah Khan").pack(anchor=W)
- def create_media_controls(self):
- control_frame = ttk.Frame(self.root)
- control_frame.pack(fill=X, padx=10, pady=10)
- Button(control_frame, text="Play", command=self.play_selected_song).pack(side=LEFT, padx=5)
- Button(control_frame, text="Stop", command=self.stop_song).pack(side=LEFT, padx=5)
- Button(control_frame, text="Previous", command=self.play_previous).pack(side=LEFT, padx=5)
- Button(control_frame, text="Next", command=self.play_next).pack(side=LEFT, padx=5)
- self.position_slider = Scale(control_frame, from_=0, to=100, orient=HORIZONTAL, length=300, command=self.seek_position)
- self.position_slider.pack(side=LEFT, padx=10)
- Label(control_frame, text="Volume").pack(side=LEFT)
- self.volume_slider = Scale(control_frame, from_=0, to=100, orient=HORIZONTAL, length=100, command=self.set_volume)
- self.volume_slider.set(50)
- self.volume_slider.pack(side=LEFT, padx=10)
- def create_status_bar(self):
- self.status_bar = Label(self.root, text="Ready", bd=1, relief=SUNKEN, anchor=W)
- self.status_bar.pack(side=BOTTOM, fill=X)
- def connect_database(self):
- try:
- self.db_connection = sqlite3.connect(self.db_path)
- self.cursor = self.db_connection.cursor()
- self.cursor.execute('''CREATE TABLE IF NOT EXISTS mp3_files
- (id INTEGER PRIMARY KEY, filename TEXT, filedata BLOB)''')
- self.db_connection.commit()
- except Exception as e:
- messagebox.showerror("Database Error", f"Failed to connect to database: {e}")
- def select_database(self):
- db_path = filedialog.askopenfilename(
- title="Select MP3 Database",
- filetypes=[("SQLite Database", "*.db"), ("All files", "*.*")]
- )
- if db_path:
- self.db_path = db_path
- self.connect_database()
- self.load_mp3s_from_database()
- self.update_status("Database loaded successfully")
- def select_streams_file(self):
- ini_path = filedialog.askopenfilename(
- title="Select Streams File",
- filetypes=[("INI Config", "*.ini"), ("All files", "*.*")]
- )
- if ini_path:
- self.load_streams_file(ini_path)
- self.update_status("Streams file loaded successfully")
- def load_streams_file(self, ini_path):
- config = configparser.ConfigParser()
- try:
- config.read(ini_path)
- self.streams = {sect: dict(config.items(sect)) for sect in config.sections()}
- if self.streams:
- self.category_combo['values'] = list(self.streams.keys())
- self.category_combo.current(0)
- self.update_stations()
- else:
- messagebox.showerror("Error", "No valid sections found in stream file.")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to load stream file: {e}")
- def update_stations(self, event=None):
- selected_category = self.category_var.get()
- if selected_category in self.streams:
- self.station_list.delete(0, END)
- for station in self.streams[selected_category]:
- self.station_list.insert(END, station)
- self.current_streams = self.streams[selected_category]
- def play_selected_station(self, event=None):
- if self.secure_mode and not self.authenticate():
- return
- selected_index = self.station_list.curselection()
- if not selected_index:
- return
- station_name = self.station_list.get(selected_index)
- stream_url = self.current_streams.get(station_name)
- if not stream_url:
- messagebox.showerror("Error", "Stream URL not found.")
- return
- try:
- media = self.vlc_instance.media_new(stream_url)
- self.media_player.set_media(media)
- self.media_player.play()
- self.update_status(f"Playing: {station_name}")
- self.current_stream_url = stream_url
- except Exception as e:
- messagebox.showerror("Error", f"Failed to play stream: {e}")
- def open_stream_url(self):
- if hasattr(self, 'current_stream_url'):
- import webbrowser
- webbrowser.open(self.current_stream_url)
- def set_password(self):
- if self.secure_mode and not self.authenticate():
- return
- new_pass = self.get_password_dialog("Set New Password", "Enter new password:")
- if new_pass:
- self.password_hash = self.hash_password(new_pass)
- self.save_password_hash()
- messagebox.showinfo("Success", "Password set successfully")
- self.update_status("Password set")
- def lock_application(self):
- if self.authenticate():
- self.root.withdraw()
- self.root.after(100, self.show_login_dialog)
- def toggle_secure_mode(self):
- self.secure_mode = self.secure_mode_var.get() == 1
- status = "enabled" if self.secure_mode else "disabled"
- self.update_status(f"Secure mode {status}")
- def authenticate(self):
- if not self.secure_mode or not self.password_hash:
- return True
- password = self.get_password_dialog("Authentication Required", "Enter password:")
- if password and self.hash_password(password) == self.password_hash:
- return True
- return False
- def get_password_dialog(self, title, prompt):
- dialog = Toplevel(self.root)
- dialog.title(title)
- dialog.geometry("300x120")
- dialog.transient(self.root)
- dialog.grab_set()
- Label(dialog, text=prompt).pack(pady=5)
- password_var = StringVar()
- entry = Entry(dialog, textvariable=password_var, show="*")
- entry.pack(pady=5)
- result = [None]
- def on_ok():
- result[0] = password_var.get()
- dialog.destroy()
- Button(dialog, text="OK", command=on_ok).pack(side=LEFT, padx=20)
- Button(dialog, text="Cancel", command=dialog.destroy).pack(side=RIGHT, padx=20)
- self.root.wait_window(dialog)
- return result[0]
- def hash_password(self, password):
- salt = b'salt_123'
- return base64.b64encode(hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)).decode()
- def load_password_hash(self):
- try:
- with open('config.dat', 'r') as f:
- return f.read().strip()
- except:
- return None
- def save_password_hash(self):
- try:
- with open('config.dat', 'w') as f:
- f.write(self.password_hash or '')
- except Exception as e:
- messagebox.showerror("Error", f"Failed to save password: {e}")
- def show_login_dialog(self):
- login_window = Toplevel()
- login_window.title("Login")
- login_window.geometry("300x120")
- login_window.transient(self.root)
- Label(login_window, text="Enter password to unlock:").pack(pady=5)
- password_var = StringVar()
- entry = Entry(login_window, textvariable=password_var, show="*")
- entry.pack(pady=5)
- def on_login():
- if self.hash_password(password_var.get()) == self.password_hash:
- login_window.destroy()
- self.root.deiconify()
- else:
- messagebox.showerror("Error", "Invalid password")
- Button(login_window, text="Login", command=on_login).pack()
- login_window.protocol("WM_DELETE_WINDOW", self.root.quit)
- def update_status(self, message):
- self.status_bar.config(text=message)
- def load_gif(self, gif_path):
- if getattr(sys, 'frozen', False):
- base_path = sys._MEIPASS
- else:
- base_path = os.path.dirname(__file__)
- full_path = os.path.join(base_path, gif_path)
- self.gif_label = Label(self.root)
- self.gif_label.pack(pady=10)
- self.gif = Image.open(full_path)
- self.frames = [ImageTk.PhotoImage(frame) for frame in ImageSequence.Iterator(self.gif)]
- self.gif_index = 0
- self.gif_label.configure(image=self.frames[0])
- self.update_gif()
- def update_gif(self):
- self.gif_index = (self.gif_index + 1) % len(self.frames)
- self.gif_label.configure(image=self.frames[self.gif_index])
- self.root.after(100, self.update_gif)
- def load_mp3s_from_database(self):
- self.listbox.delete(0, END)
- try:
- self.cursor.execute("SELECT filename FROM mp3_files")
- for row in self.cursor.fetchall():
- self.listbox.insert(END, row[0])
- except Exception as e:
- messagebox.showerror("Error", f"Failed to load MP3 files: {e}")
- def play_selected_song(self, event=None):
- selected_index = self.listbox.curselection()
- if not selected_index:
- return
- song_name = self.listbox.get(selected_index)
- try:
- self.cursor.execute("SELECT filedata FROM mp3_files WHERE filename = ?", (song_name,))
- song_data = self.cursor.fetchone()[0]
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:
- temp_file.write(song_data)
- temp_file_path = temp_file.name
- self.temp_files.append(temp_file_path)
- self.media_player.set_media(self.vlc_instance.media_new(temp_file_path))
- self.media_player.play()
- self.update_position_slider()
- except Exception as e:
- messagebox.showerror("Error", f"Failed to play song: {e}")
- def stop_song(self):
- self.media_player.stop()
- self.position_slider.set(0)
- def play_next(self):
- current_index = self.listbox.curselection()[0]
- next_index = (current_index + 1) % self.listbox.size()
- self.listbox.select_clear(current_index)
- self.listbox.select_set(next_index)
- self.play_selected_song()
- def play_previous(self):
- current_index = self.listbox.curselection()[0]
- prev_index = (current_index - 1) % self.listbox.size()
- self.listbox.select_clear(current_index)
- self.listbox.select_set(prev_index)
- self.play_selected_song()
- def set_volume(self, volume):
- self.media_player.audio_set_volume(int(volume))
- def update_position_slider(self):
- if self.media_player.is_playing():
- current_pos = self.media_player.get_time() // 1000
- self.position_slider.set(current_pos)
- self.root.after(1000, self.update_position_slider)
- def seek_position(self, position):
- self.media_player.set_time(int(position) * 1000)
- def browse_folder(self):
- folder_path = filedialog.askdirectory()
- if not folder_path:
- return
- self.listbox.delete(0, END)
- try:
- self.cursor.execute("DELETE FROM mp3_files")
- self.db_connection.commit()
- for filename in os.listdir(folder_path):
- if filename.endswith(".mp3"):
- file_path = os.path.join(folder_path, filename)
- with open(file_path, 'rb') as file:
- file_data = file.read()
- self.cursor.execute("INSERT INTO mp3_files (filename, filedata) VALUES (?, ?)", (filename, file_data))
- self.db_connection.commit()
- self.load_mp3s_from_database()
- messagebox.showinfo("Success", "MP3 files loaded from folder and saved to database!")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to load folder: {e}")
- def add_mp3_file(self):
- file_path = filedialog.askopenfilename(filetypes=[("MP3 files", "*.mp3")])
- if not file_path:
- return
- try:
- filename = os.path.basename(file_path)
- with open(file_path, 'rb') as file:
- file_data = file.read()
- self.cursor.execute("INSERT INTO mp3_files (filename, filedata) VALUES (?, ?)", (filename, file_data))
- self.db_connection.commit()
- self.listbox.insert(END, filename)
- messagebox.showinfo("Success", "MP3 file added to database!")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to add MP3: {e}")
- def delete_mp3_file(self):
- selected_index = self.listbox.curselection()
- if not selected_index:
- return
- try:
- song_name = self.listbox.get(selected_index)
- self.cursor.execute("DELETE FROM mp3_files WHERE filename = ?", (song_name,))
- self.db_connection.commit()
- self.listbox.delete(selected_index)
- messagebox.showinfo("Deleted", "MP3 file deleted from database.")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to delete MP3: {e}")
- def save_mp3_to_database(self):
- selected_index = self.listbox.curselection()
- if not selected_index:
- messagebox.showwarning("Warning", "Please select an MP3 file to save.")
- return
- try:
- song_name = self.listbox.get(selected_index)
- folder_path = filedialog.askdirectory()
- if not folder_path:
- return
- self.cursor.execute("SELECT filedata FROM mp3_files WHERE filename = ?", (song_name,))
- file_data = self.cursor.fetchone()
- if file_data:
- file_path = os.path.join(folder_path, song_name)
- with open(file_path, 'wb') as file:
- file.write(file_data[0])
- messagebox.showinfo("Success", f"MP3 file '{song_name}' saved to selected folder.")
- else:
- messagebox.showerror("Error", "File data not found in database.")
- except Exception as e:
- messagebox.showerror("Error", f"Failed to save MP3: {e}")
- def delete_temp_files(self):
- self.media_player.stop()
- deleted_files = []
- for temp_file in self.temp_files:
- try:
- if os.path.exists(temp_file):
- os.remove(temp_file)
- deleted_files.append(temp_file)
- except Exception as e:
- messagebox.showerror("Error", f"Failed to delete {temp_file}: {e}")
- self.temp_files.clear()
- if deleted_files:
- messagebox.showinfo("Success", f"Temporary files deleted: {', '.join(deleted_files)}")
- else:
- messagebox.showinfo("Success", "No temporary files to delete.")
- if __name__ == "__main__":
- root = Tk()
- app = Mp3PlayerApp(root)
- root.mainloop()
Add Comment
Please, Sign In to add comment