sábado, enero 19, 2008

OpenFlow, un coverflow para linux

Actualización [19 de Enero del 2008], más abajo:
Éste es uno de mis proyectos personales.


Mi objetivo número 1 es implementar como una aplicación independiente en opengGL (programado en ANSI C) que sea capaz de mostrat imágenes con el efecto tipo coverflow de iTunes.

He encontrado en youtube dos tipos de coverflow, así que haré dos versiones distintas para que se parezcan lo máximo posible:

1- Coverflow macbook:



2- Coverflow iTunes 7:


Mi objetivo número 2 es hacer de ésta aplicación independiente, un plug-in para todos los reproductores que conozco para linux: xmms, rhythmnox, listen, banshee, amarok, etc... Con lo que quizá tendré que traducir la aplicación a otros lenguajes.

Por cierto, cada vez que tenga una nueva versión, actualizaré el post y lo volveré a publicar en la fecha actual, así que si me seguís a través de algún lector de RSS la noticia os volverá a salir, indicando que hay nuevo contenido.


[27 de Agosto del 2007]:

Gracias a la librería glpng.h, consigo cargar y pintar todas las imágenes que se encuentran en el directorio images/ respecto al directorio de ejecución de la aplicación. Más adelante pondré una opción para escoger éste directorio. Además creo un rectángulo siempre con el mismo ancho pero con el alto en relación a la relación de aspecto original de la imagen.

El problema es que de momento uso imágenes de fondo de pantalla de unos 1600x1200 píxeles, así que a la hora de iniciar la aplicación y cargar por ejemplo, 15 imágenes, tarda unos segundos en finalzar la carga. Una vez finalizada la aplicación muestra la ventana y su contenido. Éste tema está en discusión de cómo solucionarlo y lo dejaré para el final del proyecto (del primer objetivo)

Calculo dónde hay que pintar la imagen que hay seleccionada, las distancias y rotaciones de las imágenes inmediatamente anteriores y posteriores y luego todas las demás. Ya que hay que fijarse que la imagen actual +1 y la actual -1 tienen una separación mayor que las distancias respectivas del resto de imágenes.

Así pues, la primera versión después de dos días de programación es esta:

video



[31 de Agosto del 2007]:

Es hora de implementar las animaciones y empezaré por implementar una animación lineal. Después de 3 horas de trabajo el resultado es éste:

video


[19 de Enero del 2008]:

Después de unos meses inactivos, volví a retomar el proyecto para implementar las animaciones progresivas + el reflejo y éste es el resultado:

video
[versión iTunes 7 style]


video
[version iPod NANO style]

En esta entrega, se han implementado multitud de funcionalidades que me ha costado lo mio implementarlo.

Ahora hay una progresión en las animaciones y existen dos velocidades distintas. Una cuando sólo se le hace un clic, y otra si se mantiene el botón pulsado. Ésta implementación fue complicada ya que en OpenGL para linux (no recuerdo si en windows tiene el mismo funcionamiento), la función que indica cuándo una tecla ha sido despulsada, se activa aunque no se haya despulsado, es decir, yo pulso la tecla y se van llamando a las funciones pulsa() -> despulsa() -> pulsa() -> despulsa().. Así que fue un verdadero lío. Con el tema de las dos velocidades también.

Pero además, cuando sólo se pulsa una vez, el álbum que tiene que ir de frente se acerca a la pantalla. En cambio cuando dejamos pulsada la tecla, la imagen de frente no se acerca, sino que se mantiene en la misma profundidad, y no hay una progresión en la animación, sino que es lineal. Ésto produce un muy buen efecto cuando pasamos las carátulas a toda velocidad. Conmutar entre estos dos modos ha sido muy complicado ya que la transición entre acercarse la pantalla y no, no es trivial. Si queréis que os pase un vídeo con los diferentes comportamientos iniciales a cámara lenta para que veáis la problemática, ponérmelo en los comentarios.

La velocidad en la que se realiza la animación depende de la velocidad del procesador y de la tarjeta gráfica en donde se ejecuta. Así que en un principio, en ordenadores con configuraciones distintas, la velocidad de las animaciones era totalmente distinta. Incluso en el mismo ordenador, si se cambia el tamaño de la aplicación (por ejemplo a pantalla completa), las animaciones van más lentas.

Lógicamente, lo que a mi me interesaba era que siempre, en cualquier configuración y tamaño de pantalla, las animaciones durasen lo mismo.

Una solución era definir un paso fijo (incremento de posición) y a través de un control del tiempo, permitir pintar o no. Pero con esto marcaba un nivel mínimo y tenia que definir un paso demasiado elevado para que funcionase bien en "todas" las condiciones. Un paso elevado provocaba que la animación no era del todo fluida y se veían los incrementos aplicados como "a golpes"...

