Bienvenidos señoras y señores lectores a la …ÚLTIMA PRÁCTICA DE OCA!!! BIEEEEEEEEEEEEEEEN!!! Ahora tan solo… queda…empollarla….TAN SOLOOOOOOOOOOOOOO!!!
Pues bien, como anécdota comentar que tuvimos que empezar la clase a oscuras jaja, ya que se fue la luz en las aulas y el pasillo pero no en los ordenadores. Al poco tiempo, nuestras plegarias fueron escuchadas XD, Y SE HIZO LA LUZ. Momento en el que, aunque hubiese luz, llegó el infierno.
JMF nos resultó más raro que complicado. Resulta que es otra librería que hay que instalar aparte, e incluso tiene API PROPIO!!!
Lo primero que hicimos fue cotillear el API nuevo, muy parecido al de siempre, pero en el fondo, muy diferente.
Tras esto, para poder utilizarlo, hay que configurarlo en la máquina. Para ello se podía lograr de tres maneras.
Con javac –classpath…. se le dice a la máquina que use este nuevo classpath y se olvide del otro, pero el precio que pagamos es que esta sentencia, sólo vale para un uso del compilador.
En cambio, con la sentencia set CLASSPATH=”.;/ruta completa/jmf.jar;/ruta completa/sound.jar; la ventana se queda configurada mientras se encuentre abierta. En el momento que la cierres y la vuelvas a abrir deberás colocar la sentencia completa de nuevo.
La forma de dejarlo configurado ya para “jamás de los jamases”, es configurarlo en panel de control, bla bla bla, variables de entorno, variables de sistema, como cuando se instala el classpath de java desde cero. Ay (suspiro), aquella época en el que nuestro mayor problema era configurar el java en el ordena de nuestra casa, ay! Bueno, que como ya existe el classpath, le añadimos las nuevas rutas del JMF y santas pascuas.
El objetivo de la práctica, era crear mediante las herramientas que nos ofrece Java Media Framework, un VDCMediaPlayer, vamos, un programa que tenga botones de play, stop,… para el video, y un visualizador.
Para todo esto, hay que utilizar una ventana JFrame de Swing, extraer su contentPane y añadir sus componentes visuales mediante add. Es más fácil leerlo que hacerlo. En el API encontramos lo siguiente sobre él:
javax.media
|
||||||||||||||||||||||||||||
|
Fields inherited from interface javax.media.Controller |
|
|
|
Fields inherited from interface javax.media.Clock |
|
Fields inherited from interface javax.media.Duration |
|
Method Summary |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Methods inherited from interface javax.media.MediaHandler |
|
Methods inherited from interface javax.media.Controller |
|
|
|
Methods inherited from interface javax.media.Clock |
|
|
|
Methods inherited from interface javax.media.Duration |
Teníamos constancia, por la clase teórica de Rueda, de que existía la interfaz Player, que contenía los métodos getVisualComponent() y getControlPaneComponent(), los cuales utilizaremos para esta práctica:
getControlPanelComponentpublic java.awt.Component getControlPanelComponent()
Gets the Returns: The default control panel GUI for this
getVisualComponentpublic java.awt.Component getVisualComponent()
Gets the display Returns: The media display
|
Para hacernos la vida más fácil también está la clase Manager. Clase que define métodos static y la puedo usar para apoyar el programa.
javax.media
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Method Summary |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Methods inherited from class java.lang.Object |
|
|
Como no se puede hacer Player p = new Player(…); ¡¡ERROR!! ya que Player es una interfaz, por lo que nos ayudamos de la clase Manager para crear un objeto Player. Un método que contiene Manager es el createPlayer, al que se le puede pasar por parámetro un DataSource, un MediaLocator o una URL (un fichero local se puede escribir como URL), porque necesita un reproductor de algo.
createPlayer
public static Player createPlayer(MediaLocator sourceLocator) throws java.io.IOException, NoPlayerException Create a The algorithm for creating a 1. Get the protocol from the 2. Get a list of 3. For each source class in the list: 1. Instantiate a new 2. Call the 3. Get the media content-type-name (using 4. Get a list of 5. For each 1. Instantiate a new 2. Attach the source to the 3. If there are no failures, determine the type of the 4. If the 5. If the 6. If no 4. If no 1. Instantiate the source. 2. Call the 3. Use the content package-prefix-list to create a list of 4. For each 1. If no Parameters:
Returns: A Throws: NoPlayerException – Thrown if no java.io.IOException – Thrown if there was a problem connecting with the source. createPlayerpublic static Player createPlayer(DataSource source) throws java.io.IOException, NoPlayerException Create a The algorithm for creating a 1. Get the media content-type-name from the source by calling 2. Use the content package-prefix-list to get a list of 3. For each 1. Instantiate a new 2. Attach the source to the 3. If there are no failures, return the new 4. If no 1. Use the content package-prefix-list to create a list of 2. For each 1. Instantiate a new 2. Attach the source to the 3. If there are no failures, return the new 5. If no Parameters:
Returns: A new Throws: NoPlayerException – Thrown if a java.io.IOException – Thrown if there was a problem connecting with the source.
createPlayerpublic static Player createPlayer(java.net.URL sourceURL) throws java.io.IOException, NoPlayerException Create a Parameters:
Returns: A new Throws: NoPlayerException – Thrown if no java.io.IOException – Thrown if there was a problem connecting with the source.
|
Una URL se compone de protocolo://destino/recurso, en resumen, compañeros tenemos que escribir file://(la ruta completa). No es válido poner “video.mpg” ya que no sigue la sintaxis.
Uno de nuestro errores fue olvidarnos de Manager y de su createPlayer, de tal forma que dijimos implementamos Player y a saco. Pero era muy engorroso, pesado y nos daba bastantes errores al compilar. Hasta que le dijimos: “Profe, ayúdanos, esto no nos sale y nos estamos haciendo la picha un lío”. Son de estas frases típicas made in Spain, que no las piensas y las sueltas sin mas, a lo que él contestó sin ningún enfado (cosa que agradecemos): “Procura no mezclar las palabras profe y picha en la misma frase.”. Ahora lo recordamos y nos reímos, pero pensándolo fríamente…QUE HABRÁ PENSADO EL PROFE!!! Desde este honrado blog, las más sinceras disculpas.
Después de todo este berenjenal, nos ayudó a recordar, percatándonos de que la manera más fácil era escribir Player p = Manager.createPlayer(…);
En clase se nos recordó lo explicado en la teoría sobre que un Player tiene varios estados: unrealized, realized, prefetched y started. Realized es el estado en el que se encuentra un player cuando es creado por primera vez y no tiene ningún conocimiento acerca de la fuente de datos de entrada. Por esta razón, tardará un tiempo en arrancar desconocido para nosotros. Por lo que, antes de hacer el getVisualComponent, hay que colocar p.realized(), porque no podemos reservar un tamaño para el video si no sé su tamaño. p.realized() calcula varias cosas. Realized salta al estado “me he dado cuenta” y no puedo llamar al getVisualComponent() antes de pasar a realized. Para saber cuando ocurre llamo a un escuchador de eventos.
Al player le creamos un controllerListener y se lo añadimos al panel.
javax.media
|
|||||
|
Method Summary |
|
|
|
|
controllerUpdate
public void controllerUpdate(ControllerEvent event)
This method is called when an event is generated by a Controller that this listener is registered with.
Parameters:
event – The event generated.
ControllerListener sólo tiene un método, que hay que redefinir en nuestra clase. Éste se lanza cuando ocurre un evento. Es un método para todos los eventos, entonces, dentro del método, hay que distinguir entre los diferentes eventos que nos pueden aparecer. Cuando ocurra un evento llegará un objeto que hereda de MediaEvent.
javax.media
|
|||||||||||
|
|
|
Constructor Summary |
|
|
|
|
|
Methods inherited from class java.util.EventObject |
|
|
|
Methods inherited from class java.lang.Object |
|
|
MediaEvent
public MediaEvent(java.lang.Object source)
Podemos hacer un instanceOf de tal forma que si llega un evento, ya se puede actuar, y sacamos el getVisualComponent(). El evento que de verdad nos interesa es RealizeCompleteEvent.
javax.media
|
|||||||||||||
|
Fields inherited from class java.util.EventObject |
|
|
|
Constructor Summary |
|
|
|
|
|
Methods inherited from class javax.media.TransitionEvent |
|
Methods inherited from class javax.media.ControllerEvent |
|
Methods inherited from class java.lang.Object |
|
|
|
Constructor Detail |
RealizeCompleteEvent
public RealizeCompleteEvent(Controller from, int previous, int current, int target)
Otra forma de hacerlo es con hilos. Se puede colocar entre el método realized() y el getVisualComponent(), un Thread.sleep(..) a un tiempo, el que se quiera. Este es el camino erróneo, porque con el tiempo que se coloque en el sleep, si cojo tiempo de más, desperdicio tiempo de espera, y si cojo de menos, nos sale el tiro por la culata. Además de que hilos da mucho problemas.
Esta es una mala solución. En lugar de esperar un tiempo arbitrario, lo mejor es programar con el modo de controlar los eventos, el escuchador,… y toda esa parrafada.
¡¡CUIDADO!! Advertencia, el formato de video que se puede usar en JMF depende de la versión del JMF instalado. Si se intenta usar uno que no está instalado, saltará una popi excepción, UnableToHandleFormatException, o algo parecido.
Teóricamente sabíamos lo que había que hacer, pero después estabas frente al ordenador como si tuvieses un toro delante. Después de intentar implementar la interfaz Player, usamos a Manager. Llegados a este punto, nos perdimos. No sabíamos como seguir. Miramos en el API, le dimos muchas vueltas,… nada sirvió.
No paraban de saltarnos errores. Al principio tonterías de que faltaba importar paquetes. Hasta que llegó un momento que ni comprendimos los errores que salían. Intentamos seguir las instrucciones que se nos explicaron durante la clase, pero no sacábamos nada en claro, tan solo errores.
Hay que tener especial cuidado con el control de excepciones. A nosotros nos salieron el famosísimo IOException y MediaException, los cuales eliminamos rápidamente con un try y catch.
javax.media
|
||||||||||
|
|
|
|
|
|
|
Methods inherited from class java.lang.Throwable |
|
|
|
Methods inherited from class java.lang.Object |
|
|
No logramos programar la clase.
Cuando terminó la hora, una compañera nos ayudó muuuuuuuuuuuuuuuuucho. Ella nos explicó que debíamos hacer para resolverlo. Lo resolvió como decía el profe, como nosotros intentamos, pero hay veces que te atascas y no sale ni para atrás. Aun así, nos pareció una práctica muy rara más que complicada. Es que es como siempre, una vez que la ves hecho lo entiendes, pero sino, no sabes. Esperamos que con lo que aprendimos en el aula y con la ayuda de nuestra compi ahora seamos capaces de resolver los JMF.
PUES AHORA TOCA DESPEDIRSE…L
Hacer el blog ha sido de una gran ayuda. Nos dábamos cuenta, a la hora de intentar explicar las cosas, qué no sabíamos y qué debíamos estudiar más. Además del pique que nos traíamos para ver quien de la clase colgaba primero la práctica jaja, hubo gente que la colgó a la media hora de empezar la clase, sin ni si quiera acabar jaja.
Leer los blogs de los compañeros también ayuda bastante pero eso de dejarles comentarios, se nos olvidaba siempre la verdad.
El último post que colguemos será, seguramente para dar nuestras impresiones sobre el juego, y quizá, por qué no, sobre la asignatura. Quién sabe que futuro llegará a tener este blog.
HASTA PRONTO!!! J