unit wa_ipc;

{ This is the original wa_ipc.h file from the new Winamp v2.9x API.
  Saivert has translated/adapted it for use with the Borland Delphi
  development environment (which uses the Object Pascal language).
  All comments added by me are marked with "[Saivert]". }

{ Original wa_ipc.h converted to wa_ipc.pas (Pascal for use with
  Borland Delphi) by Saivert. I converted this after downloading the
  new Winamp 2.9x API. Smokin' hot new features like the ones you only got
  in Wasabi (support for extending the preferences dialog and access to
  video interface + many common dialogs like Open URL).

  All comments added by me are marked with "[Saivert]".
  I have also written a few wrapper functions for some of the API calls.
  This includes:
    * IPC_OPENURL - function WAOpenURLBox
    * IPC_GETEQDATA/IPC_SETEQDATA - function WASetEqData

  My homepage URL is:
    http://members.tripod.com/files_saivert/
  My e-mail address is (I got spam protection, so don't bother...):
    saivert@email.com

  Following is the original Nullsoft license: }

(*
** Copyright (C) 2003 Nullsoft, Inc.
**
** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
** liable for any damages arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
** alter it and redistribute it freely, subject to the following restrictions:
**
**   1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
**      If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
**
**   2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
**
**   3. This notice may not be removed or altered from any source distribution.
**
*)

interface

uses Windows, Messages;

const

(*
** This is the modern replacement for the classic 'frontend.h'. Most of these
** updates are designed for in-process use, i.e. from a plugin.
**
*)

{* message used to sent many messages to winamp's main window.
** most all of the IPC_* messages involve sending the message in the form of:
**   result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*);
*}
  WM_WA_IPC = WM_USER;
(* but some of them use WM_COPYDATA. be afraid.
*)

  IPC_GETVERSION = 0;
(* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION);
**
** Version will be 0x20yx for winamp 2.yx. versions previous to Winamp 2.0
** typically (but not always) use 0x1zyx for 1.zx versions. Weird, I know.
*)

  IPC_GETREGISTEREDVERSION = 770;


type
  PenqueueFileWithMetaStruct = ^TenqueueFileWithMetaStruct;
  TenqueueFileWithMetaStruct = record
    filename: PChar;
    title: PChar;
    length: Integer;
  end;
{ send this to a IPC_PLAYFILE in a non WM_COPYDATA,
  and you get the nice desired result. if title is nil, it is treated as a "thing",
  otherwise it's assumed to be a file (for speed) }

{ [Saivert] What the hell do Nullsoft mean with this?! }

const
  IPC_PLAYFILE = 100;  {dont be fooled, this is really the same as enqueufile}
  IPC_ENQUEUEFILE = 100;
(* sent as a WM_COPYDATA, with IPC_PLAYFILE as the dwData, and the string to play
** as the lpData. Just enqueues, does not clear the playlist or change the playback
** state.
*)

  IPC_DELETE = 101;
  IPC_DELETE_INT = 1101; {don't use this, it's used internally by winamp when
                          dealing with some lame explorer issues.}
(* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE);
** Use IPC_DELETE to clear Winamp's internal playlist.
*)


  IPC_STARTPLAY = 102; {starts playback. almost like hitting play in Winamp.}
  IPC_STARTPLAY_INT = 1102; {used internally, don't bother using it (won't be any fun)}


  IPC_CHDIR = 103;
(* sent as a WM_COPYDATA, with IPC_CHDIR as the dwData, and the directory to change to
** as the lpData.
*)


  IPC_ISPLAYING = 104;
(* res := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING);
** If it returns 1, it is playing. if it returns 3, it is paused,
** if it returns 0, it is not playing.
*)


  IPC_GETOUTPUTTIME = 105;
(* res := SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME);
** returns the position in milliseconds of the current track (mode = 0),
** or the track length, in seconds (mode = 1). Returns -1 if not playing or error.
*)

  IPC_JUMPTOTIME = 106;
