Introducción

Objetivos

Estructuración

Problemas encontrados

Posibles mejoras

Conclusiones

Documentación y bibliografía

 

 

Introducción

 

Gestmusic es una aplicación de gestión para colecciones discográficas. Su funcionalidad, que va más allá del mero almacenamiento virtual de discos, nos permite la consulta de los elementos almacenados así como de toda la información correspondiente a cada uno, de una manera práctica y sencilla para el usuario.

En este documento web se detalla el proceso de elaboración de este programa.

 

 

Objetivos

 

El objetivo inicial de este proyecto era realizar un programa de gestión de una discoteca particular.

Uno de los problemas fundamentales de todo melómano es que su colección particular alcanza tales dimensiones a lo largo de los años, que en muchos casos es complicado saber que discos exactamente componen la discoteca. No es extraño encontrar discos repetidos dentro de grandes colecciones. Por lo tanto, uno de los objetivos principales, era crear una interfaz de fácil manejo que permitiese en unos pocos segundos, visualizar un listado de todos los discos de la colección. Además, el programa debería ser capaz de presentar por pantalla listados conformes a una serie de parámetros básicos, tales como nombre de artista o año de publicación. 

Otro objetivo a cumplir por el programa, era que junto con el título cada disco, se guardasen una serie de datos de interés para el usuario. Estos datos en un principio serian al menos: nombre del artista, fecha de publicación, formato del álbum y género musical.

La discoteca de un melómano suele ser una colección en continuo cambio (adquisiciones semanales, intercambios, pérdidas de discos, ventas...) por lo tanto, el programa debería ofrecer una forma rápida y sencilla de introducir, editar y borrar discos de la colección. Es posible que el usuario no sepa toda la información correspondiente a un disco, o que directamente no le apetezca introducirla desde un principio, esto sería un factor a tener en cuenta durante la implementación de esta la parte del programa que interaccionase con el usuario.

A pesar de que el objetivo inicial es la posibilidad de gestionar una discoteca particular, si el programa resultante funcionase como se espera, también podría ser útil para pequeñas tiendas de discos, o para consultar bases de datos en internet por ejemplo.

 

 

Estructuración

 

GestMusicMain:

Esta es la capa principal y a su vez la más superficial del programa, la que tiene mayor interacción directa con el usuario. Esta compuesta por un único archivo .cpp que incluye el main. La interfaz está realizada con ncurses.

Aquí se carga el fichero discos.dat que guarda toda la información de la discoteca. También se declara la ventana con la que vamos a trabajar con ncurses. El main está básicamente compuesto por un menú. Las distintas opciones de este llaman a distintas funciones del módulo "funciones". Se ha intentado que este archivo contenga el menor número de líneas de código posible.

 

 

Funciones:

El módulo "funciones" está compuesto por dos archivos. Uno .h donde están declaradas las distintas funciones y otro .cpp donde están definidas. Estas son las funciones incluidas:

 

void PintarOpciones();
void ShutDown();
void MovernosIzda(int &x, int &y);
void MovernosDcha(int &x, int &y);
void MovernosConTab(int &x, int &y);
void Insert(CDiscoteca &disx);
void Supr(CDiscoteca &disx);
void CompruebaGenero(TDisco &dd);
void CompruebaPuntuacion(TDisco &dd);

 

Todas estas funciones son llamadas exclusivamente desde el principal. Aquí están las funciones que presentan por pantalla la interfaz principal y nos permiten movernos por ella utilizando el teclado. También están incluidas las funciones que llaman a las funciones de la clase discoteca que se encargan de la gestión de la discoteca propiamente dicha (inserción, edición y borrado) según las instrucciones del usuario.

 

Con motivo de hacer la interfaz principal lo más minimalista posible, la opción de editado no aparece directamente, sino que se accede a ella a través de la opción de inserción. Cuando se intenta introducir un disco ya perteneciente a la colección, el programa nos pregunta si queremos editar su información. Cuando editamos, si queremos dejar algún campo con su valor anterior sin modificar no tenemos más que pulsar intro cuando se nos pida en el menú de edición para pasar al siguiente campo.

