The Plugin Library
This page applies to Harlequin v13.1r0 and later; and to Harlequin MultiRIP but not Harlequin Core
The plugin library provides services required by plugins on all supported machines. If a plugin needs to access these routines it should be linked with one of the libraries supplied in the Common/lib folder of the plugin kit. Use the release or debugging version as appropriate.
Note:
You should be aware that in CoreModule plugins, calls to D_LIB_SELECT
are only made during plugin startup and shutdown. An additional mechanism is provided to support RIP Monitor messaging during screening. See Core module plugins
for more information.
Because plugins cannot make direct calls to the RIP, the plugin library provides a method for the RIP to call back into the plugin via the ordinary selector mechanism, using a selector called D_LIB_SELECT
see D_LIB_SELECT
. For this reason, there is a global context managed jointly by the RIP, the plugin library and D_LIB_SELECT
, which all plugins using the plugin library must implement as a direct call to the library function PluginLibSelect
.
For output plugins, the global context is obtained when the plugin library is initialized with PluginLibInitialise
, which should be called during the D_INITIALISE
selector call. (This can end up being called many times as the plugin is loaded and unloaded.)
For input plugins, the plugin library is initialized with InputPluginLibInitialise
, which should be called during the D_IP_INITIALISE
selector call.
For CoreModule plugins, the global context is obtained when the plugin library is initialized with a call to its GenericPluginLibInitialise
function.
The result of the initialization function call must be stored somewhere for use by the D_LIB_SELECT selector call later. Plugins can simply store this pointer in a static variable of type:
struct pluginLibGlobals *
Alternatively, a plugin can store the variable in the d_libglobals
field of the deviceDefinition
structure (for output plugins) or in the globalState
of the IPPluginContext
(for input plugins).
For example, the typical parts of an input plugin concerned with delivering a message to the monitor window might be as follows:
static struct pluginLibGlobals * pluginLibraryContext = NULL ;
...
switch (selector) {
...
case D_IP_INITIALISE:
...
pluginLibraryContext = InputPluginLibInitialise ( (IPPluginContext *) param1,
&((plugInitParam *) param2)->version );
...
PluginOutMonitor ( pluginLibraryContext,
"Hello from this plugin\n" );
...
break;
case D_LIB_SELECT:
return PluginLibSelect ( pluginLibraryContext, (devLibSelectParam *) param2 );
break;
case D_SELECTOR_SUPPORT:
switch (* ((int32 *) param2)) { case D_IP_INITIALISE:
case D_LIB_SELECT:
case D_IP_SHUTDOWN:
case D_<some selector>:
...
return NoErr; default:
return 0;
case D_<some selector>:
...
PluginOutMonitor ( pluginLibraryContext,
"This is another message from the plugin.\n" );
...
break;
case D_IP_SHUTDOWN:
...
PluginLibShutdown (pluginLibraryContext); pluginLibraryContext = NULL ;
break;
}
We recommend that plugins “introduce” themselves in the RIP Monitor window when first loaded. This feedback can be useful if something goes wrong: it is easy to tell exactly when a plugin has been loaded, and a permanent record is kept in the RIP LOGFILE
. To deliver this message, the plugin has to use the plugin library.