[gimp] app, libgimp, libgimpbase: big plug-in API refactoring part three



commit 0a6f157d58db6b85132a7cf42ed3f9ad970bc0d4
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jul 29 01:56:58 2019 +0200

    app, libgimp, libgimpbase: big plug-in API refactoring part three
    
    - libgimpbase: change GPParam to transfer all information about the
      GValues we use, in the same way done for GPParamDef. GPParam is now
      different from GimpParam from libgimp, pointers can't be casted any
      longer. The protocol is now completely GimpPDBArgType-free. Remove
      gp_params_destroy() from the public API.
    
    - libgimp: add API to convert between an array of GPParams and
      GimpValueArray, the latter is now the new official API for dealing
      with procedure arguments and return values, GimpParam is cruft (the
      wire now talks with GimpPlugIn more directly than with the members
      of GimpPlugInInfo, which need additional compat conversions).
    
    - libgimp, app: rename gimpgpparamspecs.[ch] to simply
      gimpgpparams.[ch] which is also more accurate because they now
      contain GValue functions too. The code that used to live in
      app/plug-in/plug-in-params.h is now completely in libgimp.
    
    - app: contains no protocol compat code any longer, the only place
      that uses GimpPDBArgType is the PDB query procedure implementation,
      which also needs to change.
    
    - app: change some forgotten int32 run-modes to enums.

 app/actions/gimpgeglprocedure.c                    |   2 +-
 app/actions/vectors-commands.c                     |   2 +-
 app/gui/gui-vtable.c                               |   2 +-
 app/pdb/gimp-pdb-compat.c                          | 110 -----
 app/pdb/gimp-pdb-compat.h                          |   3 +-
 app/plug-in/Makefile.am                            |   6 +-
 app/plug-in/{gimpgpparamspecs.c => gimpgpparams.c} |  13 +-
 app/plug-in/gimpgpparams.h                         |  44 ++
 app/plug-in/gimpgpparamspecs.h                     |  35 --
 app/plug-in/gimpplugin-message.c                   |  35 +-
 app/plug-in/gimpplugin.c                           |   1 -
 app/plug-in/gimppluginmanager-call.c               |   6 +-
 app/plug-in/plug-in-params.c                       | 442 ------------------
 app/plug-in/plug-in-params.h                       |  32 --
 app/plug-in/plug-in-rc.c                           |   6 +-
 app/widgets/gimphelp.c                             |   2 +-
 libgimp/Makefile.am                                |   6 +-
 libgimp/gimp.c                                     | 293 +++++++++---
 libgimp/gimpgpcompat.c                             |  86 ++--
 libgimp/gimpgpcompat.h                             |   9 +-
 libgimp/gimpgpparams-body.c                        | 515 +++++++++++++++++++++
 libgimp/{gimpgpparamspecs.c => gimpgpparams.c}     |   6 +-
 libgimp/gimpgpparams.h                             |  42 ++
 libgimp/gimpgpparamspecs-body.c                    | 134 ------
 libgimp/gimpgpparamspecs.h                         |  33 --
 libgimp/gimpprocedure-private.c                    |   2 +-
 libgimpbase/gimpbase.def                           |   1 -
 libgimpbase/gimpprotocol.c                         | 459 +++++-------------
 libgimpbase/gimpprotocol.h                         | 103 +++--
 29 files changed, 1066 insertions(+), 1364 deletions(-)