Como se ha mencionado anteriormente, el usuario no tiene por que introducir de golpe toda la información correspondiente a un disco. Puede que no conozca toda la información, o que no le haga falta, o que prefiera introducirla en otro momento. Por esto, cuando accedemos a la opción de inserción, el programa inmediatamente nos pregunta si deseamos introducir tan solo el título del álbum o toda su información. Si elegimos la primera opción, el resto de los parámetros se le asignan por defecto. Estos parámetros por defecto serán cadenas vacía para todos los parámetros que sean de caracteres (artista, formato y tracklist), un 0 para el año y la puntuación, y el código de género 12 que se corresponde con el género "Other".

Durante la inserción de un disco con toda su información se nos preguntará por el género del disco. La identificación del género se hace a través de un código. Estos códigos son los definidos por las etiquetas ID3 que incluyen todos los archivos mp3. Como lo más probable es que el usuario no conozca el código correspondiente a cada género, se le da la opción de visualizar todo el listado de códigos antes de introducir el género. Como estamos trabajando con ncurses, el tamaño de la ventana es invariable, de modo que si tratásemos de presentar todo el listado de golpe en la pantalla, este se saldría de la ventana. Por esto, he hecho que aparezcan los discos de diez en diez, y que podamos scrollar con las flechas arriba y abajo del teclado para así movernos por toda la lista.

Las funciones CompruebaGenero y CompruebaPuntuacion se encargan de comprobar que el género introducido es uno de los 129 definidos y que la puntuación introducida es un valor entero entre 0 y 10.

 

 

Herramientas:

Este módulo está compuesto por los archivos herramientas.cpp y herramientas.h. El fin de este módulo es alojar todas aquellas funciones que se necesiten en varios varios puntos del programa pero que no estén claramente relacionadas con ninguna de las clases, sino que sean más genéricas. Por ahora la única función que hay incluida es ComparaCadenas, pero en un futuro se podrían añadir cuantas funciones fuesen necesarias para la mejora del programa.

 

 

CDiscoteca:

La clase discoteca esta compuesta por los archivos CDiscoteca.h y CDiscoteca.cpp. Los métodos de la parte pública de la clase son los siguientes:

 

CDiscoteca();
~CDiscoteca();
bool ListaDiscosVacia();
void InsertarDisco(TDisco d);
void EliminarDisco(int posi);
void EditarDisco(TDisco d, int posi);
TDisco BuscarDisco(int posi);
void CargarDiscosLista(const char *NOMBREFICHERO);
void GuardarDiscosLista(const char *NOMBREFICHERO);
int NumDiscos();
void VerListadoGeneros();
void ImprimirGeneros(int g);

 

Casi todas estas funciones son llamadas desde el principal y llaman a la clase lista no acotada. InsertarDisco recibe desde el principal un objeto disco con todos sus parámetros y lo único que tiene que hacer es llamar a la función insertar de la clase lista pasándole como elemento a insertar el objeto tipo disco recibido. Como la lista es no ordenada, se calcula la longitud de esta con la función NumDiscos() y se inserta en la posición NumDiscos()+1. EditarDisco funciona de manera idéntica solo que ahora hay que indicarle la posición del elemento que queremos editar. Esta posición se calcula en funciones.cpp mediante un bucle que va recorriendo la lista hasta que encuentra un disco con el mismo titulo que el que buscamos. Lo mismo para EliminarDisco.

 

 

CPintarLista:

Esta clase esta formada por los archivos CPintarLista.cpp y CPintarLista.h. Consta de una función en su parte publica y otra en su parte privada. En la parte pública está PintarLista, que recibe como parámetros los campos álbum, artista y fecha que el usuario tiene la opción de introducir desde la interfaz principal. Estos campos están inicialmente vacíos (álbum y artista son cadenas vacías y la fecha es 0). En este caso en el que los tres campos están vacíos, se muestra por pantalla el listado completo de discos. Cuando el usuario rellena uno o varios de esos tres campos, la función PintarLista, comprueba cuales de los discos de la colección se corresponden con los parámetros introducidos y los presenta por pantalla.

He dado por hecho que en la colección no va a haber más de un disco con el mismo título, por lo tanto, si el único campo de consulta que ha sido rellenado es el de álbum, la función PintarLista busca ese álbum en la discoteca y en vez de mostrarnos solo el título como en el resto de los casos, nos muestra directamente toda su información. 

La función de la parte privada es PintarGenero y se encarga simplemente de imprimir el género correspondiente a cada código.

 

CListaNoAc:

Se trata de una clase lista no acotada implementada con plantillas luego solo consta de un archivo .hpp. En este programa se maneja una única lista, controlada por esta clase, pero si decidiésemos ampliar el programa y para ello necesitásemos más listas recurriríamos directamente a esta clase.

 

 

 

Problemas encontrados

 

Mi principal problema en la elaboración de este proyecto ha sido probablemente el no saber ver con antelación como tendría que haber ido estructurado el programa desde un principio. Se podría decir que he ido programando de forma que el programa se adaptase a mis necesidades, en vez de adaptarme yo a las del programa. Esto me ha hecho perder innumerables horas, rehaciendo cosas que tras haberlas hecho previamente, me daba cuenta (o más bien el profesor me lo hacía ver) de que no eran la mejor solución. A continuación menciono algunos problemas concretos con los que he ido encontrando a lo largo del proceso:

En un principio tan solo usé ncurses para la interfaz principal. Esto hacia que las interacciones con el usuario no funcionasen correctamente, por lo que tuve que hacer con ncurses la totalidad del programa.

Dado que al estar trabajando con ncurses el tamaño del terminal es fijo, no se presentaban por  pantalla correctamente listados de mayor longitud que la altura del terminal. Para solucionar esto realicé la función que presenta tan solo parte de la lista y nos permite scrollar para movernos por ella.

En en un principio, todas las búsquedas de elementos en la lista, las hice con bucles que iban desde 0 hasta el tamaño de la lista-1. Esto colgaba el programa cada vez que se realizaba una búsqueda hasta que me di cuenta de que la primera posición de la lista es 1 y no 0.

En un principio realicé una clase llamada clase listado que hacia de puente entre las clases CDiscoteca y CListaNoAc, sin embargo, esta clase era totalmente innecesaria ya que sus funciones eran prácticamente las mismas que las de la clase CDiscoteca.

Un par de días de antes de la entrega final del proyecto, el archivo principal GestMusicMain había alcanzado un tamaño desmesurado. Se había llegado a convertir en una especia de cajón desastre donde se hacía de todo y donde no se usaban apenas funciones. Esto sobre todo hacía realmente difícil la comprensión del código al ver tantas cosas mezcladas, y además hacía casi imposible la tarea de modificar el programa en un futuro. Para solucionar este problema creé el archivo "funciones", de modo que el principal redujo considerablemente su tamaño. Ahora el principal ha quedado reducido prácticamente a un simple menú, y dentro de cada case de este menú se llaman a las distintas funciones del módulo con el mismo nombre.

Un problema que ha estado presente a lo largo de todo el proceso ha sido el incorrecto funcionamiento de la función NPesimo de la clase lista no acotada.

Otra cosa que no ha acabado de funcionar correctamente ha sido el destructor de la clase lista no acotada.

 

 

 

Posibles mejoras

 

Habría que hacer la función ComparaCadenas de forma que no solo comparase si dos cadenas son idénticas sino que diese por iguales cadenas que contienen la subcadena que buscamos dentro de la propia cadena en sí y que también diese por iguales cadenas sin tener en cuenta los signos de acentuación o cualquier tipo de carácter especial de cualquier idioma.

