unit uQueue;
// (C) by Marco Schulze <marco@nightlabs.com>
// [YMD] 2001-03-07
// published under GPL (GNU Public Licence)

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, ExtCtrls, ComCtrls, Menus;

type
  TFormQueue = class(TForm)
    Panel1: TPanel;
    ListViewTracks: TListView;
    PopupMenuRateTracks: TPopupMenu;
    RateSelectedSuperb1: TMenuItem;
    RateSelectedGood1: TMenuItem;
    RateSelectedNeutral1: TMenuItem;
    RateSelectedBad1: TMenuItem;
    RateSelectedAwful1: TMenuItem;
    N1: TMenuItem;
    RateCurrentSuperb1: TMenuItem;
    RateCurrentGood1: TMenuItem;
    RateCurrentNeutral1: TMenuItem;
    RateCurrentBad1: TMenuItem;
    RateCurrentAwful1: TMenuItem;
    N2: TMenuItem;
    ABORT1: TMenuItem;
    PopupQueue: TPopupMenu;
    Refresh1: TMenuItem;
    Unqueue1: TMenuItem;
    EnqueuetopX1: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    Gototrack1: TMenuItem;
    procedure Panel1Resize(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure BtnUnqueueClick(Sender: TObject);
    procedure BtnLoadQueueClick(Sender: TObject);
    procedure RateCurrent1Click(Sender: TObject);
    procedure RateSelected1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure BtnEnqueueTopClick(Sender: TObject);
   
    procedure Refresh1Click(Sender: TObject);
    procedure Unqueue1Click(Sender: TObject);
    procedure EnqueuetopX1Click(Sender: TObject);
    procedure Gototrack1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure LoadQueue;
    procedure ShowQueue;

    procedure OnQueueChange;
    procedure OnTrackChange(AlbumID,TrackID : Integer);
    procedure OnReset();

    procedure SaveSizesAndPositions();
    procedure RestoreSizesAndPositions();
  end;

var
  FormQueue: TFormQueue;

implementation

uses MServClients, MServCDatas, Defs, uEnqueueTopX, uAlbums;

const
  lvfTrackName    = 0;
  lvfQueuedBy     = 1;
  lvfRating       = 2;
  lvfLength       = 3;
  lvfAlbumID      = 4;
  lvfTrackID      = 5;
  lvfLengthInSecs = 6;

{$R *.DFM}

procedure TFormQueue.LoadQueue;
begin
  MServClient.CacheQueue;
end;

procedure TFormQueue.ShowQueue;
var
  AlbumIdx, TrackIdx : Integer;
  i                  : Integer;
  Tk                 : TTrack;
begin
  if High(MServClient.MServCData.QueueTracks)<0 then begin
    LoadQueue;
  end;

  ListViewTracks.Items.BeginUpdate;
  try
    ListViewTracks.Items.Clear;

    for i:=0 to High(MServClient.MServCData.QueueTracks) do begin
      AlbumIdx:=MServClient.MServCData.GetAlbumIdx(MServClient.MServCData.QueueTracks[i].AlbumID);
      if AlbumIdx<0 then raise Exception.Create('no album cached with AlbumID='+IntToStr(MServClient.MServCData.QueueTracks[i].AlbumID));

      if High(MServClient.MServCData.Albums[AlbumIdx].Tracks)<0 then begin
        MServClient.CacheTracks(MServClient.MServCData.QueueTracks[i].AlbumID);
      end;

      TrackIdx:=MServClient.MServCData.Albums[AlbumIdx].GetTrackIdx(MServClient.MServCData.QueueTracks[i].TrackID);
      if TrackIdx<0 then raise Exception.Create('no track cached with TrackID='+IntToStr(MServClient.MServCData.QueueTracks[i].TrackID)+' in album #'+IntToStr(MServClient.MServCData.QueueTracks[i].AlbumID));

      Tk:=MServClient.MServCData.Albums[AlbumIdx].Tracks[TrackIdx];

      with ListViewTracks.Items.Add do begin
        Caption:=Tk.TrackAuthor;
        SubItems.Add(Tk.TrackName);
        SubItems.Add(MServClient.MServCData.QueueTracks[i].QueuedByUser);
        SubItems.Add(CMServRatingStr[Tk.Rating]);
        SubItems.Add(SecsToHourMinStr(Tk.Length));
        SubItems.Add(IntToStr(Tk.AlbumID));
        SubItems.Add(IntToStr(Tk.TrackID));
        SubItems.Add(IntToStr(Tk.Length));
      end;
    end; // for i:=0 to High(MServClient.MServCData.QueueTracks) do begin

  finally
    ListViewTracks.Items.EndUpdate;
  end;

end;

procedure TFormQueue.Panel1Resize(Sender: TObject);
begin
  ListViewTracks.Width:=(Sender as TPanel).ClientWidth-16;
  ListViewTracks.Height:=(Sender as TPanel).ClientHeight-8; // -Label1.Height;
end;

procedure TFormQueue.OnQueueChange;
var
  n, i             : Integer;
  SelectedTracks   : Array of record
                       AlbumID,
                       TrackID   : Integer;
                     end;
begin
  SetLength(SelectedTracks,0);
  for i:=0 to ListViewTracks.Items.Count-1 do begin
    if ListViewTracks.Items[i].Selected then begin
      SetLength(SelectedTracks,High(SelectedTracks)+2);
      n:=High(SelectedTracks);
      SelectedTracks[n].AlbumID:=StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID]);
      SelectedTracks[n].TrackID:=StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID]);

    end; // if ListViewTracks.Items[i].Selected then begin
  end; // for i:=0 to ListViewTracks.Items.Count-1 do begin

  ShowQueue;

  for n:=0 to High(SelectedTracks) do begin
    for i:=0 to ListViewTracks.Items.Count-1 do begin
      if (SelectedTracks[n].AlbumID=StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID])) and
         (SelectedTracks[n].TrackID=StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID])) then begin

        ListViewTracks.Items[i].Selected:=True;
      end;
    end; // for i:=0 to ListViewTracks.Items.Count-1 do begin
  end; // for n:=0 to High(SelectedTracks) do begin
