ArquitecturaInternetRadio
De Open movilforum wiki
Tabla de contenidos |
[editar] Introducción
Versificator es una aplicación que permite reproducir audio en diferentes formatos. Diseñada inicialmente para Symbian 2nd Ed FP3, utiliza la arquitectura de plugins ECOM, siendo así su funcionalidad fácilmente expandible a través del desarrollo de plugins independientes a la aplicación, compartiendo todos ellos el mismo engine de streaming de audio. Actualmente existen 3 plugins desarrollados para Versificator:
* LastFm: Reprodución de estaciones de radio de un cuenta de Last.fm. * Podcast: Visualización y reproducción de feeds de audio de una podcast. * Shoutcast: Reproducción de radio de internet.
[editar] Arquitectura ECOM
Al iniciarse la aplicación, se hace un “descubrimiento” de plugins instalados en el terminal que implementen una interfaz muy concreta ( interfaz de 2nd UID 0x10001AF0 ). Todos los plugins descubiertos se listan en una opción de menú dispuestos a ser utilizados.
Para más información sobre arquitectura ECOM, consultar http://www.symbian.com/Developer/techlib/v8.1adocs/doc_source/guide/System-libraries-subsystem-guide/N1010E/EcomArchitecture/EcomIntro.guide.html.
[editar] Arquitectura CActive
A pesar que el sistema operativo Symbian soporta multithreading, no es recomendado su uso. En vez de esto, se utiliza las clases de tipo CActive. Las clases que heredan de CActive son clases que implementan un FSM ( máquina finita de estados ). Inicialmente se añaden a un “comprobador” de estado que está en continua comprobación del estado del objeto.
Para más información, consultar http://www.symbian.com/developer/techlib/v70sdocs/doc_source/reference/cpp/AsynchronousServices/index.html.
Tanto en la aplicación como en el engine y los plugins, son muchas las clases que derivan de CActive. Por esta razón se aconseja tomar interés en el aprendizaje de esta técnica.
[editar] Creación de un plugin para Versificator
Para desarrollar un plugin válido para Versificator, se debe proceder de la siguiente manera:
1. Crear un proyecto DLL para Symbian C++.
2. Establecer el segundo UID (unique identifier) a la dll. Llamémosle 0x1XXXXXX1.
3. Cambiar el TARGETTYPE del proyecto a dll.
4. Cambiar el TARGETPATH del proyecto a \system\libs\plugins.
5. Añadir un fichero de registro llamado 1XXXXXX1.rss en la carpeta /data del proyecto.
6. Añadir el siguiente código al fichero recién creado:
#include <eikon.rh>
#include <avkon.rsg>
#include <avkon.rh>
#include <avkon.mbg>
#include "RegistryInfo.rh"
// Declares info for two implementations
RESOURCE REGISTRY_INFO theInfo
{
// UID for the DLL
dll_uid = 0x1XXXXXX1;
// Declare array of interface info
interfaces =
{
INTERFACE_INFO
{
// UID of interface that is implemented
interface_uid = 0x1XXXXXXX2;
implementations =
{
IMPLEMENTATION_INFO
{
implementation_uid = 0x1XXXXXXX3;
version_no = 1;
display_name = "Name of plugin”;
default_data = "";
opaque_data = "";
}
};
}
};
}
7. Añadir una referencia a las librería \ecom\ECom.lib.
8. Crear una clase (llamémosle de tipo CMyPlugin) que herede de la clase abstracta CpluginInterface e implementar sus métodos virtuales puros.
Con esto, sería suficiente para que la aplicación Versificator detectase el plugin e instanciase un objeto de tipo CMyPlugin. Evidentemente este plugin aún no habría desarrollado ninguna funcionalidad. Para aprovechar el engine de Versificator, deberíamos añadir una referencia a la librería VersificatorEngine.lib.
[editar] Engine de Versificator
El engine de la aplicación está desarrollado en un proyecto dll aparte con objeto de reutilizar al máximo la funcionalidad en la propia aplicación y los plugins desarrollados.
En esta librería se aglutinan clases de diferente índole. Veamos las más relavantes, una a una, explicando su funcionalidad, diseño e implementación:
[editar] CConnection:
Es la clase que gestiona todas las conexiones. Es una clase de tipo singleton ( ver singleton pattern en http://en.wikipedia.org/wiki/Singleton_pattern ).
Para implementar una clase singleton en Symbian se debe recurrir al TLS (Thread Local Storage). Para más información, ver http://www.forum.nokia.com/document/Forum_Nokia_Technical_Library/contents/FNTL/How_to_implement_a_singleton_class_in_Symbian_OS.htm
El objetivo de esta clase es que, desde cualquier punto de la aplicación o de los plugins, se pueda conectar a internet a través de ella, simplemente especificando la URL (ver interfície pública).
Internamente dispone de un socket que conecta con el host, recibiendo la respuesta en bloques de datos. Cada vez que un bloque es leído, la clase notifica de este hecho a través de un Observer pattern ( ver http://en.wikipedia.org/wiki/Observer_pattern ).
Debido a este diseño, en la aplicación es imposible establecer dos conexiones simultáneas. No obstante, sin demasiada complicación, se podría modificar la clase para mantener un pool de sockets.
También se deja pendiente a la comunidad la implementación de un timeout de respuesta en la conexión.
[editar] CImageHandler:
Esta clase parte de una URL de una imagen para descargarla, decodificarla a BMP ( único formato que soporta Symbian 2nd Ed FP3 para dibujar en pantalla ) y escalarla en el tamaño deseado.
Para llevar a cabo su próposito, se ha diseñado esta clase de tipo CActive para realizar las diferentes tareas de manera asíncrona: descarga del fichero, decodificación y escalado.
Esta clase es utilizada en los plugins LastFm y Podcast para mostrar la carátula de la canción e imagen del podcast respectivamente.
Hay que destacar de esta clase que decodifica imágenes en los formatos jpg, png y gif.
[editar] CXmlEngine:
Cabe decir que en Symbian 2nd Ed FP3 no existe ningún parser de XML así que se ha utilizado un port del parser Expat ( ver http://expat.sourceforge.net ). Este port para Symbian es open source y descargable desde el siguiente link http://www.toddsoftware.com/index.php?option=com_content&task=category§ionid=13&id=102&Itemid=76.
La clase XmlEngine es un wrapper de esta librería. Parsea un xml de bloque en bloque de datos.
Esta clase es utilizada en los plugins LastFm y Podcast para interpretar la lista de canciones e interpretar el rss feed respectivamente.
[editar] CTicker:
Esta clase se responsabiliza de gestionar el movimiento de un texto fijo durante el transcurso de un cierto tiempo ( efecto Ticker ). Esta clase gestiona el hecho que un texto sea demasiado largo para visualizarse en pantalla, desplazándolo a cada cierto tiempo.
Internamente funciona con un timer ( clase CPeriodic ) que, periódicamente llama a una función de la clase que se encarga de desplazar el texto. La llamada se realiza a través de un callback utilizando la clase TCallBack.
Esta clase se utiliza en la aplicación y en todos los plugins.
[editar] Buffer de streaming:
Se compone de las siguientes clases:
CStreamBuffer CStreamReader CStreamWriter CStreamPlayer
CStreamBuffer crea un buffer en memoria de tamaño determinado ( 1048576 bytes por diseño ). A su vez, dispone de dos apuntadores que le indican los bytes leídos y los bytes escritos. Cuando se completa el llenado del buffer, se continúa por el principio, machacando los datos ya leídos; es decir, se trata de un buffer circular.
Se parte de un objeto de tipo CStreamPlayer que contiene un objeto CStreamReader y otro CStreamWriter. El CStreamWriter se comunica con el player a través de un Observer pattern.
Por un lado, el objeto de tipo CStreamReader es el encargado de ir leyendo los datos de audio mediante una conexión abierta. A medida que va recibiendo cada bloque de datos, los va escribiendo en el buffer. Los datos se copian en el buffer y se actualizan los apuntadores.
Por otro lado, el objeto de tipo CStreamWriter es un objeto de tipo CActive que contínuamente consulta al buffer para saber si tiene datos para reproducir. En tal caso, lee un bloque de datos, actualiza los apuntadores del buffer y lo envía a reproducir por el stream de audio.
Y así sucesivamente hasta que el objeto CStreamReader recibe la señal que la lectura de datos de audio ha finalizado. En tal caso, más tarde o más temprano el CStreamWriter finaliza también, puesto que tendrá más datos que leer del buffer. En este momento, notifica al CStreamPlayer la finalización de la reproducción, delegando a éste último la responsabilidad de actuar de forma consecuente ante esta situación.
[editar] Plugins
Todos el plugins comparten un mismo diseño común. A partir de aquí, cada uno es personalizado en función de sus necesidades.
Todo plugin tiene la clase central de tipo CPluginInterface que, a su vez, implementa la interfície MPluginAdapter, responsable de la interacción con el player de audio ( Play, Stop, Volumen, etc … ). En esta clase se desarrolla todo el core del plugin. En algunos casos, para aumentar la legibilidad, se separa la parte que se dedica a la interfície gráfica de la parte que se dedica a la gestión de audio ( ver, por ejemplo, en el plugin de LastFm las clases CLastFmUI y CAudioscrobblerEngine ).
Asimismo, cada plugin dispone de un player que hereda de la clase CStreamPlayer del VersificatorEngine. Su misión es crear las clases reader y writer del buffer, así como comunicarse con la clase principal a través de un Observer pattern.
La aplicación Versificator está construida utilizando la arquitectura Model – View – Controller ( ver http://www.geckim.com/symbian/symbian-articles/symbian-model-view-controller.aspx ). La vista dispone de único control ( CVersificatorContainer ) que ejerce de contenedor de la aplicación. Sobre este contenedor se dibuja el plugin que la aplicación muestra establece como plugin activo.
Cada plugin dispone de una clase acabada en “UI”; son las responsables de dibujar la interfície gráfica del plugin sobre el contenedor.
[editar] Last.Fm
Este plugin permite la reproducción de una estación de Last.Fm de una cuenta concreta. Antes de nada de debe realizar un login de la cuenta de usuario ( conocido como Handshake en el protocolo Audioscrobbler. Ver más en http://www.audioscrobbler.com ). Como respuesta al proceso de Handshake, se recupera un id de session. Con este id se realiza el proceso de recuperación de una playlist en formato XML ( conocido como XSPF. Ver más en http://www.xspf.org ). Tras interpretar este XML, se dispone de la información suficiente para la reproducción del audio, la visualización de los datos de las canciones que se reproduceny la url de la imagen de la portada del álbum de la canción.
Cabe decir que para el handshake se precisa el cálculo del MD5 del password. En Symbian 2nd Ed FP3 no existe ninguna clase que implemente esta funcionalidad. Es por eso que se ha hecho un port a Symbian de una implementación en C open source: http://www.ietf.org/rfc/rfc1321.txt.
La clase CAudioscrobblerEngine se encarga de interactuar con el servidor de LastFm a través del protocolo Audioscrobbler. Efectúa las peticiones, recibe las respuestas y las interpreta. Esta clase aisla de la clase principal de toda la lógica.
[editar] Podcast
Este plugin permite visualizar y reproducir un podcast. A través de un fichero RSS, el plugin descarga este fichero XML e interpreta su contenido, dando como resultado una lista de feeds. Cada feed puede tener un fichero de audio asociado. En tal caso, al seleccionar el feed se reproduce el audio así como se muestra la imagen asociada al podcast que, previamente ya se ha descargado, transformado y escalado con la clase CImageHandler.
[editar] Shoutcast
Con este plugin se puede escuchar cualquier emisora de radio de internet que esté reproduciendo a través de Shoutcast. Para ello, simplemente hay que introducir su url. Internamente, el plugin realiza una conexión con el servidor de shoutcast e interpreta los datos que recibe. Es capaz de detectar cuando se producen los cambios de canción, actualizando la información por pantalla.
En este plugin se debe sobreescribir la funcionalidad de la clase CStreamReader, puesto que en la petición se debe añadir información complementaria para pedir que se nos envíe la información de la canción.
