View Full Version : Unpublished API's
THEMike
14th April 2002, 17:24
After a little natter with Tag about SHOUTcast he clued me into a few unpublished winamp API's that may be handy for you all:
#ifndef __IPC_PE_H
#define __IPC_PE_H
#define IPC_PE_GETCURINDEX 100
#define IPC_PE_GETINDEXTOTAL 101
#define IPC_PE_GETINDEXINFO 102
#define IPC_PE_GETINDEXINFORESULT 103
#define IPC_PE_DELETEINDEX 104
#define IPC_PE_SWAPINDEX 105
#define IPC_PE_INSERTFILENAME 106
#define IPC_PE_GETDIRTY 107
#define IPC_PE_SETCLEAN 108
These are all sent to the playlist window not the main window.
pi8
16th April 2002, 19:31
Thanks a lot for posting this, man!! Not needed by me, though.
asandvig
16th April 2002, 21:21
This looks nice, but what do they do and how to you send them? What parameters do they take, what do they return, etc..?
Gourou
17th April 2002, 03:14
*licks his lips* time to go to work :D
THEMike
17th April 2002, 07:51
#define IPC_PE_GETCURINDEX 100
Should be obvious, get position of current track in playlist.
Returns an int.
#define IPC_PE_DELETEINDEX 104
Remove specified track from list (takes int)
#define IPC_PE_SWAPINDEX 105
Swap two files in order on playlist
#define IPC_PE_INSERTFILENAME 106
Add a track.
These two are very interesting.
#define IPC_PE_GETDIRTY 107
#define IPC_PE_SETCLEAN 108
SETCLEAN sets the playlist as clean. If get dirty returns a 1 (I think) then the list has been edited by another process since you last setclean. It's a dirty read thing...
I have more info at home, I'll post it when I get a chance.
Should be simple to figure them out tho...
zhaPP
17th April 2002, 20:07
Thanks for the APIs, but I'm having problems how to use them.. Using the following code to insert a playlistitem:
char szTmp[64];
HWND PEWnd = FindWindow("Winamp PE",NULL);
strcpy(szTmp, "C:\\mp3\\test.mp3");
SendMessage(PEWnd,WM_USER,(LPARAM)szTmp,106);
Is this wrong? Seems to be that because it doesn't work for me.. :)
How do you use IPC_PE_DELETEINDEX?
Can you just do the following:
int nIndex = 1;
SendMessage(WAWnd,WM_USER,nIndex,104);
Thanks in advance!
THEMike
19th April 2002, 09:06
#ifndef __IPC_PE_H
#define __IPC_PE_H
#define IPC_PE_GETCURINDEX 100
#define IPC_PE_GETINDEXTOTAL 101
#define IPC_PE_GETINDEXINFO 102
#define IPC_PE_GETINDEXINFORESULT 103
#define IPC_PE_DELETEINDEX 104
#define IPC_PE_SWAPINDEX 105
#define IPC_PE_INSERTFILENAME 106
#define IPC_PE_GETDIRTY 107
#define IPC_PE_SETCLEAN 108
typedef struct {
char file[MAX_PATH];
int index;
} fileinfo;
typedef struct {
HWND callback;
int index;
} callbackinfo;
#endif
g_winamp = FindWindow("Winamp v1.x",NULL);
g_playlist = FindWindow("Winamp PE",NULL);
COPYDATASTRUCT cds;
fileinfo f;
cds.dwData = IPC_PE_INSERTFILENAME;
strcpy(f.file, tempname); // Path to the new entry
if ( ins )
{
f.index=target; // Position to insert at
}
else
{
f.index=allsongs;
}
cds.lpData = (void *)&f;
cds.cbData = sizeof(fileinfo);
SendMessage(g_playlist,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
sprintf(g_lastmode," Add File to Playlist ");
sprintf(g_lastreply," Inserted: %s at position %d ",f.file,f.index);
getfilename(tempname,movesong); /* unsafe, fullpath, but we dont show on page */
cursong = SendMessage g_playlist,WM_USER,IPC_PE_GETCURINDEX ,0);
target = cursong+1;
{
COPYDATASTRUCT cds;
fileinfo f;
cds.dwData = IPC_PE_INSERTFILENAME;
strcpy(f.file, tempname); // Path to the new entry
f.index=target; // Position to insert at
cds.lpData = (void *)&f;
cds.cbData = sizeof(fileinfo);
SendMessage(g_playlist,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
}
if ( movesong > cursong ) movesong++;
SendMessage(g_playlist,WM_USER,IPC_PE_DELETEINDEX, movesong);
sprintf(g_lastmode," Move Song to next ");
sprintf(g_lastreply," From: %d To: %d ", movesong, target);
allsongs = SendMessage(g_playlist, WM_USER, IPC_PE_GETINDEXTOTAL,0);
sprintf(buf,"Status: %s | Total Songs: %d<br>", status, allsongs );
strcat(g_client[i].t_sendbuf,buf);
cursong = SendMessage(g_playlist,WM_USER,IPC_PE_GETCURINDEX ,0);
getfilename(tempname, cursong);
sprintf(buf,"Now Playing: <b>%d : %s</b><br>", cursong, tempname );
void getfilename(char *target, int index)
{
COPYDATASTRUCT cds;
callbackinfo f;
cds.dwData = IPC_PE_GETINDEXINFO;
f.callback = g_hwnd; // this is the HWND of the window which will receive the callback message
f.index=index; // Index of the entry to get info from
cds.lpData = (void *)&f;
cds.cbData = sizeof(callbackinfo);
g_callback = 1; /* Index Request */
SendMessage(g_playlist,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
while ( g_callback == 1 )
{
log_printf("stuck");
Sleep(1000);
}
strcpy(target,g_file);
}
And if that doesn't do it for you, then I don't know what will...
zhaPP
19th April 2002, 09:40
Works great.. thanks a lot!!!
Flippet
20th April 2002, 15:41
I see... what I got wrong was the message format difference between this and the normal winamp API messages...
SendMessage(hwnd,WM_USER,data,command) - Winamp main window
SendMessage(hwnd,WM_USER,command,data) - Playlist window
It works now, ta...
Phil, just me
ChrisNC
12th July 2002, 13:10
Does anyone have a Visual Basic version of the code to insert a file into the playlist? I want to be able to insert a file at a particular location within the current playlist. Can this be done?
Thanks.
apol
18th July 2002, 05:27
Does anyone know how to use IPC_PE_SWAPINDEX? I have a method, but it's not the best IMO. It works by switching the passed index with 0, so I figure I can just do it like this to swap two specific ones.
void swapindex ( int numone, int numtwo )
{
HWND hwndPlaylist = FindWindow("Winamp PE", NULL);
SendMessage(hwndPlaylist, WM_USER, IPC_PE_SWAPINDEX, numone);
SendMessage(hwndPlaylist, WM_USER, IPC_PE_SWAPINDEX, numtwo);
SendMessage(hwndPlaylist, WM_USER, IPC_PE_SWAPINDEX, numone);
}
Gabi Slonto
19th July 2002, 23:51
I want to translate it to Delphi ;-)
But there must be a problem with the pointer...
Is there anybody who could help..... ??
procedure InsertMp3ToPlayList(iAfterTrack : Integer; mp3ToAdd:string);
Type
TFileInfo = record
FileName : String;
Index : Integer;
end;
Var
cds : CopyDataStruct;
f : TFileInfo;
begin
Mp3ToAdd:=(MP3ToAdd+#0);
f.FileName := Mp3ToAdd;
f.Index := iAfterTrack;
cds.dwData := 106; //int for IPC_PE_INSERTFILENAME
cds.lpData := @f;
cds.cbData := SizeOf(TFileInfo);
GethWnd_WinAmpPL;
SendMessage(hwnd_WinampPL, WM_COPYDATA, 0, LParam(@cds));
end;
barney911
22nd July 2002, 09:19
I found a solution to load mp3-file into a playlist with C#
If anybody needs this, just search the forum for "C# COPYDATA".
It appears under one of the first given search result postings (something with VB COPYDATA or so).
Greets,
Barney.
shrom
24th July 2002, 00:41
To Gabi Slonto :
You could try this
Type
TFileInfo = packed record
FileName : Array[0..MAX_PATH-1] of Char;
Index : Integer;
end;
Var
cds : CopyDataStruct;
f : TFileInfo;
begin
StrLCopy(f.FileName, PChar(Mp3ToAdd), SizeOf(f.FileName));
f.Index := iAfterTrack;
cds.dwData := 106; //int for IPC_PE_INSERTFILENAME
cds.cbData := SizeOf(f);
cds.lpData := @f;
GethWnd_WinAmpPL;
SendMessage(hwnd_WinampPL, WM_COPYDATA, 0, LParam(@cds));
end;
It works for me : Delphi6, Winamp 2.8
spib
1st October 2002, 15:38
Anyone noticed that this code doesn't work when the Playlist in is Winshade mode? It works when the playlist is full size or even when the playlist is 'closed' but not when in winshade mode.
Anyone have a fix for this?
SpazzMan
7th October 2002, 22:58
I'm finding it to be worse than that: I get crashes when I winshade the playlist after deleting an song. It doesn't seem to matter how much time expires between the deletion and the winshading; as soon as that winshade button's clicked, Winamp goes down.
I would've like to be able to delete stuff, too. This is probably why they're unpublished...
spib
8th October 2002, 13:13
Well, that's the end of my Winamp 2 development I think. Winamp3 all the way from now on.
sicpuppy_123
11th December 2002, 15:01
Hey there
Does anyone know how choose where the new file goes in the playlist?
Pref in vb (not to good at c)
Thanks
jmoschetti45
17th February 2003, 22:37
When I delete something in the playlist from my program and then windowshade I don't have any problems accept a few miliseconds audio lag.
SpazzMan
23rd February 2003, 20:53
And, for some reason, neither do I now. I wish I still had the old code I was using so I could see what I'm doing differently now. This is really weird.
While you're at it, could you say that your code is really well-organized and works the first time you compile it? :)
jmoschetti45
24th February 2003, 14:32
Yes my code is nice and clean (includes spacing and indents)
No it didn't work the first time because I forgot to define the constants.
slabber
4th May 2003, 22:46
Aha! Victory! I got it all working in VB now, but there are some things i still don't understand, even though i got them working using trial and error. Does anyone know why the callback construction does not work? i found a nice workaround for it... And does anyone know why the length of the fileinfo struct can not be
byte(255) + long --> 256+4 = 260 bytes
but must be
byte(259) + long --> 260+4 = 264
???
i hope you can enlighten me on this...
okay, enough questions now; let's see the code:
Public Const IPC_PE_GETCURINDEX = 100
Public Const IPC_PE_GETINDEXTOTAL = 101
Public Const IPC_PE_GETINDEXINFO = 102
Public Const IPC_PE_GETINDEXINFORESULT = 103
Public Const IPC_PE_DELETEINDEX = 104
Public Const IPC_PE_SWAPINDEX = 105
Public Const IPC_PE_INSERTFILENAME = 106
Public Const IPC_PE_GETDIRTY = 107
Public Const IPC_PE_SETCLEAN = 108
Public Const WM_COPYDATA = &H4A
Public Const WM_COMMAND = &H111
Public Const WM_USER = &H400
Public Type COPYDATASTRUCT ' look this struct up in the MSDN library for more info
dwData As Long
cbData As Long
lpData As Long
End Type
Public Type fileinfo
file(259) As Byte ' (i wanted 255, but it seems the struct MUST be a multiple of 8 bytes? can someone explain this?
index As Long 'VB Long = C int = 4 bytes
End Type
Public Type callbackinfo
callback As Long 'HWND callback;
index As Long 'int index;
End Type
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function CopyDataSendMessage Lib "user32" Alias "SendMessageA" (ByVal WndID As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As COPYDATASTRUCT) As Long
Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Const PROCESS_VM_READ = &H10
Public Sub StringToByteArray(str As String, ByRef bte() As Byte)
Dim k As Integer
For k = 1 To Len(str)
bte(k - 1) = Asc(Mid(str, k, 1))
Next k
For k = Len(str) To UBound(bte) - 1
bte(k) = Asc(" ")
Next k
If Len(str) < UBound(bte) Then bte(Len(str)) = 0
End Sub
Public Sub insertsong(path As String, Optional target As Integer)
h_winamp = FindWindow("Winamp v1.x", vbNullString)
h_playlist = FindWindow("Winamp PE", vbNullString)
Dim songcount, cursong As Integer
songcount = SendMessage(h_playlist, WM_USER, IPC_PE_GETINDEXTOTAL, 0)
'set up the arguments for the INSERTFILENAME api to send to winamp:
Dim f As fileinfo
StringToByteArray path, f.file
If IsMissing(target) Then
f.index = songcount ';
Else
f.index = target '; // Position to insert at
End If
'use a windows standard COPYDATASTRUCT to package our function arguments.
Dim cds As COPYDATASTRUCT
cds.dwData = IPC_PE_INSERTFILENAME
cds.lpData = VarPtr(f)
cds.cbData = 264 'why?!? does it have to be a multiple of 8 bytes or something? 260 didn't work..
CopyDataSendMessage h_playlist, WM_COPYDATA, 0&, cds
' new song is now queued at the last position in the playlist
End Sub
'moves a song around the playlist so it becomes the next played song,
'or moves it to the specified index.
'NB: moving is interpreted as: take the song out (leaving a virtual gap),
'insert the song in the new position, by moving the song in that position and the ones after it
' to position+1, and finally deleting the gap.
Public Sub movesong(curPosition As Integer, Optional newPosition As Integer)
'TODO: sanity checks
h_winamp = FindWindow("Winamp v1.x", vbNullString)
h_playlist = FindWindow("Winamp PE", vbNullString)
Dim path As String
Dim playPosition As Integer
path = getfilename(curPosition)
'Delete the song that will be reinserted:
SendMessage h_playlist, WM_USER, IPC_PE_DELETEINDEX, curPosition
If IsMissing(newPosition) Then
' the song to be moved will be placed right after the currently playing song:
playPosition = SendMessage(h_playlist, WM_USER, IPC_PE_GETCURINDEX, 0)
newPosition = playPosition + 1
ElseIf newPosition > curPosition Then
newPosition = newPosition - 1
End If
Dim f As fileinfo
StringToByteArray path, f.file
f.index = newPosition
Dim cds As COPYDATASTRUCT
cds.dwData = IPC_PE_INSERTFILENAME
cds.lpData = VarPtr(f)
cds.cbData = 264 'why?!? does it have to be a multiple of 8 bytes or something? 260 didn't work..
CopyDataSendMessage h_playlist, WM_COPYDATA, 0&, cds
End Sub
Public Function getfilename(index As Integer) As String
On Error Resume Next
Dim Trackpos As Long
Dim mpointer As Long
Dim temp, temphandle, hwndwinampp As Long
Dim ntemp, ptemp
Dim Data As String * 256
mpointer = SendMessage(h_winamp, WM_USER, index, 211) '212 is Title
'do interprocess magic:
temp = GetWindowThreadProcessId(h_winamp, temphandle)
hwndwinampp = OpenProcess(PROCESS_VM_READ, False, temphandle)
Data = Space(256)
'pull the data:
ntemp = ReadProcessMemory(hwndwinampp, mpointer, Data, 256, temp)
'bail out:
ptemp = CloseHandle(hwndwinampp)
getfilename = Left(Data, InStr(1, Data, Chr(0)) - 1)
'the following does not work, the callback does not get called! why not?:
Dim cds As COPYDATASTRUCT
Dim f As callbackinfo
f.callback = GetProcAddress(AddressOf callbackf)
f.index = 12
cds.lpData = VarPtr(f)
cds.cbData = 8
cds.dwData = IPC_PE_GETINDEXINFO
CopyDataSendMessage h_winamp, WM_COPYDATA, 0&, cds
End Function
Public Function callbackf()
MsgBox "CALLBACK!"
Debug.Print "CALLBACK"
Stop
End Function
Public Function GetProcAddress(ByVal lngAddressOf As Long) As Long
GetProcAddress = lngAddressOf
End Function
(paste & play: paste it in a module, and call the insertsong & movesong functions te have it work)
Please let me know if you think the code is usefull!
BYTE-Smasher
10th June 2003, 01:12
The VB code doesn't seem to add songs in at all.... even though it's supposed to... any idea why? I copied and pasted fairly precisely....
slabber
12th June 2003, 17:51
I just tested it again in a clean project, from copying the above, and it really works! I use WA 2.91; maybe you have to up- / downgrade to make it work..
TazDevil
8th January 2004, 17:27
THEMike
According to the code that you posted the insert file/(s) works perfect as for the folders as well but hte only problem is that when
f.index= something
then all files of the folder are added to the bottom of the playlist and only the last file of the folder is set to the disired possition....
I would like some help here because i shouldn't have to transfer every file seperatly to the right possition.
Also about IPC_PE_SWAPINDEX it will swap the possitions of the indexes in the parenthesis, in the example the 2nd file on the list will become 5th, and the 5th -> 2nd
SendMessage(PE_WND,WM_WA_IPC,IPC_PE_SWAPINDEX, MAKELPARAM(1,4));
vBulletin® v3.8.6, Copyright ©2000-2013, Jelsoft Enterprises Ltd.