(* (requires Winamp 1.60+)
** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME);
** IPC_JUMPTOTIME sets the position in milliseconds of the
** current song (approximately).
** Returns -1 if not playing, 1 on eof, or 0 if successful
*)

  IPC_GETMODULENAME = 109;
  IPC_EX_ISRIGHTEXE = 666;
(* usually shouldnt bother using these, but here goes:
** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal
** flag gets set, which if you send a normal WM_WA_IPC message with
** IPC_EX_ISRIGHTEXE, it returns whether or not that filename
** matches. lame, I know.
*)

  IPC_WRITEPLAYLIST = 120;
(* (requires Winamp 1.666+)
** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST);
**
** IPC_WRITEPLAYLIST writes the current playlist to <winampdir>\\Winamp.m3u,
** and returns the current playlist position.
** Kinda obsoleted by some of the 2.x new stuff, but still good for when
** using a front-end (instead of a plug-in)
*)


  IPC_SETPLAYLISTPOS = 121;
(* (requires Winamp 2.0+)
** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS)
** IPC_SETPLAYLISTPOS sets the playlist position to 'position'. It
** does not change playback or anything, it just sets position, and
** updates the view if necessary
*)


  IPC_SETVOLUME = 122;
(* (requires Winamp 2.0+)
** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME);
** IPC_SETVOLUME sets the volume of Winamp (from 0-255).
*)
{ Tip from Saivert: use -666 as volume to get the current volume level,
  like: cur_vol := SendMessage(hwnd_winamp, WM_WA_IPC, -666, IPC_SETVOLUME);
  Justin likes that special number (associated with the devil). }


  IPC_SETPANNING = 123;
(* (requires Winamp 2.0+)
** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING);
** IPC_SETPANNING sets the panning of Winamp (from 0 (left) to 255 (right)).
*)
{ Tip from Saivert: use -666 as panning to get the current balance setting,
  like: cur_pan := SendMessage(hwnd_winamp, WM_WA_IPC, -666, IPC_SETPANNING); }


  IPC_GETLISTLENGTH = 124;
(* (requires Winamp 2.0+)
** length := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH);
** IPC_GETLISTLENGTH returns the length of the current playlist, in
** tracks.
*)


  IPC_GETLISTPOS = 125;
(* (requires Winamp 2.05+)
** pos := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS);
** IPC_GETLISTPOS returns the playlist position. A lot like IPC_WRITEPLAYLIST
** only faster since it doesn't have to write out the list. Heh, silly me.
*)


  IPC_GETINFO = 126;
(* (requires Winamp 2.05+)
** inf := SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO);
** IPC_GETINFO returns info about the current playing song. The value
** it returns depends on the value of 'mode'.
** Mode      Meaning
** ------------------
** 0         Samplerate (i.e. 44100)
** 1         Bitrate  (i.e. 128)
** 2         Channels (i.e. 2)
*)


  IPC_GETEQDATA = 127;
(* (requires Winamp 2.05+)
** data := SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);
** IPC_GETEQDATA queries the status of the EQ.
** The value returned depends on what 'pos' is set to:
** Value      Meaning
** ------------------
** 0-9        The 10 bands of EQ data. 0-63 (+20db - -20db)
** 10         The preamp value. 0-63 (+20db - -20db)
** 11         Enabled. zero if disabled, nonzero if enabled.
** 12         Autoload. zero if disabled, nonzero if enabled.
*)


  IPC_SETEQDATA = 128;
(* (requires Winamp 2.05+)
** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA);
** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA);
** IPC_SETEQDATA sets the value of the last position retrieved
** by IPC_GETEQDATA. This is pretty lame, and we should provide
** an extended version that lets you do a MAKELPARAM(pos,value).
** someday...
*)


  IPC_ADDBOOKMARK = 129;
(* (requires Winamp 2.4+)
** Sent as a WM_COPYDATA, using IPC_ADDBOOKMARK, adds the specified
** file/url to the Winamp bookmark list.
*)


  IPC_INSTALLPLUGIN = 130;
