unit srv_getinfo;

interface

uses m_api, wat_api;

function GetPlayerInfo(var dst:tSongInfo;flags:cardinal):integer;
{
  WAT_RES_OK
  WAT_RES_NEWPLAYER
  WAT_RES_NOTFOUND
}

function GetFileInfo(var dst:tSongInfo;flags:cardinal;timeout:cardinal):integer;
{
  WAT_RES_OK
  WAT_RES_NEWFILE
  WAT_RES_UNKNOWN
  WAT_RES_NOTFOUND
}

function GetChangingInfo(var dst:tSongInfo;flags:cardinal):integer;
{
  WAT_RES_OK
}

function GetInfo(var dst:tSongInfo;flags:cardinal):integer;
{
  WAT_RES_OK
  WAT_RES_NEWFILE
}
function GetFileFormatInfo(var dst:tSongInfo):integer;
{
  WAT_RES_OK
  WAT_RES_NOTFOUND
}


implementation

uses
  windows,
  common, msninfo, syswin, wrapper, io, winampapi,
  srv_player, srv_format;

//----- get player info -----

function DefGetVersionText(ver:integer):pWideChar;
begin
  if ver<>0 then
  begin
    mGetMem(result,10*SizeOf(WideChar));
    IntToHex(result,ver);
  end
  else
    result:=nil;
end;

procedure MirMMToInt(var txt:PWideChar);
var
  tmp:PWideChar;
begin
  if txt<>nil then
  begin
    StrDupW(tmp,txt); mir_free(txt); txt:=tmp;
  end;
end;

procedure GetInfoInt(pl:pPlayerCell;var dst:tSongInfo;flags:cardinal);
begin
  tInfoProc(pl^.GetInfo)(dst,flags);
  if (pl^.flags and (WAT_OPT_INTERNAL or WAT_OPT_TEMPLATE))=0 then
  begin
    if (flags and WAT_OPT_PLAYERDATA)<>0 then
    begin
    // player name and homepage url we got from registration
      MirMMToInt(dst.txtver);
    end
    else if (flags and WAT_OPT_CHANGES)<>0 then
    begin
      MirMMToInt(dst.wndtext);
    end
    else
    begin
      MirMMToInt(dst.artist);
      MirMMToInt(dst.title);
      MirMMToInt(dst.album);
      MirMMToInt(dst.genre);
      MirMMToInt(dst.comment);
      MirMMToInt(dst.year);
      MirMMToInt(dst.lyric);
      MirMMToInt(dst.cover);
    end;
  end;
end;

function GetPlayerInfo(var dst:tSongInfo;flags:cardinal):integer;
var
  plwnd:HWND;
  pl:pPlayerCell;
  PlayerChanged:bool;
begin
  plwnd:=CheckAllPlayers(flags,dst.status,PlayerChanged);

  if plwnd<>HWND(WAT_RES_NOTFOUND) then
  begin
    if PlayerChanged then
    begin
      ClearPlayerInfo(dst);

      pl:=GetActivePlayer;
      AnsiToWide(pl^.Desc,dst.player);
      dst.plwnd:=plwnd;
      FastAnsiToWide(pl^.URL,dst.url);
      if pl^.icon<>0 then
        dst.icon:=CopyIcon(pl^.icon);

      if pl^.GetInfo<>nil then
        GetInfoInt(pl,dst,flags or WAT_OPT_PLAYERDATA)
      else if (pl^.flags and WAT_OPT_WINAMPAPI)<>0 then
        WinampGetInfo(wparam(@dst),flags or WAT_OPT_PLAYERDATA);
      
     if (pl^.flags and WAT_OPT_PLAYERINFO)=0 then
       if dst.txtver=NIL then dst.txtver:=DefGetVersionText(dst.plyver);

      result:=WAT_RES_NEWPLAYER;
    end
    else
    begin
      dst.plwnd:=plwnd; // to prevent same player, another instance
      result:=WAT_RES_OK;
    end
  end
  else
    result:=WAT_RES_NOTFOUND;
end;

//----- get file info -----

function GetFileInfo(var dst:tSongInfo;flags:cardinal;timeout:cardinal):integer;
var
  ftime:int64;
  f:THANDLE;
  fname:pWideChar;
  pl:pPlayerCell;
  remote,FileChanged:boolean;
  tmp:integer;
