aprovecha y usa cualquier librerías de java
TRANSCRIPT
-
7/31/2019 Aprovecha y usa cualquier libreras de Java.
1/5
-
7/31/2019 Aprovecha y usa cualquier libreras de Java.
2/5
Python DESARROLLO
61Nmero 07W W W . L I NUX - M A G A Z I N E . E S
En Java, en general, para reproducir unsonido es necesario definir varias partes:
Obtener el stream de audio, descodificar-
lo, tratarlo y escribirlo en el dispositivo de
nuestro PC.
RequisitosComo requisitos fundamentales, vamos a
necesitar nuestro querido intrprete de
Jython. Para obtenerlo nos dirigimos a su
web [1] y descargamos la ultima versin
(versin 2.1 en el momento de escribir
esto). Necesitamos la nueva versin de
Java (JRE 1.5 o JDK 1.5), disponible en
[3], ya que incorpora algunas novedades
y mejoras que necesitaremos para nuestro
pequeo reproductor deMP3. Por ultimo
necesitamos obtener las libreras que
vamos a utilizar, MPSPI que podemos
encontrar en la web de Javazoom (ver
[2]) y ms concretamente en http://www.
Javazoom.net/mp3spi/mp3spi.html.
Una vez instalados el interprete de
Jython y el JDK 1.5 (o JRE 1.5) debemos
proceder a instalar las libreras de
Javazoom. Para ello, descomprimimos elfichero que contiene las libreras de
Javazoom (ya sabis, unzip -x fichero.zip
o bien tar xvfz fichero.tar.gz ) y, como en
la mayora de los casos, se nos crear undirectorio nuevo con el contenido del
fichero. El primer paso ser copiar las
libreras que necesitamos al directorio
lib/ext/de nuestro JRE (Maquina virtual
de Java). En nuestro caso, despus de ins-
talar el JDK 1.5, este directorio se encuen-
tra en/usr/Java/jdk1.5.0_02/jre/lib/ext/y
debemos copiar aqu (obviamente como
root) los paquetes mp3spi1.9.2.jar, y den-
tro del directorio lib, jl1.0.jar y
tritonus_share.jar.
Una vez hecho esto, al arrancar el intr-
prete deJython nos aparecer un mensaje
por cada archivo que hemos copiado,
indicando que dicho paquete se est pro-
cesando para su uso (justo antes de arran-
car nuestro intrprete). Para confirmar
que todo es correcto, en el interprete
introducimos import Javazoom y no debe-
ra salir ningn mensaje de error (en caso
de que as fuera, comprobad que los
archivos estn copiados en el sitio correc-
to).
Con estas libreras tenemos ahora un
descodificador del stream de nuestrosarchivos MP3 adems de algunas otras
utilidades (libreras para conversin de
formatos, lector de la informacin de las
El formato de sonidoMP3 es uno delos mas consolidados dentro de la
msica. A diario miles de personas
en todo el mundo comparten y crean
millones de ficheros enMP3 y los repro-
ductores de msica, ya sea en el ordena-
dor, en los equipos de msica o para el
coche, se han adaptado para reproducir
este formato. Actualmente la mayora de
los reproductores de MP3 desarrollados
para PC (como xmms, etc..) soportan este
formato de msica. Pero, cmo podemos
crear nuestro propio reproductor deMP3?
Programar un reproductor de sonido
en Java, exceptuando que reproduzca los
formatos comunes que soporta, es bas-
tante complicado. Se necesita mucho
tiempo para realizar el descodificador
del formato (MP3 en este caso) que pro-
cese los datos (conocidos como stream
de audio) que contiene cada cancin
codificada en este formato. Por eso, lo
mejor para poder crear nuestro reproduc-
tor, es utilizar libreras que ya estn pre-
paradas para descodificar el stream y
para que podamos reproducirlo. En estecaso utilizaremos libreras bajo la licen-
cia LGPL (Lesser General Public
License).
JUKEBOX CON
JYTHON
Aprovecha y usa cualquier libreras de Java.
JUKEBOX CON
JYTHON
Damos otro pequeo avance con Jython: Este mes utilizamos libreras Java y analizamos la reproduccin de
sonidos desde Java para crear un mini reproductor de MP3donde reproducir nuestra msica.
POR JOS PEDRO ORANTES Y JOS MARA RUZ
-
7/31/2019 Aprovecha y usa cualquier libreras de Java.
3/5
DESARROLLO Python
62 Nmero 07 W W W . L I NUX - M A G A Z I N E . E S
01 import org.tritonus.share.sam-
pled.TAudioFormat as taf
02 import org.tritonus.share.sam-
pled.file.TAudioFileFormat as ftaf
03 import javax.sound.sampled as
sampled
04 import java.io as io
05 import jarray
06 import java.util as util
07 import javax.swing as swing
08 import java.lang as lang
09 import java.awt as awt
10 import java.util as util
11
12 class jyMusica(lang.Thread):
13 def __init__(self):
14self.panelReproductor()
15 self.menu()
16 self.win =
swing.JFrame("JyMusica",
size=(150,
150),windowClosing=self.exit)
17
self.win.setJMenuBar(self.menu
)
18
self.win.contentPane.add(self.
pnlBoton,
awt.BorderLayout.NORTH)
19
self.win.contentPane.add(self.
pnlBoton2,
awt.BorderLayout.CENTER)
20 self.win.show()
21
self.win.setResizable(0)
22 self.win.pack()
23
24 def exit(self, event):
25 lang.System.exit(0)
2627 def run(self):
28 archivo =
io.File(self.nombre)
29 inp =
sampled.AudioSystem.getAudioIn
putStream(archivo)
30 baseFileFormat = sam-
pled.AudioSystem.getAudioFileF
ormat(archivo)
31 baseFormat =
baseFileFormat.getFormat()
32self.getTag(baseFileFormat)
33 self.player.play()
34
35 def getTag(self,
baseFileFormat):
36 properties = ftaf.pro-
perties(baseFileFormat)
37 key = "author"
38 val =
properties.get(key)
39 key = "title"
40 tag=
properties.get(key)
41 key = "album"
42 alb =
properties.get(key)
43
self.txtArea.setText("")
44
self.txtArea.append("\nAuthor:")
45
self.txtArea.append(val +
"\n")
46
self.txtArea.append("title: ")
47
self.txtArea.append(tag +"\n")
48
self.txtArea.append("Album: ")
49
self.txtArea.append(alb +
"\n")
50
51 def
panelReproductor(self):
52 self.pnlBoton =
swing.JPanel(awt.FlowLayout())
53 self.pnlBoton2 =
swing.JPanel(awt.FlowLayout())
54 acciones = ["Play",
"Stop"]
55 self.txtArea =
swing.JTextArea(6,18)
56 self.areaSrl =swing.JScrollPane(self.txtArea
)
57
self.pnlBoton.add(self.areaSrl
)
58 for cadaBoton in
acciones:
59
self.pnlBoton2.add(swing.JButt
on(cadaBoton,
actionPerformed=self.accionMen
u))60
61 def menu(self):
62 opciones = ["Play",
"Stop"]
63 self.menu =
swing.JMenuBar()
64 archivo =
swing.JMenu("Archivo")
65 for eachOpcion in
opciones:
66
archivo.add(swing.JMenuItem(ea
chOpcion,
actionPerformed=self.accionMen
u))
67
archivo.addSeparator()
68 self.menu.add(archivo)
69
70 def accionMenu(self,event):
71 self.accion =
event.getActionCommand()
72 if self.accion ==
'Play':
73 selector =
swing.JFileChooser()
74 rtn =
selector.showOpenDialog(self.w
in)
75 archivo = selec-
tor.getSelectedFile()
76 self.player =
pad.AdvancedPlayer(io.FileInpu
tStream(archivo))
77 self.nombre=archi-
vo.toString()
78 self.play()
79
80 elif
self.accion=='Stop':
81 self.stop()
82
83 def play(self):
84 self.hilo =lang.Thread(self)
85 self.hilo.start()
86
87 def stop(self):
88 self.player.stop()
89 # self.line.drain()
90 # self.line.stop()
91 # self.line.close()
92 # self.din.close()
93 # self.hilo.interrupt()
94 # self.hilo.finalize()
95 #96
97 if __name__=='__main__':
98 jyMusica()
Listado 1: jython-julebox.py
-
7/31/2019 Aprovecha y usa cualquier libreras de Java.
4/5
applets. Una de las limitaciones de CLIP,
es que necesita cargar el sonido entero en
memoria antes de reproducirlo lo cual
aumenta los recursos utilizados, adems
de que slo est preparada
para reproducir los formatostpicos enJava (Wav,A-Law,
U-Law, etc.). Nosotros utili-
zaremos un SourceDataLine
y trabajaremos con un
pequeo Buffer que llenare-
mos con el stream de sonido
descodificado que luego
introduciremos en nuestro
dispositivo de sonido.
Los pasos que seguiremos para tratar el
sonido sern los siguientes. Primero,
obtendremos el Stream y el formato de
sonido (utilizando AudioSystem y sus
mtodos getAudioInputStream, y
getAudioFileFormat). Adems, del forma-
to de audio (AudioFormat) leeremos los
datos del MP3 (el ttulo, el lbum, el
autor, etc).
Una vez obtenido
todo esto (el descodifi-
cador ya esta haciendo
su trabajo), necesitare-
mos crear el buffer,
que no es otra cosa
que un array deBytes.Para crear dicho array.
Jython nos provee de
un modulo llamado
jarray que tiene dos
constructores: zeros y
array. El primero crea un array inicializa-
do a 0 del tamao y del tipo que nosotros
necesitemos y el segundo crea un array ya
inicializado (por nosotros) de un tipo de
datos.
Veamos una ejemplo del uso de Jarray.
>>> import jarray
>>> a = jarray.zeros(4,'i')
>>> print a
array([0, 0, 0, 0], int)
>>> b = jarray.array([1,2,3,4],U
'i')
>>> print b
array([1, 2, 3, 4], int)
Como podis ver el funcionamiento es
sencillo.Jarray.zeros recibe dos argumen-
tos que son el numero de elementos y el
tipo de datos, en este caso 'i' son enteros(integer). Yjarray.array recibe la secuen-
cia que forma el array y el tipo de datos
tambin. Para nuestro buffer necesitamos
un array de 4096 Bytes que crearemos
usandojarray.zeros(4096,'b'). Si quisira-
mos que nuestro array fuera de Strings,
haramos un jarray.zeros(45,Java.
lang.String). En caso de que necesitra-
mos (que, de hecho, necesitamos) pasarcomo argumento la longitud de nuestro
array a un mtodo, haramos len(array)
ya que los arrays deJython no tienen un
mtodo como .length() de los arrays de
Java.
Por ultimo, crearemos el
SourceDataLine y desde su mtodo
write() escribiremos nuestro sonido en
nuestro dispositivo de audio (entonces ya
empezaremos a or msica) y luego basta-
ra con rellenar el buffer (desde nuestro
AudioInputStream) y volver a escribirlo
en nuestro dispositivo de sonido hasta
que lleguemos al final de la cancin o
hasta que paremos la reproduccin.
Finalmente, y dado que vamos a usar
un pequeo interfaz para manejarnos
(hecho con swing),
necesitaremos progra-
mar Java con hilos
(Thread), por lo que
nuestro reproductor
heredara de la clase
Thread y en el
momento de reprodu-cir, se lanzar un hilo
que ser el encargado
de reproducir la msi-
ca mientras seguimos
teniendo el control en
nuestro pequeo reproductor. Un Thread
es una secuencia de instrucciones que se
ejecuta en paralelo con la aplicacin que
lo invoca, podramos decir que mientras
nosotros usamos nuestra aplicacin, lan-
zamos otra pequea aplicacin que repro-
ducir nuestro sonido sin interferir en la
primera (ejecucin en paralelo).
Mtodos y LibrerasVamos a implementar un total de once
mtodos. Empezaremos describiendo el
motor del reproductor y terminaremos
describiendo los de creacin del interfaz.
Son cuatro mtodos.
Run(). Desde este mtodo es de
donde comienza el proceso del
tratamiento de nuestro fichero
MP3. Desde aqu obtendremos
elInputStream y elAudioFormaty una vez que los tengamos,
pasaremos a llamar al siguiente
mtodo (Reproducir() ha de lla-
canciones -artista, lbum, etc.- y algunas
cosas ms).
Nos falta un ltimo paso: Debemos eli-
minar una de las limitaciones deJython.
Java tiene distintos tipos de
variables, mtodos, cons-tructores, etc., que pueden
ser privados (private) o
pblicos (public). Es impor-
tante saber que en Jython no
se pueden declarar variables,
mtodos, etc., como pblicas
ni como privadas y cuando
intentamos acceder, por
ejemplo, a una interfaz abs-
tracta privada, nos saltar un mensaje de
error diciendo que no es posible acceder a
la interfaz abstracta con el denominador
public.
Solventar esta limitacin es sencillo.
Basta con editar el fichero de registro de
jython que se encuentra en el direc-
tor io donde hay amos i n s t a l ado
jython (en nuestro caso $HOME/
Desarrol lo/jython-2.1/registry) y bus-
camos la lnea python.
security.respectJavaAccessibility = true y
cambiamos true por false. Ya tenemos
nuestro sistema preparado.
Por ltimo, es muy importante tener a
mano la API (documentacin) de Javadisponible tambin en su web y la de las
libreras que vamos a utilizar. De
Javazoom deberis bajar la documenta-
cin de JLayer (la de MPSPI viene en el
fichero que bajasteis al principio) y laAPI
de las libreras tritonus la podis bajar de
[4] (estn al final de la pgina).
Sonido en Java?El sonido de Java requiere que los progra-
madores conozcan como funcionan sus
clases principales. Las que vamos a utili-
zar son AudioSystem, AudioFormat y
SourceDataLine.AudioSystem est conec-
tada a los dispositivos del sistema de
forma que podemos acceder a ellos ade-
ms de que dentro de ella tenemos mto-
dos para tratar el stream de audio.
AudioFormatcon el que manejaremos el
formato de audio que necesitaremos. Y
SourceDataLine que nos proporciona la
entrada al dispositivo de sonido, es decir,
que podremos introducir nuestro sonido
en el dispositivo y de esta forma escu-
charlo).Java proporciona una clase ms directa
que es CLIP. Suele utilizarse ms para
sonidos pequeos en aplicaciones o en
Figura 1: Aqu tenemos
a nuestro pequeo
reproductor de MP3.
Figura 2: Este es el selector de
ficheros (JFileChooser) que se lan-
zar al ejecutar su mtodo
showOpenDialog().
Python DESARROLLO
63Nmero 07W W W . L I NUX - M A G A Z I N E . E S
-
7/31/2019 Aprovecha y usa cualquier libreras de Java.
5/5
marse run() ya que es una
implementacin del mtodo
run() que heredamos de la clase
Thread. De esta forma al invocar
el mtodo start() del hilo nuevo,
directamente ejecutara elmtodo run().
Reproducir(). Aqu es donde
creamos el buffer deBytes y el
SourceDataLine. De esta forma,
recibimos el AudioInputStream
(el stream de audio) y creare-
mos el SourceDataLine (que
recibimos desde el mtodo
getLine que definiremos un poco
ms adelante). Luego entrare-
mos en un bucle en el que con-
taremos los bytes que lemos y
los bytes que escribamos, y
desde el que leeremos (llenando
el buffer) desde elAudioInputS-
tream y luego lo escribiremos en
el dispositivo de sonido desde el
SourceDataLine. Finalmente,
cuando se termina la cancin,
cerraremos el SourceDataLine y
elAudioInputSource.
GetLine(). Desde este mtodo
creamos el SourceDataLine
(desdeAudioSystem) a partir del
stream ya descodificado y nos lodevolver. Usaremos un mtodo
que implementa el JDK1.5 que
es el getSourceDataLine(), de
esta forma nos evitamos hacer
downcasting desde el mtodo
getLine() de AudioSystem (que
nos devuelve unDataLine.info).
Finalmente tenemos getTag().
Este mtodo ser el encargado
de devolvernos la informacin
de la cancin (autor, titulo,
etc). Recibir el formato del
fichero sin descodificar, creara
una ocurrencia de tipo Map
desde la cual accederemos a los
datos que mas nos interesan, en
este caso, lbum, titulo y autor.
Para los mtodos de la interfaz (fig1), ten-
dremos el creador del botn y del cuadro
de texto (panelReproductor()) desde el
que crearemos los botones (JButtons) y el
rea de texto (JTextArea()) que nos mos-
trar la informacin delMP3, el creador
del men (menu()) que crear un men
con dos opciones (play y stop) que reali-zarn las mismas funciones que los boto-
nes, el recogedor de los eventos del ratn
(accionMenu()) que ejecutar los meto-
dos Play y Stop, el mtodoPlay() que ini-
ciara el hilo que reproducir la cancin,
adems de lanzar el selector de ficheros y
el mtodo Stop() que detendr la repro-
duccin en curso.
La interfaz es muy simple, una rea detexto (donde se insertarn los datos del
MP3) el botn Play que abrir un selector
de ficheros (fig2) desde el que selecciona-
remos el fichero a reproducir y el botn
Stop que detendr la reproduccin de la
msica. Cada vez que pulsemos en Play
tendremos que seleccionar de nuevo la
cancin a reproducir. En vosotros queda
la idea de mejorarlo aadindole una lista
de reproduccin, botn para pasar a la
siguiente cancin y a la anterior, etc. En el
nmero 4 de Linux Magzine, vimos el uso
de otros componentes como JList y alma-
cenar datos en ficheros, con eso sabris
ponerle una lista de reproduccin a nues-
troplayer.
Para reducir el tamao de la aplicacin
hemos omitido algunos puntos como
recoger las excepciones, esto lo podris
notar cuando se abra el selector de fiche-
ros y pulsis el botn cancelar, abris un
fichero que no contiene MP3, etc.
Deberis depurarlo.
Y por ltimo, el mtodo __init__() tpi-
co en las aplicaciones Python y Jythonque inicializar los valores de la aplica-
cin creando el panel contenedor de la
interfaz grfica, e inicializar la variable
booleana desde la que se controlar la
parada del reproductor (Stop) y el mtodo
exit() que permitir a nuestra aplicacin
salir cuando hagamos clic en el botn de
cerrar la ventana (la tpica X arriba a la
derecha).
Otro punto que debemos comentar es el
trato que le da Jython a las variables boo-
leanas ya que no existen los valores true y
false. Para solucionar este problema, en
vez de true utilizamos el valor 1 y en vez
de false utilizaremos el 0, que son los
valores equivalentes para Java.
Las libreras que vamos a utilizar son
las siguientes: org.tritonus.share.sam-
pled.TAudioFormat y org.tritonus
.share.sampled.file.TAudioFileFormatque
vamos a usar para obtener la informacin
de nuestro MP3. Javax.sound.sampled
aqu dentro estn nuestras preciadas cla-
ses SourceDataLine, AudioSystem, etc.
Java.io para el acceso a ficheros. jarrayque nos permite crear arrays compatibles
con Java, y por ultimo Java.util,
Javax.swing, Java.lang, Java.awt,
Java.util que nos servirn para el resto de
nuestras tareas.
En caso de que quisiramos reproducir
canciones situadas en Internet abriramos la
ubicacin creando una ocurrencia URL
(deberemos aadir la libreraJava.net, a lacual le pasamos el protocolo que vamos a
usar, el host al que tiene que conectarse, el
puerto de conexin y el nombre del fichero.
Una vez que tenemos preparada la ubica-
cin, el objeto URL con el mtodo
openStream() empieza a extraer el stream de
ese fichero, ya solo tenemos que pasrselo a
nuestro reproductor (desde el
get.AudioInputStream()) y al poco rato
(dependiendo de la velocidad de conexin y
el tamao) empezaremos a escuchar msica.
Todo el programa se puede ver en el
Listado 1.
Otro Reproductor es PosibleS, s que tenemos una forma mas fcil de
crear un reproductor. El cometido de este
artculo era ver como podamos crear, a
partir de los elementos que tenemos de
Java, un reproductor segn nuestras nece-
sidades (como el tamao del buffer). En
las libreras que hemos instalado de
Javazoom, en JLayer concretamente, exis-
te una clase que crea un reproductor de
MP3 completo al que nicamente hemosde pasarle el InputStream (con
FileInputStream) cuando lo creamos, y al
ejecutar el mtodo .play() (Fig3) de dicho
reproductor y l se encargar del resto.
Y El mes que viene volveremos con
ms scripts en Python y Jython. s
Jos Pedro Orantes Casado cursa
3 de Ingeniera Tcnica en
Informtica de Sistemas y desde
hace varios aos utiliza linux
como herramienta de trabajo y
como sistema de escritorio. Jose
Mara Ruz est realizando el
Proyecto Fn de Carrera de
Ingeniera Tcnica en Informtica
de Sistemas y lleva mas de 7 aos
usando y desarrollando Software
Libre, y desde hace 2 en FreeBSD
LOS
AUTORES
[1] http://www.jython.org
[2] http://www.Javazoom.net
[3] http://Java.sun.com
[4] http://www.tritonus.org
[5] Descargas de http://www.linux-
magazine.es
RECURSOS
DESARROLLO Python
64 Nmero 07 W W W . L I NUX - M A G A Z I N E . E S