Talk:Beginner's Basic Plugin Guide

From Winamp Developer Wiki
Jump to: navigation, search

Is this format okay?

Hey everyone, this is my first work with any Winamp plugin code and my first edits to the wiki. Sorry if anything is in the wrong format or wrong place. Please feel free to move or work on it; I'm open to suggestions on how to improve. --Culix 02:29, 10 June 2009 (UTC)

Questions and TODO

I still have a few questions about writing plugins. These should probably be filled into the guide at some point. --Culix 02:34, 10 June 2009 (UTC)

  • How do the naming conventions work for plugins? It seems more complicated than simply naming your file 'gen_*' or 'ml_*'.

The answer to this is complicated, as so much with Winamp. The prefix is actually used by Winamp.exe to find plugins and identify what type they are. There is another way to create plugins that does not require the prefix. This second way is called Wasabi. Wasabi is a way to 'share' code among components of a software system (i.e., Winamp). Wasabi dlls do not need the prefix. We'll get to Wasabi if we keep writing these kinds of tutorials. Is there something specific about the prefixes that leads you to believe that there is a 'real' answer? Maybe I can investigate further.


  • For the "cannot convert parameter from 'const char [x]' to 'LPCTSTR'" error, which option from the MSDN FAQ should we actually use? Is it better to change the project settings to use a multi-byte character set?

I would not change the project settings and instead use the L"" or _TEXT constructs to indicate that the strings are wide strings. Winamp programmers prefer to be even more specific and actually call the MessageBoxW() or MessageBoxA() methods to make it absolutely clear as to which function and what form the input is in (this would make the project switch meaningless). Since Winamp is a very popular application around the world it is best to use UNICODE.

Having said that, Winamp is also ancient (in computer years) and so every once in a while you might run across places within Winamp that do not handle UNICODE and will require ASCII strings. For example, notice the description field of the winampGeneralPurposePlugin structure. It was never converted to use UNICODE since that would change the size of the structure requiring a new revision and all the attendant problems that go along with that.


  • Why do some people put their 'extern "C" __declspec' code in the header and others in the .cpp? Does it matter?

The point of the extern "C" is to tell the linker not to perform C++ name mangling on the function name. This is necessary when some other application needs to invoke the method and therefore needs to use a name that is easier to use. Technically it doesn't matter whether you put them in a header or cpp file and it boils down to the more common reasons why you choose to put things in header files rather than including them in the cpp file.

Crash Issue

Basic gen_empty.dll File Crashes WinAMP On Start Of WinAMP.

I have turned off pre-compiled headers in VS 2008 Pro. Right Click On Solution-->Properties-->Configuration Properties-->Linker-->Additional Dependencies has been blanked. Right Click On Solution-->Properties-->Configuration Properties-->C/C++ -->Precompiled Headers-->Create/Use Precompiled Header = "Not Using Precompiled Headers" WinXP with service pack 3. WinAMP 5.56 with Pacemaker and Playlist File Remover plugins installed. WinAMP was running just fine with Pacemaker, though Playlist File Remover doesn't send files to the recycle bin like it should (It worked in prior versions of WinAMP, but not 5.56, that's why I want to write a plugin)

I get Visual Studio to compile a gen_empty.dll, but when I copy that to the "C:\Program Files\Winamp\Plugins" folder, WinAMP will crash on launch. It begins to create visible WinAMP application window outlines on the screen, but then it fails to complete. The outlined windows dissapear, and WinAMP.exe process vanishes from the task manager.

Removing the empty blank gen_empty.dll from "C:\Program Files\Winamp\Plugins" fixes the problem, WinAMP starts normally, just as it did before.

I even commented out the MessageBox-es so the functions would do NOTHING, and tried the resulting gen_empty.dll.

What is wrong with this generic, blank plugin source code that causes WinAMP 5.56 to fail? —The preceding unsigned comment was added by Ace Frahm (talkcontribs) 22:44, 20 September 2009.

//---------------------------------------------------------------------------
#ifndef gen_empty_h
#define gen_empty_h
#include <windows.h>
#include <stdio.h>
 
 
// plugin version (don't touch this)
#define GPPHDR_VER 0x10
 
// plugin name/title (change this to something you like)
#define GPPHDR_NAME "gen_empty v1.0 (gen_empty.dll)"
 
 
// main structure with plugin information, version, name...
typedef struct {
  int version;                   // version of the plugin, defined in "gen_empty.h"
  char *description;             // name/title of the plugin, defined in "gen_empty.h"
  int (*init)();                 // function which will be executed on init event
  void (*config)();              // function which will be executed on config event
  void (*quit)();                // function which will be executed on quit event
  HWND hwndParent;               // (?)
  HINSTANCE hDllInstance;        // (?)
} winampGeneralPurposePlugin;
 
 
extern winampGeneralPurposePlugin *gen_plugins[256];
typedef winampGeneralPurposePlugin * (*winampGeneralPurposePluginGetter)();
#endif
//---------------------------------------------------------------------------


//-----------------------------------------------------------------
// This is the main DLL file.
 
#include <stdio.h>
#include <windows.h>
#include "gen_empty.h"
 
 
// these are callback functions/events which will be called by Winamp
int  init(void);
void config(void);
void quit(void);
 
 
// this structure contains plugin information, version, name...
winampGeneralPurposePlugin plugin = {
  GPPHDR_VER,  // version of the plugin, defined in "gen_empty.h"
  GPPHDR_NAME, // name/title of the plugin, defined in "gen_empty.h"
  init,        // function name which will be executed on init event
  config,      // function name which will be executed on config event
  quit,        // function name which will be executed on quit event
};
 
 
// event functions follow
 
int init() {
//MessageBox(plugin.hwndParent, L"Init event triggered for gen_empty. Plugin installed successfully!", L"", MB_OK);
  return 0;
 
}
 
void config() {
//  MessageBox(plugin.hwndParent, L"Config event triggered for gen_empty.", L"", MB_OK);
 
}
 
void quit() {
//  MessageBox(0, L"Quit event triggered for gen_empty.", L"", MB_OK);
}
 
 
// this is an export function called by winamp which returns this plugin info
extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() {
  return &plugin;
}
//-----------------------------------------------------------------

Doesn't appear to be in the code

Hi, I examined your code and could see nothing that would cause Winamp to crash. I then copied the code you posted to my development machine, compiled it and moved it to the plugins directory and Winamp worked fine. I tested this on 5.56 and 5.57.

My thought would be to look at some of the project options you may have set as I believe the C++ code is not the problem. My first thought might be the packing for structures. —The preceding unsigned comment was added by SMonty (talkcontribs) 16:33, 21 September 2009 .

Next Steps

I think a good extension of this article would be to answer the user's question of "Okay, now what?". If we could give them hints about where to go next, possibly depending on the type of plugin they want to write, that might be useful. This may just involve fleshing out the guide articles for each type of plugin and then linking to those... unless someone can think of something better? --Culix 14:54, 10 June 2009 (UTC)

CLR Library

You're making a CLR library (which gives you full access to the .NET Framework), but using the Win32 MessageBox() call. Why? You can just add a reference to System.Windows.Forms and then use System::Windows::Forms::MessageBox::Show("Message")

)

--Daniel15 05:51, 25 November 2009 (UTC)