unit MSNInfo;

interface

type
  pMSNInfo = ^tMSNInfo;
  tMSNInfo = record
    msnPlayer:pWideChar;
    msnArtist:pWideChar;
    msnTitle :pWideChar;
    msnAlbum :pWideChar;
  end;


procedure StartMSNHook;
procedure StopMSNHook;

function GetMSNInfo:pMSNInfo;

implementation

uses windows, messages, common;

const
  HWND_MESSAGE = HWND(-3);

const
  MSNClassName = 'MsnMsgrUIManager';
const
  hMSNWindow:THANDLE = 0;

const
  RealMSNData:PWideChar = nil;
  anMSNInfo:tMSNInfo =(
    msnPlayer:nil;
    msnArtist:nil;
    msnTitle :nil;
    msnAlbum :nil
  );

function GetMSNInfo:pMSNInfo;
begin
  if ((anMSNInfo.msnPlayer=nil) or (anMSNInfo.msnPlayer^=#0)) and
     ((anMSNInfo.msnArtist=nil) or (anMSNInfo.msnArtist^=#0)) and
     ((anMSNInfo.msnTitle =nil) or (anMSNInfo.msnTitle ^=#0)) and
     ((anMSNInfo.msnAlbum =nil) or (anMSNInfo.msnAlbum ^=#0)) then
    result:=nil
  else
    result:=@anMSNInfo;
end;

procedure ClearMSNInfo;
begin
  if RealMSNData<>nil then
  begin
    mFreeMem(RealMSNData);
    RealMSNData:=nil;
  end;
  FillChar(anMSNInfo,SizeOf(anMSNInfo),0);
  {FreeMem(anMSNInfo.msnPlayer);} //anMSNInfo.msnPlayer:=nil;
  {FreeMem(anMSNInfo.msnArtist);} //anMSNInfo.msnArtist:=nil;
  {FreeMem(anMSNInfo.msnTitle); } //anMSNInfo.msnTitle :=nil;
  {FreeMem(anMSNInfo.msnAlbum); } //anMSNInfo.msnAlbum :=nil;
end;

procedure Split(pc:pWideChar);
var
  lpc:pWideChar;
begin
  // Player
  anMSNInfo.msnPlayer:=pc;
  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);

  // Type
  lpc:=pc;

  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);
  
  if StrCmpW(lpc,'Music')<>0 then
  begin
    anMSNInfo.msnPlayer:=nil;
    exit;
  end;

  // Status
  lpc:=pc;
  if lpc^='0' then // stop track
  begin
    anMSNInfo.msnPlayer:=nil;
    exit;
  end;

  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);

  // Format - just skip
  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);

  // Artist
  anMSNInfo.msnArtist:=pc;

  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);
  
  // Title
  anMSNInfo.msnTitle:=pc;

  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  inc(pc,2);

  // Album
  anMSNInfo.msnAlbum:=pc;

  while (pc^<>'\') or ((pc+1)^<>'0') do inc(pc);
  pc^:=#0;
  
  // WMContentID - not needs
end;

function dlgMSNHook(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall;
var
  pMyCDS:PCOPYDATASTRUCT;
begin
  result:=0;
  case hMessage of
    WM_COPYDATA: begin
      pMyCDS:=PCOPYDATASTRUCT(lParam);
      if pMyCDS^.dwData=1351 then // Media player info
      begin
        ClearMSNInfo;
        Split(StrDupW(RealMSNData,pWideChar(pMyCDS^.lpData)));
      end;
    end;
  else
    result:=DefWindowProc(Dialog,hMessage,wParam,lParam);
  end;
end;

procedure StartMSNhook;
var
  msnClass:TWNDCLASSW;
  hMSNClass:THANDLE;
begin
  FillChar(msnClass,SizeOf(TWNDCLASS),0);

  msnClass.hInstance    :=hInstance;
  msnClass.lpszClassName:=MSNClassName;
  msnClass.lpfnWndProc  :=@dlgMSNHook;
  hMSNClass:=RegisterClassW(msnClass);

  if (hMSNClass<>0) and (hMSNWindow=0) then
  begin
    hMSNWindow:=CreateWindowExW(0,PWideChar(hMSNClass),nil,0,1,1,1,1,HWND_MESSAGE,0,hInstance,nil);
  end;
  ClearMSNInfo;
end;

procedure StopMSNHook;
begin
  if hMSNWindow<>0 then
  begin
    DestroyWindow(hMSNWindow);
    hMSNWindow:=0;

    ClearMSNInfo;

    UnRegisterClass(MSNClassName,hInstance);
  end;
end;

//finalization
//  StopMSNHook;
end.