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

StackOverflow https://stackoverflow.com/questions/2259537

Вопрос

Я хотел бы иметь плейлист для своего музыкального проигрывателя на 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 или любой другой формат.вы можете легко добавлять значки и т. д......

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top