Basic Plugin Guide - Tutorial

From Winamp Developer Wiki
Revision as of 20:04, 13 July 2009 by SMonty (Talk | contribs)

Jump to: navigation, search

Accessing information from Winamp

Our first page Beginner's Basic Plugin Guide showed you how to create a general plugin dll that will be invoked by Winamp when it is loaded, configured and quit. While this is really cool, it lacks something. Let's fix that now.

Keeping it simple

In order to keep these explanations simple, I'd rather not add a lot of code to create a Windows UI. We will eventually create a UI, but first let's invoke some Winamp 2 API methods. Just to see how they work.

When we last left our hero....err plugin, we had created three methods 'init', 'config' and 'quit'. 'init' is invoked by Winamp when the plugin is first loaded. 'quit' is invoked by Winamp when the plugin is unloaded, i.e., when Winamp is closing. 'config' is invoked when someone configures the plugin. A user can configure a plugin by selecting Options->Preferences->Plug-ins->General Purpose, clicking on the plug-in in the right hand pane and then pressing the 'Configure selected plug-in' button. Note that I will refer to this as 'configuring the plugin' from now on as that much typing is annoying.

While we would normally add code to 'init' to set up our UI and event notification system, let's keep it even simpler than that (we'll cover the basics of that in a future tutorial). Let's add the API calls to the 'config' method for now. Just to see how they work.


The top secret, knows everything, key to the executive washroom file is called wa_ipc.h. This file defines constants for all of the Winamp 2 API methods that are made available for external developers. And they are fairly well documented (gasp). Yes, I know this sounds impossible, when do developers actually write documentation? Well trust me this file is very well documented so it does happen.

This header can be found in the SDK under the Winamp SDK\Winamp directory. Add these two lines to the top of gen_myplugin.cpp:

#include "wa_ipc.h"
#include <stdio.h>

But wait! This isn't enough. There's always a catch. The compiler has no idea where to find wa_ipc.h. So we have to tell it. Navigate to Project->gen_myplugin Properties->Configuration Properties->C/C++->General and enter the path to the Winamp directory under the base directory where you installed the Winamp SDK. Now Visual studio should be able to find the header.

Calling an API Method

Hmmm, what should we do....How about we get the version of Winamp that is currently running? Sounds like a useful thing for a plug-in to do. Place the following code into the 'config' method, immediately under the MessageBox about the config event.

wchar_t msg[1024];
int version = SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETVERSION);
int majVersion = WINAMP_VERSION_MAJOR(version);
int minVersion = WINAMP_VERSION_MINOR(version);
wsprintf(msg,L"The version of Winamp is: %x\n"
  L"Major version: %x\nMinor version: %x\n",
MessageBox(plugin.hwndParent,msg,L"Winamp Version",MB_OK);

Compile the plugin and move the dll over into the Winamp plug-ins directory (make sure to exit Winamp before trying to copy the dll, Windows can be so possessive.) Start Winamp. After Winamp starts and you see the message about the 'init' being called, 'configure' the plugin and you should see the 'config' event message, press OK. If you've done everything correctly you should now see the version message box appear.

Examining the Code

The first line declares a buffer of 1024 wchar_t. This buffer is used to format output that we want to add to the MessageBox.

The second line uses Windows SendMessage API to send a message, WM_WA_IPC (second parameter), in this case to plugin.hwndParent (first parameter). WM_WA_IPC indicates a message that Winamp is supposed to handle rather than Windows itself. The third parameter is usually used to pass a parameter (known as a WPARAM in Windows) and is set to 0. The fourth parameter (known as an LPARAM in Windows) is a constant that identifies what we want Winamp to do for us, in this case 'get me the version of winamp'.

But 'Hold on Thar Partner' you might be saying. Where did that plugin.hwndParent come from? We didn't set it in our plug-in. Turns out that Winamp stored the handle to its main window into the plugin structure when it loaded it. Notice the method used to retrieve the plugin (winampGetGeneralPurposePlugin) actually returns a reference to the plugin? Cool huh, Winamp can then load the hwndParent and hDllInstance and it becomes available to the plug-in. The point is that we are sending messages to the Winamp main window so that it can give us the info we're looking for.

The next two lines use macros defined in WA_IPC.h to break apart the version into major and minor numbers. Another useful feature when you need to know the version of Winamp to determine whether a feature is supported.

The rest of the new lines format a wide string (wsprintf) so we can use it in MessageBox to print it to the screen.

Examining the wa_ipc.h file

How did I know what to use for WPARAM and LPARAM? Well the wa_ipc.h file of course. Go ahead and open it in Visual Studio. The first thing you'll notice is blocks of comments. Blocks of comments? OH YEAH. Let's just look at the comments for five minutes, I'll wait......

Seriously, if you scroll down in this file you'll see the Winamp 2 API methods.