end;

procedure TFormQueue.OnTrackChange(AlbumID,TrackID : Integer);
var
  i                  : Integer;
  AlbumIdx, TrackIdx : Integer;
begin
  AlbumIdx:=MServClient.MServCData.GetAlbumIdx(AlbumID);
  if AlbumIdx<0 then raise Exception.Create('no album cached with AlbumID='+IntToStr(AlbumID));

  if High(MServClient.MServCData.Albums[AlbumIdx].Tracks)<0 then begin
    MServClient.CacheTracks(AlbumID);
  end;

  TrackIdx:=MServClient.MServCData.Albums[AlbumIdx].GetTrackIdx(TrackID);
  if TrackIdx<0 then raise Exception.Create('no track cached with TrackID='+IntToStr(TrackID)+' in album #'+IntToStr(AlbumID));

  for i:=0 to ListViewTracks.Items.Count-1 do begin
    if (StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID])=AlbumID) and
       (StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID])=TrackID) then begin
      ListViewTracks.Items[i].Caption:=
        MServClient.MServCData.Albums[AlbumIdx].Tracks[TrackIdx].TrackAuthor;

      ListViewTracks.Items[i].SubItems[lvfTrackName]:=
        MServClient.MServCData.Albums[AlbumIdx].Tracks[TrackIdx].TrackName;

      ListViewTracks.Items[i].SubItems[lvfRating]:=
        CMServRatingStr[MServClient.MServCData.Albums[AlbumIdx].Tracks[TrackIdx].Rating];
    end;
  end; // for i:=0 to ListViewTracks.Items.Count-1 do begin
end;

procedure TFormQueue.OnReset();
begin
  LoadQueue;
  ShowQueue;
end;

procedure TFormQueue.FormShow(Sender: TObject);
begin
  //Panel1.OnResize(Panel1);
  //Panel2.OnResize(Panel2);

  MServClient.OnQueueChange:=OnQueueChange;
end;

procedure TFormQueue.BtnUnqueueClick(Sender: TObject);
var
  i           : Integer;
begin
  if ListViewTracks.SelCount<1 then Exit;

  for i:=ListViewTracks.Items.Count-1 downto 0 do begin
	 if ListViewTracks.Items[i].Selected then begin
		MServClient.Unqueue(
		  StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID]),
		  StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID])
		);
	 end; // if ListViewTracks.Items[i].Selected then begin
  end; // for i:=0 to ListViewTracks.Items.Count-1 do begin
end;

procedure TFormQueue.BtnLoadQueueClick(Sender: TObject);
begin
  LoadQueue;
  ShowQueue;
end;

