unit uStatus;
// (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,
  ExtCtrls, StdCtrls, Buttons, Defs, Menus, ComCtrls;

type
  TFormStatus = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    BtnPlay: TBitBtn;
    BtnPause: TBitBtn;
    BtnStop: TBitBtn;
    BtnNext: TBitBtn;
    Timer1: TTimer;
    Panel6: TPanel;
    Label4: TLabel;
    PanelServerInfo: TPanel;
    LabelTracksIncluded: TLabel;
    LabelTracksExcluded: TLabel;
    Panel3: TPanel;
    Label1: TLabel;
    PanelCurrentAlbum: TPanel;
    LabelAlbumAuthor: TLabel;
    LabelAlbumName: TLabel;
    Panel4: TPanel;
    Label2: TLabel;
    PanelCurrentTrack: TPanel;
    LabelTrackAuthor: TLabel;
    LabelTrackName: TLabel;
    Panel5: TPanel;
    Label3: TLabel;
    PanelPosition: TPanel;
    LabelPosition: TLabel;
    LabelTrackLength: TLabel;
    BtnRepeat: TBitBtn;
    PopupMenuRate: TPopupMenu;
    RateCurrentSuperb1: TMenuItem;
    RateCurrentGood1: TMenuItem;
    RateCurrentNeutral1: TMenuItem;
    RateCurrentBad1: TMenuItem;
    RateCurrentAwful1: TMenuItem;
    N1: TMenuItem;
    ABORT1: TMenuItem;
    LabelRating: TLabel;
    Panel7: TPanel;
    Label5: TLabel;
    Panel8: TPanel;
    ListViewRatings: TListView;
    procedure LoadStatus();
    procedure ShowStatus(SetOnlyPosition:Boolean);
    procedure BtnPlayClick(Sender: TObject);
    procedure BtnPauseClick(Sender: TObject);
    procedure BtnStopClick(Sender: TObject);
    procedure BtnNextClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Panel1Resize(Sender: TObject);
    procedure BtnRepeatClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure RateCurrent1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure OnStatusChange;
    procedure OnReset;
  end;

var
  FormStatus: TFormStatus;

implementation
uses MServClients, MServCDatas;

const
  StatusRefreshPeriod = 60; // Sekunden

{$R *.DFM}

procedure TFormStatus.LoadStatus();
begin
  MServClient.ReadStatus;
end;

procedure TFormStatus.ShowStatus(SetOnlyPosition:Boolean);
var
  DifSecs    : Integer;
  Current    : record
                 AlbumID,
                 TrackID    : Integer;
                 AlbumIdx,
                 TrackIdx   : Integer;
               end;
  i          : Integer;
begin
  try
    Current.AlbumID:=MServClient.MServCData.Status.AlbumID;
    Current.TrackID:=MServClient.MServCData.Status.TrackID;
    Current.AlbumIdx:=-1;
    Current.TrackIdx:=-1;

    if not SetOnlyPosition then begin
      LabelTracksIncluded.Caption:=IntToStr(MServClient.MServCData.Status.NumberOfTracksIncluded);
      LabelTracksExcluded.Caption:=IntToStr(MServClient.MServCData.Status.NumberOfTracksExcluded);
    end;

    if Current.AlbumID<0 then begin
      if not SetOnlyPosition then begin
        LabelAlbumAuthor.Caption:='';
        LabelAlbumName.Caption:='';
        LabelTrackAuthor.Caption:='';
        LabelTrackName.Caption:='';
        LabelTrackLength.Caption:='';
        LabelRating.Caption:='';
        ListViewRatings.Items.Clear;
      end; // if not SetOnlyPosition then begin
      LabelPosition.Caption:='';
    end // if Current.AlbumID<0 then begin
    else begin
      Current.AlbumIdx:=MServClient.MServCData.GetAlbumIdx(Current.AlbumID);

      if High(MServClient.MServCData.Albums[Current.AlbumIdx].Tracks)<0 then begin
        MServClient.CacheTracks(Current.AlbumID);
      end;
      Current.TrackIdx:=MServClient.MServCData.Albums[Current.AlbumIdx].GetTrackIdx(Current.TrackID);

      DifSecs:=Trunc((Now-MServClient.MServCData.Status.FetchPosDT)* 24 * 3600);
  //    DifSecs:=Timer1.Tag;

      LabelPosition.Caption:=SecsToHourMinStr(
        MServClient.MServCData.Status.Position+
        DifSecs
      );

      if not SetOnlyPosition then begin
        LabelAlbumAuthor.Caption:=
          MServClient.MServCData.Albums[Current.AlbumIdx].AlbumAuthor;
        LabelAlbumName.Caption:=
          MServClient.MServCData.Albums[Current.AlbumIdx].AlbumName;

        LabelTrackAuthor.Caption:=
          MServClient.MServCData.Albums[Current.AlbumIdx].Tracks[Current.TrackIdx].TrackAuthor;
        LabelTrackName.Caption:=
          MServClient.MServCData.Albums[Current.AlbumIdx].Tracks[Current.TrackIdx].TrackName;

        LabelTrackLength.Caption:=SecsToHourMinStr(
          MServClient.MServCData.Albums[Current.AlbumIdx].Tracks[Current.TrackIdx].Length
        );

        LabelRating.Caption:=CMServRatingStr[MServClient.MServCData.Albums[Current.AlbumIdx].Tracks[Current.TrackIdx].Rating];


        ListViewRatings.Items.BeginUpdate;
        try
          ListViewRatings.Items.Clear;
          for i:=0 to High(MServClient.MServCData.Status.Ratings) do begin
            if MServClient.MServCData.Status.Ratings[i].Rating=msrUndefined then
              Continue;
            
            with ListViewRatings.Items.Add do begin
              Caption:=MServClient.MServCData.Status.Ratings[i].UserName;
                SubItems.Add(CMServRatingStr[MServClient.MServCData.Status.Ratings[i].Rating]);
            end; // with ListViewRatings.Items.Add do begin
          end; // for i:=0 to High(MServClient.MServCData.Status.Ratings) do begin
        finally
          ListViewRatings.Items.EndUpdate;
        end;
      end; // if not SetOnlyPosition then begin
    end;
  except
    on E:Exception do raise Exception.Create('TFormStatus.ShowStatus: '+E.Message);
  end;
