Bienvenidos una semana más a «El Programador Chapuzas» vuestra página sobre programación en Python en la que en esta ocasión nos proponemos programar un sencillo reproductor de audio (cuyo código completo podéis ver en el enlace que dejamos al final) con «tkinter«, el cual, tendrá la particularidad de permitirnos añadir nuestros temas (los cuales habremos buscado previamente a través de la navegación por nuestro sistema de carpetas) favoritos a un «listbox» de modo que podamos oírlo de modo directo seleccionándolo de la lista. Dicho esto, el reproductor que vamos a crear tendría este aspecto:
Como se ve, se trata de un reproductor que cuenta con algunos de los elementos típicos de este tipo de aplicaciones (contador de tiempo, espacio para mostrar el título, botón de búsqueda, de ‘play’, ‘stop’. A lo que e añade un botón para incorporar el archivo seleccionado a un ‘listbox‘ el cual mostrará su contenido cada vez que iniciamos la aplicación y que nos permitirá un acceso más directo a los archivos contenidos en el mismo.
Como solemos hacer, empezaremos creando el apartado gráfico de nuestra aplicación, no sin antes importar las librerías y recursos que vamos a emplear:
En este caso, importamos «tkinter» para la interfaz, «wave» para abrir los archivos de audio, «pyaudio» para reproducirlos, «threading» para los procesos en paralelo, «json» (del que hablamos la semana pasada) para serializar la información de acceso a los elementos del «listbox» y «os» para mostrar el directorio de ejecución.
Antes de continuar, nos aseguraremos de tener instalados todos estos recursos, de modo que aquel que no tengamos, procederemos a instalarlo mediante el comando «pip«:
Pasemos ahora a diseñas el aspecto gráfico de nuestra aplicación, empezando, como no, por definir las dimensiones de la ventana (mediante el método «geometry«) en la que se ubicarán los distintos elementos, el color de fondo (mediante el atributo «bg» del método «configure()«) y el título de la ventana (con el método «title()«):
El siguiente paso será el de ir introduciendo los diferentes elementos interactivos de nuestra interfaz, empezando por el temporizador, el espacio para el nombre del audio y los botones principales:
Como se ve, utilizamos las funciones «Button()«, «Label()» y «Entry()» para crear los botones, la etiqueta para el contador de tiempo y la entradas para mostrar el nombre del archivo abierto y el directorio de ejecución, respectivamente. Para la muestra del directorio de ejecución usamos la variable «self.currentDir» cuyo valor será el referido directorio que obtenemos con «os.getcwd()«. En este punto también crearemos la variable «self.filename» cuyo valor será el nombre del archivo abierto.
Pasemos a los elementos de la parte inferior, consistentes en dos botones para eliminar el contenido íntegro (o algún elemento) del «listbox» un «Label» indicador del número de elementos y el propio «listbox» al que asociaremos la pertinente barra lateral de «scroll». Aquí, a las funciones vistas antes, añadiremos la función «Listbox()» que mostrará los elementos guardados en nuestra lista de favoritos «self.fav_list«. Este elemento (al igual que las barras de scroll que crearemos mediante la función «Scrollbar()«) lo insertaremos dentro de un componente «Canvas» que habremos definido con anterioridad («self.canvas=Canvas(self.root)«):
Pasemos a continuación a crear las funciones que se encargarán de hacer funcionar nuestro reproductor. Aunque antes debemos tener en cuenta que para almacenar el título y ruta de los audios añadidos a la lista de favoritos (el «listbox«) almacenaremos tal información en un archivo «JSON» con estructura de diccionario y al que llamaremos «data.json» y que deberá estar ubicado en el mismo directorio de ejecución. No obstante podemos hacer que el programa, antes de mostrar la ventana compruebe si dicho archivo se encuentra presente en el directorio, creándolo en el caso de que no sea así:
Una vez asegurada la presencia del archivo «data.json«, haremos que se muestren los archivos guardados en el «listbox«. Esta función (a la que hemos llamado «show_list()» será la primera que se ejecute al iniciar el programa:
Ahora pasemos a definir la función de selección de archivo (que se ejecutará al clickar en el botón «SEARCH») a la que hemos llamado «open_file()«:
La función «open_file()» tiene como cometido, navegar por el sistema de archivos y carpetas para seleccionar el archivo (en formato «wav») que luego podremos reproducir y/o almacenar en nuestra lista de favoritos. No sin antes ejecutar las funciones «stop_music()» (para parar el audio que pueda estar reproduciéndose) y «if_any_selected()» que devolverá «True» o «False» en función de si hay o no, algún elemento seleccionado en las lisbox de modo que en caso afirmativo, proceder a deseleccionarlo con la función «selection_clear()«.
Una vez seleccionado el archivo, lo normal es querer reproducir el audio, para ello usamos las funciones «init_task()» (para iniciar con «threading» el proceso de reproducción en paralelo) y «music()» (para reproducir el archivo):
Tenemos aquí, en primer lugar la función «init_task()» que se encarga de iniciar el proceso en paralelo consistente en ejecutar la función «music()» (encargada de reproducir el audio haciendo uso de las librerías «wave» y «pyaudio«). Dicha función «init_task()» se inicia ejecutando «is_any_selected()» para comprobar si hay algún elemento seleccionado en el listbox. Esto es importante en la medida que de estar seleccionado algún elemento, el archivo a leer será ese.
A su vez, también crearemos la función (a la que hemos llamado «add()«) encargada de añadir un archivo abierto al lisbox de modo que el acceso a este sea más rápido la próxima vez que ejecutemos el programa:
Del mismo modo que hemos creado una función para añadir elementos a la lista de favoritos, también crearemos otras dos funciones encargadas de eliminar la totalidad de los elementos o solo uno previamente seleccionado. Para ello usaremos las funciones «remove_playlist()» y «remove_from_list()«:
Nótese que en ambos casos, antes de ejecutarse la acción que modifica el contenido de «data.json«, usamos la función «messagebox.askquestion()» para que el usuario confirme la realización de la misma:
Finalmente, definiremos las funciones encargadas de hacer funcionar el contador de tiempo durante la reproducción de los audios. Dichas funciones son «clear_counter()» (para establecer el valor inicial de los minutos, segundos y horas), «counter_format()» (para mantener durante toda la ejecución el formato de dos dígitos para los minutos y segundos) y «timer_count()» (para representar el transcurso del tiempo en el marcador durante la reproducción):
Estas serían las funciones que nos permitirán hacer funcionar nuestro reproductor. Eso sin olvidar que algunas de ellas se han de ejecutar al pinchar en un determinado botón. Por ello para terminar, usaremos el atributo «command» para vincular cada botón con la ejecución de la correspondiente función:
Dejando a nuestra aplicación lista para ser usada.
Tal y como señalamos al principio de este artículo, en el siguiente enlace encontrareis el código completo del programa junto con el archivo «data.json«:
https://github.com/antonioam82/Music-Player
Saludos.