(* not implemented, but if it was you could do a WM_COPYDATA with
** a path to a .wpz, and it would install it.
*)


  IPC_RESTARTWINAMP = 135;
(* (requires Winamp 2.2+)
** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP);
** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :)
*)


  IPC_ISFULLSTOP = 400;
(* (requires winamp 2.7+ I think)
** ret := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP);
** useful for when you're an output plugin, and you want to see
** if the stop/close is a full stop, or just between tracks.
** returns nonzero if it's full, zero if it's just a new track.
*)


  IPC_INETAVAILABLE = 242;
(* (requires Winamp 2.05+)
** val := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE);
** IPC_INETAVAILABLE will return 1 if the Internet connection is available for Winamp.
*)


  IPC_UPDTITLE = 243;
(* (requires Winamp 2.2+)
** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE);
** IPC_UPDTITLE will ask Winamp to update the informations about the current title.
*)


  IPC_REFRESHPLCACHE = 247;
(* (requires Winamp 2.2+)
** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE);
** IPC_REFRESHPLCACHE will flush the playlist cache buffer.
** (send this if you want it to go refetch titles for tracks)
*)


  IPC_GET_SHUFFLE = 250;
(* (requires Winamp 2.4+)
** val := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE);
**
** IPC_GET_SHUFFLE returns the status of the Shuffle option (1 if set)
*)


  IPC_GET_REPEAT = 251;
(* (requires Winamp 2.4+)
** val := SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT);
**
** IPC_GET_REPEAT returns the status of the Repeat option (1 if set)
*)


  IPC_SET_SHUFFLE = 252;
(* (requires Winamp 2.4+)
** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE);
**
** IPC_SET_SHUFFLE sets the status of the Shuffle option (1 to turn it on)
*)


  IPC_SET_REPEAT = 253;
(* (requires Winamp 2.4+)
** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT);
**
** IPC_SET_REPEAT sets the status of the Repeat option (1 to turn it on)
*)


  IPC_ENABLEDISABLE_ALL_WINDOWS = 259; { 0xdeadbeef to disable }
(* (requires Winamp 2.9+)
** if enable then
**   SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ENABLEDISABLE_ALL_WINDOWS)
** else SendMessage(hwnd_winamp,WM_WA_IPC,$DEADBEEF,IPC_ENABLEDISABLE_ALL_WINDOWS);
** sending with $DEADBEEF as the param disables all winamp windows,
** any other values will enable all winamp windows.
*)


  IPC_GETWND = 260;
(* (requires Winamp 2.9+)
** _hwnd := SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND);
** returns the HWND of the window specified.
*)
    IPC_GETWND_EQ = 0; {use one of these for the param}
    IPC_GETWND_PE = 1;
    IPC_GETWND_MB = 2;
    IPC_GETWND_VIDEO = 3;
    
  IPC_ISWNDVISIBLE  = 261;



(************************************************************************
***************** in-process only (WE LOVE PLUGINS)
************************************************************************)


  IPC_SETSKIN = 200;
(* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(PChar('skinname')),IPC_SETSKIN);
** IPC_SETSKIN sets the current skin to "skinname". Note that skinname
** can be the name of a skin, a skin .zip file, with or without path.
** If path isn't specified, the default search path is the winamp skins
** directory.
*)


  IPC_GETSKIN = 201;
(* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(skinname_buffer),IPC_GETSKIN);
** IPC_GETSKIN puts the directory where skin bitmaps can be found
** into  skinname_buffer.
** skinname_buffer must be MAX_PATH characters in length.
** When using a .zip'd skin file, it'll return a temporary directory
** where the ZIP was decompressed.
*)


  IPC_EXECPLUG = 202;
(* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(PChar('vis_file.dll')),IPC_EXECPLUG);
** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM.
** the format of this string can be:
** "vis_whatever.dll"
** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir)
** "C:\dir\vis_whatever.dll,1"
*)


  IPC_GETPLAYLISTFILE = 211;
(* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** name := PChar(SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE));
** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index].
** returns a pointer to it. returns NULL on error.
*)


  IPC_GETPLAYLISTTITLE = 212;
(* (requires Winamp 2.04+, only usable from plug-ins (not external apps))
** name = PChar(SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE));
**
** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index].
** returns a pointer to it. returns NULL on error.
*)


  IPC_GETHTTPGETTER = 240;
(* retrieves a function pointer to a HTTP retrieval function.
** if this is unsupported, returns 1 or 0.
** the function should be:
** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle);
** if you call this function, with a parent window, a URL, an output file, and a dialog title,
** it will return 0 on successful download, 1 on error.
*)

{ [Saivert] I have made a pascal prototype, here it is: }
type
  TFNhttpRetrieveFile = function(parentwnd: HWND; url, _file, dlgtitle: PChar): Integer; stdcall;

{ [Saivert] Get the function by calling this:
  var
    httpgetfn: TFNhttpRetrieveFile;
  begin
    @httpgetfn := Pointer(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETHTTPGETTER));
  end;
}

const
  IPC_MBOPEN = 241;
(* (requires Winamp 2.05+)
** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN);
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(PChar(url)),IPC_MBOPEN);
** IPC_MBOPEN will open a new URL in the minibrowser. if url is nil, it will open the Minibrowser window.
*)



  IPC_CHANGECURRENTFILE = 245;
(* (requires Winamp 2.05+)
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(PChar(file)),IPC_CHANGECURRENTFILE);
** IPC_CHANGECURRENTFILE will set the current playlist item.
*)


  IPC_GETMBURL = 246;
(* (requires Winamp 2.2+)
** var buffer: array[0..4095] of Char; // Urls can be VERY long
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(Pointer(buffer)),IPC_GETMBURL);
** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer.
** buffer must be at least 4096 bytes long.
*)


  IPC_MBBLOCK = 248;
(* (requires Winamp 2.4+)
** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK);
**
** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1
*)

  IPC_MBOPENREAL = 249;
(* (requires Winamp 2.4+)
** SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(PChar(url)),IPC_MBOPENREAL);
**
** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if
** IPC_MBBLOCK has been set to 1
*)

  IPC_ADJUST_OPTIONSMENUPOS = 280;
(* (requires Winamp 2.9+)
** newpos := SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(adjust_offset),IPC_ADJUST_OPTIONSMENUPOS);
** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a
** menu item above the options/skins/vis menus.
*)

  IPC_GET_HMENU = 281;
(* (requires Winamp 2.9+)
** _hMenu := SendMessage(hwnd_winamp,WM_WA_IPC,WPARAM(0),IPC_GET_HMENU);
** returns the main popup menu if the data is 0.
** other values are currently undefined, and will return nil.
*)

  IPC_GET_EXTENDED_FILE_INFO = 290; {pass a pointer to the following struct in wParam}
(* (requires Winamp 2.9+)
** to use, create an extendedFileInfoStruct, point the values filename and metadata to the
** filename and metadata field you wish to query, and ret to a buffer, with retlen to the
** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,Integer(@struct),IPC_GET_EXTENDED_FILE_INFO);
** the results should be in the buffer pointed to by ret.
** returns 1 if the decoder supports a getExtendedFileInfo method
*)
type
  PextendedFileInfoStruct = ^TextendedFileInfoStruct;
  TextendedFileInfoStruct = record
    filename: PChar;
    metadata: PChar;
    ret: PChar;
    retlen: Integer;
  end;

const
  IPC_GET_BASIC_FILE_INFO = 291; {pass a pointer to the following struct in wParam}

type
  PbasicFileInfoStruct = ^TbasicFileInfoStruct;
  TbasicFileInfoStruct = record
    filename: PChar;
    quickCheck: Integer;

    {filled in by winamp}
    length: Integer;
    title: PChar;
    titlelen: Integer;
  end;

const
  IPC_GET_EXTLIST = 292; {returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename}


  IPC_INFOBOX = 293;

