There are some things every plug-in simply must have if it is to be considered a plug-in, no matter what its purpose. Mainly, the plug-in has to register itself in the GIMP's procedure database, and it has to have a function to run when GIMP calls for that procedure. Here we'll look at how these functions are called, and just what components they really need.
Every C program has a main()
function
— the first function that is called when the program is
executed. The typical GIMP plug-in's main function is, in its
entirety, as follows:
MAIN()
MAIN is a macro, defined in libgimp/gimp.h, which calls a
gimp_main
function, which in turn does all
sorts of neat stuff. It tries to make sure the plug-in is being
called by GIMP, sets up some signal handling, sets up
communication between the plug-in and GIMP, and queries the
plug-in if need be.
GIMP queries plug-ins on start-up, and it expects them
to register themselves in the procedural database (PDB). But
how does GIMP know what function to call when it queries? It
checks the value of the global variable
PLUG_IN_INFO, of type
GimpPlugInInfo
. From gimp.h:
Figure 2-1. The GimpPlugInInfo Structure
typedef void (* GimpInitProc) (void); typedef void (* GimpQuitProc) (void); typedef void (* GimpQueryProc) (void); typedef void (* GimpRunProc) (gchar *name, gint nparams, GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); struct _GimpPlugInInfo { /* called when the gimp application initially starts up */ GimpInitProc init_proc; /* called when the gimp application exits */ GimpQuitProc quit_proc; /* called by the gimp so that the plug-in can inform the * gimp of what it does. (ie. installing a procedure database * procedure). */ GimpQueryProc query_proc; /* called to run a procedure the plug-in installed in the * procedure database. */ GimpRunProc run_proc; };
So PLUG_IN_INFO consists of pointers to
four functions. The first two are ran when GIMP starts and
exits, not commonly used among the plug-ins, and so are usually
set to NULL. The third is the
query
function, which many plug-in authors
have chosen to name query()
. The fourth is
called when the plug-in's procedure is to be run, and is,
surprisingly enough, often called run()
.
An example:
Example 2-1. Defining PLUG_IN_INFO
/* Function prototypes */ static void query (void); static void run (gchar *name, gint nparams, GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); /* Setting PLUG_IN_INFO */ GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ };
As mentioned, GIMP expects plug-ins to register
themselves in the PDB when they're queried. This is done through
gimp_install_procedure
(again, from
gimp.h):
Figure 2-2. gimp_install_procedure
void gimp_install_procedure
(char* name, char* blurb, char* help, char* author, char* copyright, char* menu_path, char* image_types, GimpPDBProcType type, int nparams, int nreturn_vals, GimpParamDef* params, GimpParamDef* return_vals);Parameters name through date should be fairly self-explanatory. On the rest, I'll make some comment:
A string describing where in the menu the procedure should be installed. It begins with one of <Toolbox>, <Image>, <Load>, or <Save>, followed by the menu path. For example, the Maze plug-in's menu_path is "<Image>/Filters/Render/Patterns/Maze...".
GIMP uses this information not only to place the menu, but also to decide what type of procedure it is. This affects its decision on which parameters are necessary for the procedure. Note also that a menu_path isn't required if you wish to install a procedure without one, but that's not the case for most plug-ins.
Source reference: app/plug_in.c, plug_in_handle_proc_install
A string listing what image types the plug-in will accept; any of RGB, RGBA, RGB*, GRAY, GRAYA, GRAY*, INDEXED, INDEXEDA, INDEXED*. RGB* is simply shorthand for both RGB and RGBA (same applies for GRAY* and INDEXED*). The list may be separated by spaces, tabs, or commas. Example: "RGB*, INDEXED" means the plug-in likes all RGB images (with or without alpha), indexed-color images (only without alpha), but not grayscale images of any sort.
Source reference: app/plug_in.c, plug_in_image_types_parse
The number of parameters (or return values) the procedure uses.
See below.
*params points to an array of
parameter definitions. nparams is an
integer that tells the number of parameters (equal to the
length of the array). A parameter definition is of type
GimpParamDef
, which has three parts gimp.h:
struct _GimpParamDef { GimpPDBArgType type; gchar *name; gchar *description; };
Values for GimpPDBArgType are listed in gimpenums.h. Setting up parameters can be done like so:
Example 2-2. Establishing an array of parameters.
static GParamDef params[] = { { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" }, { GIMP_PDB_IMAGE, "image_id", "(unused)" }, { GIMP_PDB_DRAWABLE, "drawable_id", "Drawable to draw on" }, { GIMP_PDB_COLOR, "fgcolor", "Color to draw with"} }
You may be required to take certain parameters, depending on where in the menu you registered. You may ignore them once you get them, but they will be passed to you, so you must accept them nonetheless. (app/plug-in.c, plug_in_handle_proc_install):
Table 2-1. Menu locations and required parameters
Menu Location | # | Parameter type | Description |
---|---|---|---|
<Toolbox> | 0 | INT32 | run mode |
<Image> | 0 | INT32 | run mode |
1 | IMAGE | ID of current image | |
2 | DRAWABLE | ID of current drawable | |
<Load> | 0 | INT32 | run mode |
1 | STRING | FIXME | |
2 | STRING | FIXME | |
<Save> | 0 | INT32 | run mode |
1 | IMAGE | ID of current image | |
2 | DRAWABLE | ID of current drawable | |
3 | STRING | FIXME | |
4 | STRING | FIXME |
You may take any parameters you like in addition to the ones required. The required parameters must come first and in order, however.
Declaring return values works much the same way, with
one note: Your procedure will have at least one return value
(a status code), but that should not be counted in your
nreturn_vals or included in your GParamDef
return_vals.
/* called to run a procedure the plug-in installed in the * procedure database. */ typedef void (* GimpRunProc) (gchar *name, gint nparams, GimpParam *param, gint *nreturn_vals, GimpParam **return_vals);
The run procedure is where the action begins. Its responsibilities include making sure the plug-in was called correctly and setting return values, as well as making sure that your plug-in does whatever it is that it's supposed to do.
GIMP 1.1 Compatibility Note: In GIMP 1.1, the run parameter is always called with nparams == 3, when called in the normal interactive fashion (plug_in_callback, app/plug_in.c). This differs from GIMP 1.0 behaviour, where nparams was equal to whatever it was set to upon installation of the procedure in the query function.
struct _GimpParam { GimpPDBArgType type; GimpParamData data; };
union _GimpParamData { gint32 d_int32; gint16 d_int16; gint8 d_int8; gdouble d_float; gchar *d_string; gint32 *d_int32array; gint16 *d_int16array; gint8 *d_int8array; gdouble *d_floatarray; gchar **d_stringarray; GimpParamColor d_color; GimpParamRegion d_region; gint32 d_display; gint32 d_image; gint32 d_layer; gint32 d_layer_mask; gint32 d_channel; gint32 d_drawable; gint32 d_selection; gint32 d_boundary; gint32 d_path; gint32 d_unit; GimpParasite d_parasite; gint32 d_tattoo; gint32 d_status; };
Note that GimpParamData is a union, not a structure. It only holds one value at a time.
It's expected (in app/procedural_db.c
that you return a status code as the first return value (the
zeroth in C land). That's a GimpPDBArgType
of
GIMP_PDB_STATUS, and a value from
GimpPDBStatusType
(GIMP_PDB_EXECUTION_ERROR,
GIMP_PDB_CALLING_ERROR,
GIMP_PDB_PASS_THROUGH,
GIMP_PDB_SUCCESS), or
GIMP_PDB_CANCEL).
What every plug-in needs:
#include <libgimp/gimp.h>
PLUG_IN_INFO
MAIN
A query
function, with a call
to gimp_install_procedure
.
A run
function, setting a status code return value.
We've said what's required. Now, what's a good idea? This section previously contained some well-intentioned practical advise on how to implement what you just learned, but it was so terribly written that I can't bear to bring it back. So for learning about implementations, I'm afraid you'll be much better off reading source code until this gets re-written.
Move on to the next section to learn more things…