Список воспроизведения для музыкального проигрывателя в Delphi / Список нескольких элементов данных - PullRequest
1 голос
/ 14 февраля 2010

Я хотел бы иметь список воспроизведения для своего музыкального проигрывателя в Delphi / Pascal.

Я подумал, что было бы лучшим решением иметь TStringList с путем к файлу MP3 и - дополнительно - TListBox с названиями песен. Соответствующие строки в обоих списках должны находиться в одной и той же позиции. Поэтому, если пользователь выбирает элемент 5 в TListBox, я могу просто взять путь в позиции 5 в TStringList.

Это отлично работает.

Но теперь мне нужен плейлист с двумя столбцами: «Artist» и «Название песни». Вы должны иметь возможность сортировать плейлист по исполнителю (по возрастанию и по убыванию), а также по названию песни (по возрастанию и по убыванию) - конечно, в алфавитном порядке.

Как я мог это сделать? Имеет два объекта TStringList - один отсортирован по исполнителю, а другой по названию песни?

Ответы [ 4 ]

4 голосов
/ 14 февраля 2010

Я бы сделал класс TSong, содержащий как минимум свойства Artist и Title, и TSongList, обеспечивающий 1 или более методов сортировки (может быть универсальным), используя правильное поле сортировки (s.
). Конечно, не поддерживаются 2 отдельных списка StringList, которыми вы должны управлять, синхронизировать и переставлять при сортировке ...

Один дешевый способ реализовать это может заключаться в том, чтобы иметь в памяти DataSet с записью, содержащей Artist и Path, отображаемой в сетке, которую можно сортировать по разным столбцам.
В текущем ряду обе данные будут предоставлены напрямую.

2 голосов
/ 14 февраля 2010

Одним простым решением было бы реализовать ваш список песен / информацию о песне в виде 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;
1 голос
/ 14 февраля 2010

Если вы не хотите создавать глобальную структуру объектов, вы всегда можете использовать структуру TlistView в режиме отчета. У вас есть список с подпунктами. Вы можете отсортировать по столбцу и сохранить в CSV или любой другой формат. Вы можете легко добавлять иконки и т.д .....

и у вас есть правильные события для запуска.

1 голос
/ 14 февраля 2010

Я сделал несколько таких «списков» с течением времени, и в конце концов я всегда находил, что делать классы довольно легко, но хранение и особенно чтение списков с диска оказалось «по меньшей мере сложным».

Проблема заключалась в том, что пользователи фактически манипулировали списками с помощью внешних редакторов, что делало чтение списков ошибочным.

Для общепринятого формата списка воспроизведения (M3U) посмотрите http://schworak.com/programming/music/playlist_m3u.asp.

Компонент VCL с источником, который читает несколько форматов, доступен в Torry под названием «PlayList v.0.5.1». http://www.torry.net/quicksearchd.php?String=PlayList+v.0.5.1&Title=Yes

...