Delphi中音乐播放器的播放列表/多个数据项列表

时间:2010-02-13 23:30:06

标签: delphi string sorting pascal playlist

我想在Delphi / Pascal中为自己的音乐播放器添加播放列表。

我认为使用带有MP3文件路径的TStringList是最好的解决方案 - 另外 - 带有歌曲名称的TListBox。两个列表中的匹配字符串必须位于相同的位置。因此,如果用户在TListBox中选择第5项,我只需要获取TStringList中第5位的路径。

这很好用。

但现在我需要一个包含两列的播放列表:“艺术家”和“歌曲名称”。您应该能够按艺术家(升序和降序)以及歌曲标题(升序和降序)对播放列表进行排序 - 当然,按字母顺序排序。

我怎么能这样做?有两个TStringList对象 - 一个按艺术家排序,一个按歌曲标题排序?

4 个答案:

答案 0 :(得分:4)

我会做一个至少包含Artist和Title属性的TSong类,以及一个使用正确的排序字段提供一个或多个排序方法(可以是通用的)的TSongList(s。
当然不会维护你必须管理的2个单独的StringLists,在排序时保持同步和重新洗牌......

一种廉价的实现方法,可能是在内存中使用包含艺术家和路径的记录的DataSet显示在网格中,您可以在不同的列上排序。
当前行将直接提供两种信息。

答案 1 :(得分:2)

一个简单的解决方案是将您的歌曲列表/歌曲信息实现为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;

答案 2 :(得分:1)

随着时间的推移,我已经完成了一些这样的“列表”,最后我总是发现让这些类变得相当容易,但是至少可以说,存储并特别是从磁盘读取列表已经证明是“具有挑战性”。

在用户实际使用外部编辑器操作列表的情况下遇到了挑战,因此阅读列表容易出错。

对于普遍接受的播放列表格式(M3U),请查看http://schworak.com/programming/music/playlist_m3u.asp

Torry的名为“PlayList v.0.5.1”的VCL组件包含多种格式的源代码。 http://www.torry.net/quicksearchd.php?String=PlayList+v.0.5.1&Title=Yes

答案 3 :(得分:1)

如果您不想构建全局对象结构,则可以始终在报告模式下使用TlistView结构。 你有一个列表,子项目。 您可以按列排序,并保存为csv或任何格式。 你可以轻松添加图标等.....

并且您有正确的事件要触发。