procedure TFormQueue.SaveSizesAndPositions();
procedure DoSaveListViewParams(LV:TListView;const SectionName,KeyPrefix:String);
var
  Key, Value  : String;
  i           : Integer;
begin
  for i:=0 to LV.Columns.Count-1 do begin
    Key:=KeyPrefix+'ColWidth'+IntToStr(i);
    Value:=IntToStr(LV.Columns[i].Width);
    IniFile.WriteString(SectionName,Key,Value);
  end; // for i:=0 to LV.Columns.Count-1 do begin
end;

begin
  DoSaveListViewParams(ListViewTracks,'PositionsSizes','FormQueue.ListViewTracks.');
end;

procedure TFormQueue.RestoreSizesAndPositions();
procedure DoRestoreListViewParams(LV:TListView;const SectionName,KeyPrefix:String);
var
  Key, Value  : String;
  i           : Integer;
begin
  for i:=0 to LV.Columns.Count-1 do begin
    Key:=KeyPrefix+'ColWidth'+IntToStr(i);
    Value:=IniFile.ReadString(SectionName,Key,IntToStr(LV.Columns[i].Width));
    LV.Columns[i].Width:=StrToInt(Value);
  end; // for i:=0 to LV.Columns.Count-1 do begin
end;

begin
  DoRestoreListViewParams(ListViewTracks,'PositionsSizes','FormQueue.ListViewTracks.');
end;

procedure TFormQueue.RateCurrent1Click(Sender: TObject);
var
  Rating     : TMServRating;
  ResI       : Integer;
  ResS       : String;
begin
  Rating:=TMServRating((Sender as TMenuItem).Tag);
  if not MServClient.Rate(-1,-1,Rating,ResI,ResS) then begin
    MessageDlg('Unable to rate current track! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    Exit;
  end;
end;

procedure TFormQueue.RateSelected1Click(Sender: TObject);
var
  Rating                  : TMServRating;
  ResI                    : Integer;
  ResS                    : String;
  i                       : Integer;
  AlbumID, TrackID        : Integer;
begin
  Rating:=TMServRating((Sender as TMenuItem).Tag-10);

  for i:=0 to ListViewTracks.Items.Count-1 do begin
    if ListViewTracks.Items[i].Selected then begin
      AlbumID:=StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID]);
      TrackID:=StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID]);
      if not MServClient.Rate(AlbumID,TrackID,Rating,ResI,ResS) then begin
        MessageDlg('Unable to rate selected track (AlbumID='+IntToStr(AlbumID)+', TrackID='+IntToStr(TrackID)+')! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
        Exit;
      end;
    end; // if ListViewTracks.Items[i].Selected then begin
  end; // for i:=0 to ListViewTracks.Items.Count-1 do begin
end;

procedure TFormQueue.FormDestroy(Sender: TObject);
begin
  FormQueue:=nil;
end;

procedure TFormQueue.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key=VK_F5 then begin
		LoadQueue;
		ShowQueue;
  end;
end;

procedure TFormQueue.BtnEnqueueTopClick(Sender: TObject);
begin
  FormEnqueueTopX.Execute();
end;


procedure TFormQueue.Refresh1Click(Sender: TObject);
begin
	LoadQueue;
	ShowQueue;
end;

procedure TFormQueue.Unqueue1Click(Sender: TObject);
var
  i           : Integer;
begin
  if ListViewTracks.SelCount<1 then Exit;

  for i:=ListViewTracks.Items.Count-1 downto 0 do begin
	 if ListViewTracks.Items[i].Selected then begin
		MServClient.Unqueue(
		  StrToInt(ListViewTracks.Items[i].SubItems[lvfAlbumID]),
		  StrToInt(ListViewTracks.Items[i].SubItems[lvfTrackID])
		);
	 end; // if ListViewTracks.Items[i].Selected then begin
  end; // for i:=0 to ListViewTracks.Items.Count-1 do begin
end;

procedure TFormQueue.EnqueuetopX1Click(Sender: TObject);
begin
	FormEnqueueTopX.Execute();
end;

procedure TFormQueue.Gototrack1Click(Sender: TObject);
begin
	if (MServClient.MServCData.Status.AlbumID>=0) and
		(MServClient.MServCData.Status.TrackID>=0) then
		FormAlbums.FocusTrack(
		  MServClient.MServCData.Status.AlbumID,
		  MServClient.MServCData.Status.TrackID
		)
end;

initialization
  FormQueue:=nil;
end.
