Archivo por meses: noviembre 2005

Recuperar los títulos de las canciones de un CD con FREEDB

Desde hace mucho tiempo estan disponibles dos servicios en Internet cuyo cometido es almacenar una gigantesca base de datos con los títulos de las canciones de cualquier CD de música que se haya editado. La primera es Gracenote (también conocida antes del 2000 por cddb), de la cual no hablaremos en este artículo por requerir licencia. La segunda es freedb la cual sigue siendo gratuita y con una simple página web podemos consultar la información que nos interesa. En la sección developers podreis encontrar la información necesaria para trabajar con esta tecnología.

Básicamente consiste en obtener una identificación única a partir de la información de la tabla de contenidos de un CD (TOC). Una vez obtenida la identificación, solo hay que hacer una petición web al servidor de freedb con la misma para que nos devuelva el título del CD y la lista de títulos de canciones y sus respectivos autores de las distintas pistas que conforman el CD.

El algoritmo para hallar el identificador único consiste en:
-Sumar los números en segundos de lo que dura cada pista. Es decir, si una cancion dura 4:17, entónces son 257 segundos, luego la suma es 2+5+7=14.
-Una vez obtenido el sumatorio de todas las pistas con el anterior algoritmo, se le saca el módulo de 255 y a continuación se le multiplica por 16777216 (2^24); a este resultado se le suma el tiempo total del CD multiplicado por 256 (2^8) y finalmente a este resultado se le suma el número total de pistas que contiene el CD.

Una vez hallado el identificador único, se transforma a un número hexadecimal y se hace una peticion a freedb de la siguiente manera:

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+<ID UNICO>&hello=name+host.com+appname+1.0&proto=1

cddb read misc <ID UNICO> del parámetro cmd es el comando que indica que estamos haciendo una petición a la base de datos con el ID UNICO. Por ejemplo cddb read misc c510910d.

name host.com appname 1.0 del parámetro hello indica que persona, dominio, aplicación y versión de la misma esta solicitando la información. Por ejemplo: sistemasorp sistemasorp.blogspot.com testeoCDDB 1.0.

Y finalmente el 1 del parámetro proto indica que versión del protocolo queremos usar para hacer la petición a la base de datos, devolviendonos acorde a la versión una información formateada.

Así por ejemplo si lanzamos esta petición:

http://freedb.freedb.org/~cddb/cddb.cgi?cmd=cddb+read+misc+c510910d&hello=sistemasorp+sistemasorp.blogspot.com+testeoCDDB+1.0&proto=1

Nos devuelve lo siguiente (terminado en una linea con un punto, al estilo del SMTP):

