From af644b195084e32175f8c2eb4d92b91ec47e529d Mon Sep 17 00:00:00 2001 From: Jehan Date: Sat, 5 Aug 2023 18:58:57 +0200 Subject: [PATCH] =?UTF-8?q?libgimp,=20libgimpbase:=20new=20gimp=5Fload=5Fp?= =?UTF-8?q?rocedure=5Fnew2()=20for=20run()=20function=20using=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … a GimpProcedureConfig for arguments. This also factorizes the code to load metadata. By default, a GimpLoadProcedure will try and load metadata from a file (if Exiv2 knows the format). The run() function will be allowed to edit the GimpMetadata object but also the load flags before it is actually attached to the image, allowing plug-ins to have custom metadata handling code when needed. --- libgimp/gimp.def | 1 + libgimp/gimpimagemetadata.c | 1 - libgimp/gimploadprocedure.c | 151 ++++++++++++++++++++++++++++++++++-- libgimp/gimploadprocedure.h | 29 +++++++ libgimpbase/gimpmetadata.h | 2 + po-libgimp/POTFILES.in | 1 + 6 files changed, 179 insertions(+), 6 deletions(-) diff --git a/libgimp/gimp.def b/libgimp/gimp.def index 976df353b8..cc2279c440 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -619,6 +619,7 @@ EXPORTS gimp_load_procedure_get_thumbnail_loader gimp_load_procedure_get_type gimp_load_procedure_new + gimp_load_procedure_new2 gimp_load_procedure_set_handles_raw gimp_load_procedure_set_thumbnail_loader gimp_main diff --git a/libgimp/gimpimagemetadata.c b/libgimp/gimpimagemetadata.c index 35d8e44793..805ccaf4d7 100644 --- a/libgimp/gimpimagemetadata.c +++ b/libgimp/gimpimagemetadata.c @@ -121,7 +121,6 @@ gimp_image_metadata_load_finish (GimpImage *image, GimpMetadataLoadFlags flags) { g_return_if_fail (GIMP_IS_IMAGE (image)); - g_return_if_fail (mime_type != NULL); g_return_if_fail (GEXIV2_IS_METADATA (metadata)); if (flags & GIMP_METADATA_LOAD_COMMENT) diff --git a/libgimp/gimploadprocedure.c b/libgimp/gimploadprocedure.c index 09476dfe74..7b49dda525 100644 --- a/libgimp/gimploadprocedure.c +++ b/libgimp/gimploadprocedure.c @@ -25,6 +25,8 @@ #include "gimploadprocedure.h" #include "gimppdb_pdb.h" +#include "libgimp-intl.h" + /** * GimpLoadProcedure: @@ -53,6 +55,7 @@ struct _GimpLoadProcedurePrivate { GimpRunLoadFunc run_func; + GimpRunLoadFunc2 run_func2; gpointer run_data; GDestroyNotify run_data_destroy; @@ -193,11 +196,102 @@ gimp_load_procedure_run (GimpProcedure *procedure, gimp_value_array_append (remaining, value); } - return_values = load_proc->priv->run_func (procedure, - run_mode, - file, - remaining, - load_proc->priv->run_data); + if (load_proc->priv->run_func2) + { + GimpProcedureConfig *config; + GimpImage *image = NULL; + GimpMetadata *metadata = NULL; + gchar *mimetype = NULL; + GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL; + GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR; + + config = gimp_procedure_create_config (procedure); + mimetype = (gchar *) gimp_file_procedure_get_mime_types (GIMP_FILE_PROCEDURE (procedure)); + + if (mimetype != NULL) + { + char *delim; + + mimetype = g_strdup (mimetype); + mimetype = g_strstrip (mimetype); + delim = strstr (mimetype, ","); + if (delim) + *delim = '\0'; + /* Though docs only writes about the list being comma-separated, our + * code apparently also split by spaces. + */ + delim = strstr (mimetype, " "); + if (delim) + *delim = '\0'; + delim = strstr (mimetype, "\t"); + if (delim) + *delim = '\0'; + + metadata = gimp_metadata_load_from_file (file, NULL); + g_free (mimetype); + } + else + { + flags = GIMP_METADATA_LOAD_NONE; + } + + if (metadata == NULL) + metadata = gimp_metadata_new (); + + return_values = load_proc->priv->run_func2 (procedure, + run_mode, + file, + metadata, &flags, + config, + load_proc->priv->run_data); + + if (return_values != NULL && + gimp_value_array_length (return_values) > 0 && + G_VALUE_HOLDS_ENUM (gimp_value_array_index (return_values, 0))) + status = GIMP_VALUES_GET_ENUM (return_values, 0); + + gimp_procedure_config_end_run (config, status); + + if (status == GIMP_PDB_SUCCESS) + { + if (gimp_value_array_length (return_values) < 2 || + ! GIMP_VALUE_HOLDS_IMAGE (gimp_value_array_index (return_values, 1))) + { + GError *error = NULL; + + status = GIMP_PDB_EXECUTION_ERROR; + g_set_error (&error, GIMP_PLUG_IN_ERROR, 0, + _("This file loading plug-in returned SUCCESS as a status without an image. " + "This is a bug in the plug-in code. Contact the plug-in developer.")); + gimp_value_array_unref (return_values); + return_values = gimp_procedure_new_return_values (procedure, status, error); + } + else + { + image = GIMP_VALUES_GET_IMAGE (return_values, 1); + } + } + + if (image != NULL && metadata != NULL && flags != GIMP_METADATA_LOAD_NONE) + gimp_image_metadata_load_finish (image, NULL, metadata, flags); + + /* This is debug printing to help plug-in developers figure out best + * practices. + */ + if (G_OBJECT (config)->ref_count > 1) + g_printerr ("%s: ERROR: the GimpSaveProcedureConfig object was refed " + "by plug-in, it MUST NOT do that!\n", G_STRFUNC); + + g_object_unref (config); + } + else + { + return_values = load_proc->priv->run_func (procedure, + run_mode, + file, + remaining, + load_proc->priv->run_data); + } gimp_value_array_unref (remaining); @@ -275,6 +369,53 @@ gimp_load_procedure_new (GimpPlugIn *plug_in, return GIMP_PROCEDURE (procedure); } +/** + * gimp_load_procedure_new2: + * @plug_in: a #GimpPlugIn. + * @name: the new procedure's name. + * @proc_type: the new procedure's #GimpPDBProcType. + * @run_func: the run function for the new procedure. + * @run_data: user data passed to @run_func. + * @run_data_destroy: (nullable): free function for @run_data, or %NULL. + * + * Creates a new load procedure named @name which will call @run_func + * when invoked. + * + * See gimp_procedure_new() for information about @proc_type. + * + * Returns: (transfer full): a new #GimpProcedure. + * + * Since: 3.0 + **/ +GimpProcedure * +gimp_load_procedure_new2 (GimpPlugIn *plug_in, + const gchar *name, + GimpPDBProcType proc_type, + GimpRunLoadFunc2 run_func, + gpointer run_data, + GDestroyNotify run_data_destroy) +{ + GimpLoadProcedure *procedure; + + g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); + g_return_val_if_fail (gimp_is_canonical_identifier (name), NULL); + g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_INTERNAL, NULL); + g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_EXTENSION, NULL); + g_return_val_if_fail (run_func != NULL, NULL); + + procedure = g_object_new (GIMP_TYPE_LOAD_PROCEDURE, + "plug-in", plug_in, + "name", name, + "procedure-type", proc_type, + NULL); + + procedure->priv->run_func2 = run_func; + procedure->priv->run_data = run_data; + procedure->priv->run_data_destroy = run_data_destroy; + + return GIMP_PROCEDURE (procedure); +} + /** * gimp_load_procedure_set_handles_raw: * @procedure: A load procedure object. diff --git a/libgimp/gimploadprocedure.h b/libgimp/gimploadprocedure.h index 51d8e77968..d3e70d75e3 100644 --- a/libgimp/gimploadprocedure.h +++ b/libgimp/gimploadprocedure.h @@ -50,6 +50,29 @@ typedef GimpValueArray * (* GimpRunLoadFunc) (GimpProcedure *procedure, const GimpValueArray *args, gpointer run_data); +/** + * GimpRunLoadFunc2: + * @procedure: the #GimpProcedure that runs. + * @run_mode: the #GimpRunMode. + * @file: the #GFile to load from. + * @config: the @procedure's remaining arguments. + * @run_data: (closure): the run_data given in gimp_load_procedure_new(). + * + * The load function is run during the lifetime of the GIMP session, + * each time a plug-in load procedure is called. + * + * Returns: (transfer full): the @procedure's return values. + * + * Since: 3.0 + **/ +typedef GimpValueArray * (* GimpRunLoadFunc2) (GimpProcedure *procedure, + GimpRunMode run_mode, + GFile *file, + GimpMetadata *metadata, + GimpMetadataLoadFlags *flags, + GimpProcedureConfig *config, + gpointer run_data); + #define GIMP_TYPE_LOAD_PROCEDURE (gimp_load_procedure_get_type ()) #define GIMP_LOAD_PROCEDURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_LOAD_PROCEDURE, GimpLoadProcedure)) @@ -84,6 +107,12 @@ GimpProcedure * gimp_load_procedure_new (GimpPlugIn *plu GimpRunLoadFunc run_func, gpointer run_data, GDestroyNotify run_data_destroy); +GimpProcedure * gimp_load_procedure_new2 (GimpPlugIn *plug_in, + const gchar *name, + GimpPDBProcType proc_type, + GimpRunLoadFunc2 run_func, + gpointer run_data, + GDestroyNotify run_data_destroy); void gimp_load_procedure_set_handles_raw (GimpLoadProcedure *procedure, gboolean handles_raw); diff --git a/libgimpbase/gimpmetadata.h b/libgimpbase/gimpmetadata.h index 7038af3906..bb69480646 100644 --- a/libgimpbase/gimpmetadata.h +++ b/libgimpbase/gimpmetadata.h @@ -34,6 +34,7 @@ G_BEGIN_DECLS /** * GimpMetadataLoadFlags: + * @GIMP_METADATA_LOAD_NONE: Do not load the metadata * @GIMP_METADATA_LOAD_COMMENT: Load the comment * @GIMP_METADATA_LOAD_RESOLUTION: Load the resolution * @GIMP_METADATA_LOAD_ORIENTATION: Load the orientation (rotation) @@ -44,6 +45,7 @@ G_BEGIN_DECLS **/ typedef enum { + GIMP_METADATA_LOAD_NONE = 0, GIMP_METADATA_LOAD_COMMENT = 1 << 0, GIMP_METADATA_LOAD_RESOLUTION = 1 << 1, GIMP_METADATA_LOAD_ORIENTATION = 1 << 2, diff --git a/po-libgimp/POTFILES.in b/po-libgimp/POTFILES.in index 454a69f693..59c1001d99 100644 --- a/po-libgimp/POTFILES.in +++ b/po-libgimp/POTFILES.in @@ -6,6 +6,7 @@ libgimp/gimpbrushselectbutton.c libgimp/gimpexport.c libgimp/gimpimagemetadata.c libgimp/gimpimagemetadata-save.c +libgimp/gimploadprocedure.c libgimp/gimpparamspecs-desc.c libgimp/gimppatternselectbutton.c libgimp/gimppdb.c