type
  PinfoBoxParam = ^TinfoBoxParam;
  TinfoBoxParam = record
    parent: HWND;
    filename: PChar;
  end;

{ [Saivert] Nullsoft didn't specify this, but I guess you call it like:
  SendMessage(hwnd_winamp,WM_WA_IPC,Integer(@AnInfoBoxParam),IPC_INFOBOX);
  }



const
  IPC_SET_EXTENDED_FILE_INFO = 294; {pass a pointer to the a extendedFileInfoStruct in wParam}
(* (requires Winamp 2.9+)
** to use, create an extendedFileInfoStruct, point the values filename and metadata to the
** filename and metadata field you wish to write in ret. (retlen is not used). and then
** SendMessage(hwnd_winamp,WM_WA_IPC,Integer(@struct),IPC_SET_EXTENDED_FILE_INFO);
** returns 1 if the metadata is supported
** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update
*)

  IPC_WRITE_EXTENDED_FILE_INFO = 295;
(* (requires Winamp 2.9+)
** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file
** returns 1 if the file has been successfully updated, 0 if error
*)

  IPC_FORMAT_TITLE  = 297;

type
  PwaFormatTitle = ^TwaFormatTitle;
  TwaFormatTitle = record
    spec : pchar; // NULL=default winamp spec
    p : Pointer;

   _out : pchar;
   out_len : integer;

   TAGFUNC : function(tag : pchar;p : Pointer) : pchar; cdecl; //return 0 if not found
   TAGFREEFUNC : procedure(tag : pchar;p : Pointer); cdecl;
 end;

const

  IPC_GETUNCOMPRESSINTERFACE = 331;
(* returns a function pointer to uncompress().
** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen);
** right out of zlib, useful for decompressing zlibbed data.
*)
{ [Saivert] Here I have a function prototype suitable for use in Delphi: }
type
  TFNuncompress = function(dest: PChar; var destLen: Integer; source: PChar; sourceLen: Longint): Integer; stdcall;

  Pwa_inflate_struct = ^Twa_inflate_struct;
  Twa_inflate_struct = record
    inflateReset : function(strm : Pointer) : integer; cdecl;
    inflateInit_ : function(strm : Pointer;version : pchar;stream_size : integer) : integer; cdecl;
    inflate : function(strm : Pointer;flush : integer) : integer; cdecl;
    inflateEnd : function(strm : Pointer) : integer; cdecl;
    crc32 : function(crc : DWORD;buf : Pointer;len : DWORD) : DWORD; cdecl;
  end;

{ [Saivert] Please read my comments about IPC_ADD_PREFS_DLG below }
const
  IPC_ADD_PREFS_DLG = 332;
  IPC_REMOVE_PREFS_DLG = 333;