begin
  pl:=GetActivePlayer;

  if pl^.GetName<>nil then
  begin
    fname:=tNameProc(pl^.GetName)(dst.plwnd,flags);

    if (pl^.flags and (WAT_OPT_INTERNAL or WAT_OPT_TEMPLATE))=0 then
    begin
      MirMMToInt(fname);
    end;
  end
  else
    fname:=nil;

  if (fname=nil) and (dst.plwnd<>0) then
  begin
   tmp:=0;
   if (flags and WAT_OPT_KEEPOLD)<>0 then tmp:=tmp or gffdOld;
   fname:=GetFileFromWnd(dst.plwnd,KnownFileType,tmp,timeout);
  end;

  if fname<>nil then
  begin
    remote:=StrPosW(fname,'://')<>nil;
    // file changing time (local/lan only)
    if not remote then
    begin
      f:=Reset(fname);

      if f<>THANDLE(INVALID_HANDLE_VALUE) then
      begin
        GetFileTime(f,nil,nil,@ftime);
        CloseHandle(f);
      end;
    end;
    // same file
    if (dst.mfile<>nil) and (lstrcmpiw(dst.mfile,fname)=0) then
    begin
      if (not remote) and ((flags and WAT_OPT_CHECKTIME)<>0) then
        FileChanged:=dst.date<>ftime
      else
        FileChanged:=false;
    end
    else  // new filename
    begin
      FileChanged:=true;
    end;

    // if not proper ext (we don't working with it)
    //!!!! check for remotes
    if (not remote) and (CheckExt(fname)=WAT_RES_NOTFOUND) then
    begin
      if (flags and WAT_OPT_UNKNOWNFMT)<>0 then
      begin
        ClearFileInfo(dst);

        dst.mfile:=fname;
        dst.date :=ftime;
        dst.fsize:=GetFSize(dst.mfile);

        result:=WAT_RES_UNKNOWN;
      end
      else
      begin
        mFreeMem(fname);
        result:=WAT_RES_NOTFOUND;
      end;
    end
    else if FileChanged {or isContainer(fname)} then
    begin
      ClearFileInfo(dst);

      dst.mfile:=fname; //!! must be when format recognized or remote
      dst.date :=ftime; //!!
      dst.fsize:=GetFSize(dst.mfile);
      result:=WAT_RES_NEWFILE;
    end
    else
    begin
      result:=WAT_RES_OK;
      mFreeMem(fname);
    end;
  end
  else
  begin
    result:=WAT_RES_NOTFOUND;
  end;
end;

//----- get changing info -----

function DefGetWndText(pl:pPlayerCell; wnd:HWND):pWideChar;
var
  p:pWideChar;
begin
  if wnd<>0 then
  begin
    result:=GetDlgText(wnd);
    if result<>nil then
    begin
      if (pl^.flags and WAT_OPT_TEMPLATE)<>0 then
      begin
        with pTmplCell(pl^.Check)^ do
        begin
          if p_prefix<>nil then
          begin
            p:=StrPosW(result,p_prefix);
            if p=result then
              StrCopyW(result,result+StrLenW(p_prefix));
          end;
          if p_postfix<>nil then
          begin
            p:=StrPosW(result,p_postfix);
            if p<>nil then
              p^:=#0;
          end;
        end;
      end;
    end;
  end
  else
    result:=nil;
end;

function GetChangingInfo(var dst:tSongInfo;flags:cardinal):integer;
var
  pl:pPlayerCell;
begin
  result:=WAT_RES_OK;

  ClearChangingInfo(dst);

  pl:=GetActivePlayer;

  if pl^.GetInfo<>nil then
    GetInfoInt(pl,dst,flags or WAT_OPT_CHANGES)
  else if (pl^.flags and WAT_OPT_WINAMPAPI)<>0 then
    WinampGetInfo(wparam(@dst),flags or WAT_OPT_CHANGES);

  if (pl^.flags and WAT_OPT_PLAYERINFO)=0 then
    if dst.wndtext=NIL then dst.wndtext:=DefGetWndText(pl,dst.plwnd);
end;

//----- get track info -----