---
diff --git a/app/actions/gimpgeglprocedure.c b/app/actions/gimpgeglprocedure.c
index a901fba0ec..93bb49c944 100644
--- a/app/actions/gimpgeglprocedure.c
+++ b/app/actions/gimpgeglprocedure.c
@@ -273,7 +273,7 @@ gimp_gegl_procedure_execute_async (GimpProcedure  *procedure,
   GimpTool    *active_tool;
   const gchar *tool_name;
 
-  run_mode = g_value_get_int    (gimp_value_array_index (args, 0));
+  run_mode = g_value_get_enum   (gimp_value_array_index (args, 0));
   settings = g_value_get_object (gimp_value_array_index (args, 3));
 
   if (! settings &&
diff --git a/app/actions/vectors-commands.c b/app/actions/vectors-commands.c
index e2be6fa90a..d4be866cbf 100644
--- a/app/actions/vectors-commands.c
+++ b/app/actions/vectors-commands.c
@@ -406,7 +406,7 @@ vectors_selection_to_vectors_cmd_callback (GimpAction *action,
   args = gimp_procedure_get_arguments (procedure);
   gimp_value_array_truncate (args, 2);
 
-  g_value_set_int      (gimp_value_array_index (args, 0),
+  g_value_set_enum     (gimp_value_array_index (args, 0),
                         GIMP_RUN_INTERACTIVE);
   gimp_value_set_image (gimp_value_array_index (args, 1),
                         image);
diff --git a/app/gui/gui-vtable.c b/app/gui/gui-vtable.c
index f8a3374632..ad7bd3d2ce 100644
--- a/app/gui/gui-vtable.c
+++ b/app/gui/gui-vtable.c
@@ -496,7 +496,7 @@ gui_wait (Gimp         *gimp,
   args = gimp_procedure_get_arguments (procedure);
   gimp_value_array_truncate (args, 5);
 
-  g_value_set_int    (gimp_value_array_index (args, 0),
+  g_value_set_enum   (gimp_value_array_index (args, 0),
                       GIMP_RUN_INTERACTIVE);
   g_value_set_int    (gimp_value_array_index (args, 1),
                       output_pipe[0]);
diff --git a/app/pdb/gimp-pdb-compat.c b/app/pdb/gimp-pdb-compat.c
index 8493984f0c..fb68c8ea86 100644
--- a/app/pdb/gimp-pdb-compat.c
+++ b/app/pdb/gimp-pdb-compat.c
@@ -33,94 +33,8 @@
 #include "gimp-pdb-compat.h"
 
 
-/*  local function prototypes  */
-
-static gchar * gimp_pdb_compat_arg_type_to_string (GimpPDBArgType type);
-
-
 /*  public functions  */
 
-GType
-gimp_pdb_compat_arg_type_to_gtype (GimpPDBArgType  type)
-{
-  switch (type)
-    {
-    case GIMP_PDB_INT32:
-      return GIMP_TYPE_INT32;
-
-    case GIMP_PDB_INT16:
-      return GIMP_TYPE_INT16;
-
-    case GIMP_PDB_INT8:
-      return GIMP_TYPE_INT8;
-
-    case GIMP_PDB_FLOAT:
-      return G_TYPE_DOUBLE;
-
-    case GIMP_PDB_STRING:
-      return G_TYPE_STRING;
-
-    case GIMP_PDB_INT32ARRAY:
-      return GIMP_TYPE_INT32_ARRAY;
-
-    case GIMP_PDB_INT16ARRAY:
-      return GIMP_TYPE_INT16_ARRAY;
-
-    case GIMP_PDB_INT8ARRAY:
-      return GIMP_TYPE_INT8_ARRAY;
-
-    case GIMP_PDB_FLOATARRAY:
-      return GIMP_TYPE_FLOAT_ARRAY;
-
-    case GIMP_PDB_STRINGARRAY:
-      return GIMP_TYPE_STRING_ARRAY;
-
-    case GIMP_PDB_COLOR:
-      return GIMP_TYPE_RGB;
-
-    case GIMP_PDB_ITEM:
-      return GIMP_TYPE_ITEM_ID;
-
-    case GIMP_PDB_DISPLAY:
-      return GIMP_TYPE_DISPLAY_ID;
-
-    case GIMP_PDB_IMAGE:
-      return GIMP_TYPE_IMAGE_ID;
-
-    case GIMP_PDB_LAYER:
-      return GIMP_TYPE_LAYER_ID;
-
-    case GIMP_PDB_CHANNEL:
-      return GIMP_TYPE_CHANNEL_ID;
-
-    case GIMP_PDB_DRAWABLE:
-      return GIMP_TYPE_DRAWABLE_ID;
-
-    case GIMP_PDB_SELECTION:
-      return GIMP_TYPE_SELECTION_ID;
-
-    case GIMP_PDB_COLORARRAY:
-      return GIMP_TYPE_RGB_ARRAY;
-
-    case GIMP_PDB_VECTORS:
-      return GIMP_TYPE_VECTORS_ID;
-
-    case GIMP_PDB_PARASITE:
-      return GIMP_TYPE_PARASITE;
-
-    case GIMP_PDB_STATUS:
-      return GIMP_TYPE_PDB_STATUS_TYPE;
-
-    case GIMP_PDB_END:
-      break;
-    }
-
-  g_warning ("%s: returning G_TYPE_NONE for %d (%s)",
-             G_STRFUNC, type, gimp_pdb_compat_arg_type_to_string (type));
-
-  return G_TYPE_NONE;
-}
-
 GimpPDBArgType
 gimp_pdb_compat_arg_type_from_gtype (GType type)
 {
@@ -183,13 +97,6 @@ gimp_pdb_compat_arg_type_from_gtype (GType type)
 
   pdb_type = GPOINTER_TO_INT (g_type_get_qdata (type, pdb_type_quark));
 
-#if 0
-  g_printerr ("%s: arg_type = %p (%s)  ->  %d (%s)\n",
-              G_STRFUNC,
-              (gpointer) type, g_type_name (type),
-              pdb_type, gimp_pdb_arg_type_to_string (pdb_type));
-#endif
-
   return pdb_type;
 }
 
@@ -340,20 +247,3 @@ gimp_pdb_compat_procs_register (GimpPDB           *pdb,
                                             compat_procs[i].new_name);
     }
 }
-
-
-/*  private functions  */
-
-static gchar *
-gimp_pdb_compat_arg_type_to_string (GimpPDBArgType type)
-{
-  const gchar *name;
-
-  if (! gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, type,
-                             &name, NULL, NULL, NULL))
-    {
-      return  g_strdup_printf ("(PDB type %d unknown)", type);
-    }
-
-  return g_strdup (name);
-}
diff --git a/app/pdb/gimp-pdb-compat.h b/app/pdb/gimp-pdb-compat.h
index 0a53e3eb24..e79881ba56 100644
--- a/app/pdb/gimp-pdb-compat.h
+++ b/app/pdb/gimp-pdb-compat.h
@@ -19,8 +19,7 @@
 #define __GIMP_PDB_COMPAT_H__
 
 
-GType            gimp_pdb_compat_arg_type_to_gtype   (GimpPDBArgType  type);
-GimpPDBArgType   gimp_pdb_compat_arg_type_from_gtype (GType           type);
+GimpPDBArgType   gimp_pdb_compat_arg_type_from_gtype (GType type);
 
 void             gimp_pdb_compat_procs_register (GimpPDB           *pdb,
                                                  GimpPDBCompatMode  compat_mode);
diff --git a/app/plug-in/Makefile.am b/app/plug-in/Makefile.am
index 9a939f310b..248b96d6c3 100644
--- a/app/plug-in/Makefile.am
+++ b/app/plug-in/Makefile.am
@@ -20,8 +20,8 @@ libappplug_in_a_SOURCES = \
        \
        gimpenvirontable.c                      \
        gimpenvirontable.h                      \
-       gimpgpparamspecs.c                      \
-       gimpgpparamspecs.h                      \
+       gimpgpparams.c                          \
+       gimpgpparams.h                          \
        gimpinterpreterdb.c                     \
        gimpinterpreterdb.h                     \
        gimpplugindebug.c                       \
@@ -71,8 +71,6 @@ libappplug_in_a_SOURCES = \
        \
        plug-in-menu-path.c                     \
        plug-in-menu-path.h                     \
-       plug-in-params.c                        \
-       plug-in-params.h                        \
        plug-in-rc.c                            \
        plug-in-rc.h
 
diff --git a/app/plug-in/gimpgpparamspecs.c b/app/plug-in/gimpgpparams.c
similarity index 97%
rename from app/plug-in/gimpgpparamspecs.c
rename to app/plug-in/gimpgpparams.c
index da99b0a5c5..b9d90db45f 100644
--- a/app/plug-in/gimpgpparamspecs.c
+++ b/app/plug-in/gimpgpparams.c
@@ -1,7 +1,7 @@
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
- * gimpgpparamspecs.c
+ * gimpgpparams.c
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,15 +32,20 @@
 #include "core/gimp.h"
 #include "core/gimpparamspecs.h"
 
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 
 
 /*  public functions  */
 
-/*  include the implementation of _gimp_param_spec_to_gp_param_def()
+/*  include the implementations of
+ *
+ *  _gimp_param_spec_to_gp_param_def()
+ *  _gimp_gp_params_to_value_array()
+ *  _gimp_value_array_to_gp_params()
+ *
  *  from libgimp, they are identical.
  */
-#include "../../libgimp/gimpgpparamspecs-body.c"
+#include "../../libgimp/gimpgpparams-body.c"
 
 GParamSpec *
 _gimp_gp_param_def_to_param_spec (Gimp       *gimp,
diff --git a/app/plug-in/gimpgpparams.h b/app/plug-in/gimpgpparams.h
new file mode 100644
index 0000000000..627de34fa0
--- /dev/null
+++ b/app/plug-in/gimpgpparams.h
@@ -0,0 +1,44 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpgpparams.h
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_GP_PARAMS_H__
+#define __GIMP_GP_PARAMS_H__
+
+
+/*  function names start with an underscore because we incude code
+ *  from libgimp/ which is private there
+ */
+
+void             _gimp_param_spec_to_gp_param_def (GParamSpec      *pspec,
+                                                   GPParamDef      *param_def);
+
+GParamSpec     * _gimp_gp_param_def_to_param_spec (Gimp            *gimp,
+                                                   GPParamDef      *param_def);
+
+GimpValueArray * _gimp_gp_params_to_value_array   (GParamSpec     **pspecs,
+                                                   gint             n_pspecs,
+                                                   GPParam         *params,
+                                                   gint             n_params,
+                                                   gboolean         return_values,
+                                                   gboolean         full_copy);
+GPParam        * _gimp_value_array_to_gp_params   (GimpValueArray  *args,
+                                                   gboolean         full_copy);
+
+
+#endif /* __GIMP_GP_PARAMS_H__ */
diff --git a/app/plug-in/gimpplugin-message.c b/app/plug-in/gimpplugin-message.c
index b1499d59da..adf34013c1 100644
--- a/app/plug-in/gimpplugin-message.c
+++ b/app/plug-in/gimpplugin-message.c
@@ -31,7 +31,6 @@
 #include "plug-in-types.h"
 
 #include "gegl/gimp-babl.h"
-#include "gegl/gimp-babl-compat.h"
 #include "gegl/gimp-gegl-tile-compat.h"
 
 #include "core/gimp.h"
@@ -42,7 +41,7 @@
 #include "pdb/gimppdb.h"
 #include "pdb/gimppdberror.h"
 
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 #include "gimpplugin.h"
 #include "gimpplugin-cleanup.h"
 #include "gimpplugin-message.h"
@@ -50,7 +49,6 @@
 #include "gimpplugindef.h"
 #include "gimppluginshm.h"
 #include "gimptemporaryprocedure.h"
-#include "plug-in-params.h"
 
 #include "gimp-intl.h"
 
@@ -568,10 +566,11 @@ gimp_plug_in_handle_proc_run (GimpPlugIn *plug_in,
   if (! proc_name)
     proc_name = canonical;
 
-  args = plug_in_params_to_args (procedure ? procedure->args     : NULL,
-                                 procedure ? procedure->num_args : 0,
-                                 proc_run->params, proc_run->nparams,
-                                 FALSE, FALSE);
+  args = _gimp_gp_params_to_value_array (procedure ? procedure->args     : NULL,
+                                         procedure ? procedure->num_args : 0,
+                                         proc_run->params,
+                                         proc_run->nparams,
+                                         FALSE, FALSE);
 
   /*  Execute the procedure even if gimp_pdb_lookup_procedure()
    *  returned NULL, gimp_pdb_execute_procedure_by_name_args() will
@@ -612,7 +611,7 @@ gimp_plug_in_handle_proc_run (GimpPlugIn *plug_in,
        */
       proc_return.name    = proc_run->name;
       proc_return.nparams = gimp_value_array_length (return_vals);
-      proc_return.params  = plug_in_args_to_params (return_vals, FALSE);
+      proc_return.params  = _gimp_value_array_to_gp_params (return_vals, FALSE);
 
       if (! gp_proc_return_write (plug_in->my_write, &proc_return, plug_in))
         {
@@ -636,11 +635,11 @@ gimp_plug_in_handle_proc_return (GimpPlugIn   *plug_in,
   g_return_if_fail (proc_return != NULL);
 
   proc_frame->return_vals =
-    plug_in_params_to_args (proc_frame->procedure->values,
-                            proc_frame->procedure->num_values,
-                            proc_return->params,
-                            proc_return->nparams,
-                            TRUE, TRUE);
+    _gimp_gp_params_to_value_array (proc_frame->procedure->values,
+                                    proc_frame->procedure->num_values,
+                                    proc_return->params,
+                                    proc_return->nparams,
+                                    TRUE, TRUE);
 
   if (proc_frame->main_loop)
     {
@@ -671,11 +670,11 @@ gimp_plug_in_handle_temp_proc_return (GimpPlugIn   *plug_in,
       GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
 
       proc_frame->return_vals =
-        plug_in_params_to_args (proc_frame->procedure->values,
-                                proc_frame->procedure->num_values,
-                                proc_return->params,
-                                proc_return->nparams,
-                                TRUE, TRUE);
+        _gimp_gp_params_to_value_array (proc_frame->procedure->values,
+                                        proc_frame->procedure->num_values,
+                                        proc_return->params,
+                                        proc_return->nparams,
+                                        TRUE, TRUE);
 
       gimp_plug_in_main_loop_quit (plug_in);
       gimp_plug_in_proc_frame_pop (plug_in);
diff --git a/app/plug-in/gimpplugin.c b/app/plug-in/gimpplugin.c
index 46b2e66bcf..908e6a69d5 100644
--- a/app/plug-in/gimpplugin.c
+++ b/app/plug-in/gimpplugin.c
@@ -91,7 +91,6 @@
 #include "gimppluginmanager-help-domain.h"
 #include "gimppluginmanager-locale-domain.h"
 #include "gimptemporaryprocedure.h"
-#include "plug-in-params.h"
 
 #include "gimp-intl.h"
 
diff --git a/app/plug-in/gimppluginmanager-call.c b/app/plug-in/gimppluginmanager-call.c
index c3716521fb..82604fdfbe 100644
--- a/app/plug-in/gimppluginmanager-call.c
+++ b/app/plug-in/gimppluginmanager-call.c
@@ -39,6 +39,7 @@
 
 #include "pdb/gimppdbcontext.h"
 
+#include "gimpgpparams.h"
 #include "gimpplugin.h"
 #include "gimpplugin-message.h"
 #include "gimpplugindef.h"
@@ -48,7 +49,6 @@
 #include "gimppluginmanager-call.h"
 #include "gimppluginshm.h"
 #include "gimptemporaryprocedure.h"
-#include "plug-in-params.h"
 
 #include "gimp-intl.h"
 
@@ -228,7 +228,7 @@ gimp_plug_in_manager_call_run (GimpPlugInManager   *manager,
 
       proc_run.name    = GIMP_PROCEDURE (procedure)->original_name;
       proc_run.nparams = gimp_value_array_length (args);
-      proc_run.params  = plug_in_args_to_params (args, FALSE);
+      proc_run.params  = _gimp_value_array_to_gp_params (args, FALSE);
 
       if (! gp_config_write (plug_in->my_write, &config, plug_in)     ||
           ! gp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
@@ -323,7 +323,7 @@ gimp_plug_in_manager_call_run_temp (GimpPlugInManager      *manager,
 
       proc_run.name    = GIMP_PROCEDURE (procedure)->original_name;
       proc_run.nparams = gimp_value_array_length (args);
-      proc_run.params  = plug_in_args_to_params (args, FALSE);
+      proc_run.params  = _gimp_value_array_to_gp_params (args, FALSE);
 
       if (! gp_temp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
           ! gimp_wire_flush (plug_in->my_write, plug_in))
diff --git a/app/plug-in/plug-in-rc.c b/app/plug-in/plug-in-rc.c
index 500e543ebb..03aea87c55 100644
--- a/app/plug-in/plug-in-rc.c
+++ b/app/plug-in/plug-in-rc.c
@@ -31,9 +31,7 @@
 
 #include "core/gimp.h"
 
-#include "pdb/gimp-pdb-compat.h"
-
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 #include "gimpplugindef.h"
 #include "gimppluginprocedure.h"
 #include "plug-in-rc.h"
@@ -41,7 +39,7 @@
 #include "gimp-intl.h"
 
 
-#define PLUG_IN_RC_FILE_VERSION 5
+#define PLUG_IN_RC_FILE_VERSION 6
 
 
 /*
diff --git a/app/widgets/gimphelp.c b/app/widgets/gimphelp.c
index 4d96201528..3335c859e7 100644
--- a/app/widgets/gimphelp.c
+++ b/app/widgets/gimphelp.c
@@ -384,7 +384,7 @@ gimp_help_browser (Gimp         *gimp,
       args = gimp_procedure_get_arguments (procedure);
       gimp_value_array_truncate (args, 5);
 
-      g_value_set_int              (gimp_value_array_index (args, 0),
+      g_value_set_enum             (gimp_value_array_index (args, 0),
                                     GIMP_RUN_INTERACTIVE);
       g_value_set_int              (gimp_value_array_index (args, 1),
                                     n_domains);
diff --git a/libgimp/Makefile.am b/libgimp/Makefile.am
index cafc2e00db..66ea23eb5f 100644
--- a/libgimp/Makefile.am
+++ b/libgimp/Makefile.am
@@ -109,8 +109,8 @@ libgimp_built_sources = \
 libgimp_private_sources = \
        gimpgpcompat.c          \
        gimpgpcompat.h          \
-       gimpgpparamspecs.c      \
-       gimpgpparamspecs.h      \
+       gimpgpparams.c          \
+       gimpgpparams.h          \
        gimpplugin-private.c    \
        gimpplugin-private.h    \
        gimpprocedure-private.c \
@@ -118,7 +118,7 @@ libgimp_private_sources = \
 
 libgimp_extra_sources = \
        gimpenums.c.tail        \
-       gimpgpparamspecs-body.c
+       gimpgpparams-body.c
 
 libgimp_@GIMP_API_VERSION@_la_SOURCES = \
        $(libgimp_built_sources)        \
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index 36c8d419cf..c57d4321bc 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -119,7 +119,7 @@
 
 #include "gimp.h"
 #include "gimpgpcompat.h"
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 #include "gimpplugin-private.h"
 #include "gimpunitcache.h"
 
@@ -195,6 +195,10 @@ static void       gimp_loop                    (void);
 static void       gimp_config                  (GPConfig        *config);
 static void       gimp_proc_run                (GPProcRun       *proc_run);
 static void       gimp_temp_proc_run           (GPProcRun       *proc_run);
+static void       gimp_proc_run_internal       (GPProcRun       *proc_run,
+                                                GimpProcedure   *procedure,
+                                                GimpRunProc      run_proc,
+                                                GPProcReturn    *proc_return);
 static void       gimp_process_message         (GimpWireMessage *msg);
 static void       gimp_single_message          (void);
 static gboolean   gimp_extension_read          (GIOChannel      *channel,
@@ -765,7 +769,47 @@ gimp_main_internal (GType                 plug_in_type,
   gimp_wire_set_writer (gimp_write);
   gimp_wire_set_flusher (gimp_flush);
 
-  gimp_enums_init ();
+  /*  initialize GTypes, they need to be known to g_type_from_name()  */
+  {
+    GType init_types[] =
+    {
+      GIMP_TYPE_INT32,         GIMP_TYPE_PARAM_INT32,
+      GIMP_TYPE_INT16,         GIMP_TYPE_PARAM_INT16,
+      GIMP_TYPE_INT8,          GIMP_TYPE_PARAM_INT8,
+
+      GIMP_TYPE_PARAM_STRING,
+
+      GIMP_TYPE_ARRAY,         GIMP_TYPE_PARAM_ARRAY,
+      GIMP_TYPE_INT8_ARRAY,    GIMP_TYPE_PARAM_INT8_ARRAY,
+      GIMP_TYPE_INT16_ARRAY,   GIMP_TYPE_PARAM_INT16_ARRAY,
+      GIMP_TYPE_INT32_ARRAY,   GIMP_TYPE_PARAM_INT32_ARRAY,
+      GIMP_TYPE_FLOAT_ARRAY,   GIMP_TYPE_PARAM_FLOAT_ARRAY,
+      GIMP_TYPE_STRING_ARRAY,  GIMP_TYPE_PARAM_STRING_ARRAY,
+      GIMP_TYPE_RGB_ARRAY,     GIMP_TYPE_PARAM_RGB_ARRAY,
+
+      GIMP_TYPE_DISPLAY_ID,    GIMP_TYPE_PARAM_DISPLAY_ID,
+      GIMP_TYPE_IMAGE_ID,      GIMP_TYPE_PARAM_IMAGE_ID,
+      GIMP_TYPE_ITEM_ID,       GIMP_TYPE_PARAM_ITEM_ID,
+      GIMP_TYPE_DRAWABLE_ID,   GIMP_TYPE_PARAM_DRAWABLE_ID,
+      GIMP_TYPE_LAYER_ID,      GIMP_TYPE_PARAM_LAYER_ID,
+      GIMP_TYPE_CHANNEL_ID,    GIMP_TYPE_PARAM_CHANNEL_ID,
+      GIMP_TYPE_LAYER_MASK_ID, GIMP_TYPE_PARAM_LAYER_MASK_ID,
+      GIMP_TYPE_SELECTION_ID,  GIMP_TYPE_PARAM_SELECTION_ID,
+      GIMP_TYPE_VECTORS_ID,    GIMP_TYPE_PARAM_VECTORS_ID
+    };
+
+    gint i;
+
+    for (i = 0; i < G_N_ELEMENTS (init_types); i++, i++)
+      {
+        GType type = init_types[i];
+
+        if (G_TYPE_IS_CLASSED (type))
+          g_type_class_ref (type);
+      }
+
+    gimp_enums_init ();
+  }
 
   /*  initialize units  */
   {
@@ -1433,31 +1477,41 @@ gimp_run_procedure2 (const gchar     *name,
 {
   GPProcRun        proc_run;
   GPProcReturn    *proc_return;
+  GimpValueArray  *arguments;
+  GimpValueArray  *return_values;
   GimpWireMessage  msg;
   GimpParam       *return_vals;
 
   g_return_val_if_fail (name != NULL, NULL);
   g_return_val_if_fail (n_return_vals != NULL, NULL);
 
+  arguments = _gimp_params_to_value_array (params, n_params, FALSE);
+
   proc_run.name    = (gchar *) name;
-  proc_run.nparams = n_params;
-  proc_run.params  = (GPParam *) params;
+  proc_run.nparams = gimp_value_array_length (arguments);
+  proc_run.params  = _gimp_value_array_to_gp_params (arguments, FALSE);
 
   gp_lock ();
   if (! gp_proc_run_write (_writechannel, &proc_run, NULL))
     gimp_quit ();
 
+  g_free (proc_run.params);
+  gimp_value_array_unref (arguments);
+
   gimp_read_expect_msg (&msg, GP_PROC_RETURN);
   gp_unlock ();
 
   proc_return = msg.data;
 
-  *n_return_vals = proc_return->nparams;
-  return_vals    = (GimpParam *) proc_return->params;
+  return_values = _gimp_gp_params_to_value_array (NULL, 0,
+                                                  proc_return->params,
+                                                  proc_return->nparams,
+                                                  TRUE, FALSE);
 
-  proc_return->nparams = 0;
-  proc_return->params  = NULL;
+  *n_return_vals = gimp_value_array_length (return_values);
+  return_vals    = _gimp_value_array_to_params (return_values, TRUE);
 
+  //gimp_value_array_unref (return_values);
   gimp_wire_destroy (&msg);
 
   gimp_set_pdb_error (return_vals, *n_return_vals);
@@ -1477,7 +1531,78 @@ void
 gimp_destroy_params (GimpParam *params,
                      gint       n_params)
 {
-  gp_params_destroy ((GPParam *) params, n_params);
+  gint i;
+
+  for (i = 0; i < n_params; i++)
+    {
+      switch (params[i].type)
+        {
+        case GIMP_PDB_INT32:
+        case GIMP_PDB_INT16:
+        case GIMP_PDB_INT8:
+        case GIMP_PDB_FLOAT:
+        case GIMP_PDB_COLOR:
+        case GIMP_PDB_ITEM:
+        case GIMP_PDB_DISPLAY:
+        case GIMP_PDB_IMAGE:
+        case GIMP_PDB_LAYER:
+        case GIMP_PDB_CHANNEL:
+        case GIMP_PDB_DRAWABLE:
+        case GIMP_PDB_SELECTION:
+        case GIMP_PDB_VECTORS:
+        case GIMP_PDB_STATUS:
+          break;
+
+        case GIMP_PDB_STRING:
+          g_free (params[i].data.d_string);
+          break;
+
+        case GIMP_PDB_INT32ARRAY:
+          g_free (params[i].data.d_int32array);
+          break;
+
+        case GIMP_PDB_INT16ARRAY:
+          g_free (params[i].data.d_int16array);
+          break;
+
+        case GIMP_PDB_INT8ARRAY:
+          g_free (params[i].data.d_int8array);
+          break;
+
+        case GIMP_PDB_FLOATARRAY:
+          g_free (params[i].data.d_floatarray);
+          break;
+
+        case GIMP_PDB_STRINGARRAY:
+          if ((i > 0) && (params[i-1].type == GIMP_PDB_INT32))
+            {
+              gint count = params[i-1].data.d_int32;
+              gint j;
+
+              for (j = 0; j < count; j++)
+                g_free (params[i].data.d_stringarray[j]);
+
+              g_free (params[i].data.d_stringarray);
+            }
+          break;
+
+        case GIMP_PDB_COLORARRAY:
+          g_free (params[i].data.d_colorarray);
+          break;
+
+        case GIMP_PDB_PARASITE:
+          if (params[i].data.d_parasite.name)
+            g_free (params[i].data.d_parasite.name);
+          if (params[i].data.d_parasite.data)
+            g_free (params[i].data.d_parasite.data);
+          break;
+
+        case GIMP_PDB_END:
+          break;
+        }
+    }
+
+  g_free (params);
 }
 
 /**
@@ -2526,93 +2651,119 @@ gimp_config (GPConfig *config)
 static void
 gimp_proc_run (GPProcRun *proc_run)
 {
-  if (PLUG_IN || PLUG_IN_INFO.run_proc)
-    {
-      GPProcReturn  proc_return;
-      GimpParam    *return_vals   = NULL;
-      gint          n_return_vals = 0;
+  GPProcReturn proc_return;
 
-      if (PLUG_IN)
-        {
-          GimpProcedure   *procedure;
-          GimpValueArray  *arguments;
-          GimpValueArray  *return_values;
-          GParamSpec     **arg_specs;
-          gint             n_arg_specs;
+  if (PLUG_IN)
+    {
+      GimpProcedure *procedure;
 
-          procedure = gimp_plug_in_create_procedure (PLUG_IN, proc_run->name);
+      procedure = gimp_plug_in_create_procedure (PLUG_IN, proc_run->name);
 
-          if (procedure)
-            {
-              arg_specs = gimp_procedure_get_arguments (procedure,
-                                                        &n_arg_specs);
+      if (procedure)
+        {
+          gimp_proc_run_internal (proc_run, procedure, NULL,
+                                  &proc_return);
 
-              arguments = _gimp_pdb_params_to_args (arg_specs,
-                                                    n_arg_specs,
-                                                    (GimpParam *) proc_run->params,
-                                                    proc_run->nparams,
-                                                    FALSE, FALSE);
+          g_object_unref (procedure);
+        }
+    }
+  else if (PLUG_IN_INFO.run_proc)
+    {
+      gimp_proc_run_internal (proc_run, NULL, PLUG_IN_INFO.run_proc,
+                              &proc_return);
+    }
 
-              return_values = gimp_procedure_run (procedure, arguments);
+  if (! gp_proc_return_write (_writechannel, &proc_return, NULL))
+    gimp_quit ();
+}
 
-              gimp_value_array_unref (arguments);
+static void
+gimp_temp_proc_run (GPProcRun *proc_run)
+{
+  GPProcReturn proc_return;
 
-              n_return_vals = gimp_value_array_length (return_values);
-              return_vals   = _gimp_pdb_args_to_params (return_values, TRUE);
+  if (PLUG_IN)
+    {
+      GimpProcedure *procedure;
 
-              gimp_value_array_unref (return_values);
+      procedure = gimp_plug_in_get_procedure (PLUG_IN, proc_run->name);
 
-              g_object_unref (procedure);
-            }
-         }
-      else
+      if (procedure)
         {
-          PLUG_IN_INFO.run_proc (proc_run->name,
-                                 proc_run->nparams,
-                                 (GimpParam *) proc_run->params,
-                                 &n_return_vals, &return_vals);
+          gimp_proc_run_internal (proc_run, procedure, NULL,
+                                  &proc_return);
         }
+    }
+  else
+    {
+      GimpRunProc run_proc = g_hash_table_lookup (temp_proc_ht,
+                                                  proc_run->name);
 
-      proc_return.name    = proc_run->name;
-      proc_return.nparams = n_return_vals;
-      proc_return.params  = (GPParam *) return_vals;
+      if (run_proc)
+        {
+#ifdef GDK_WINDOWING_QUARTZ
+          if (proc_run->params &&
+              proc_run->params[0].data.d_int == GIMP_RUN_INTERACTIVE)
+            {
+              [NSApp activateIgnoringOtherApps: YES];
+            }
+#endif
 
-      if (! gp_proc_return_write (_writechannel, &proc_return, NULL))
-        gimp_quit ();
+          gimp_proc_run_internal (proc_run, NULL, run_proc,
+                                  &proc_return);
+        }
     }
+
+  if (! gp_temp_proc_return_write (_writechannel, &proc_return, NULL))
+    gimp_quit ();
 }
 
 static void
-gimp_temp_proc_run (GPProcRun *proc_run)
+gimp_proc_run_internal (GPProcRun     *proc_run,
+                        GimpProcedure *procedure,
+                        GimpRunProc    run_proc,
+                        GPProcReturn  *proc_return)
 {
-  GimpRunProc run_proc = g_hash_table_lookup (temp_proc_ht, proc_run->name);
+  GimpValueArray *arguments;
+  GimpValueArray *return_values = NULL;
+
+  arguments = _gimp_gp_params_to_value_array (NULL, 0,
+                                              proc_run->params,
+                                              proc_run->nparams,
+                                              FALSE, FALSE);
 
-  if (run_proc)
+  if (procedure)
     {
-      GPProcReturn  proc_return;
-      GimpParam    *return_vals;
-      gint          n_return_vals;
+      return_values = gimp_procedure_run (procedure, arguments);
+    }
+  else
+    {
+      GimpParam *params;
+      GimpParam *return_vals;
+      gint       n_params;
+      gint       n_return_vals;
 
-#ifdef GDK_WINDOWING_QUARTZ
-      if (proc_run->params &&
-          proc_run->params[0].data.d_int32 == GIMP_RUN_INTERACTIVE)
-        {
-          [NSApp activateIgnoringOtherApps: YES];
-        }
-#endif
+      n_params = gimp_value_array_length (arguments);
+      params   = _gimp_value_array_to_params (arguments, FALSE);
 
-      (* run_proc) (proc_run->name,
-                    proc_run->nparams,
-                    (GimpParam *) proc_run->params,
-                    &n_return_vals, &return_vals);
+      run_proc (proc_run->name,
+                n_params,       params,
+                &n_return_vals, &return_vals);
 
-      proc_return.name    = proc_run->name;
-      proc_return.nparams = n_return_vals;
-      proc_return.params  = (GPParam *) return_vals;
+      return_values = _gimp_params_to_value_array (return_vals,
+                                                   n_return_vals,
+                                                   FALSE);
 
-      if (! gp_temp_proc_return_write (_writechannel, &proc_return, NULL))
-        gimp_quit ();
+      g_free (params);
     }
+
+  gimp_value_array_unref (arguments);
+
+  proc_return->name    = proc_run->name;
+  proc_return->nparams = gimp_value_array_length (return_values);
+  proc_return->params  = _gimp_value_array_to_gp_params (return_values, TRUE);
+
+  gimp_value_array_unref (return_values);
 }
 
 static void
diff --git a/libgimp/gimpgpcompat.c b/libgimp/gimpgpcompat.c
index 9d9fb5d633..edb55f9a00 100644
--- a/libgimp/gimpgpcompat.c
+++ b/libgimp/gimpgpcompat.c
@@ -32,6 +32,13 @@
 #include "gimpgpcompat.h"
 
 
+/*  local function prototypes  */
+
+static gchar * _gimp_pdb_arg_type_to_string (GimpPDBArgType type);
+
+
+/*  public functions  */
+
 GParamSpec *
 _gimp_gp_compat_param_spec (GimpPDBArgType  arg_type,
                             const gchar    *name,
@@ -335,33 +342,14 @@ _gimp_pdb_gtype_to_arg_type (GType type)
   return pdb_type;
 }
 
-gchar *
-_gimp_pdb_arg_type_to_string (GimpPDBArgType type)
-{
-  const gchar *name;
-
-  if (! gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, type,
-                             &name, NULL, NULL, NULL))
-    {
-      return g_strdup_printf ("(PDB type %d unknown)", type);
-    }
-
-  return g_strdup (name);
-}
-
 GimpValueArray *
-_gimp_pdb_params_to_args (GParamSpec      **pspecs,
-                          gint              n_pspecs,
-                          const GimpParam  *params,
-                          gint              n_params,
-                          gboolean          return_values,
-                          gboolean          full_copy)
+_gimp_params_to_value_array (const GimpParam  *params,
+                             gint              n_params,
+                             gboolean          full_copy)
 {
   GimpValueArray *args;
   gint            i;
 
-  g_return_val_if_fail ((pspecs != NULL && n_pspecs  > 0) ||
-                        (pspecs == NULL && n_pspecs == 0), NULL);
   g_return_val_if_fail ((params != NULL && n_params  > 0) ||
                         (params == NULL && n_params == 0), NULL);
 
@@ -370,40 +358,9 @@ _gimp_pdb_params_to_args (GParamSpec      **pspecs,
   for (i = 0; i < n_params; i++)
     {
       GValue value = G_VALUE_INIT;
-      GType  type;
+      GType  type  = _gimp_pdb_arg_type_to_gtype (params[i].type);
       gint   count;
 
-      /*  first get the fallback compat GType that matches the pdb type  */
-      type = _gimp_pdb_arg_type_to_gtype (params[i].type);
-
-      /*  then try to try to be more specific by looking at the param
-       *  spec (return values have one additional value (the status),
-       *  skip that, it's not in the array of param specs)
-       */
-      if (i > 0 || ! return_values)
-        {
-          gint pspec_index = i;
-
-          if (return_values)
-            pspec_index--;
-
-          /*  are there param specs left?  */
-          if (pspec_index < n_pspecs)
-            {
-              GType          pspec_gtype;
-              GimpPDBArgType pspec_arg_type;
-
-              pspec_gtype    = G_PARAM_SPEC_VALUE_TYPE (pspecs[pspec_index]);
-              pspec_arg_type = _gimp_pdb_gtype_to_arg_type (pspec_gtype);
-
-              /*  if the param spec's GType, mapped to a pdb type, matches
-               *  the passed pdb type, use the param spec's GType
-               */
-              if (pspec_arg_type == params[i].type)
-                type = pspec_gtype;
-            }
-        }
-
       g_value_init (&value, type);
 
       switch (_gimp_pdb_gtype_to_arg_type (type))
@@ -575,8 +532,8 @@ _gimp_pdb_params_to_args (GParamSpec      **pspecs,
 }
 
 GimpParam *
-_gimp_pdb_args_to_params (GimpValueArray *args,
-                          gboolean        full_copy)
+_gimp_value_array_to_params (GimpValueArray *args,
+                             gboolean        full_copy)
 {
   GimpParam *params;
   gint       length;
@@ -754,3 +711,20 @@ _gimp_pdb_args_to_params (GimpValueArray *args,
 
   return params;
 }
+
+
+/*  private functions  */
+
+gchar *
+_gimp_pdb_arg_type_to_string (GimpPDBArgType type)
+{
+  const gchar *name;
+
+  if (! gimp_enum_get_value (GIMP_TYPE_PDB_ARG_TYPE, type,
+                             &name, NULL, NULL, NULL))
+    {
+      return g_strdup_printf ("(PDB type %d unknown)", type);
+    }
+
+  return g_strdup (name);
+}
diff --git a/libgimp/gimpgpcompat.h b/libgimp/gimpgpcompat.h
index 34128b6128..be596d65f6 100644
--- a/libgimp/gimpgpcompat.h
+++ b/libgimp/gimpgpcompat.h
@@ -30,15 +30,10 @@ GParamSpec     * _gimp_gp_compat_param_spec   (GimpPDBArgType   arg_type,
 GType            _gimp_pdb_arg_type_to_gtype  (GimpPDBArgType   type);
 GimpPDBArgType   _gimp_pdb_gtype_to_arg_type  (GType            type);
 
-gchar          * _gimp_pdb_arg_type_to_string (GimpPDBArgType   type);
-
-GimpValueArray * _gimp_pdb_params_to_args     (GParamSpec     **pspecs,
-                                               gint             n_pspecs,
-                                               const GimpParam *params,
+GimpValueArray * _gimp_params_to_value_array  (const GimpParam *params,
                                                gint             n_params,
-                                               gboolean         return_values,
                                                gboolean         full_copy);
-GimpParam      * _gimp_pdb_args_to_params     (GimpValueArray  *args,
+GimpParam      * _gimp_value_array_to_params  (GimpValueArray  *args,
                                                gboolean         full_copy);
 
 
diff --git a/libgimp/gimpgpparams-body.c b/libgimp/gimpgpparams-body.c
new file mode 100644
index 0000000000..8fd115d285
--- /dev/null
+++ b/libgimp/gimpgpparams-body.c
@@ -0,0 +1,515 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpgpparams-body.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+/*  this file is included by both
+ *
+ *  libgimp/gimpgpparams.c
+ *  app/plug-in/gimpgpparams.c
+ */
+
+void
+_gimp_param_spec_to_gp_param_def (GParamSpec *pspec,
+                                  GPParamDef *param_def)
+{
+  GType pspec_type;
+
+  param_def->param_def_type = GP_PARAM_DEF_TYPE_DEFAULT;
+  param_def->type_name      = (gchar *) G_PARAM_SPEC_TYPE_NAME (pspec);
+  param_def->name           = (gchar *) g_param_spec_get_name (pspec);
+  param_def->nick           = (gchar *) g_param_spec_get_nick (pspec);
+  param_def->blurb          = (gchar *) g_param_spec_get_blurb (pspec);
+
+  pspec_type = G_PARAM_SPEC_TYPE (pspec);
+
+  if (pspec_type == GIMP_TYPE_PARAM_INT32 ||
+      pspec_type == GIMP_TYPE_PARAM_INT16)
+    {
+      GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_INT;
+
+      param_def->meta.m_int.min_val     = ispec->minimum;
+      param_def->meta.m_int.max_val     = ispec->maximum;
+      param_def->meta.m_int.default_val = ispec->default_value;
+    }
+  else if (pspec_type == GIMP_TYPE_PARAM_INT8)
+    {
+      GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_INT;
+
+      param_def->meta.m_int.min_val     = uspec->minimum;
+      param_def->meta.m_int.max_val     = uspec->maximum;
+      param_def->meta.m_int.default_val = uspec->default_value;
+    }
+  else if (pspec_type == G_TYPE_PARAM_ENUM)
+    {
+      GParamSpecEnum *espec     = G_PARAM_SPEC_ENUM (pspec);
+      GType           enum_type = pspec->value_type;
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_ENUM;
+
+      param_def->meta.m_enum.type_name    = (gchar *) g_type_name (enum_type);
+      param_def->meta.m_float.default_val = espec->default_value;
+    }
+  else if (pspec_type == G_TYPE_PARAM_BOOLEAN)
+    {
+      GParamSpecBoolean *bspec = G_PARAM_SPEC_BOOLEAN (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_BOOLEAN;
+
+      param_def->meta.m_boolean.default_val = bspec->default_value;
+    }
+  else if (pspec_type == G_TYPE_PARAM_DOUBLE)
+    {
+      GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_FLOAT;
+
+      param_def->meta.m_float.min_val     = dspec->minimum;
+      param_def->meta.m_float.max_val     = dspec->maximum;
+      param_def->meta.m_float.default_val = dspec->default_value;
+    }
+  else if (pspec_type == GIMP_TYPE_PARAM_STRING)
+    {
+      GParamSpecString    *gsspec = G_PARAM_SPEC_STRING (pspec);
+      GimpParamSpecString *sspec  = GIMP_PARAM_SPEC_STRING (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_STRING;
+
+      param_def->meta.m_string.allow_non_utf8 = sspec->allow_non_utf8;
+      param_def->meta.m_string.null_ok        = ! gsspec->ensure_non_null;
+      param_def->meta.m_string.non_empty      = sspec->non_empty;
+      param_def->meta.m_string.default_val    = gsspec->default_value;
+    }
+  else if (pspec_type == GIMP_TYPE_PARAM_RGB)
+    {
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_COLOR;
+
+      param_def->meta.m_color.has_alpha =
+        gimp_param_spec_rgb_has_alpha (pspec);
+
+      gimp_param_spec_rgb_get_default (pspec,
+                                       &param_def->meta.m_color.default_val);
+    }
+  else if (pspec_type == GIMP_TYPE_PARAM_DISPLAY_ID)
+    {
+      GimpParamSpecDisplayID *ispec = GIMP_PARAM_SPEC_DISPLAY_ID (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_ID;
+
+      param_def->meta.m_id.none_ok = ispec->none_ok;
+    }
+  else if (pspec_type == GIMP_TYPE_PARAM_IMAGE_ID)
+    {
+      GimpParamSpecImageID *ispec = GIMP_PARAM_SPEC_IMAGE_ID (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_ID;
+
+      param_def->meta.m_id.none_ok = ispec->none_ok;
+    }
+  else if (GIMP_IS_PARAM_SPEC_ITEM_ID (pspec))
+    {
+      GimpParamSpecItemID *ispec = GIMP_PARAM_SPEC_ITEM_ID (pspec);
+
+      param_def->param_def_type = GP_PARAM_DEF_TYPE_ID;
+
+      param_def->meta.m_id.none_ok = ispec->none_ok;
+    }
+}
+
+GimpValueArray *
+_gimp_gp_params_to_value_array (GParamSpec **pspecs,
+                                gint         n_pspecs,
+                                GPParam     *params,
+                                gint         n_params,
+                                gboolean     return_values,
+                                gboolean     full_copy)
+{
+  GimpValueArray *args;
+  gint            i;
+
+  g_return_val_if_fail ((params != NULL && n_params  > 0) ||
+                        (params == NULL && n_params == 0), NULL);
+
+  args = gimp_value_array_new (n_params);
+
+  for (i = 0; i < n_params; i++)
+    {
+      GValue value = G_VALUE_INIT;
+      GType  type;
+
+      /*  first get the GType from the passed GPParam  */
+      type = g_type_from_name (params[i].type_name);
+
+      /*  then try to try to be more specific by looking at the param
+       *  spec (return values have one additional value (the status),
+       *  skip that, it's not in the array of param specs)
+       */
+      if (i > 0 || ! return_values)
+        {
+          gint pspec_index = i;
+
+          if (return_values)
+            pspec_index--;
+
+          /*  are there param specs left?  */
+          if (pspec_index < n_pspecs)
+            {
+              GType pspec_type = G_PARAM_SPEC_VALUE_TYPE (pspecs[pspec_index]);
+
+              if (type != pspec_type)
+                {
+                  if (g_type_is_a (pspec_type, type))
+                    {
+                      /*  if the param spec's GType is more specific
+                       *  than the one from the GPParam, use the param
+                       *  spec's GType.
+                       */
+                      type = pspec_type;
+                    }
+                  else if (type == GIMP_TYPE_INT32)
+                    {
+                      if (g_type_is_a (pspec_type, G_TYPE_ENUM))
+                        {
+                          /*  if the param spec's type is enum, but an
+                           *  int32 was passed, use the enum type.
+                           */
+                          type = pspec_type;
+                        }
+                      else if (g_type_is_a (pspec_type, G_TYPE_BOOLEAN))
+                        {
+                          /*  if the param spec's type is boolean, but
+                           *  an int32 was passed, use the boolean
+                           *  type.
+                           */
+                          type = pspec_type;
+                        }
+                    }
+                }
+            }
+        }
+
+      g_value_init (&value, type);
+
+      if (type == G_TYPE_INT      ||
+          type == GIMP_TYPE_INT32 ||
+          type == GIMP_TYPE_INT16)
+        {
+          g_value_set_int (&value, params[i].data.d_int);
+        }
+      else if (G_VALUE_HOLDS_UINT (&value))
+        {
+          g_value_set_uint (&value, params[i].data.d_int);
+        }
+      else if (G_VALUE_HOLDS_ENUM (&value))
+        {
+          g_value_set_enum (&value, params[i].data.d_int);
+        }
+      else if (G_VALUE_HOLDS_BOOLEAN (&value))
+        {
+          g_value_set_boolean (&value, params[i].data.d_int ? TRUE : FALSE);
+        }
+      else if (G_VALUE_HOLDS_DOUBLE (&value))
+        {
+          g_value_set_double (&value, params[i].data.d_float);
+        }
+      else if (G_VALUE_HOLDS_STRING (&value))
+        {
+          if (full_copy)
+            g_value_set_string (&value, params[i].data.d_string);
+          else
+            g_value_set_static_string (&value, params[i].data.d_string);
+        }
+      else if (GIMP_VALUE_HOLDS_RGB (&value))
+        {
+          gimp_value_set_rgb (&value, &params[i].data.d_color);
+        }
+      else if (GIMP_VALUE_HOLDS_PARASITE (&value))
+        {
+          if (full_copy)
+            g_value_set_boxed (&value, &params[i].data.d_parasite);
+          else
+            g_value_set_static_boxed (&value, &params[i].data.d_parasite);
+        }
+      else if (GIMP_VALUE_HOLDS_INT32_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_int32_array (&value,
+                                        (gint32 *) params[i].data.d_array.data,
+                                        params[i].data.d_array.size /
+                                        sizeof (gint32));
+          else
+            gimp_value_set_static_int32_array (&value,
+                                               (gint32 *) params[i].data.d_array.data,
+                                               params[i].data.d_array.size /
+                                               sizeof (gint32));
+        }
+      else if (GIMP_VALUE_HOLDS_INT16_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_int16_array (&value,
+                                        (gint16 *) params[i].data.d_array.data,
+                                        params[i].data.d_array.size /
+                                        sizeof (gint16));
+          else
+            gimp_value_set_static_int16_array (&value,
+                                               (gint16 *) params[i].data.d_array.data,
+                                               params[i].data.d_array.size /
+                                               sizeof (gint16));
+        }
+      else if (GIMP_VALUE_HOLDS_INT8_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_int8_array (&value,
+                                       params[i].data.d_array.data,
+                                       params[i].data.d_array.size /
+                                       sizeof (guint8));
+          else
+            gimp_value_set_static_int8_array (&value,
+                                              params[i].data.d_array.data,
+                                              params[i].data.d_array.size /
+                                              sizeof (guint8));
+        }
+      else if (GIMP_VALUE_HOLDS_FLOAT_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_float_array (&value,
+                                        (const gdouble *)
+                                        params[i].data.d_array.data,
+                                        params[i].data.d_array.size /
+                                        sizeof (gdouble));
+          else
+            gimp_value_set_static_float_array (&value,
+                                               (const gdouble *)
+                                               params[i].data.d_array.data,
+                                               params[i].data.d_array.size /
+                                               sizeof (gdouble));
+        }
+      else if (GIMP_VALUE_HOLDS_STRING_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_string_array (&value,
+                                         (const gchar **)
+                                         params[i].data.d_string_array.data,
+                                         params[i].data.d_string_array.size);
+          else
+            gimp_value_set_static_string_array (&value,
+                                                (const gchar **)
+                                                params[i].data.d_string_array.data,
+                                                params[i].data.d_string_array.size);
+        }
+      else if (GIMP_VALUE_HOLDS_RGB_ARRAY (&value))
+        {
+          if (full_copy)
+            gimp_value_set_rgb_array (&value,
+                                      (GimpRGB *)
+                                      params[i].data.d_array.data,
+                                      params[i].data.d_array.size /
+                                      sizeof (GimpRGB));
+          else
+            gimp_value_set_static_rgb_array (&value,
+                                             (GimpRGB *)
+                                             params[i].data.d_array.data,
+                                             params[i].data.d_array.size /
+                                             sizeof (GimpRGB));
+        }
+      else if (GIMP_VALUE_HOLDS_DISPLAY_ID    (&value) ||
+               GIMP_VALUE_HOLDS_IMAGE_ID      (&value) ||
+               GIMP_VALUE_HOLDS_ITEM_ID       (&value) ||
+               GIMP_VALUE_HOLDS_DRAWABLE_ID   (&value) ||
+               GIMP_VALUE_HOLDS_LAYER_ID      (&value) ||
+               GIMP_VALUE_HOLDS_CHANNEL_ID    (&value) ||
+               GIMP_VALUE_HOLDS_LAYER_MASK_ID (&value) ||
+               GIMP_VALUE_HOLDS_SELECTION_ID  (&value) ||
+               GIMP_VALUE_HOLDS_VECTORS_ID    (&value))
+        {
+          g_value_set_int (&value, params[i].data.d_int);
+        }
+
+      gimp_value_array_append (args, &value);
+      g_value_unset (&value);
+    }
+
+  return args;
+}
+
+GPParam *
+_gimp_value_array_to_gp_params (GimpValueArray  *args,
+                                gboolean         full_copy)
+{
+  GPParam *params;
+  gint     length;
+  gint     i;
+
+  g_return_val_if_fail (args != NULL, NULL);
+
+  params = g_new0 (GPParam, gimp_value_array_length (args));
+
+  length = gimp_value_array_length (args);
+
+  for (i = 0; i < length; i++)
+    {
+      GValue *value = gimp_value_array_index (args, i);
+      GType   type  = G_VALUE_TYPE (value);
+
+      params[i].param_type = -1;
+
+      if (full_copy)
+        params[i].type_name = g_strdup (g_type_name (type));
+      else
+        params[i].type_name = (gchar *) g_type_name (type);
+
+      if (type == G_TYPE_INT      ||
+          type == GIMP_TYPE_INT32 ||
+          type == GIMP_TYPE_INT16)
+        {
+          params[i].param_type = GP_PARAM_TYPE_INT;
+
+          params[i].data.d_int = g_value_get_int (value);
+        }
+      else if (type == G_TYPE_UINT ||
+               type == GIMP_TYPE_INT8)
+        {
+          params[i].param_type = GP_PARAM_TYPE_INT;
+
+          params[i].data.d_int = g_value_get_uint (value);
+        }
+      else if (G_VALUE_HOLDS_ENUM (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_INT;
+
+          params[i].data.d_int = g_value_get_enum (value);
+        }
+      else if (G_VALUE_HOLDS_BOOLEAN (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_INT;
+
+          params[i].data.d_int = g_value_get_boolean (value);
+        }
+      else if (G_VALUE_HOLDS_DOUBLE (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_FLOAT;
+
+          params[i].data.d_float = g_value_get_double (value);
+        }
+      else if (G_VALUE_HOLDS_STRING (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_STRING;
+
+          if (full_copy)
+            params[i].data.d_string = g_value_dup_string (value);
+          else
+            params[i].data.d_string = (gchar *) g_value_get_string (value);
+        }
+      else if (GIMP_VALUE_HOLDS_RGB (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_COLOR;
+
+          gimp_value_get_rgb (value, &params[i].data.d_color);
+        }
+      else if (GIMP_VALUE_HOLDS_PARASITE (value))
+        {
+          GimpParasite *parasite = (full_copy ?
+                                    g_value_dup_boxed (value) :
+                                    g_value_get_boxed (value));
+
+          params[i].param_type = GP_PARAM_TYPE_PARASITE;
+
+          if (parasite)
+            {
+              params[i].data.d_parasite.name  = parasite->name;
+              params[i].data.d_parasite.flags = parasite->flags;
+              params[i].data.d_parasite.size  = parasite->size;
+              params[i].data.d_parasite.data  = parasite->data;
+
+              if (full_copy)
+                {
+                  parasite->name  = NULL;
+                  parasite->flags = 0;
+                  parasite->size  = 0;
+                  parasite->data  = NULL;
+
+                  gimp_parasite_free (parasite);
+                }
+            }
+          else
+            {
+              params[i].data.d_parasite.name  = NULL;
+              params[i].data.d_parasite.flags = 0;
+              params[i].data.d_parasite.size  = 0;
+              params[i].data.d_parasite.data  = NULL;
+            }
+        }
+      else if (GIMP_VALUE_HOLDS_INT32_ARRAY (value) ||
+               GIMP_VALUE_HOLDS_INT16_ARRAY (value) ||
+               GIMP_VALUE_HOLDS_INT8_ARRAY  (value) ||
+               GIMP_VALUE_HOLDS_FLOAT_ARRAY (value) ||
+               GIMP_VALUE_HOLDS_RGB_ARRAY (value))
+        {
+          GimpArray *array = g_value_get_boxed (value);
+
+          params[i].param_type = GP_PARAM_TYPE_ARRAY;
+
+          params[i].data.d_array.size = array->length;
+
+          if (full_copy)
+            params[i].data.d_array.data = g_memdup (array->data,
+                                                    array->length);
+          else
+            params[i].data.d_array.data = array->data;
+        }
+      else if (GIMP_VALUE_HOLDS_STRING_ARRAY (value))
+        {
+          GimpArray *array = g_value_get_boxed (value);
+
+          params[i].param_type = GP_PARAM_TYPE_STRING_ARRAY;
+
+          params[i].data.d_string_array.size = array->length;
+
+          if (full_copy)
+            params[i].data.d_string_array.data =
+              gimp_value_dup_string_array (value);
+          else
+            params[i].data.d_string_array.data =
+              (gchar **) gimp_value_get_string_array (value);
+        }
+      else if (GIMP_VALUE_HOLDS_DISPLAY_ID (value)    ||
+               GIMP_VALUE_HOLDS_IMAGE_ID (value)      ||
+               GIMP_VALUE_HOLDS_ITEM_ID (value)       ||
+               GIMP_VALUE_HOLDS_DRAWABLE_ID (value)   ||
+               GIMP_VALUE_HOLDS_LAYER_ID (value)      ||
+               GIMP_VALUE_HOLDS_CHANNEL_ID (value)    ||
+               GIMP_VALUE_HOLDS_LAYER_MASK_ID (value) ||
+               GIMP_VALUE_HOLDS_SELECTION_ID (value)  ||
+               GIMP_VALUE_HOLDS_VECTORS_ID (value))
+        {
+          params[i].param_type = GP_PARAM_TYPE_INT;
+
+          params[i].data.d_int = g_value_get_int (value);
+        }
+
+      if (params[i].param_type == -1)
+        g_printerr ("%s: GValue contains unsupported type '%s'\n",
+                    G_STRFUNC, params[i].type_name);
+    }
+
+  return params;
+}
diff --git a/libgimp/gimpgpparamspecs.c b/libgimp/gimpgpparams.c
similarity index 92%
rename from libgimp/gimpgpparamspecs.c
rename to libgimp/gimpgpparams.c
index 58bfe0c92e..ef1237348b 100644
--- a/libgimp/gimpgpparamspecs.c
+++ b/libgimp/gimpgpparams.c
@@ -1,7 +1,7 @@
 /* LIBGIMP - The GIMP Library
  * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
  *
- * gimpgpparamspecs.c
+ * gimpgpparams.c
  *
  * This library is free software: you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,7 +30,7 @@
 #include "libgimpbase/gimpprotocol.h"
 
 #include "gimp.h"
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 
 
 /*  public functions  */
@@ -38,4 +38,4 @@
 /*  include the implementation of _gimp_param_spec_to_gp_param_def()
  *  from libgimp, they are identical.
  */
-#include "gimpgpparamspecs-body.c"
+#include "gimpgpparams-body.c"
diff --git a/libgimp/gimpgpparams.h b/libgimp/gimpgpparams.h
new file mode 100644
index 0000000000..c6287b94c9
--- /dev/null
+++ b/libgimp/gimpgpparams.h
@@ -0,0 +1,42 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
+ *
+ * gimpgpparams.h
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_GP_PARAMS_H__
+#define __GIMP_GP_PARAMS_H__
+
+G_BEGIN_DECLS
+
+
+void             _gimp_param_spec_to_gp_param_def (GParamSpec      *pspec,
+                                                   GPParamDef      *param_def);
+
+GimpValueArray * _gimp_gp_params_to_value_array   (GParamSpec     **pspecs,
+                                                   gint             n_pspecs,
+                                                   GPParam         *params,
+                                                   gint             n_params,
+                                                   gboolean         return_values,
+                                                   gboolean         full_copy);
+GPParam        * _gimp_value_array_to_gp_params   (GimpValueArray  *args,
+                                                   gboolean         full_copy);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_GP_PARAMS_H__ */
diff --git a/libgimp/gimpprocedure-private.c b/libgimp/gimpprocedure-private.c
index 506802ae08..2be6a39b58 100644
--- a/libgimp/gimpprocedure-private.c
+++ b/libgimp/gimpprocedure-private.c
@@ -30,7 +30,7 @@
 #include "libgimpbase/gimpprotocol.h"
 
 #include "gimp.h"
-#include "gimpgpparamspecs.h"
+#include "gimpgpparams.h"
 #include "gimpprocedure-private.h"
 
 
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index d829ebbdd7..00b2833374 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -278,7 +278,6 @@ EXPORTS
        gp_has_init_write
        gp_init
        gp_lock
-       gp_params_destroy
        gp_proc_install_write
        gp_proc_return_write
        gp_proc_run_write
diff --git a/libgimpbase/gimpprotocol.c b/libgimpbase/gimpprotocol.c
index 9e7ebc8574..9515ed189c 100644
--- a/libgimpbase/gimpprotocol.c
+++ b/libgimpbase/gimpprotocol.c
@@ -22,6 +22,7 @@
 
 #include "gimpbasetypes.h"
 
+#include "gimpparamspecs.h"
 #include "gimpparasite.h"
 #include "gimpprotocol.h"
 #include "gimpwire.h"
@@ -132,6 +133,9 @@ static void _gp_params_write             (GIOChannel       *channel,
                                           GPParam          *params,
                                           gint              nparams,
                                           gpointer          user_data);
+static void _gp_params_destroy           (GPParam          *params,
+                                          gint              nparams);
+
 
 static void _gp_has_init_read            (GIOChannel       *channel,
                                           GimpWireMessage  *msg,
@@ -200,6 +204,22 @@ gp_init (void)
                       _gp_has_init_destroy);
 }
 
+/* lock/unlock the global wire mutex */
+
+void
+gp_lock (void)
+{
+  g_mutex_lock (&readwrite_mutex);
+}
+
+void
+gp_unlock (void)
+{
+  g_mutex_unlock (&readwrite_mutex);
+}
+
+/* public writing API */
+
 gboolean
 gp_quit_write (GIOChannel *channel,
                gpointer    user_data)
@@ -899,7 +919,7 @@ _gp_proc_run_destroy (GimpWireMessage *msg)
 
   if (proc_run)
     {
-      gp_params_destroy (proc_run->params, proc_run->nparams);
+      _gp_params_destroy (proc_run->params, proc_run->nparams);
 
       g_free (proc_run->name);
       g_slice_free (GPProcRun, proc_run);
@@ -951,7 +971,7 @@ _gp_proc_return_destroy (GimpWireMessage *msg)
 
   if (proc_return)
     {
-      gp_params_destroy (proc_return->params, proc_return->nparams);
+      _gp_params_destroy (proc_return->params, proc_return->nparams);
 
       g_free (proc_return->name);
       g_slice_free (GPProcReturn, proc_return);
@@ -1541,7 +1561,7 @@ _gp_params_read (GIOChannel  *channel,
                  guint       *nparams,
                  gpointer     user_data)
 {
-  gint i, j;
+  gint i;
 
   if (! _gimp_wire_read_int32 (channel, (guint32 *) nparams, 1, user_data))
     return;
@@ -1557,197 +1577,90 @@ _gp_params_read (GIOChannel  *channel,
   for (i = 0; i < *nparams; i++)
     {
       if (! _gimp_wire_read_int32 (channel,
-                                   (guint32 *) &(*params)[i].type, 1,
+                                   (guint32 *) &(*params)[i].param_type, 1,
                                    user_data))
         goto cleanup;
 
-      switch ((*params)[i].type)
+      if (! _gimp_wire_read_string (channel,
+                                    &(*params)[i].type_name, 1,
+                                    user_data))
+        return;
+
+      switch ((*params)[i].param_type)
         {
-        case GIMP_PDB_INT32:
+        case GP_PARAM_TYPE_INT:
           if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_int32, 1,
+                                       (guint32 *) &(*params)[i].data.d_int, 1,
                                        user_data))
             goto cleanup;
           break;
 
-        case GIMP_PDB_INT16:
-          if (! _gimp_wire_read_int16 (channel,
-                                       (guint16 *) &(*params)[i].data.d_int16, 1,
-                                       user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_INT8:
-          if (! _gimp_wire_read_int8 (channel,
-                                      &(*params)[i].data.d_int8, 1,
-                                      user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_FLOAT:
+        case GP_PARAM_TYPE_FLOAT:
           if (! _gimp_wire_read_double (channel,
                                         &(*params)[i].data.d_float, 1,
                                         user_data))
             goto cleanup;
           break;
 
-        case GIMP_PDB_STRING:
+        case GP_PARAM_TYPE_STRING:
           if (! _gimp_wire_read_string (channel,
                                         &(*params)[i].data.d_string, 1,
                                         user_data))
             goto cleanup;
           break;
 
-        case GIMP_PDB_INT32ARRAY:
-          (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
-          (*params)[i].data.d_int32array = g_new (gint32,
-                                                  (*params)[i-1].data.d_int32);
-
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) (*params)[i].data.d_int32array,
-                                       (*params)[i-1].data.d_int32,
-                                       user_data))
-            {
-              g_free ((*params)[i].data.d_int32array);
-              goto cleanup;
-            }
-          break;
-
-        case GIMP_PDB_INT16ARRAY:
-          (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
-          (*params)[i].data.d_int16array = g_new (gint16,
-                                                  (*params)[i-1].data.d_int32);
-          if (! _gimp_wire_read_int16 (channel,
-                                       (guint16 *) (*params)[i].data.d_int16array,
-                                       (*params)[i-1].data.d_int32,
-                                       user_data))
-            {
-              g_free ((*params)[i].data.d_int16array);
-              goto cleanup;
-            }
-          break;
-
-        case GIMP_PDB_INT8ARRAY:
-          (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
-          (*params)[i].data.d_int8array = g_new (guint8,
-                                                 (*params)[i-1].data.d_int32);
-          if (! _gimp_wire_read_int8 (channel,
-                                      (*params)[i].data.d_int8array,
-                                      (*params)[i-1].data.d_int32,
-                                      user_data))
-            {
-              g_free ((*params)[i].data.d_int8array);
-              goto cleanup;
-            }
-          break;
-
-        case GIMP_PDB_FLOATARRAY:
-          (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
-          (*params)[i].data.d_floatarray = g_new (gdouble,
-                                                  (*params)[i-1].data.d_int32);
-          if (! _gimp_wire_read_double (channel,
-                                        (*params)[i].data.d_floatarray,
-                                        (*params)[i-1].data.d_int32,
-                                        user_data))
-            {
-              g_free ((*params)[i].data.d_floatarray);
-              goto cleanup;
-            }
-          break;
-
-        case GIMP_PDB_STRINGARRAY:
-          (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
-          (*params)[i].data.d_stringarray = g_new0 (gchar *,
-                                                    (*params)[i-1].data.d_int32);
-          if (! _gimp_wire_read_string (channel,
-                                        (*params)[i].data.d_stringarray,
-                                        (*params)[i-1].data.d_int32,
-                                        user_data))
-            {
-              for (j = 0; j < (*params)[i-1].data.d_int32; j++)
-                g_free (((*params)[i].data.d_stringarray)[j]);
-              g_free ((*params)[i].data.d_stringarray);
-              goto cleanup;
-            }
-          break;
-
-        case GIMP_PDB_COLOR:
+        case GP_PARAM_TYPE_COLOR:
           if (! _gimp_wire_read_color (channel,
                                        &(*params)[i].data.d_color, 1,
                                        user_data))
             goto cleanup;
           break;
 
-        case GIMP_PDB_ITEM:
+        case GP_PARAM_TYPE_ARRAY:
           if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_item, 1,
+                                       &(*params)[i].data.d_array.size, 1,
                                        user_data))
             goto cleanup;
-          break;
 
-        case GIMP_PDB_DISPLAY:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_display, 1,
-                                       user_data))
-            goto cleanup;
-          break;
+          (*params)[i].data.d_array.data = g_new0 (guint8,
+                                                   (*params)[i].data.d_array.size);
 
-        case GIMP_PDB_IMAGE:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_image, 1,
-                                       user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_LAYER:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_layer, 1,
-                                       user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_CHANNEL:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_channel, 1,
-                                       user_data))
-            goto cleanup;
+          if (! _gimp_wire_read_int8 (channel,
+                                      (*params)[i].data.d_array.data,
+                                      (*params)[i].data.d_array.size,
+                                      user_data))
+            {
+              g_free ((*params)[i].data.d_array.data);
+              (*params)[i].data.d_array.data = NULL;
+              goto cleanup;
+            }
           break;
 
-        case GIMP_PDB_DRAWABLE:
+        case GP_PARAM_TYPE_STRING_ARRAY:
           if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_drawable, 1,
+                                       &(*params)[i].data.d_string_array.size, 1,
                                        user_data))
             goto cleanup;
-          break;
 
-        case GIMP_PDB_SELECTION:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_selection, 1,
-                                       user_data))
-            goto cleanup;
-          break;
+          (*params)[i].data.d_string_array.data = g_new0 (gchar *,
+                                                          (*params)[i].data.d_array.size);
 
-        case GIMP_PDB_COLORARRAY:
-          (*params)[i].data.d_colorarray = g_new (GimpRGB,
-                                                  (*params)[i-1].data.d_int32);
-          if (! _gimp_wire_read_color (channel,
-                                       (*params)[i].data.d_colorarray,
-                                       (*params)[i-1].data.d_int32,
-                                       user_data))
+          if (! _gimp_wire_read_string (channel,
+                                        (*params)[i].data.d_string_array.data,
+                                        (*params)[i].data.d_array.size,
+                                        user_data))
             {
-              g_free ((*params)[i].data.d_colorarray);
+              gint j;
+
+              for (j = 0; j < (*params)[i].data.d_array.size; j++)
+                g_free ((*params)[i].data.d_string_array.data[j]);
+              g_free ((*params)[i].data.d_string_array.data);
+              (*params)[i].data.d_string_array.data = NULL;
               goto cleanup;
             }
           break;
 
-        case GIMP_PDB_VECTORS:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_vectors, 1,
-                                       user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_PARASITE:
+        case GP_PARAM_TYPE_PARASITE:
           if (! _gimp_wire_read_string (channel,
                                         &(*params)[i].data.d_parasite.name, 1,
                                         user_data))
@@ -1782,16 +1695,6 @@ _gp_params_read (GIOChannel  *channel,
           else
             (*params)[i].data.d_parasite.data = NULL;
           break;
-
-        case GIMP_PDB_STATUS:
-          if (! _gimp_wire_read_int32 (channel,
-                                       (guint32 *) &(*params)[i].data.d_status, 1,
-                                       user_data))
-            goto cleanup;
-          break;
-
-        case GIMP_PDB_END:
-          break;
         }
     }
 
@@ -1818,158 +1721,68 @@ _gp_params_write (GIOChannel *channel,
   for (i = 0; i < nparams; i++)
     {
       if (! _gimp_wire_write_int32 (channel,
-                                    (const guint32 *) &params[i].type, 1,
+                                    (const guint32 *) &params[i].param_type, 1,
                                     user_data))
         return;
 
-      switch (params[i].type)
+      if (! _gimp_wire_write_string (channel,
+                                     &params[i].type_name, 1,
+                                     user_data))
+        return;
+
+      switch (params[i].param_type)
         {
-        case GIMP_PDB_INT32:
+        case GP_PARAM_TYPE_INT:
           if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_int32, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_INT16:
-          if (! _gimp_wire_write_int16 (channel,
-                                        (const guint16 *) &params[i].data.d_int16, 1,
+                                        (const guint32 *) &params[i].data.d_int, 1,
                                         user_data))
             return;
           break;
 
-        case GIMP_PDB_INT8:
-          if (! _gimp_wire_write_int8 (channel,
-                                       (const guint8 *) &params[i].data.d_int8, 1,
-                                       user_data))
-            return;
-          break;
-
-        case GIMP_PDB_FLOAT:
+        case GP_PARAM_TYPE_FLOAT:
           if (! _gimp_wire_write_double (channel,
-                                         &params[i].data.d_float, 1,
+                                         (const gdouble *) &params[i].data.d_float, 1,
                                          user_data))
             return;
           break;
 
-        case GIMP_PDB_STRING:
+        case GP_PARAM_TYPE_STRING:
           if (! _gimp_wire_write_string (channel,
                                          &params[i].data.d_string, 1,
                                          user_data))
             return;
           break;
 
-        case GIMP_PDB_INT32ARRAY:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) params[i].data.d_int32array,
-                                        params[i-1].data.d_int32,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_INT16ARRAY:
-          if (! _gimp_wire_write_int16 (channel,
-                                        (const guint16 *) params[i].data.d_int16array,
-                                        params[i-1].data.d_int32,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_INT8ARRAY:
-          if (! _gimp_wire_write_int8 (channel,
-                                       (const guint8 *) params[i].data.d_int8array,
-                                       params[i-1].data.d_int32,
-                                       user_data))
-            return;
-          break;
-
-        case GIMP_PDB_FLOATARRAY:
-          if (! _gimp_wire_write_double (channel,
-                                         params[i].data.d_floatarray,
-                                         params[i-1].data.d_int32,
-                                         user_data))
-            return;
-          break;
-
-        case GIMP_PDB_STRINGARRAY:
-          if (! _gimp_wire_write_string (channel,
-                                         params[i].data.d_stringarray,
-                                         params[i-1].data.d_int32,
-                                         user_data))
-            return;
-          break;
-
-        case GIMP_PDB_COLOR:
+        case GP_PARAM_TYPE_COLOR:
           if (! _gimp_wire_write_color (channel,
-                                        &params[i].data.d_color, 1, user_data))
-            return;
-          break;
-
-        case GIMP_PDB_ITEM:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_item, 1,
+                                        &params[i].data.d_color, 1,
                                         user_data))
             return;
           break;
 
-        case GIMP_PDB_DISPLAY:
+        case GP_PARAM_TYPE_ARRAY:
           if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_display, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_IMAGE:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_image, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_LAYER:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_layer, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_CHANNEL:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_channel, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_DRAWABLE:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_drawable, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_SELECTION:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_selection, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_COLORARRAY:
-          if (! _gimp_wire_write_color (channel,
-                                        params[i].data.d_colorarray,
-                                        params[i-1].data.d_int32,
-                                        user_data))
+                                        (const guint32 *) &params[i].data.d_array.size, 1,
+                                        user_data) ||
+              ! _gimp_wire_write_int8 (channel,
+                                       (const guint8 *) params[i].data.d_array.data,
+                                       params[i].data.d_array.size,
+                                       user_data))
             return;
           break;
 
-        case GIMP_PDB_VECTORS:
+        case GP_PARAM_TYPE_STRING_ARRAY:
           if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_vectors, 1,
-                                        user_data))
+                                        &params[i].data.d_string_array.size, 1,
+                                        user_data) ||
+              ! _gimp_wire_write_string (channel,
+                                         params[i].data.d_string_array.data,
+                                         params[i].data.d_string_array.size,
+                                         user_data))
             return;
           break;
 
-        case GIMP_PDB_PARASITE:
+        case GP_PARAM_TYPE_PARASITE:
           {
             GimpParasite *p = &params[i].data.d_parasite;
 
@@ -1994,110 +1807,62 @@ _gp_params_write (GIOChannel *channel,
               }
           }
           break;
-
-        case GIMP_PDB_STATUS:
-          if (! _gimp_wire_write_int32 (channel,
-                                        (const guint32 *) &params[i].data.d_status, 1,
-                                        user_data))
-            return;
-          break;
-
-        case GIMP_PDB_END:
-          break;
         }
     }
 }
 
-void
-gp_params_destroy (GPParam *params,
-                   gint     nparams)
+static void
+_gp_params_destroy (GPParam *params,
+                    gint     nparams)
 {
   gint i;
 
   for (i = 0; i < nparams; i++)
     {
-      switch (params[i].type)
+      g_free (params[i].type_name);
+
+      switch (params[i].param_type)
         {
-        case GIMP_PDB_INT32:
-        case GIMP_PDB_INT16:
-        case GIMP_PDB_INT8:
-        case GIMP_PDB_FLOAT:
-        case GIMP_PDB_COLOR:
-        case GIMP_PDB_ITEM:
-        case GIMP_PDB_DISPLAY:
-        case GIMP_PDB_IMAGE:
-        case GIMP_PDB_LAYER:
-        case GIMP_PDB_CHANNEL:
-        case GIMP_PDB_DRAWABLE:
-        case GIMP_PDB_SELECTION:
-        case GIMP_PDB_VECTORS:
-        case GIMP_PDB_STATUS:
+        case GP_PARAM_TYPE_INT:
+        case GP_PARAM_TYPE_FLOAT:
           break;
 
-        case GIMP_PDB_STRING:
+        case GP_PARAM_TYPE_STRING:
           g_free (params[i].data.d_string);
           break;
 
-        case GIMP_PDB_INT32ARRAY:
-          g_free (params[i].data.d_int32array);
+        case GP_PARAM_TYPE_COLOR:
           break;
 
-        case GIMP_PDB_INT16ARRAY:
-          g_free (params[i].data.d_int16array);
+        case GP_PARAM_TYPE_ARRAY:
+          g_free (params[i].data.d_array.data);
           break;
 
-        case GIMP_PDB_INT8ARRAY:
-          g_free (params[i].data.d_int8array);
-          break;
-
-        case GIMP_PDB_FLOATARRAY:
-          g_free (params[i].data.d_floatarray);
-          break;
-
-        case GIMP_PDB_STRINGARRAY:
-          if ((i > 0) && (params[i-1].type == GIMP_PDB_INT32))
+        case GP_PARAM_TYPE_STRING_ARRAY:
+          if (params[i].data.d_string_array.size > 0 &&
+              params[i].data.d_string_array.data)
             {
-              gint count = params[i-1].data.d_int32;
               gint j;
 
-              for (j = 0; j < count; j++)
-                g_free (params[i].data.d_stringarray[j]);
+              for (j = 0; j < params[i].data.d_string_array.size; j++)
+                g_free (params[i].data.d_string_array.data[j]);
 
-              g_free (params[i].data.d_stringarray);
+              g_free (params[i].data.d_string_array.data);
             }
           break;
 
-        case GIMP_PDB_COLORARRAY:
-          g_free (params[i].data.d_colorarray);
-          break;
-
-        case GIMP_PDB_PARASITE:
+        case GP_PARAM_TYPE_PARASITE:
           if (params[i].data.d_parasite.name)
             g_free (params[i].data.d_parasite.name);
           if (params[i].data.d_parasite.data)
             g_free (params[i].data.d_parasite.data);
           break;
-
-        case GIMP_PDB_END:
-          break;
         }
     }
 
   g_free (params);
 }
 
-void
-gp_lock (void)
-{
-  g_mutex_lock (&readwrite_mutex);
-}
-
-void
-gp_unlock (void)
-{
-  g_mutex_unlock (&readwrite_mutex);
-}
-
 /* has_init */
 
 static void
@@ -2109,7 +1874,7 @@ _gp_has_init_read (GIOChannel      *channel,
 
 static void
 _gp_has_init_write (GIOChannel      *channel,
-                         GimpWireMessage *msg,
+                    GimpWireMessage *msg,
                     gpointer         user_data)
 {
 }
diff --git a/libgimpbase/gimpprotocol.h b/libgimpbase/gimpprotocol.h
index fcb0ee9bfb..c45a5aa5ad 100644
--- a/libgimpbase/gimpprotocol.h
+++ b/libgimpbase/gimpprotocol.h
@@ -26,7 +26,7 @@ G_BEGIN_DECLS
 
 /* Increment every time the protocol changes
  */
-#define GIMP_PROTOCOL_VERSION  0x0104
+#define GIMP_PROTOCOL_VERSION  0x0105
 
 
 enum
@@ -46,6 +46,17 @@ enum
   GP_HAS_INIT
 };
 
+typedef enum
+{
+  GP_PARAM_TYPE_INT,
+  GP_PARAM_TYPE_FLOAT,
+  GP_PARAM_TYPE_STRING,
+  GP_PARAM_TYPE_COLOR,
+  GP_PARAM_TYPE_PARASITE,
+  GP_PARAM_TYPE_ARRAY,
+  GP_PARAM_TYPE_STRING_ARRAY
+} GPParamType;
+
 typedef enum
 {
   GP_PARAM_DEF_TYPE_DEFAULT,
@@ -59,23 +70,25 @@ typedef enum
 } GPParamDefType;
 
 
-typedef struct _GPConfig          GPConfig;
-typedef struct _GPTileReq         GPTileReq;
-typedef struct _GPTileAck         GPTileAck;
-typedef struct _GPTileData        GPTileData;
-typedef struct _GPParam           GPParam;
-typedef struct _GPParamDef        GPParamDef;
-typedef struct _GPParamDefInt     GPParamDefInt;
-typedef struct _GPParamDefEnum    GPParamDefEnum;
-typedef struct _GPParamDefBoolean GPParamDefBoolean;
-typedef struct _GPParamDefFloat   GPParamDefFloat;
-typedef struct _GPParamDefString  GPParamDefString;
-typedef struct _GPParamDefColor   GPParamDefColor;
-typedef struct _GPParamDefID      GPParamDefID;
-typedef struct _GPProcRun         GPProcRun;
-typedef struct _GPProcReturn      GPProcReturn;
-typedef struct _GPProcInstall     GPProcInstall;
-typedef struct _GPProcUninstall   GPProcUninstall;
+typedef struct _GPConfig           GPConfig;
+typedef struct _GPTileReq          GPTileReq;
+typedef struct _GPTileAck          GPTileAck;
+typedef struct _GPTileData         GPTileData;
+typedef struct _GPParam            GPParam;
+typedef struct _GPParamArray       GPParamArray;
+typedef struct _GPParamStringArray GPParamStringArray;
+typedef struct _GPParamDef         GPParamDef;
+typedef struct _GPParamDefInt      GPParamDefInt;
+typedef struct _GPParamDefEnum     GPParamDefEnum;
+typedef struct _GPParamDefBoolean  GPParamDefBoolean;
+typedef struct _GPParamDefFloat    GPParamDefFloat;
+typedef struct _GPParamDefString   GPParamDefString;
+typedef struct _GPParamDefColor    GPParamDefColor;
+typedef struct _GPParamDefID       GPParamDefID;
+typedef struct _GPProcRun          GPProcRun;
+typedef struct _GPProcReturn       GPProcReturn;
+typedef struct _GPProcInstall      GPProcInstall;
+typedef struct _GPProcUninstall    GPProcUninstall;
 
 
 struct _GPConfig
@@ -123,36 +136,32 @@ struct _GPTileData
   guchar  *data;
 };
 
+struct _GPParamArray
+{
+  guint32  size;
+  guint8  *data;
+};
+
+struct _GPParamStringArray
+{
+  guint32   size;
+  gchar   **data;
+};
+
 struct _GPParam
 {
-  guint32 type;
+  GPParamType  param_type;
+  gchar       *type_name;
 
   union
   {
-    gint32        d_int32;
-    gint16        d_int16;
-    guint8        d_int8;
-    gdouble       d_float;
-    gchar        *d_string;
-    gint32       *d_int32array;
-    gint16       *d_int16array;
-    guint8       *d_int8array;
-    gdouble      *d_floatarray;
-    gchar       **d_stringarray;
-    GimpRGB      *d_colorarray;
-    GimpRGB       d_color;
-    gint32        d_display;
-    gint32        d_image;
-    gint32        d_item;
-    gint32        d_layer;
-    gint32        d_layer_mask;
-    gint32        d_channel;
-    gint32        d_drawable;
-    gint32        d_selection;
-    gint32        d_boundary;
-    gint32        d_vectors;
-    gint32        d_status;
-    GimpParasite  d_parasite;
+    gint32              d_int;
+    gdouble             d_float;
+    gchar              *d_string;
+    GimpRGB             d_color;
+    GimpParasite        d_parasite;
+    GPParamArray        d_array;
+    GPParamStringArray  d_string_array;
   } data;
 };
 
@@ -258,6 +267,8 @@ struct _GPProcUninstall
 
 
 void      gp_init                   (void);
+void      gp_lock                   (void);
+void      gp_unlock                 (void);
 
 gboolean  gp_quit_write             (GIOChannel      *channel,
                                      gpointer         user_data);
@@ -295,12 +306,6 @@ gboolean  gp_extension_ack_write    (GIOChannel      *channel,
 gboolean  gp_has_init_write         (GIOChannel      *channel,
                                      gpointer         user_data);
 
-void      gp_params_destroy         (GPParam         *params,
-                                     gint             nparams);
-
-void      gp_lock                   (void);
-void      gp_unlock                 (void);
-
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]