(* (requires Winamp 2.9+)
** to use, allocate a prefsDlgRec structure (either on the heap or some global
** data, but NOT on the stack), initialze the members:
** hInst to the DLL instance where the resource is located
** dlgID to the ID of the dialog,
** proc to the window procedure for the dialog
** name to the name of the prefs page in the prefs.
** where to 0 (eventually we may add more options)
** then, SendMessage(hwnd_winamp,WM_WA_IPC,Integer(@prefsRec,IPC_ADD_PREFS_DLG);
**
** you can also IPC_REMOVE_PREFS_DLG with the address of the same prefsRec,
** but you shouldn't really ever have to.
**
*)

(* [Saivert] original c statement kept for reference
typedef struct _prefsDlgRec {
  HINSTANCE hInst;
  int dlgID;
  void *proc;

  char *name;
  int where; // 0 for options, tho we need to define more


  int _id;
  struct _prefsDlgRec *next;
} prefsDlgRec;
*)

type
  PprefsDlgRec = ^TprefsDlgRec;
  TprefsDlgRec = record
    _hInst: HINST;
    dlgID: Integer;
    proc: Pointer;

    name: PChar;
    where: Integer; {0 for options, though we they need to define more}

    _id: Integer;
    _prefsDlgRec: PprefsDlgRec;
  end;

const
  IPC_GETINIFILE = 334; {returns a pointer to winamp.ini}

  IPC_OPENURLBOX = 360; {pass a HWND to a parent, returns a HGLOBAL that needs to be freed with GlobalFree(), if successful}
  IPC_OPENFILEBOX = 362; // pass a HWND to a parent
  IPC_OPENDIRBOX  = 363; // pass a HWND to a parent


{ pass 0 for a copy of the skin HBITMAP
  pass 1 for name of font to use for playlist editor likeness
  pass 2 for font charset
  pass 3 for font size }
  IPC_GET_GENSKINBITMAP = 503;


  IPC_GET_EMBEDIF = 505; {pass an embedWindowState}
{ returns an HWND embedWindow(embedWindowState *); if the data is NULL, otherwise returns the HWND directly }
(*
typedef struct
{
  HWND me; //hwnd of the window

  int flags;

  RECT r;

  void *user_ptr; // for application use

  int extra_data[64]; // for internal winamp use
} embedWindowState;
*)

  IPC_EMBED_ENUM     = 532;

  IPC_EMBED_ISVALID  = 533;


type
  PembedWindowState = ^TembedWindowState;
  TembedWindowState = record
    me: HWND;
    flags: Integer;
    r: TRect;
    user_ptr: Pointer;
    extra_data: array[0..65] of Integer;
  end;

{ Here is a function prototype for IPC_GET_EMBEDIF }
  TembedWindow = function(ews: PembedWindowState): HWND; cdecl;

  PembedEnumStruct = ^TembedEnumStruct;
  TembedEnumStruct = record
    enumProc : function(ws : PembedWindowState;param : PembedEnumStruct) : integer; cdecl;
    user_data : integer;
  end;

const
  EMBED_FLAGS_NORESIZE = 1; { set this bit in embedWindowState.flags to keep window from being resizable}


{  system tray sends this (you might want to simulate it) }
  WM_WA_SYSTRAY = WM_USER+1;

// input plugins send this when they are done playing back
  WM_WA_MPEG_EOF = WM_USER+2;

{ Still to be converted, do it yourself if you like. }

 IPC_GETSADATAFUNC = 800;
// 0: returns a char *export_sa_get() that returns 150 bytes of data
// 1: returns a export_sa_setreq(int want);

 IPC_ISMAINWNDVISIBLE  = 900;


//// video stuff
const
  IPC_GET_IVIDEOOUTPUT = 500; { see below for IVideoOutput interface }

{ VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) }
{ There is no MACRO equivalent in Pascal, so here is a function which does the same: }
function Video_MakeType(A, B, C, D: Integer): Integer;

const
  VIDUSER_SET_INFOSTRING = $1000;
  VIDUSER_GET_VIDEOHWND  = $1001;
  VIDUSER_SET_VFLIP      = $1002;

type
 PYV12_PLANE = ^TYV12_PLANE;
 TYV12_PLANE = record
   baseAddr : pchar;
   rowBytes : integer;
 end;

 PYV12_PLANES = ^TYV12_PLANES;
 TYV12_PLANES = record
   y : TYV12_PLANE;
   u : TYV12_PLANE;
   v : TYV12_PLANE;
 end;

 Tmsgcallback = function(token : Pointer;hwnd :THandle;uMsg,wParam,lParam : integer) : HResult; cdecl;

 PVideoOutput = ^IVideoOutput;
 IVideoOutput = object
   procedure DesVideoOutput; virtual; cdecl; abstract;
   function  open(w,h,vflip : integer;aspectratio : double;fmt : Cardinal) : integer; virtual; cdecl; abstract;
   procedure setcallback(func : Tmsgcallback;token : Pointer); virtual; cdecl; abstract;
   procedure close; virtual; cdecl; abstract;
   procedure draw(frame : Pointer); virtual; cdecl; abstract;
   procedure drawSubtitle(item : Pointer); virtual; cdecl; abstract;
   procedure showStatusMsg(text : pchar); virtual; cdecl; abstract;
   function  get_latency : integer; virtual; cdecl; abstract;
   procedure notifyBufferState(bufferstate : integer); virtual; cdecl; abstract;

   function  extended(param1,param2,param3 : integer) : integer; virtual; cdecl; abstract;
 end;

