Developing PM123 Plug-ins

PM123 supports four kinds of plug-ins: visual, decoder, output and filter. Visual plug-ins are used to peek at the data currently being heard (or not) by the user through the output plug-in and visually produce data from it back to the user. Decoder plug-ins are used to decode different types of files, tracks or streams the user can play. Output plug-ins is the final destination of the decoded data. It can be rerouted to a sound card, to the hard disk or anywhere else appropriate. The data is in standard PCM format. Filter plug-ins are chained between the decoder and the output plug-in to modify the PCM data before getting to the output plug-in.

Visual plug-in interface has not been changed since version 1.0, eventhough they could be ameliorated in the future. Currently, Visual plug-ins allow the creation of internal or external windows and they can tap into PM123 in several ways: they can retrieve currently playing samples, control PM123 and so on. Plug-ins are Dynamic Linked Libraries, DLLs, which PM123 loads on use.

Note that visual plug-ins cannot be loaded via PM123's Properties dialog because they are skin specific. They can of course be loaded when loading a new skin.

plugin.h contains the necessary structures for all pm123 plug-ins. All exported and callback functions must use the calling convention _System. A plug-in must have a function that identifies it as a plug-in:

     int DLLENTRY plugin_query( PPLUGIN_QUERYPARAM param );
The plug-in will then have to fill the variables in the param structure, for example:
     param->type         = PLUGIN_VISUAL; 
     /* Identify the plug-in as visual plug-in. Types can be ORred to
        include multiple plug-in types in the same DLL. */

     param->author       = "Matti Meikäläinen";
      /* Author of the plug-in */

     param->desc         = "Example plug-in";
      /* A short description of the plug-in */

     param->configurable = TRUE;
      /* Toggles plug-in configurability via PM123 Properties dialog */
      
     param->interface    = 2;
      /* This is the required interface revision level.
       * This parameter defaults to 0 which is the same as before this field existed.
       * Plug-ins with Level 0 must not fill this field to be compatible with older
       * versions of PM123.
       */
     
     return 0;
If you set param->configurable = TRUE, configuration dialog should appear when PM123 calls
     void DLLENTRY plugin_configure( HWND hwnd, HMODULE module );
where hwnd is the notebook or player window so that you can "lock" your window on it if you want and where module can be used to load a resource from your DLL

Plug-ins should deinitialize and destroy their windows and free allocated memory when receiving a

     int DLLENTRY plugin_deinit( int unload );
It can also be used to save settings in your INI file for other sort of plug-ins.

Plugin types

Now, which type of plug-in to you want to program?

Interface levels

The interface level is used to ensure compatibility of plug-ins over different versions of PM123. The field defaults to 0 representing the oldest implementation. Larger values reflect changes to the plug-in interface. The interface level reflects changes to any of the plugin interfaces, so different levels do not neccessarily mean different interfaces of one plug-in interface. A change in the interface may be only a modified semantic of a function call or it may be a complete change of the interface with entirely other function names or whatever. See the individual PDK documentation of the desired plug-in type to get further information for each plug-in type.
A new plugin is not necessarily required to use the most recent interface level.

Overview:
Interface-Level PM123 version Visual Filter Decoder Output
0 n/a no longer supported! supported supported supported but deprecated
1 ≥ 1.32 1 recent supported,
same as level 0
supported,
same as level 0
supported but deprecated,
same as level 0
2 ≥ 1.4 recent,
same as level 1
recent redesign recent redesign recent redesign

  1. PM123 version 1.32 does not check for the compatibility of plug-ins. When a wrong plug-in is used, the application will most likely crash.

For example a filter plug-in will be loaded depending on it's interface level by a PM123 instance with interface level 2 (compile time constant) in the following way:
Interface level Action taken
2 Loaded native
1 Loaded via a proxy in compatibility mode.
0 Loaded via a proxy in compatibility mode.
Level 0 is identical to level 1 with respect to the filter plug-in interface.
>2 Error, because the interface is potentially incompatible and not supported by this PM123 core.