Otra solución, que es la que al final he implementado, es la definición de la duración deseada de la animación, y automáticamente calculo el paso necesario para la velocidad actual de renderizado, es decir, el paso se va calculando dinámicamente en función de la velocidad actual de la aplicación. Así, si redimensionamos la aplicación o lo ejecutamos en un ordenador rápido o lento, no sólo la animación va a durar lo mismo, si no que pongamos imágenes pesada, o muy ligeras, siempre vamos a obtener la misma experiencia.

Además, otro problema era que inicialmente se pintaban todas las imágenes cargadas, aunque éstas no se vieran (en pantalla sólo caben un número determinado de imágenes), pero ahora sólo se pintan un puñado de ellas, las que caben en pantalla. Gracias a esto podemos cargar 200 imágenes y la aplicación siempre va a tener un muy buen rendimiento.

En fin, tan solo faltan cuatro pinceladas al proyecto para alcanzar una versión final estable y estoy muy satisfecho con el resultado obtenido hasta ahora. Así que si a alguien le interesa probar la aplicación, que me envíe un correo electrónico o a través de un comentario y yo me pondré en contacto para pasar la aplicación y las instrucciones de uso.

PD: Por cierto, las capturas de vídeo que realizo no pueden estar a la misma calidad que la aplicación original ya que el programa para realizar la captura a 20fps consume muchos recursos. Así que he de redimensionar el programa a un tamaño en el que la velocidad de grabación sea la mínima deseable. Con ésto quiero decir que la aplicación real va mucho más fluida que en los vídeos, como es lógico.. :D

8 comentarios:

Anónimo dijo...

Felicidades! Realmente se ve muy muy muy prometedor. De todos modos, has visto el plugin que están desarrollando para Banshee? No se si estás en el equipo. Quizás deberías unirte, ayudar, y después trabajar portándolo al resto de aplicaciones. Un saludo.

Ferran Garriga dijo...

Gracias por el comentario !!

Ciertamente vi el proyecto para Banshee pero no estoy en su equipo. Banshee está programado en c# (mono) y yo de momento lo estoy programando en ansi c, bastante más eficiente, aunque ese no es el tema ya que la idea es hacer plug-ins para todos los navegadores, estén en el lenguaje que estén.

La idea de éste proyecto es personal, así que es como un reto. No tendría sentido para mi unirme a un grupo que ya llevan mucho realizado. Para mi el reto es empezar desde cero y ver hasta dónde llego.

Un saludo !

macuoren dijo...

Tío, de mayor quiero ser como tu :D

En serio, me parece estupendo lo que pretendes y lo que tienes hecho hasta ahora.

Si quieres, me ofrezco voluntario para probar la aplicación. Me gusta trastear los ordenadores mucho, aunque todavía no se me da muy bien lo de compilar.

Un saludo!

Ramón dijo...

Sencillamente genial.

Creo que el mundo Linux no debe perder la filosofía Unix de construirlo todo "a trocitos": mejor una excelente pero única implementación de algo que pueda usarse en muchos proyectos que multiplicar esfuerzos en varios proyectos a la vez innecesariamente. Por eso me encanta tu desarrollo.

Una cosa, ¿conoces Elisa Media Center? Es un media center para Gnome que utiliza Gstreamer y en su última versión han implementado una vista tipo coverflow, pero no funciona del todo fluida. ¡Quizá les sea útil tu desarrollo! :)

Por último, darte una pequeña sugerencia: estaría bien que implementaras la posibilidad de modificar el ángulo de visión de las imágenes, es decir, que se pudieran ver las imágenes más tumbadas hacia uno u otro lado o más desde arriba o desde abajo, no sé si me explico... Y no sé cómo de complicado será hacer eso sobre el código que ya tienes, pero sería una buena característica, lo haría más flexible y adaptable (por ejemplo, de cara a que el usuario pueda personalizar la vista coverflow en los plugins para los reproductores).

Nada más, siento todo este rollo jeje. Enhorabuena y sigue así.

Un saludo.

Ferran Garriga dijo...

Hola Ramón, muchas gracias por tu comentario.

Elisa Media Center me encanta, llego siguiendo su desarrollo desde su primera versión y lo están haciendo muy, pero que muy bien. Espero liberarles el código en cuanto llegue a la versión 1.0

Y que por cierto, para la versión final, casi todo será configurable, entre esas cosas el ángulo de visualización y un poco de zoom así que tendrás lo que pides...

macuoren dijo...

Tienes que ver esto: PictureFlow: implementación libre y eficiente del efecto Coverflow de Mac

Eduardo dijo...

Tambien me encanta. Has pensado en incorporarlo en Elisa para darle mas tiron?

antraXactive dijo...

Felicidades por tu proyecto, veo que lo llevas bastante avanzado.

Cualquier cosa que necesites no dudes en solicitar ayuda, realmente es espectacular tu trabajo.

Mucha suerte y gracias de parte de la comunidad en general y de la mçia en particular