Список воспроизведения для музыкального проигрывателя в Delphi/Список нескольких элементов данных
Вопрос
Я хотел бы иметь плейлист для своего музыкального проигрывателя на Delphi/Pascal.
Я подумал, что лучшим решением будет иметь TStringList с путем к файлу MP3 и, дополнительно, TListBox с названиями песен.Соответствующие строки в обоих списках должны находиться в одной и той же позиции.Итак, если пользователь выберет элемент 5 в TListBox, я могу просто выбрать путь в позиции 5 в TStringList.
Это работает нормально.
Но теперь мне нужен плейлист с двумя столбцами:«исполнитель» и «название песни».У вас должна быть возможность сортировать список воспроизведения по исполнителям (по возрастанию и убыванию), а также по названию песни (по возрастанию и убыванию) — конечно, в алфавитном порядке.
Как я мог это сделать?У вас есть два объекта TStringList — один отсортирован по исполнителю, а другой — по названию песни?
Решение
Со временем я составил несколько таких «списков», и в конце концов мне всегда казалось, что создавать классы довольно легко, но хранение и особенно чтение списков с диска оказалось, мягко говоря, «сложным».
Проблема заключалась в случаях, когда пользователи фактически манипулировали списками с помощью внешних редакторов, что делало чтение списков подверженным ошибкам.
Информацию о общепринятом формате плейлиста (M3U) см. http://schworak.com/programming/music/playlist_m3u.asp.
Компонент VCL с исходным кодом, который читает несколько форматов, доступен на сайте Torry's под названием «PlayList v.0.5.1». http://www.torry.net/quicksearchd.php?String=PlayList+v.0.5.1&Title=Да
Другие советы
Я бы создал класс TSong, содержащий как минимум свойства Artist и Title, а также TSongList, предоставляющий 1 или несколько методов сортировки (может быть универсальными), используя соответствующие поля сортировки.
Конечно, не нужно поддерживать два отдельных списка строк, которыми вам нужно управлять, синхронизировать и перетасовывать при сортировке...
Одним из дешевых способов реализовать это может быть размещение в памяти DataSet с записью, содержащей Artist и Path, отображаемой в сетке, которую вы можете сортировать по разным столбцам.
Текущая строка предоставит обе информации напрямую.
Одним из простых решений было бы реализовать список песен/информацию о песнях в виде TCollection.
Используя коллекции, вы можете позволить VCL обрабатывать загрузку и сохранение на диск.
Например:
Обратите внимание, что это не функционально полно, я оставлю это на ваше усмотрение, и поскольку я написал это с самого начала, возможно, я что-то напутал.Это всего лишь пример, с которого можно начать.
{...}
interface
Type
TSongCollectionItem = class(TCollectionItem)
public
constructor create(Owner:TCollection); override;
procedure assign(source : TPersistent); override;
published
property FileName : String read fFileName Write fFileName;
property Artist : string read fArtist write fArtist;
property Title : string read fTitle write fTitle;
{...}
property Album : string read fAlbum write fAlbum;
end;
TSongCollection = class(TOwnedCollection)
private
function GetItem(Index: Integer): TSongCollectionItem;
procedure SetItem(Index: Integer; Value: TSongCollectionItem);
public
constructor Create(AOwner: TPersistent);
function Add: TSongCollectionItem;
property Songs[Index: Integer]: TSongCollectionItem read GetItem write SetItem; default;
end;
procedure SaveSongList(Songs : TSongCollection; FileName:string; Binary:boolean);
procedure LoadSongList(Songs : TSongCollection; FileName:string; Binary:boolean);
{...}
implementation
{...}
type
TSongComponent = class(TComponent)
published
property SongList : TSongCollection read fsonglist write SetSongList;
end;
procedure SaveSongList(Songs : TSongCollection; FileName:string; Binary:boolean);
var
wFile : TFileStream;
wConvert : TMemoryStream;
wSongList : TSongComponent;
begin
RegisterClass(TSongComponent);
Try
wConvert := TMemoryStream.Create;
wFile := TFileStream.Create(filename, fmcreate);
wSongList := TSongComponent.create(nil);
try
wSongList.SongList.Assign(Songs);
if not Binary then
begin
wConvert.WriteComponent(wSongList);
wConvert.Position := 0;
ObjectBinaryToText(wConvert, wFile);
end
else
wFile.WriteComponent(wSongList);
finally
wConvert.Free;
wFile.Free;
wSongList.free;
end;
finally
Unregisterclass(TSongComponent);
end;
end;
procedure LoadSongList(Songs : TSongCollection; FileName:string; Binary:boolean);
var
wFile : TFileStream;
wConvert : TMemoryStream;
wSongList : TSongComponent;
begin
RegisterClass(TSongComponent);
Try
wConvert := TMemoryStream.Create;
wFile := TFileStream.Create(filename, fmOpenRead);
try
if not Binary then
begin
ObjectTextToBinary(wFile, wConvert);
wConvert.Position := 0;
wSongList := TSongComponent(wConvert.ReadComponent(Nil));
end
else
wSongList := TSongComponent(wFile.ReadComponent(Nil));
if assigned(Songs) and assigned(wSongList) then
Songs.Assign(wSongList.Songs);
if assigned(wSongList) then
wSongList.free;
finally
wConvert.Free;
wFile.Free;
end;
finally
Unregisterclass(TSongComponent);
end;
end;
Если вы не хотите создавать глобальную структуру объекта, вы всегда можете использовать структуру TlistView в режиме отчета.У вас есть список с подпунктами.Вы можете сортировать по столбцам и сохранять в CSV или любой другой формат.вы можете легко добавлять значки и т. д......
и у вас есть правильные события для запуска.