Actualmente el tracklist se pide como una sola cadena de caracteres suficientemente larga, sin embargo, debería hacerse de forma que el usuario tuviese pulsar el tabulador entre los títulos de las canciones, para que luego al imprimir el tracklist por pantalla se pudiese presentar una sola canción por línea.

Tal y como esta hecho el programa, el único caso en el que se nos muestra toda la información de un determinado disco es cuando rellenamos solamente el campo álbum. Sin embargo creo que sería buena idea hacerlo de forma que también nos presentase toda la información de un álbum cuando buscando según otros parámetros, el resultado de la búsqueda es un solo álbum. Además seria conveniente tener en cuenta que puede haber más de un álbum con el mismo nombre.

Creo que el programa ganaría en riqueza visual se en vez de imprimir la puntuación numérica de un álbum dibujase estrellitas. Como la puntuación es un entero de 0 a 10 lo idóneo sería que dibujase de 0 a 5 estrellitas pudiendo dejar las estrellitas a medio dibujar. De esta forma, una puntuación de 5 se correspondería con 2 estrellitas y media.

Sería interesante poder incluir las imágenes de las portadas de los discos, aunque esto no sé como se haría.

También sería conveniente mejorar algunas cosas de la estructura. En la clase CDiscoteca por ejemplo, la estructura tipo disco debería ir dentro y no fuera de la clase.

 

 

 

Conclusiones

 

Aunque el programa aún dista bastante de ser perfecto en muchos aspectos, en líneas generales estoy satisfecho con el resultado final, fruto de dos meses de duro trabajo. He cumplido la mayoría de los objetivos iniciales. Aunque aún habría que depurar algunos errores he conseguido un programa que funciona, y que se puede manejar de una forma sencilla por el usuario.

He conseguido superar algunos momentos de frustración a lo largo del proceso en los que me quedaba estancado y no sabía como seguir o como solucionar algunos errores. He conseguido aplicar la mayoría de las sugerencias del profesor. A pesar de que esto en alguna ocasión me ha hecho reescribir un porcentaje bastante alto de líneas del código, los resultados obtenidos tras las modificaciones han sido claramente mejores.

Además de todo esto, realizar el proyecto me ha servido para afianzar muchos de los conocimientos adquiridos en clase a lo largo de este cuatrimestre así como para aprender cosas nuevas como por ejemplo el manejo de ncurses.

Sin embargo soy consciente de que la estructura interna del programa puede y debe ser mejorada si no quiero que quede condenado al olvido en cualquier disco duro. Me gustaría poder usarlo para gestionar mi propia discoteca y así ver recompensadas tantas horas de trabajo.

Espero poder dedicarle pronto el tiempo que me ha faltado en estas últimas semanas de curso tan ajetreadas.

 

 

 

Documentación y bibliografía

 

Información general:

   Apuntes de la asignatura.

   Trabajos de años anteriores de la página del profesor Juan Falgueras: http://juanfc.lcc.uma.es/

   Códigos de la tabla ascii: http://www.lookuptables.com/

 

Información sobre ncurses:

   http://bulma.net/body.phtml?nIdNoticia=2004

   http://www.tldp.org/HOWTO/NCURSES-Programming-HOWTO/

   http://ditec.um.es/~piernas/manpages-es/otros/tutorial-ncurses.html

 

Información específica sobre etiquetas ID3 y archivos mp3:

   http://es.wikipedia.org/wiki/ID3   

   http://en.wikipedia.org/wiki/ID3

   http://www.linuxselfhelp.com/HOWTO/MP3-HOWTO-13.html#ss13.3

   http://www.id3.org/

 

Información sobre bases de datos de discos:

   http://www.gracenote.com/

   http://www.freedb.org/

   www.allmusic.com

 

  

 

Creative Commons License

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.5 Spain License.

© Carlos Sánchez García 2006.