{ these messages are callbacks that you can grab by subclassing the winamp window }

{ wParam = }
const
  IPC_CB_WND_EQ = 0; { use one of these for the param }
  IPC_CB_WND_PE = 1;
  IPC_CB_WND_MB = 2;
  IPC_CB_WND_VIDEO = 3;

  IPC_CB_ONSHOWWND = 600;
  IPC_CB_ONHIDEWND = 601;

  IPC_PLAYING_FILE  = 3003;


(*
  [Saivert]
  The new feature where you can add your own page to the prefs in Winamp,
  only supports native Windows dialogs. So to add a TForm based window to
  the preferences dialog in winamp, you have to manually create a resource
  script containing these lines:

    your_id DIALOG 0 0 144 154
    STYLE WS_CHILD
    BEGIN
    END

  where your_id must be a number not used by any other DIALOG resource.
  Save this as a text file named something like "myprefs.rc" and save it
  in the same folder as your project.

  This file has to be compiled into a binary resource form.
  To do this type at the command prompt:
  (you must CD to your projects directory, and it assumes
  that your Delphi program directory is in the path)

    brcc32 myprefs.rc <ENTER>
  or if that didn't work...
    brc32 -r myprefs.rc <ENTER>

  This creates a file called "myprefs.res".

  Now it is time to import this resource into your Delphi project.
  Add a line anywhere in your source (e.g. your .DPR file) that looks like
  this:
    {$R myprefs.res}

  Now when you have set up a dialog resource and imported it into your project,
  it is time to write the code that actually make it work. Here it goes:

  Prepare your form for use in the prefs dialog. Be sure...
    ...that all controls fits within a rectangle of 287x309 in size.
    ...that the form is not loaded automatically at startup.
    E.g.: "Application.CreateForm(yourform, Tyourform)" does not exist.


  Now assuming your form is "yourform" write this window procedure:

    function myprefsDlgProc(dlg: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall; {very important with stdcall calling convention}
    begin
      result := False;
      case msg of
        WM_INITDIALOG: begin
          yourform := Tyourform.Create(nil);
          SetParent(yourform.Handle, dlg);
          yourform.BorderStyle := bsNone;
          SetWindowPos(yourform.Handle, 0, 0, 0, 287, 309, SWP_NOZORDER);
          ConfigForm.Show;
          result := False;
        end;
        WM_DESTROY: yourform.Free;
      end;
    end;

  Set up a TprefsDlgRec record (must be in a interface section):
    var
      myprefsRec: TprefsDlgRec;


  Fill the members of the record
  (do this in a Plugin initialization function):
    with myprefsrec do
    begin
      _hInst := HInstance; { or This_Mod^.hDLLInstance }
      dlgID := your_id; { set to id specified in resource script, must be a number }
      proc := @myprefsDlgProc;
      name := 'My Prefs'; {page name}
      where := 0; {0 means to place it under "Options". More to come...}
      { do not care about _id and/or _prefsDlgRec which is handled by Winamp }
    end;

  Now it is time to put it into winamp's preferences dialog, call this:
    SendMessage(hwnd_winamp,WM_WA_IPC,Integer(@myprefsrec),IPC_ADD_PREFS_DLG);

  That's it!
  PS! Any OnMouseEnter and OnMouseLeave events associated with VCL controls,
  won't be triggered because of compatibility issues, sorry!

*)


implementation

{ VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) }
{ There is no MACRO equivalent in Pascal, so here is a function which does the same: }
function Video_MakeType(A, B, C, D: Integer): Integer;
begin
 Result:= A or (B shl 8) or (C shl 16) or (D shl 24);
end;

end.