end;

procedure TFormStatus.BtnPlayClick(Sender: TObject);
var
  ResI            : Integer;
  ResS            : String;
begin
  if not MServClient.Play(ResI,ResS) then begin
    MessageDlg('Unable to play! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    Exit;
  end;
end;

procedure TFormStatus.BtnPauseClick(Sender: TObject);
var
  ResI            : Integer;
  ResS            : String;
begin
  if not MServClient.Pause(ResI,ResS) then begin
    MessageDlg('Unable to pause! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;
end;

procedure TFormStatus.BtnStopClick(Sender: TObject);
var
  ResI            : Integer;
  ResS            : String;
begin
  if not MServClient.Stop(ResI,ResS) then begin
    MessageDlg('Unable to stop! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;
end;

procedure TFormStatus.BtnNextClick(Sender: TObject);
var
  ResI            : Integer;
  ResS            : String;
begin
{  if not MServClient.Next(ResI,ResS) then begin
    MessageDlg('Unable to go to next track! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;
}


  // Next erzeugt zuweilen Probleme mit der Soundkarte.
  // Wahrscheinlich, weil was mit dem enslaveten mpeg123 schiefgeht
  // daher stop, warten, start 

  if not MServClient.Stop(ResI, ResS) then begin
    MessageDlg('Unable to go to stop playing! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;

  Sleep(500);

  if not MServClient.Play(ResI, ResS) then begin
    MessageDlg('Unable to go to start playing! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;

end;

procedure TFormStatus.Timer1Timer(Sender: TObject);
begin
  Timer1.Tag:=Timer1.Tag+1;

  if Timer1.Tag>=24*3600 then Timer1.Tag:=0;
  if Timer1.Tag mod StatusRefreshPeriod =0 then begin
    LoadStatus;
  end;

  ShowStatus(True);
end;

procedure TFormStatus.OnStatusChange;
begin
  ShowStatus(False);
  Timer1.Enabled:=MServClient.MServCData.Status.Action=msaPlaying;
end;

procedure TFormStatus.OnReset;
begin
  LoadStatus;
  OnStatusChange;
end;

procedure TFormStatus.Panel1Resize(Sender: TObject);
var
  CurrLeftPos  : Integer;
  CurrTopPos   : Integer;
  CurrControl  : Integer;

const
  MinLeft = 8;
  MinTop  = 8;
begin
  CurrLeftPos:=MinLeft;
  CurrTopPos:=MinTop;

  for CurrControl:=0 to Panel1.ControlCount-1 do begin
    Panel1.Controls[CurrControl].Left:=CurrLeftPos;
    Panel1.Controls[CurrControl].Top:=CurrTopPos;
    if CurrControl<Panel1.ControlCount-1 then begin

      CurrLeftPos:=CurrLeftPos+Panel1.Controls[CurrControl].Width;

      if CurrLeftPos+Panel1.Controls[CurrControl+1].Width>=Panel1.ClientWidth then begin
        CurrLeftPos:=MinLeft;
        CurrTopPos:=Panel1.Controls[CurrControl].Top+Panel1.Controls[CurrControl].Height;
      end; // if CurrLeftPos+Panel1.Controls[CurrControl+1].Width>=Panel1.ClientWidth then begin

    end; // if CurrControl<Panel1.ControlCount-1 then begin
  end; // for CurrControl:=0 to Panel1.ControlCount-1 do begin

end;

procedure TFormStatus.BtnRepeatClick(Sender: TObject);
var
  ResI            : Integer;
  ResS            : String;
begin
  if not MServClient.Repeat_(ResI,ResS) then begin
    MessageDlg('Unable to repeat current track! Reason: ['+IntToStr(ResI)+'] '+ResS,mtError,[mbOK],0);
    LoadStatus;
    ShowStatus(False);
    Exit;
  end;
end;

procedure TFormStatus.FormDestroy(Sender: TObject);
begin
  Timer1.Enabled:=False;

  FormStatus:=nil;
end;

procedure TFormStatus.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);
//    LoadStatus;
//    ShowStatus;
    Exit;
  end;
end;


initialization
  FormStatus:=nil;
end.
