-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmp3.py
More file actions
193 lines (153 loc) · 7.7 KB
/
mp3.py
File metadata and controls
193 lines (153 loc) · 7.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import os
import json
import pygame
import tkinter as tk
from tkinter import Toplevel, ttk, messagebox
from mutagen.mp3 import MP3
from modules.add_music import añadir_musica
from modules.setup_ui import setup_ui
pygame.init()
pygame.mixer.init()
class ReproductorMP3:
def __init__(self, master):
self.master = master
self.master.title("Reproductor MP3")
self.master.geometry("850x400")
self.master.configure(bg="#282c34")
self.archivos_mp3 = []
self.archivo_actual = None
self.indice_actual = 0
self.MUSICA_TERMINADA = pygame.USEREVENT + 1
pygame.mixer.music.set_endevent(self.MUSICA_TERMINADA)
setup_ui(self) # Llama a la función setup_ui
self.modo_mostrar_por = self.cargar_ajustes()
self.cargar_mp3()
self.configurar_evento_finalizacion()
self.duracion_total = 0 # Variable para almacenar la duración total de la canción
self.tiempo_actual = 0 # Variable para almacenar el tiempo actual
self.master.after(1000, self.actualizar_tiempo_actual) # Actualizar el tiempo actual cada segundo
def abrir_ajustes(self):
ventana_ajustes = Toplevel(self.master)
ventana_ajustes.title("Ajustes")
ventana_ajustes.geometry("300x200")
tk.Label(ventana_ajustes, text="Mostrar por:").pack(pady=10)
self.combo_mostrar_por_ajustes = ttk.Combobox(ventana_ajustes, state='readonly', values=["Canción"])
self.combo_mostrar_por_ajustes.current(0)
self.combo_mostrar_por_ajustes.pack(pady=10)
tk.Button(ventana_ajustes, text="Guardar", command=lambda: self.guardar_ajustes(ventana_ajustes)).pack(pady=10)
def crear_boton(self, parent, texto, comando):
boton = tk.Button(parent, text=texto, command=comando, bg="#007BFF", fg="#ffffff", font=("Arial", 14), width=3)
boton.grid(row=0, column=len(parent.grid_slaves()), padx=5)
return boton
def mostrar_menu_contextual(self, event):
self.menu_contextual.post(event.x_root, event.y_root)
def añadir_musica(self):
añadir_musica(self.cargar_mp3)
def cargar_ajustes(self):
if os.path.exists('ajustes.json'):
with open('ajustes.json', 'r') as archivo:
ajustes = json.load(archivo)
return ajustes.get("modo_mostrar_por", "Canción")
return "Canción"
def guardar_ajustes(self, ventana):
ajustes = {"modo_mostrar_por": self.modo_mostrar_por}
with open('ajustes.json', 'w') as archivo:
json.dump(ajustes, archivo)
ventana.destroy()
def configurar_evento_finalizacion(self):
self.master.after(100, self.check_music_end)
def check_music_end(self):
for event in pygame.event.get():
if event.type == self.MUSICA_TERMINADA:
self.cambiar_cancion(1)
self.master.after(100, self.check_music_end)
def cargar_mp3(self):
directorio = 'files'
self.archivos_mp3.clear()
self.limpiar_lista()
for root, _, files in os.walk(directorio):
for file in files:
if file.endswith(".mp3"):
ruta_completa = os.path.join(root, file)
self.archivos_mp3.append(ruta_completa)
self.crear_label_cancion(file, ruta_completa)
def limpiar_lista(self):
for widget in self.scrollable_frame.winfo_children():
widget.destroy()
def crear_label_cancion(self, file, ruta_completa):
artista = self.obtener_artista(ruta_completa)
frame_label = tk.Frame(self.scrollable_frame, bg="#3e444f")
frame_label.pack(pady=5, padx=5, fill=tk.X)
titulo_label = tk.Label(frame_label, text=file, bg="#3e444f", fg="#ffffff", font=("Arial", 12, "bold"), anchor='w')
titulo_label.pack(fill=tk.X)
artista_label = tk.Label(frame_label, text=artista, bg="#3e444f", fg="#ffffff", font=("Arial", 10), anchor='w')
artista_label.pack(anchor='w')
self.asignar_evento_click(frame_label, titulo_label, artista_label)
def asignar_evento_click(self, frame_label, titulo_label, artista_label):
index = len(self.archivos_mp3) - 1 # Use el último índice disponible
for widget in (frame_label, titulo_label, artista_label):
widget.bind('<Button-1>', lambda event, idx=index: self.reproducir_cancion(idx))
def obtener_artista(self, ruta):
try:
audio = MP3(ruta)
return audio.get('TPE1', ["Artista desconocido"])[0] or "Artista desconocido"
except Exception:
return "Artista desconocido"
def on_mouse_wheel(self, event):
self.canvas.yview_scroll(-1 if event.delta > 0 else 1, "units")
def reproducir_cancion(self, index):
if 0 <= index < len(self.archivos_mp3):
self.indice_actual = index
self.archivo_actual = self.archivos_mp3[self.indice_actual]
self.intentar_reproducir()
def intentar_reproducir(self):
try:
pygame.mixer.music.load(self.archivo_actual)
pygame.mixer.music.play()
# Obtener la duración con Mutagen
audio = MP3(self.archivo_actual)
self.duracion_total = audio.info.length # Duración total de la canción (en segundos)
self.actualizar_info_cancion()
self.boton_pausa_reproducir.config(text="⏸️")
except Exception as e:
self.mostrar_error("No se pudo reproducir la canción", str(e))
def mostrar_error(self, mensaje, detalle):
messagebox.showerror(mensaje, detalle)
def actualizar_info_cancion(self):
if self.archivo_actual:
nombre_archivo = os.path.basename(self.archivo_actual)
nombre_sin_extension = os.path.splitext(nombre_archivo)[0]
self.titulo_cancion.config(text=(nombre_sin_extension[:21] + '...') if len(nombre_sin_extension) > 24 else nombre_sin_extension)
artista = self.obtener_artista(self.archivo_actual)
self.artista_cancion.config(text=artista)
# Actualizar la duración total de la canción en la interfaz
self.tiempo_total_label.config(text=self.formatear_tiempo(int(self.duracion_total)))
def pausar_reproducir(self):
if pygame.mixer.music.get_busy():
pygame.mixer.music.pause()
self.boton_pausa_reproducir.config(text="▶️")
else:
pygame.mixer.music.unpause()
self.boton_pausa_reproducir.config(text="⏸️")
def cambiar_cancion(self, direccion):
nuevo_indice = self.indice_actual + direccion
if 0 <= nuevo_indice < len(self.archivos_mp3):
self.reproducir_cancion(nuevo_indice)
def actualizar_tiempo_actual(self):
if pygame.mixer.music.get_busy(): # Solo actualizar si la música está sonando
self.tiempo_actual = pygame.mixer.music.get_pos() / 1000 # Obtener el tiempo actual en segundos
self.tiempo_actual_label.config(text=self.formatear_tiempo(int(self.tiempo_actual))) # Mostrar el tiempo actual
self.master.after(1000, self.actualizar_tiempo_actual) # Actualizar cada segundo
def mover_slider(self, event):
nuevo_tiempo = self.slider.get() / 100 * self.duracion_total
pygame.mixer.music.set_pos(nuevo_tiempo)
self.tiempo_actual = nuevo_tiempo # Actualizar el tiempo actual
self.tiempo_actual_label.config(text=self.formatear_tiempo(int(self.tiempo_actual))) # Actualizar el tiempo actual
def formatear_tiempo(self, segundos):
minutos = segundos // 60
segundos = segundos % 60
return f"{minutos:02}:{segundos:02}"
if __name__ == "__main__":
root = tk.Tk()
app = ReproductorMP3(root)
root.mainloop()