function GetSeparator(str:pWideChar):dword;
begin
  result:=StrIndexW(str,' '#$2013' ');
  if result=0 then
    result:=StrIndexW(str,' - ');
  if result<>0 then
  begin
    result:=result-1 + (3 SHL 16);
    exit;
  end;
  result:=StrIndexW(str,#$2013);
  if result=0 then
    result:=StrIndexW(str,'-');
  if result>0 then
    result:=result-1 + (1 SHL 16);
end;

function DefGetTitle(wnd:HWND;fname,wndtxt:pWideChar):pWideChar;
var
  i:integer;
  tmp:pWideChar;
begin
  if fname<>nil then
    tmp:=DeleteKnownExt(ExtractW(fname,true))
  else
    tmp:=wndtxt;
  if tmp=nil then
  begin
    result:=nil;
    exit;
  end;
  StrDupW(result,tmp);
  i:=GetSeparator(result);
  if i>0 then
    StrCopyW(result,result+LoWord(i)+HiWord(i));
  if fname<>nil then
    mFreeMem(tmp);
end;

function DefGetArtist(wnd:HWND;fname,wndtxt:pWideChar):pWideChar;
var
  i:integer;
  tmp:pWideChar;
begin
  if fname<>nil then
    tmp:=DeleteKnownExt(ExtractW(fname,true))
  else
    tmp:=wndtxt;
  if tmp=nil then
  begin
    result:=nil;
    exit;
  end;
  StrDupW(result,tmp);
  i:=GetSeparator(result);
  if i>0 then
    result[LoWord(i)]:=#0;
  if fname<>nil then
    mFreeMem(tmp);
end;

function GetFileFormatInfo(var dst:tSongInfo):integer;
var
  fmt:pMusicFormat;
begin
  result:=CheckExt(dst.mfile);
  if result=WAT_RES_OK then
  begin
    fmt:=GetActiveFormat;
    fmt^.proc(dst);
  end;
end;

function GetInfo(var dst:tSongInfo;flags:cardinal):integer;
var
  oldartist,oldtitle:pWideChar;
  fname:pWideChar;
  pl:pPlayerCell;
  lmsnInfo:pMSNInfo;
  remote:boolean;
begin
  result:=WAT_RES_OK;

  remote:=StrPosW(dst.mfile,'://')<>nil;

//  if remote or ((plyLink^[0].flags and WAT_OPT_PLAYERINFO)<>0) then
  StrDupW(oldartist,dst.artist);
  StrDupW(oldtitle,dst.title);

  ClearTrackInfo(dst);

  // info from player
  pl:=GetActivePlayer;
  if pl^.GetInfo<>nil then
    GetInfoInt(pl,dst,flags and not WAT_OPT_CHANGES)
  else if (pl^.flags and WAT_OPT_WINAMPAPI)<>0 then
    WinampGetInfo(wparam(@dst),flags and not WAT_OPT_CHANGES);

  // info from file
  GetFileFormatInfo(dst);

  if (pl^.flags and WAT_OPT_PLAYERINFO)=0 then
    with dst do
    begin
      if remote then
        fname:=nil
      else
        fname:=mfile;

      lmsnInfo:=GetMSNInfo;

      if lmsnInfo<>nil then
      begin
        if artist=NIL then StrDupW(artist,lmsnInfo.msnArtist);
        if title =NIL then StrDupW(title ,lmsnInfo.msnTitle);
        if album =NIL then StrDupW(album ,lmsnInfo.msnAlbum);
      end;

      if artist=NIL then artist:=DefGetArtist(plwnd,fname,wndtext);
      if title =NIL then title :=DefGetTitle (plwnd,fname,wndtext);
    end;

  if remote or ((pl^.flags and WAT_OPT_PLAYERINFO)<>0) or
     isContainer(dst.mfile) then
  begin
    if (oldartist=oldtitle) or
       ((oldartist<>nil) and (StrCmpW(dst.artist,oldartist)<>0)) or
       ((oldtitle <>nil) and (StrCmpW(dst.title ,oldtitle )<>0)) then
    begin
      result:=WAT_RES_NEWFILE;
    end;
  end;

  mFreeMem(oldartist);
  mFreeMem(oldtitle);
end;

end.