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.
_cdecl.
A plug-in must have a function that identifies it as a plug-in:
plugin_query is called before any other function and exactly once by PM123. The plug-in will then have to fill the variables in the param structure, for example:int DLLENTRY plugin_query( PPLUGIN_QUERYPARAM param );
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;
A second initialization function, plugin_init, is called by the plug-in manager once per plug-in after plugin_query.
int DLLENTRY plugin_init(const PLUGIN_CONTEXT* ctx);
The export of this function is optional. It provides some global entry points of PM123. They might be used to handle asynchronous events or requests. The structure and the functions must not be used after plugin_deninit returned.
/* Error message function. */
void DLLENTRY (*error_display)( const char* msg );
/* Info message function */
/* This information is always displayed to the user right away. */
void DLLENTRY (*info_display)( const char* msg );
/* Execute remote command */
/* See the documentation of remote commands for a description. */
const char* DLLENTRY (*exec_command)( const char* cmd );
/* retrieve configuration setting */
int DLLENTRY (*query_profile)( const char* key, void* buffer, int maxlength );
/* store configuration setting */
int DLLENTRY (*write_profile)( const char* key, const void* buffer, int length );
The exec_command
function causes
PM123 to execute a remote command as if it were sent to the remote pipe
interface. It returns the reply string. The returned storage is valid
until the next call to exec_command or until plugin_deinit.
Calls to exec_command must be
serialized.
The remote state information
like the currently selected playlist is private to the plug-in and does
not interfere with commands sent to the remote pipe or from other
plug-ins.
query_profile and write_profile
are similar to the profile OS/2 API functions PrfQueryProfileData
and PrfWriteProfileData.
But they read and write to a section dedicated to your plug-in the
current PM123.INI file which may not be the one in the application
folder. Using this functions is recommended over creating an individual
profile.
query_profile returns the length of the requested
Parameter or -1 on error. Independent of the returned length at most maxlen
characters are stored in buffer.
If you pass NULL as key,
a list of '\0' delimited keys is
returned. write_profile returns TRUE
on success and FALSE on error.
If you set param->configurable = TRUE in plugin_query, a 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.
Now, which type of plug-in to you want to program?
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 |
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. |