gimpimagemetadata.[ch] was built into libgimpui because GTK+ was used
for dialog query for rotation metadata. gimpimagemetadata-save.c only
was built into libgimp, which made no sense as the declaration for its
public function was inside gimpimagemetadata.h!
That was a weird situation and somehow only made visible in the build
system because GIR build was complaining about missing annotations to
gimp_image_metadata_save_prepare() (the annotation was actually present
but in the implementation which was not in the same library as the
header, how weird!):
> Warning: GimpUi: gimp_image_metadata_save_prepare: return value: Missing (transfer) annotation
Moreover it means that only plug-ins linking libgimpui had access to the
gimp_image_metadata*() API, which is obviously not cool (that should be
a core API).
Instead I moved everything into libgimp and replaced
gimp_image_metadata_load_finish() with
gimp_image_metadata_load_finish_batch(), which is essentially the same
function except that it's not interactive (it will proceed to rotate the
image without user confirmation, provided the right flag is present).
Then I add gimpimagemetadata-interactive.[ch] which contains only
gimp_image_metadata_load_finish() and is the alternative interactive
version of gimp_image_metadata_load_finish_batch(). Most plug-ins won't
even have to be changed (at least none in core GIMP) and would still
work as before, whereas now a non-interactive version exists, which
doesn't mandate to link GTK+.
We're exposing symbols in our header files like `GType`, `GFile` and
others, without actually including the proper headers. This also gives
errors in the GIR scanner (who can't resolve those symbols).
export it to libgimp via GPConfig and add new API gimp_export_comment().
Bump the protocol version and improve variable names in both GPConfig
and libgimp/gimp.c.
Break reference cycles between the objects and the procedures they
keep by moving procedure destruction to dispose() and calling
g_object_run_dispose() before unrefing PLUG_IN and PDB in gimp.c.
Also some formatting and "Since: 3.0" annotation .
No need of is_id_arg() anymore in pdb/lib.pl. Let's reuse the {id}
value. Also I had to add an additional trick for GimpDisplay which we
will now generate as such in libgimp PDB files, but still need to show
as GimpObject on app/pdb/.
As previously, only the new classes and the PDB generation for a first
step.
which looks much like gimpconfig-params.h and contains macros
(e.g. GIMP_PROC_ARG_BOOLEAN() and GIMP_PROC_VAL_BOOLEAN()) for all
GimpProcedure argument and return value types supported by the
protocol, and makes the boilerplate of setting up a procedure more
readable and much less indented.
This file is C-only and not introspected.
which are GimpProcedure subclasses with API to register as load/save
handlers and their own kind of run functions that get their standard
arguments passed directly instead of packed into a GimpValueArray.
They also register their standard arguments themselves, which removes
quite some boilerplate from load/save plug-ins.
Remove gimpprocedure-private.[ch] because install() and uninstall()
are now virtual functions of GimpProcedure.
The idea is that we already have a GimpProcedure object in libgimp
which has name, help, blurb, arguments, return values and everything,
so we really don't need a parallel API to query PDB procedures for
their properties.
- make run() a virtual function of GimpProcedure
- move GIMP_PDB_ERROR to GimpPDB
- GimpPDBProcedure is a trivial subblass which populates
GimpProcedure's members by querying the PDB.
- make "plug-in", "procedure-type" and "name" construct-only
properties of GimpProcedure.
This is all work in progress.
Start copying all the actual wire communication to GimpPlugIn, and
move the legacy versions to gimplegacy.c.
This implies having the entire protocol code twice, but without any
if(PLUG_IN) { plug_in_stuff(); } else { legacy_stuff(); }
At the moment it is a wild mixture of old and new, but when finished
the wire code in gimplegacy.c will be entirely separate from the wire
code in GimpPlugIn, which will make it easy to g_assert() that only
one API is used by a plug-in.
which must be called by GIMP_EXTENSION procedures when they are ready
to run their temporary procedures. Move gimp_extension_ack() to
gimpobsolete.[ch].
which takes and returns GimpValueArrays. This or something similar is
the new central function for running core procedures. Use the new
function from gimp_run_procedure2().
The `data` property of a GimpParam is a union. Unfortunately setting a
union is not supported by GObject Introspection yet. So I create some
APIs to create GimpParam-s from values. Note that this is temporary API
(i.e. it may be removed before GIMP 3 release) since we likely won't use
this GimpParam type anymore with the new plug-in API. But for now, this
is necessary, at least for testing and porting Python plug-ins.
Also for GimpParam to be actually introspectable, I had to make it a
boxed type, but since no length information is available for various
variants of the type (arrays, whose length information is a separate
parameter), the copy and free functions are basically broken or leaking
respectively for all types requiring a length.
Bottom line: this is ugly and we really need a new introspectable
parameter type. But for now, it allows to start porting some of our
Python plug-ins.
Mostly the same code as GimpProcedure in app/pdb/.
Move the "run" function to GimpProcedure. Add API to GimpPlugIn to
list and create procedures, and always keep a list of the plug-ins
procedures around. Still only using the old params and return_vals.
The new way of doing plug-ins:
- subclass GimpPlugIn in your plug-in
- implement its query() and run() methods, run() will move to a
new GimpProcedure class soon
- instead of MAIN(), say GIMP_MAIN(YOUR_PLUG_IN_TYPE)
Instead of keeping around a GimpPlugInInfo struct, libgimp will
create an instance of your plug-in class, keep it around during
the plug-in's lifetime, and call its virtual functions.
... GimpRunProc function type.
In gimp_install_procedure(), make sure that @params and @return_vals are
processed as arrays, otherwise they are unusable.
As for the run procedure, make so that @return_vals and @n_return_vals
are considered as returned values. In Python binding for instance, that
makes these not parameters anymore, but actually returnable by the run
function.
With these changes, I made the first fully functional GI Python plug-in,
which just creates a new image and a display for this image. Still a lot
to improve clearly, but we are on the right track. :-)
This is an alternative way to set up a plug-in callbacks, apart from
setting directly the PlugInInfo struct properties.
The reason is that setting directly the Gimp*Proc properties crashes the
plug-in, when done through the Python GI binding.
It is most likely a bug in Pygobject, unless we need the proper
annotation (which I haven't found yet). See:
https://gitlab.gnome.org/GNOME/pygobject/issues/24#note_564968
Setting these callbacks from the C code works fine though, hence this
new API. It is to be noted that the '(scope async)' is the most
important part in this function annotations. Without these annotations,
the function pointers become invalid at the end of the set_callbacks()
call, hence the plug-in crashes when they are actually called.
Unfortunally I am also notified by ebassi that using (scope) at all (any
of the 3 possible values) is just wrong. An API change will be
necessary. For the time being, I leave this like this, for the sake of
testing further, but we'll need to improve things.
It doesn't really help yet with the problem I encountered allowing to
set and run these Python callbacks from the C code (cf. pygobject#347),
but at least let's improve a bit the documentation.
...upon exporting an image
Step 1: make it configurable just like "Export EXIF" etc.
app, libgimp: add "export-color-profile" config option
Add it to the preferences dialog, and pass it on to plug-ins in the
GPConfig message. Add gimp_export_color_profile() to libgimp.
Nothing uses this yet.
Also remove all traces of it from the plug-in protocol and raise the
protocol version to 0x0100 (we now allow features and therefore
version bumps in stable, and the master protocol version should always
be higher). Fix the code that aborts plug-in startup on protocol
version mismatch, we can't use gimp_message() because we have no
protocol.
Pass the current icon theme directory to plug-ins through the
config message, and add a gimp_icon_theme_dir() libgimp function
for retrieving it. Note that we already have a similar
gimp_icon_get_theme_dir() PDB function, which we keep around, since
it can be used to dynamically query for the current icon dir,
unlike the former, and since it returns a dynamically-allocated
string, while the rest of the config-related functions return
statically allocated strings.
Use the new function, instead of gimp_get_icon_theme_dir(), in
gimp_ui_init(). This allows gimp_ui_init() to run without making
any PDB calls. Consequently, this allows us to start plug-ins that
call gimp_ui_init() without entering the main loop in the main app.
We're going to add a plug-in that displays an interactive dialog
while the main app is blocking waiting for an operation to
complete, and we need to be able to start the plug-in without
entering the main loop, to avoid the possibility of arbitrary code
being executed during the wait.
Bump the protocol version.
... procedure call.
This is needed for plug-ins which depends on other plug-in's procedures.
If for instance, the second-level plug-in is interrupted interactively,
we don't want to process this as an error but as a cancellation.
Therefore we need to know the returned value of the plug-in. Currently
only way was to use gimp_get_pdb_error() but that was returning a
human-readable error, not a computer-processable error.