Feliz Navidad Para tod@s l@s taringuer@s!!!!!!!!
[Editado con el video del resultado final]Hoy Navidad mostraré como hacer tu propio reproductor mp3 para disfrutar en estas fiestasv de algo de música en tu propio MP3Player...
Lo primero que necesitareis es un par de librerías de código libre que nos van a permitir la reproducción de música en formato MP3 en java (nativamente java no reproduce MP3).
BasicPlayer3.0
Luego, dependiendo del IDE con el que trabajen será la forma de incluir los .jar en la carpeta "lib" que se crea al compilar.
En netbeans, una vez descomprimida la carpeta BasicPlayer3.0, encontrarán: BasicPlayer3.0/BasicPlayer3.0.jar
solo debes dar click derecho en la parte que dice "Libraries", luego en "Add Jar/Folder" y allí solo seleccionas el .jar a incluir.
Luego repites la operación pero esta vez seleccionas tooodos los .jar que se encuentran en:
BasicPlayer3.0/lib
Allí encontrarás unos cuantos .jar ejecutables los que añadirás a las librerias de tu proyecto.
Al final debería quedar así tu proyecto con todos los jar incluidos:
A este proyecto le puse de nombre TPlayer...
Bueno, a esta altura estamos prontos para empezar!!!
Primero que nada debemos crear una clase que será la encargada de manejar todos los controles del reproductor (Play, pausa, busqueda, stop, Etc.).
Solo debes dar click derecho sobre la carpeta "Source Packages" y en "New Class", no confundir con "New Main Class", x ahora no tenemos main, ya que el main será nuestra propia interfaz (mas adelante vemos...).
========================
public class ZPlayer{
}
======================
Yo de nombre le puse ZPlayer.
Bien, en principio nuestra clase debe "implementar" a la clase BasicPlayerListener, al ser esta abstracta, nosotros Sobreescribiremos todos sus métodos:
==================================
public class ZPlayer implements BasicPlayerListener{
....métodos...
}
=================================
Los métodos son:
Opened, Progress, StateUpdated, setController, Display.
De los cuales el mas interesante para nosotros será Progress, el cual es ejecutado varias veces x segundo, mostrando la información escencial del archivo en reproducción (Tiempo total, formato, tags ID3, tiempo actual, Etc.).
Pero antes debemos crear una instancia de la clase BasicPlayer a la que llamaremos sencillamente player y un stream privado para mostrar en la consola, toda la acción desarrollada por nuestro player usando el método display();
=============================
private PrintStream out = null;
BasicPlayer player = new BasicPlayer( );
=============================
Ya cuando creemos el "constructor" de nuestra clase, le pasamos dentro de las llaves lo siguiente:
==============================
//Constructor de la clase
public ZPlayer() {
//esta linea puede generar una advertencia ("leaking this on constructor" pero no le den bola X )
player.addBasicPlayerListener(this);//añadimos el "escuchador" de eventos
out = System.out;
}
´=============================
Lo principal que hicimos aquí fué crear un escuchador de eventos para nuestra instancia de player, aprovechando que nuestra clase implementa Listeners del player, para así poder lograr que cada método invocado sea tomado también como un "evento" que generará información adicional en el método display... (sirve para ver que sucede cada vez que realizamos una acción, abrir, pausar, reprodicir, ya veremos...).
Luego creamos el controlador para tooodos los métodos (Play, Pause, Resume, Etc.):
=========================================
BasicController control = (BasicController) player;//Controlador para player
=========================================
Bueno y ahora los métodos:
//esta linea puede generar una advertencia ("leaking this on constructor" pero no le den bola X )
player.addBasicPlayerListener(this);//añadimos el "escuchador" de eventos
out = System.out;
}
´=============================
Lo principal que hicimos aquí fué crear un escuchador de eventos para nuestra instancia de player, aprovechando que nuestra clase implementa Listeners del player, para así poder lograr que cada método invocado sea tomado también como un "evento" que generará información adicional en el método display... (sirve para ver que sucede cada vez que realizamos una acción, abrir, pausar, reprodicir, ya veremos...).
Luego creamos el controlador para tooodos los métodos (Play, Pause, Resume, Etc.):
=========================================
BasicController control = (BasicController) player;//Controlador para player
=========================================
Bueno y ahora los métodos:
================================================
public void opened(Object stream, Map properties) {//Se llama cada vez que abrimos un nuevo archivo
display("opened : " + properties.toString());//Muestra en consola los datos del archivo abierto
}
public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties) {
//Quizá el método mas importante de todos, nos va a permitir recibir información continua y
//en tiempo real de todo lo que sucede en la ejecución de nuestro archivo (incluyendo todas sus propiedades)
display("progress : " + properties.toString());
}
public void stateUpdated(BasicPlayerEvent event) {
display("stateUpdated : " + event.toString());
//Muestra en consola que ha sucedido, si se dio play, pausa, stop o lo que sea...
}
public void setController(BasicController controller) {
display("setController : " + controller);
//Este método es para Ehhh... Bueno la verdad no lo uso para nada, je!
}
public void display(String msg) {
//Este es el método que muestra la información en la consola
if (out != null) {
out.println(msg);
}
}
display("opened : " + properties.toString());//Muestra en consola los datos del archivo abierto
}
public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties) {
//Quizá el método mas importante de todos, nos va a permitir recibir información continua y
//en tiempo real de todo lo que sucede en la ejecución de nuestro archivo (incluyendo todas sus propiedades)
display("progress : " + properties.toString());
}
public void stateUpdated(BasicPlayerEvent event) {
display("stateUpdated : " + event.toString());
//Muestra en consola que ha sucedido, si se dio play, pausa, stop o lo que sea...
}
public void setController(BasicController controller) {
display("setController : " + controller);
//Este método es para Ehhh... Bueno la verdad no lo uso para nada, je!
}
public void display(String msg) {
//Este es el método que muestra la información en la consola
if (out != null) {
out.println(msg);
}
}
===================================
La clase completa debería verse así:
======================================================================
import java.io.File;
import java.io.PrintStream;
import java.util.Map;
import javazoom.jlgui.basicplayer.*;
public class ZPlayer implements BasicPlayerListener {
private PrintStream out = null;//Stream para el Debbugging(println)...
BasicPlayer player = new BasicPlayer();//Instancia de BasicPlayer
public ZPlayer() {//Constructor de la clase
player.addBasicPlayerListener(this);
out = System.out;
}
BasicController control = (BasicController) player;//Controlador para player
//Metodos sobreescritos:
public void opened(Object stream, Map properties) {
display("opened : " + properties.toString());
}
public void progress(int bytesread, long microseconds, byte[] pcmdata, Map properties) {
display("progress : " + properties.toString());
}
public void stateUpdated(BasicPlayerEvent event) {
display("stateUpdated : " + event.toString());
}
public void setController(BasicController controller) {
display("setController : " + controller);
}
public void display(String msg) {
if (out != null) {
out.println(msg);
}
}
}
====================================================================
Bueno, si han seguido paso a paso, la clase del Player está pronta, ahora entonces no dedicaremos a la parte que mas me gusta, la GUI o interfaz gráfica!
Para esto lo primero que debemos hacer es crear Si trabajas en NetBeans un nuevo formulario jFrame, si lo hacés en eclipse... Suerte!, naaa, ya veremos, si trabajas en eclipse puedes crear el frame con código (lo que no es tarea fácil) pero es lo mismo... (aunq recomiendo aaaampliamente NetBeans).
Para esto damos click derecho sobre SourcePackages y en New JFrame Form:
Le ponemos el nombre que queramos, yo le puse ZPlayerFrame.
Bien, se crea la plantilla en blanco y solo nos resta en principio para realizar un reproductor bieen básico, añadir un JMenuBar y dos JButton, si, x ahora espo es todo, lo que queremos es ver si todo lo anterior anda bien, ya luego veremos toooodas las funciones avanzadas, volúmen, balance, búsqueda, animación de un jSlider, Etc.
Creo que está demás decir que para añadir los componentes solo arrastramos y los tiramos en el frame desde el asistente de GUI (parecido a Visual... no?)...
Al jMenuBar le ponemos de texto: " Opciones" y le añadimos un jMenuItem "Abrir".
y a los botones le ponemos: "Play" y "Stop"
debe quedar algo así...:
Antes que nada también declararemos un par de variables "públicas" en la clase ZPlayerFrame:
Primero que nada instaciaremos un objeto de la clase ZPlayer, luego un jFileChooser y x últimno un archivo:
============================
import java.io.File;
import javax.swing.JFileChooser;
public class ZPlayerFrame extends javax.swing.JFrame {
ZPlayer mizplayer = new ZPlayer();
JFileChooser fileChooser = new JFileChooser();
File file;
public ZPlayerFrame() {
initComponents();
}
...
//Métodos del Frame...
...main, Etc...
}
===============================
Bien, pues le damos doble click al jMenuItem para declarar su "ActionPerformed", o click derecho sobre el y en events, ActionPerformed...
Una vez que se ha desplegado automáticamente nuestro método vacío, en el lo que vamos a hacer es llamar a nuestra instancia del jFileChooser que es una ventana que sirve para seleccionar archivos navegando por el sistema del usuario...
Pero antes le pondremos un filtro para que en primer lugar busque sólo archivos con extension .mp3:
y algo para poder abrir solo mp3...l
==========================================================
private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {
FileNameExtensionFilter filtro = new FileNameExtensionFilter("Archivo MP3", "mp3", "mp3";
fileChooser.setFileFilter(filtro);
int seleccion = fileChooser.showOpenDialog(this);
if (seleccion == JFileChooser.APPROVE_OPTION) {
file = fileChooser.getSelectedFile();
try {
mizplayer.control.open(file);//Le decimos al control del player que abra el archivo
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
//todo entre try y catch x las excepciones que lanzan los métodos del player...
}
==========================================================
Y bueno, falta menos, ahora le damos función al botón play:
Lo mismo, doble click sobre el botón y se crea el método "ActionPerformed" vacío:
Y allí ponemos lo siguiente:
=====================================================
try {
mizplayer.control.play();//solo le decimos al control que de play (el archivo supuestamente ya fue abierto)
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
====================================================
y en el botón Stop:
=====================================================
mizplayer.control.stop();
=====================================================
Recuerden que los nombres de la clases los eligen ustedes, y que en este último código no agregué las excepciones, pues es solo dar un click, lo hice para que se vea claro...
Ya luego para hacerlo un poquito mas completo, p'ara además ahorrarnos poner otro botón, podemos dentro del mismo botón play, un switch basado en lo que se recibe del texto del botón, debemos haber creado una variable de tipo boolean que sea falsa al inicio que se llame x Ej.: running (para saber si se ha dado play x primera vez...
Luego en el ActionPerformed del botón "Play" (jButton1 en mi caso) ponemos:
================================================================
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
switch (jButton1.getText()) {
case "Play":
if (!running&&file!=null) {
try {
mizplayer.control.play();
jButton1.setText("Pausa";
running = true;
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (running) {
try {
mizplayer.control.resume();
jButton1.setText("Pausa";
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
break;
case "Pausa":
try {
mizplayer.control.pause();
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
jButton1.setText("Play";
break;
}
}
=================================================================
y al Actionperformed del botón Stop agregamos:
===============================================================
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try {
mizplayer.control.stop();
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
running = false;
jButton1.setText("Play";
}
================================================================
Lo que logramos es que de Play solo la primera vez que lo pulsamos, luego aol decir pausa si lo presionamos quedará en pausa y dirá de nuevo play, pero al darle play se reanudará la reproducción donde había quedado...
Luego al dar Stop se detendrá la reproducción el boton dirá Play y además running volverá a ser false, sencillo no?
Para el vólumen:
Agregamos un jSlider (que ya x defecto viene con 0 minimo y 100 máximo) y En el event "StateChangedEvent"(click derecho sobre el componente/events), le agregamos lo siguiente:
===================================================
private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {//Esto no va, se pone solo...
try {
mizplayer.control.setGain((double)jSlider1.getValue()/100);
} catch (BasicPlayerException ex) {
Logger.getLogger(ZPlayerFrame.class.getName()).log(Level.SEVERE, null, ex);
}
jLabel1.setText(jSlider1.getValue()+"%";
}//esto tampoco... es para que quede claro el evento...
==============================================
y jLabel 1 es una etiqueta adicionada al lado del Slider la que mostrará el valor del vólumen, cuando en realidad nosotros seteamos el vólumen casteando el Value del Slider a double y dividiendolo entre 100 (setGain va de 0.0 a 1.0 double).
También en el APROVE_OPTION del filechooser podemos hacer que muestre en una etiqueta el nombre de la canción:
jLabel2.setText("Abriendo: "+file.getName());
Y bueno, está pronto!!! es solo cuestión de probarlo!!!
Aquí un video del resultado final en funcionamiento:
Ya en el siguiente post veremos como animar un Slider de acuerdo al progreso de la reproducción, manejo del balance (paneo), creacion de listas e inclusive podremos ver como crear una persistencia para poder guardar listas para luego cargarlas.
Espero le sea de provecho.
Dudas, comentarios, criticas y/o puntos BIENVENIDOS!!!

