dd wrote:
I'm not talking about writing a script, I'm talking about writing a real gimp plugin. Vala is a compiled language, not a scripting language.
You are correct in characterizing what you want to do as writing a plug-in; however, it should be noted that the distinction between a script and a plug-in has nothing to do with whether the code is compiled. Plug-ins execute "outside" of GIMP and interface with GIMP functions through the PDB and libgimp. Scripts are written in Scheme and interpreted by GIMP's built-in Script-fu interpreter. A filter written in Python is still a plug-in; even though its code may be interpreted, it is interpreted "outside" of GIMP.
dd wrote:
Furthermore, Vala compiles to C and uses the same GObject type system that Gimp uses, so it should be totally possible to write plugins for Gimp with it.
GIMP's plug-in/PDB functionality does not use the GObject type system; to write plug-ins in Vala, when calling PDB/libgimp functions, you will need to convert your GObject parameters to their corresponding PDB arguments (and conversely for the return values). Your task is simplified by the fact that there is a great deal of similarity between the two types, but the data objects are not the same.
To write a plug-in in VALA, you would need to implement at least the following functionality:
Create a C GimpPlugInInfo struct that contains pointers to four "callback" procedures: INIT, QUIT, QUERY, and RUN. 'RUN' is typically the only one that is actually needed (the rest can be NULLs).
Define your four callbacks, or at least the ones you are using (e.g., just RUN). The first three procedures don't accept any parameters, while RUN is expected to handle the following arguments: name, number_of_parameters, list_of_parameters, number_of_return_values, and a list_of_return_values. See
libgimp/gimp.h for more details.
Call the C function 'gimp_main()', passing it the GimpPlugInfo struct you created, as well as argc and argv. (NOTE: because Microsoft requires some additional information for setting up the "gimp_main" process, this approach will not work on Windows. I don't quite know how this would be accomplished in Vala but you could look at the MAIN macro in libgimp/gimp.h to see how it is done in C). This gimp_main() function is effectively an "event loop" that waits for messages from GIMP and executes the corresponding callback function (INIT, QUIT, QUERY, RUN) when received; in a manner similar to how gtk_main or GMainloop work for graphics/glib programming.
In addition to the above, you will need a binding to the 'gimp_install_procedure()' C function, so you can install your plug-in. This function takes a set of arguments similar to the ones passed to your RUN callback, but with additional arguments for the help blurb, author, copyright, data. menu placement, and menu constraints. Again, see libgimp/gimp.h for further details.
Finally, you will need to implement 'gimp_run_procedure()' in Vala (i.e., create a binding to the C function) so that you can invoke the RUN callbacks of other PDB functions. The arguments passed to 'gimp_run_procedure()' need to match the parameters expected by the PDB procedure you are calling.
That is the gist of how you'd write a GIMP plug-in in Vala (or any other language). However, you will likely want to create some Vala-specific helper functions or else your code would need to be written similar to the following (which is a simple call to create a new image):
struct GimpParam arg[3];
arg[0].type = 0; /* GIMP_PDB_INT32 */
arg[0].value = 640; /* width of the new image */
arg[1].type = 0; /* GIMP_PDB_INT32 */
arg[1].value = 480; /* height of the new image */
arg[2].type = 0; /* GIMP_PDB_INT32 */
arg[2].value = 0; /* RGB image */
struct GimpParam rval[1];
gimp_run_procedure("gimp_image_new", 2, arg, 1, &rval);
gint32 img;
img = rval[0].value;
That is obviously not how you'd want to write a plug-in!
The task of going through the PDB and autogenerating Vala templates for each of the procedures is conceptually trivial (you'd need a binding to 'gimp_procedural_db-query()') but it is something you'd only want to be done once -- you wouldn't want every Vala plug-in written to declare all the possible data types and generate all of the PDB procedure templates. Therefore you'd write a Vala extension to GIMP, just as people have written extensions for Python, Perl, and various other languages.
Should you decide to tackle this problem, the above will hopefully prove helpful in getting you started. It is obviously not an impossible task, but it is also not something you're likely to finish in a weekend.
Also, I might suggest an alternative that is a bit larger in scope, but in the long run should prove of greater benefit to the GIMP project as a whole. That would be to convert the entire GIMP PDB/plug-in interface to use DBUS instead -- or at least write a DBUS wrapper for libgimp/PDB. I believe that if this were done than your Vala interface would become almost trivial because DBUS
does use the same GObject system for data and facilitates procedure calls between processes. Just a thought.