¿Y cómo imaginas que tal unidad o dll (en caso de que exista) va a manejar las distintas versiones?
De una u otra forma tendrá que tener código para cada una; así que tu pregunta más bien sería:
¿Existe una unidad o dll que maneje listas de Winamp para no tener yo que programarla?
Es una pregunta válida.
Pero si quieres programarla tú mismo tendrás que manejar la distintas versiones
de una u otra forma.
Esto no lo puedes evitar. Pero sí puedes diseñarla de manera que no tengas que alterar el código
que ´haga uso de tal unidad.
Para empezar fíjate que la lista como tal la puedes mantener en memoria sin depender del formato en particular. Digamos que cada entrada de la lista la guardas en una clase:
Código Delphi
[-]
type
TWinampItem = class
public
property Duration: Double;
property Artist: String;
property Theme: String;
end;
Puedes entonces usar un TObjectList (unidad Contnrs) para almacenar objetos de esta clase.
Entonces lo único que debe preocuparte es cómo leer una lista desde un archivo y como guardarla en un archivo:
Código Delphi
[-]
type
TWinampList = class(TObjectList)
public
procedure LoadFromFile(FileName: String); virtual;
procedure SaveToFile(FileName: String); virtual;
end;
El declarar los métodos como virtuales te permite diseñar un descendiente de esta clase por cada nueva versión:
Código Delphi
[-]
type
TWinampList27 = class(TWinampList)
procedure LoadFromFile(FileName: String); override;
procedure SaveToFile(FileName: String); override;
end;
TWinampList31 = class(TWinampList)
procedure LoadFromFile(FileName: String); override;
procedure SaveToFile(FileName: String); override;
end;
TWinampList56 = class(TWinampList)
procedure LoadFromFile(FileName: String); override;
procedure SaveToFile(FileName: String); override;
end;
Cada descendiente se ocupa del formato en particular para implementar los métodos virtuales. Tu aplicación (o aplicaciones) que requieran usar listas de Winamp lo único que requieren es que se les provea de un objeto TWinampList
sin tener que saber exactamente de qué descendiente en particular se trata.
Veamos un ejemplo. Suponte que tu aplicación tiene un botón para cargar una lista de ejecución. Con este botón el usuario escoge un archivo del disco y tu aplicación carga la lista en un ListBox:
Código Delphi
[-]
procedure LoadButtonClick(Sender: TObject);
var
I: Integer;
begin
if OpenDialog.Execute then
begin
WinampList.LoadFromFile(OpenDialog.FileName);
for I := 0 to WinampList.Count - 1 do
ListBox.Items.Add(TWinampItem(WinampList[i]).Theme);
end;
end;
donde WinampList es un objeto de tipo TWinampList (la clase base).
Lo importante aquí es que idependientemente de qué descendiente de TWinampList uses para construir el obejto WinampList, el código de tu botón no cambia, asó como no cambiará cualquier código que deba utilizar WinampList.
Lo que hay que ver entonces es cómo escoges cual descendiente usar:
Código Delphi
[-]
WinampList := TWinampList27.Create;
WinampList := TWinampList31.Create;
WinampList := TWinampList56.Create;
sin tener que alterar el código que ya tienes. Lo más simple sería cambiar por la línea adecuada con cada nueva versión y recompilar pero a fin de cuentas no esperarás que todos los usuarios trabajen con la misma versión: quizá quieran leer una lista de un formato distinto al que tienes preparado.
Una opción elegante es usar un
fábrica. En la unidad donde declares la clase base, pones una variable global que mantenga una asociación entre la versión y la clase a usar:
Código Delphi
[-]
unit WinampList;
interface
uses
Classes, Contnrs;
type
TWinampList = class(TObjectList)
public
procedure LoadFromFile(FileName: String); virtual; abstract;
procedure SaveToFile(FileName: String); virtual; abstract;
end;
TWinampListClass = class of TWinampList;
var
Factory: TStringList;
implementation
initialization
Factory := TStringList.Create;
end.
Factory mantendría la asociación:
'ver27' --> TWinampList27
'ver31' --> TWinampList31
'ver56' --> TWinampList56
etc.
Cada nueva versión la implementas en una unidad distinta y ahí añades la correspondiente asociación:
Código Delphi
[-]
unit WinampList27;
interface
uses
WinampList;
type
TWinampList27 = class(TWinampList)
procedure LoadFromFile(FileName: String); override;
procedure SaveToFile(FileName: String); override;
end;
implementation
initialization
Factory.AddObject('ver27', TObject(TWinampList27));
end.
Con esto, lo único que necesitas para construir WinampList adecuadamente es una cadena con el número de versión:
Código Delphi
[-]
var
Version: String;
...
var
WinampList: TWinampList;
WinampListClass: TWinampListClass;
begin
WinampListClass := TWinampListClass(Factory.Objects[Version]);
WinampList := WinampListClass.Create;
end;
Al requerir sólo el número de versión para construir la clase adecuada logras no tener que incluir la unidad correspondiente en el código de tu aplicación, únicamente tienes que incluir la unidad de la clase base: WinampList. Así tal código no necesita ni siquiera ser recompilado con cada versión nueva que aparezca.
Incluso puedes permitir que el usuario escriba el mismo de qué versión es la lista que va a leer y todo el formulario donde haga esto no cambia en lo absoluto con la aparición de nuevas versiones.
Tomando en cuenta que el código del botón para leer una lista desde el disco es seguramente tan sólo un ejemplo, en balance, aun cuando debes preocuparte por implementar LoadFromFile y SaveToFile para cada versión, ganas bastante al dejar intacto todo el código alrededor.
// Saludos