View Full Version : How to react on user-interactions
Luke-23
16th March 2007, 17:45
Hi,
I'm writing a plugin for winamp to remotely control winamp with a PSP. I already can already control winamp with my PSP but what if you do something with winamp on your PC; For that problem I need to react on events like the user pushes the 'play'- 'next'- or 'previous'-button, which brings me to the point that I don't have a clue how to do that. Can somebody tell me how to do that or has an idea where to start reading or what to search for?
Thank you
Luke
Luke-23
19th March 2007, 21:34
Ok, now I am a step further in the winamp-event-thing. I figured out how to react on events, what I did not figure out though, is how to react on the event I want to react on.
To clear things up and for those who will search th forums lateron, this is how to catch events (at least it's how I'd do it, if there's a better way - tell me); Subclass Winamp's window, catch all events, and react on those you wish to react on:
LRESULT CALLBACK MWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == YOUR_MESSAGE)
{
if (lParam==YOUR_LPARAM)
{
if (wParam==YOUR_WPARAM)
{
// do summin'
}
}
}
return CallWindowProc(lpWndProcOld,hwnd,message,wParam,lParam);
}
int init() {
lpWndProcOld = (WNDPROC)SetWindowLong(plugin.hwndParent, GWL_WNDPROC, (LONG)MWndProc);
}
...so I tried this:
LRESULT CALLBACK MWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_WA_IPC)
{
if (lParam==IPC_CB_MISC)
{
switch(wParam)
{
case IPC_CB_MISC_VOLUME:
MessageBox(plugin.hwndParent,"Did something to the volume!","",MB_OK);
break;
case IPC_CB_MISC_STATUS:
MessageBox(plugin.hwndParent,"Status changed!","",MB_OK);
break;
}
} else if ((lParam & 0x40000000) == 0x40000000) {
switch(wParam)
{
case 666:
MessageBox(plugin.hwndParent,"Track changed!","",MB_OK);
break;
}
}
}
return CallWindowProc(lpWndProcOld,hwnd,message,wParam,lParam);
}
but I get an odd behaviour:
[You can skip this, it is probably not very important]
When I change the volume it says 2 times 'Did something to the volume!'. When I press play when it's not playing, it says 'Status changed!' one time, then 2 times 'Did something to the volume!'. When I press play when it is playing it says 'Status changed!', then 2 times 'Did something to the volume!', then 'Status changed!' again. When I press stop it says 'Status changed!', but only if it's playing. Next has the same behaviour as play, but when it's not playing already it only says 'Status changed!' for a single time. Pressing previous does nothing at all.
[/skip]
So does anyone know where I can read which parameters are for which event? Or does someone probably know some events and could post the parameters for it?
I would really appreciate that
Thank you
Luke
DrO
19th March 2007, 22:53
all of the events are generally the IPC_CB_* stuff. it all depends on what you're trying to track since you can then use some of the other apis to see what the condition of things is, etc. IPC_PLAYING_FILE is also a better one to detect the start of playback (and it gives you the filename in the wparam as well).
-daz
Luke-23
20th March 2007, 00:40
I must say the more I look the more I get confused :/
I want to track the 5 main control buttons, volume, shuffle and repeat, and actions done to the playlist. Therefore I checked what the parameters are when I press play and stop and so on, but i don't seem to figure out what actually happens. In wa_ipc.h it says
// wParam =
[...]
#define IPC_CB_MISC 603
but I used IPC_CB_MISC as lParam and it works! I mean, my problem really is that I don't really have an idea which parameter when is used. Can you give me a hint where I can read about it or how to figure it out?
Luke-23
22nd March 2007, 16:50
I'm sure no one will answer me again, but... how do you get the volume? There's a lot of set_volume stuff but I just can't seem to find anything for reading the volume, so if anyone knows, please, please answer me...
edit: And oh, I forgot. In order to do that event-subclassing properly you need to put
SetWindowLong(plugin.hwndParent, GWL_WNDPROC, (LONG)lpWndProcOld);
in your quit()-function
DrO
22nd March 2007, 17:02
for the buttons thing, i think you just need to look for WINAMP_BUTTON1, etc for the relevant buttons in LOWORD(wparam) for the WM_COMMAND message (sure that'll work even in the main window)
for getting the volume call ipc_setvolume with -666 as the value of wparam.
as for the unsubclassing, the following is slightly better i've found for the unsubclassing...
if(GetWindowLongPtr(winampwnd,GWLP_WNDPROC) == MY_WND_PROC_USED){
SetWindowLong(winampwnd,GWLP_WNDPROC,(LONG_PTR)lpWndProcOld);
}
also see this (http://forums.winamp.com/showthread.php?postid=2154693#post2154693) for better handling when doing the subclass of the main winamp wndproc otherwise you'll have angry unicode users on your door :)
-daz
Luke-23
22nd March 2007, 21:55
Wow, thanks a lot for your answer!
But... I know it sucks when newbies keep asking for every step they make showing no sign of trying to find out something for themselves, but I still have one big question: How do you track changes made to the playlist? I've seen there's IPC_PLAYLIST_MODIFIED, but it just says "something happened to the playlist" and doesn't provide any further information. I'm writing an application that will work as a WLAN-remote-control for Winamp, so I need to track the changes exactly (sending the whole playlist every time a change has been made would be insane); do I have to do that 'manually' (like comparing the playlist with it's previous state every time) or do you know any nice way to do this?
DrO
22nd March 2007, 23:08
there's no nice way to do it. for my jtfe plugin i use a delayed update cache to resynch up against changes in the playlist (though it's far from ideal). there's other ways such as comparing the playlist against you're copy and altering what doesn't match. or like i do with gen_undo, just make winamp save the current playlist and work from that. either way it's something that's never been great and from my understanding, to make it give what/where the action was wouldn't easily fit with the existing code (and it then falls into the if it ain't broke don't fix it option for what's already there).
remote interaction of the level i think you're going to aim for has never really happened (or at least too well i think) but there's always a first :)
-daz
Luke-23
23rd March 2007, 19:45
Originally posted by DrO
there's no nice way to do it.
Too bad, anyways, it's do-able.
Originally posted by DrO
remote interaction of the level i think you're going to aim for has never really happened
Really? I wonder why... . However, Thank you for your help!
Luke-23
25th March 2007, 20:51
I know it sucks asking for everything, but I'm stuck with getting the playlist. How do you do that? Do you really have to go through the whole list and fetch information on every item? Is there no IPC_GETPLAYLIST or something?
DrO
25th March 2007, 21:15
it's either doing IPC_GETPLAYLISTFILE based on IPC_GETLISTLENGTH entries or you call IPC_WRITEPLAYLIST and read it manually (is staved to %inidir%\winamp.ini & use IPC_GETINIDIRECTORY to get the correct path of %inidir%)
-daz
Luke-23
25th March 2007, 21:37
So I guess there's no way to get like a unique ID for each song, without creating it manually?
DrO
25th March 2007, 21:40
correct
-daz
Luke-23
25th March 2007, 21:41
Ok, thanks a lot for your help daz.
vBulletin® v3.8.6, Copyright ©2000-2013, Jelsoft Enterprises Ltd.