210 misc c510910d CD database entry follows (until terminating `.’)
# xmcd CD database file
#
# Track frame offsets:
# 150
# 24460
# 45650
# 71127
# 98425
# 118997
# 146585
# 164707
# 188897
# 216340
# 240932
# 271642
# 297722
#
# Disc length: 4243 seconds
#
# Revision: 2
# Processed by: cddbd v1.5PL3 Copyright (c) Steve Scherf et al.
# Submitted via: CDex 1.40Beta9
#
DISCID=c510910d
DTITLE=Various / Rave Massacre [Disk 1]
TTITLE0=Raving Bastards – Love Time
TTITLE1=Chill’n Force – Move Raver (Kemo Mix)
TTITLE2=M.A.F. X-Perience – Dreamland
TTITLE3=Society for Psychical Research – Silversky
TTITLE4=Obsessiv – Tune In, Tune On, Drop Out
TTITLE5=Nettuno – I Cry
TTITLE6=Razor – Is It Love
TTITLE7=Sunbeam – Outside World
TTITLE8=Raver’s Nature – Tricky Symphony
TTITLE9=NIP Collective – I’m About
TTITLE10=RBM – Banyo Love
TTITLE11=Paranoia X – Party Program
TTITLE12=NR-Gizer – Raving Generation
EXTD= YEAR: 1994 ID3G: 31
EXTT0=
EXTT1=
EXTT2=
EXTT3=
EXTT4=
EXTT5=
EXTT6=
EXTT7=
EXTT8=
EXTT9=
EXTT10=
EXTT11=
EXTT12=
PLAYORDER=
.

Donde entre comentarios (con la almohadilla delante) da información sobre el disco, copyright y demás; continuando con una lista de parejas nombre/valor que contienen la información que queremos:

DISCID: El mismo identificador de disco que le hemos pasado
DTITLE: El autor y título del CD
TTITLEX: El título de canción que está en la pista X
EXTD: Información extendida sobre el disco
EXTTX: Información extendida sobre la canción que está en la pista X
PLAYORDER: El orden en el que se deberían reproducir las pistas
YEAR: El año de edición del disco
ID3G: La categoría o clase de música que contiene el CD

A continuación expongo dos codigos fuentes (el primero para windows y el segundo para linux) que muestran como recoger el identificador único de un cd y a continuación solicitar la información de ese cd a freedb. Ambos se ejecutan en la consola de texto pasandoles como parámetro la unidad o dispositivo de cd.

WINDOWS(ejecutable y fuentes)

LINUX(ejecutable y fuentes)

webchat en tiempo real con php y mysql

Después de un pequeño descanso volvemos a las andadas. Esta vez voy a mostrar como crear un webchat en tiempo real.

El problema de los webchat es que la inmensa mayoría de los que existen se dedican a refrescar la página de la charla cada X tiempo o cuando el usuario ha escrito un mensaje. Esto es debido a que el protocolo HTTP esta diseñado para que una vez recibido los datos cierre la conexión, y si queremos recuperar datos nuevos tenemos que hacer una nueva petición.

Para lograr una interactividad y un realismo temporal cercanos al irc, messenger, etc. y seguir usando la web tenemos que usar un truco, y es crear una página que nunca termine de ejecutarse. Quizá os pregunteis que si nunca termina de ejecutarse, entónces no saldrá ningún resultado, pues bién, podemos desactivar el buffer del php desde el principio o hacer un volcado continuo para que cada dato nuevo se vaya enviando al navegador del cliente. Los navegadores muestran el contenido según les va llegando, por lo que una sentencia como esta (en pseudocodigo):

mientras verdadero
recupera mensajes nuevos
muestra mensajes nuevos
fin del mientras

haría que cada vez que un mensaje nuevo apareciese se enviase al navegador y este lo mostrara instantaneamente, con lo que habríamos conseguido que fuese el tiempo real.

Parar lograr este planteamiento en php tenemos que seguir los siguientes pasos (he reducido su código para simplificarlo):

ob_start();

Que activa el tratamiento del buffer en php

set_time_limit(0);

Indica al motor de php que el script nunca debe caducar a pesar de lo que dure.


for(;;)
{

Este es el bucle que constantemente se va repitiendo.


$rs=mysql_query(«SELECT * FROM chat_mensajes WHERE IDMensaje>'» . $id . «‘ AND WEEK(DatFecha,1)=WEEK(NOW(),1) AND YEAR(DatFecha)=YEAR(NOW()) ORDER BY IDMensaje»)
or die («No se puede realizar la consulta»);

En mi caso guardo los mensajes en una base de datos mysql, por lo que con la consulta SQL compruebo aquellos mensajes cuyo ID sea mayor que el último ID de mensaje que se ha mostrado (solo aquellos dentro de la semana actual del año en curso).


if(mysql_num_rows($rs)>0)
{
while($fila=mysql_fetch_array($rs,MYSQL_ASSOC)) {

Compruebo si hay nuevos mensajes y los recorro.


$id=$fila[«IDMensaje»];

Voy actualizando la variable id para que contenga al final el último ID y así en la siguiente pasada del bucle solo recoger los últimos mensajes escritos a partir del indicado.


echo «<div>\n»;
echo «<span>» . $fila[«DatFecha»] . » » . «</span>»;
echo «<span>» . $fila[«StrUsuario»] . «&gt;</span>»;
echo «<span>» . $fila[«StrMensaje»] . «</span>»;
echo «</div>\n»;
}

Se va mostrando el contenido de los mensajes (fecha, remitente y mensaje).


echo «<script>scrollTo(0,999999999);</script>\n»;
ob_flush();
flush();
}

Con un pequeño truco en javascript logramos desplazar la ventana del navegador siempre hasta el final del contenido. A continuacuón vaciamos el buffer hacia el navegador del cliente.


sleep(1);
}

Para no recargar mucho el servidor mysql haciendo constantemente consultas, pausamos durante un segundo la ejecución para después continuar con la siguiente iteración del bucle.

Quizá penseis que esta solución recarga mucho el servidor (tanto el web como el de mysql), pero el impacto es mínimo y si teneis un hosting esto os ahorrará ancho de banda puesto que gasta más por usuario el estar haciendo peticiones al servidor web cada X tiempo que una sola petición que dure eternamente (solo gasta lo que envia, como una petición normal); en cuanto al servidor mysql si este esta en localhost (como el 99% de los hosting) el impacto es mínimo porque no consume ningún recurso de red, además de que el propio mysql es rapídisimo y eficiente haciendo las consultas y no mermará el rendimiento por estar haciendo una cada segundo por cada usuario. Sin embargo si no quereis usar mysql, podeis usar ficheros (fopen) o bién memoria compartida (Shmop). Por supuesto esto no es la panacea, pero para cosas pequeñas (20 personas a la vez) si puede ir bién tenerlo así montado.

En la web en la que colaboro tengo implementado este sistema, que aunque lo tengo bastante desarollado, todavía tengo que mejorar ciertos aspectos de funcionalidad.