[gimp] libgimp: add gimp_plug_in_extension_enable() and _extension_process()
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimp: add gimp_plug_in_extension_enable() and _extension_process()
- Date: Fri, 2 Aug 2019 10:02:44 +0000 (UTC)
commit 5f8d0ef27b95ffb9b7bb41a47e7496bdcf7fa918
Author: Michael Natterer <mitch gimp org>
Date: Fri Aug 2 11:06:48 2019 +0200
libgimp: add gimp_plug_in_extension_enable() and _extension_process()
Start copying all the actual wire communication to GimpPlugIn, and
move the legacy versions to gimplegacy.c.
This implies having the entire protocol code twice, but without any
if(PLUG_IN) { plug_in_stuff(); } else { legacy_stuff(); }
At the moment it is a wild mixture of old and new, but when finished
the wire code in gimplegacy.c will be entirely separate from the wire
code in GimpPlugIn, which will make it easy to g_assert() that only
one API is used by a plug-in.
libgimp/gimp-private.h | 2 +
libgimp/gimp.c | 249 +-------------------------------------
libgimp/gimp.h | 8 --
libgimp/gimplegacy.c | 259 ++++++++++++++++++++++++++++++++++++++++
libgimp/gimplegacy.h | 12 ++
libgimp/gimpplugin-private.c | 110 ++++++++++++++++-
libgimp/gimpplugin-private.h | 13 +-
libgimp/gimpplugin.c | 140 +++++++++++++++++++++-
libgimp/gimpplugin.h | 4 +
plug-ins/common/goat-exercise.c | 2 +
plug-ins/help/help.c | 4 +-
11 files changed, 541 insertions(+), 262 deletions(-)
---
diff --git a/libgimp/gimp-private.h b/libgimp/gimp-private.h
index ba0ac8834a..89fbb88d09 100644
--- a/libgimp/gimp-private.h
+++ b/libgimp/gimp-private.h
@@ -27,10 +27,12 @@ G_BEGIN_DECLS
#include "libgimpbase/gimpwire.h"
+extern GIOChannel *_gimp_readchannel;
extern GIOChannel *_gimp_writechannel;
extern GHashTable *_gimp_temp_proc_ht;
+void _gimp_config (GPConfig *config);
void _gimp_read_expect_msg (GimpWireMessage *msg,
gint type);
diff --git a/libgimp/gimp.c b/libgimp/gimp.c
index bd56c4194b..77a264e7a7 100644
--- a/libgimp/gimp.c
+++ b/libgimp/gimp.c
@@ -178,18 +178,11 @@ static gboolean gimp_write (GIOChannel *channel,
static gboolean gimp_flush (GIOChannel *channel,
gpointer user_data);
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,
- GIOCondition condition,
- gpointer data);
static void gimp_set_pdb_error (GimpValueArray *return_vals);
@@ -198,7 +191,7 @@ static LPTOP_LEVEL_EXCEPTION_FILTER _prevExceptionFilter = NULL;
static gchar *plug_in_backtrace_path = NULL;
#endif
-static GIOChannel *_gimp_readchannel = NULL;
+GIOChannel *_gimp_readchannel = NULL;
GIOChannel *_gimp_writechannel = NULL;
#ifdef USE_WIN32_SHM
@@ -811,31 +804,6 @@ gimp_quit (void)
exit (EXIT_SUCCESS);
}
-void
-_gimp_read_expect_msg (GimpWireMessage *msg,
- gint type)
-{
- while (TRUE)
- {
- if (! gimp_wire_read_msg (_gimp_readchannel, msg, NULL))
- gimp_quit ();
-
- if (msg->type == type)
- return; /* up to the caller to call wire_destroy() */
-
- if (msg->type == GP_TEMP_PROC_RUN || msg->type == GP_QUIT)
- {
- gimp_process_message (msg);
- }
- else
- {
- g_error ("unexpected message: %d", msg->type);
- }
-
- gimp_wire_destroy (msg);
- }
-}
-
GimpValueArray *
gimp_run_procedure_with_array (const gchar *name,
GimpValueArray *arguments)
@@ -1228,113 +1196,6 @@ gimp_get_progname (void)
return progname;
}
-/**
- * gimp_extension_enable:
- *
- * Enables asynchronous processing of messages from the main GIMP
- * application.
- *
- * Normally, a plug-in is not called by GIMP except for the call to
- * the procedure it implements. All subsequent communication is
- * triggered by the plug-in and all messages sent from GIMP to the
- * plug-in are just answers to requests the plug-in made.
- *
- * If the plug-in however registered temporary procedures using
- * gimp_install_temp_proc(), it needs to be able to receive requests
- * to execute them. Usually this will be done by running
- * gimp_extension_process() in an endless loop.
- *
- * If the plug-in cannot use gimp_extension_process(), i.e. if it has
- * a GUI and is hanging around in a #GMainLoop, it must call
- * gimp_extension_enable().
- *
- * Note that the plug-in does not need to be a #GIMP_EXTENSION to
- * register temporary procedures.
- *
- * See also: gimp_install_procedure(), gimp_install_temp_proc()
- **/
-void
-gimp_extension_enable (void)
-{
- static gboolean callback_added = FALSE;
-
- if (! callback_added)
- {
- g_io_add_watch (_gimp_readchannel, G_IO_IN | G_IO_PRI,
- gimp_extension_read,
- NULL);
-
- callback_added = TRUE;
- }
-}
-
-/**
- * gimp_extension_process:
- * @timeout: The timeout (in ms) to use for the select() call.
- *
- * Processes one message sent by GIMP and returns.
- *
- * Call this function in an endless loop after calling
- * gimp_extension_ack() to process requests for running temporary
- * procedures.
- *
- * See gimp_extension_enable() for an asynchronous way of doing the
- * same if running an endless loop is not an option.
- *
- * See also: gimp_install_procedure(), gimp_install_temp_proc()
- **/
-void
-gimp_extension_process (guint timeout)
-{
-#ifndef G_OS_WIN32
- gint select_val;
-
- do
- {
- fd_set readfds;
- struct timeval tv;
- struct timeval *tvp;
-
- if (timeout)
- {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tvp = &tv;
- }
- else
- tvp = NULL;
-
- FD_ZERO (&readfds);
- FD_SET (g_io_channel_unix_get_fd (_gimp_readchannel), &readfds);
-
- if ((select_val = select (FD_SETSIZE, &readfds, NULL, NULL, tvp)) > 0)
- {
- gimp_single_message ();
- }
- else if (select_val == -1 && errno != EINTR)
- {
- perror ("gimp_extension_process");
- gimp_quit ();
- }
- }
- while (select_val == -1 && errno == EINTR);
-#else
- /* Zero means infinite wait for us, but g_poll and
- * g_io_channel_win32_poll use -1 to indicate
- * infinite wait.
- */
- GPollFD pollfd;
-
- if (timeout == 0)
- timeout = -1;
-
- g_io_channel_win32_make_pollfd (_gimp_readchannel, G_IO_IN, &pollfd);
-
- if (g_io_channel_win32_poll (&pollfd, 1, timeout) == 1)
- gimp_single_message ();
-#endif
-}
-
/* private functions */
@@ -1707,7 +1568,7 @@ gimp_loop (void)
return;
case GP_CONFIG:
- gimp_config (msg.data);
+ _gimp_config (msg.data);
break;
case GP_TILE_REQ:
@@ -1747,8 +1608,8 @@ gimp_loop (void)
}
}
-static void
-gimp_config (GPConfig *config)
+void
+_gimp_config (GPConfig *config)
{
GFile *file;
gchar *path;
@@ -1903,47 +1764,6 @@ gimp_proc_run (GPProcRun *proc_run)
gimp_quit ();
}
-static void
-gimp_temp_proc_run (GPProcRun *proc_run)
-{
- GPProcReturn proc_return;
-
- if (PLUG_IN)
- {
- GimpProcedure *procedure;
-
- procedure = gimp_plug_in_get_temp_procedure (PLUG_IN, proc_run->name);
-
- if (procedure)
- {
- gimp_proc_run_internal (proc_run, procedure, NULL,
- &proc_return);
- }
- }
- else
- {
- GimpRunProc run_proc = g_hash_table_lookup (_gimp_temp_proc_ht,
- proc_run->name);
-
- 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
-
- gimp_proc_run_internal (proc_run, NULL, run_proc,
- &proc_return);
- }
- }
-
- if (! gp_temp_proc_return_write (_gimp_writechannel, &proc_return, NULL))
- gimp_quit ();
-}
-
static void
gimp_proc_run_internal (GPProcRun *proc_run,
GimpProcedure *procedure,
@@ -1992,67 +1812,6 @@ gimp_proc_run_internal (GPProcRun *proc_run,
gimp_value_array_unref (return_values);
}
-static void
-gimp_process_message (GimpWireMessage *msg)
-{
- switch (msg->type)
- {
- case GP_QUIT:
- gimp_quit ();
- break;
- case GP_CONFIG:
- gimp_config (msg->data);
- break;
- case GP_TILE_REQ:
- case GP_TILE_ACK:
- case GP_TILE_DATA:
- g_warning ("unexpected tile message received (should not happen)");
- break;
- case GP_PROC_RUN:
- g_warning ("unexpected proc run message received (should not happen)");
- break;
- case GP_PROC_RETURN:
- g_warning ("unexpected proc return message received (should not happen)");
- break;
- case GP_TEMP_PROC_RUN:
- gimp_temp_proc_run (msg->data);
- break;
- case GP_TEMP_PROC_RETURN:
- g_warning ("unexpected temp proc return message received (should not happen)");
- break;
- case GP_PROC_INSTALL:
- g_warning ("unexpected proc install message received (should not happen)");
- break;
- case GP_HAS_INIT:
- g_warning ("unexpected has init message received (should not happen)");
- break;
- }
-}
-
-static void
-gimp_single_message (void)
-{
- GimpWireMessage msg;
-
- /* Run a temp function */
- if (! gimp_wire_read_msg (_gimp_readchannel, &msg, NULL))
- gimp_quit ();
-
- gimp_process_message (&msg);
-
- gimp_wire_destroy (&msg);
-}
-
-static gboolean
-gimp_extension_read (GIOChannel *channel,
- GIOCondition condition,
- gpointer data)
-{
- gimp_single_message ();
-
- return TRUE;
-}
-
static void
gimp_set_pdb_error (GimpValueArray *return_values)
{
diff --git a/libgimp/gimp.h b/libgimp/gimp.h
index 5ea89b02be..f92af4db0b 100644
--- a/libgimp/gimp.h
+++ b/libgimp/gimp.h
@@ -149,14 +149,6 @@ gint gimp_main (GType plug_in_type,
*/
void gimp_quit (void) G_GNUC_NORETURN;
-/* Enable asynchronous processing of temp_procs
- */
-void gimp_extension_enable (void);
-
-/* Process one temp_proc and return
- */
-void gimp_extension_process (guint timeout);
-
/* Run a procedure in the procedure database. The parameters are
* specified as a GimpValueArray, so are the return values.
*
diff --git a/libgimp/gimplegacy.c b/libgimp/gimplegacy.c
index 1b31c3cb27..68f750e0d5 100644
--- a/libgimp/gimplegacy.c
+++ b/libgimp/gimplegacy.c
@@ -20,6 +20,8 @@
#include "config.h"
+#include "errno.h"
+
#include <gio/gio.h>
#include "libgimpbase/gimpbase.h"
@@ -46,6 +48,13 @@
static gpointer gimp_param_copy (gpointer boxed);
static void gimp_param_free (gpointer boxed);
+static void gimp_process_message (GimpWireMessage *msg);
+static void gimp_single_message (void);
+static gboolean gimp_extension_read (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer data);
+static void gimp_temp_proc_run (GPProcRun *proc_run);
+
/**
* gimp_plug_in_info_set_callbacks:
@@ -465,6 +474,138 @@ gimp_extension_ack (void)
gimp_quit ();
}
+/**
+ * gimp_extension_enable:
+ *
+ * Enables asynchronous processing of messages from the main GIMP
+ * application.
+ *
+ * Normally, a plug-in is not called by GIMP except for the call to
+ * the procedure it implements. All subsequent communication is
+ * triggered by the plug-in and all messages sent from GIMP to the
+ * plug-in are just answers to requests the plug-in made.
+ *
+ * If the plug-in however registered temporary procedures using
+ * gimp_install_temp_proc(), it needs to be able to receive requests
+ * to execute them. Usually this will be done by running
+ * gimp_extension_process() in an endless loop.
+ *
+ * If the plug-in cannot use gimp_extension_process(), i.e. if it has
+ * a GUI and is hanging around in a #GMainLoop, it must call
+ * gimp_extension_enable().
+ *
+ * Note that the plug-in does not need to be a #GIMP_EXTENSION to
+ * register temporary procedures.
+ *
+ * See also: gimp_install_procedure(), gimp_install_temp_proc()
+ **/
+void
+gimp_extension_enable (void)
+{
+ static gboolean callback_added = FALSE;
+
+ if (! callback_added)
+ {
+ g_io_add_watch (_gimp_readchannel, G_IO_IN | G_IO_PRI,
+ gimp_extension_read,
+ NULL);
+
+ callback_added = TRUE;
+ }
+}
+
+/**
+ * gimp_extension_process:
+ * @timeout: The timeout (in ms) to use for the select() call.
+ *
+ * Processes one message sent by GIMP and returns.
+ *
+ * Call this function in an endless loop after calling
+ * gimp_extension_ack() to process requests for running temporary
+ * procedures.
+ *
+ * See gimp_extension_enable() for an asynchronous way of doing the
+ * same if running an endless loop is not an option.
+ *
+ * See also: gimp_install_procedure(), gimp_install_temp_proc()
+ **/
+void
+gimp_extension_process (guint timeout)
+{
+#ifndef G_OS_WIN32
+ gint select_val;
+
+ do
+ {
+ fd_set readfds;
+ struct timeval tv;
+ struct timeval *tvp;
+
+ if (timeout)
+ {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tvp = &tv;
+ }
+ else
+ tvp = NULL;
+
+ FD_ZERO (&readfds);
+ FD_SET (g_io_channel_unix_get_fd (_gimp_readchannel), &readfds);
+
+ if ((select_val = select (FD_SETSIZE, &readfds, NULL, NULL, tvp)) > 0)
+ {
+ gimp_single_message ();
+ }
+ else if (select_val == -1 && errno != EINTR)
+ {
+ perror ("gimp_extension_process");
+ gimp_quit ();
+ }
+ }
+ while (select_val == -1 && errno == EINTR);
+#else
+ /* Zero means infinite wait for us, but g_poll and
+ * g_io_channel_win32_poll use -1 to indicate
+ * infinite wait.
+ */
+ GPollFD pollfd;
+
+ if (timeout == 0)
+ timeout = -1;
+
+ g_io_channel_win32_make_pollfd (_gimp_readchannel, G_IO_IN, &pollfd);
+
+ if (g_io_channel_win32_poll (&pollfd, 1, timeout) == 1)
+ gimp_single_message ();
+#endif
+}
+
+void
+_gimp_read_expect_msg (GimpWireMessage *msg,
+ gint type)
+{
+ while (TRUE)
+ {
+ if (! gimp_wire_read_msg (_gimp_readchannel, msg, NULL))
+ gimp_quit ();
+
+ if (msg->type == type)
+ return; /* up to the caller to call wire_destroy() */
+
+ if (msg->type == GP_TEMP_PROC_RUN || msg->type == GP_QUIT)
+ {
+ gimp_process_message (msg);
+ }
+ else
+ {
+ g_error ("unexpected message: %d", msg->type);
+ }
+
+ gimp_wire_destroy (msg);
+ }
+}
+
/**
* gimp_run_procedure: (skip)
* @name: the name of the procedure to run
@@ -1045,3 +1186,121 @@ gimp_plugin_icon_register (const gchar *procedure_name,
return _gimp_plugin_icon_register (procedure_name,
icon_type, icon_data_length, icon_data);
}
+
+
+/* private functions */
+
+static void
+gimp_process_message (GimpWireMessage *msg)
+{
+ switch (msg->type)
+ {
+ case GP_QUIT:
+ gimp_quit ();
+ break;
+ case GP_CONFIG:
+ _gimp_config (msg->data);
+ break;
+ case GP_TILE_REQ:
+ case GP_TILE_ACK:
+ case GP_TILE_DATA:
+ g_warning ("unexpected tile message received (should not happen)");
+ break;
+ case GP_PROC_RUN:
+ g_warning ("unexpected proc run message received (should not happen)");
+ break;
+ case GP_PROC_RETURN:
+ g_warning ("unexpected proc return message received (should not happen)");
+ break;
+ case GP_TEMP_PROC_RUN:
+ gimp_temp_proc_run (msg->data);
+ break;
+ case GP_TEMP_PROC_RETURN:
+ g_warning ("unexpected temp proc return message received (should not happen)");
+ break;
+ case GP_PROC_INSTALL:
+ g_warning ("unexpected proc install message received (should not happen)");
+ break;
+ case GP_HAS_INIT:
+ g_warning ("unexpected has init message received (should not happen)");
+ break;
+ }
+}
+
+static void
+gimp_single_message (void)
+{
+ GimpWireMessage msg;
+
+ /* Run a temp function */
+ if (! gimp_wire_read_msg (_gimp_readchannel, &msg, NULL))
+ gimp_quit ();
+
+ gimp_process_message (&msg);
+
+ gimp_wire_destroy (&msg);
+}
+
+static gboolean
+gimp_extension_read (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer data)
+{
+ gimp_single_message ();
+
+ return TRUE;
+}
+
+static void
+gimp_temp_proc_run (GPProcRun *proc_run)
+{
+ GPProcReturn proc_return;
+ GimpRunProc run_proc = g_hash_table_lookup (_gimp_temp_proc_ht,
+ proc_run->name);
+
+ if (run_proc)
+ {
+ GimpValueArray *arguments;
+ GimpValueArray *return_values = NULL;
+ 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_int == GIMP_RUN_INTERACTIVE)
+ {
+ [NSApp activateIgnoringOtherApps: YES];
+ }
+#endif
+
+ arguments = _gimp_gp_params_to_value_array (NULL, 0,
+ proc_run->params,
+ proc_run->nparams,
+ FALSE, FALSE);
+
+ n_params = gimp_value_array_length (arguments);
+ params = _gimp_value_array_to_params (arguments, FALSE);
+
+ run_proc (proc_run->name,
+ n_params, params,
+ &n_return_vals, &return_vals);
+
+ return_values = _gimp_params_to_value_array (return_vals,
+ n_return_vals,
+ FALSE);
+
+ 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);
+ }
+
+ if (! gp_temp_proc_return_write (_gimp_writechannel, &proc_return, NULL))
+ gimp_quit ();
+}
diff --git a/libgimp/gimplegacy.h b/libgimp/gimplegacy.h
index a714dd09c3..ad735ad4e8 100644
--- a/libgimp/gimplegacy.h
+++ b/libgimp/gimplegacy.h
@@ -27,6 +27,8 @@
G_BEGIN_DECLS
+#ifndef GIMP_DISABLE_COMPAT_CRUFT
+
/**
* GimpInitProc:
@@ -265,6 +267,14 @@ void gimp_uninstall_temp_proc (const gchar *name);
*/
void gimp_extension_ack (void);
+/* Enable asynchronous processing of temp_procs
+ */
+void gimp_extension_enable (void);
+
+/* Process one temp_proc and return
+ */
+void gimp_extension_process (guint timeout);
+
/* Run a procedure in the procedure database. The parameters are
* specified via the variable length argument list. The return
* values are returned in the 'GimpParam*' array.
@@ -317,6 +327,8 @@ gboolean gimp_plugin_icon_register (const gchar *procedure_name,
const guint8 *icon_data);
+#endif /* GIMP_DISABLE_COMPAT_CRUFT */
+
G_END_DECLS
#endif /* __GIMP_LEGACY_H__ */
diff --git a/libgimp/gimpplugin-private.c b/libgimp/gimpplugin-private.c
index 1a88a92190..0142cacf36 100644
--- a/libgimp/gimpplugin-private.c
+++ b/libgimp/gimpplugin-private.c
@@ -22,14 +22,23 @@
#include "config.h"
#include "gimp.h"
+
+#include "libgimpbase/gimpprotocol.h"
+
+#include "gimp-private.h"
+#include "gimpgpparams.h"
#include "gimpplugin-private.h"
#include "gimpprocedure-private.h"
/* local function prototpes */
-static void gimp_plug_in_register (GimpPlugIn *plug_in,
- gboolean init);
+static void gimp_plug_in_register (GimpPlugIn *plug_in,
+ gboolean init);
+static void gimp_plug_in_process_message (GimpPlugIn *plug_in,
+ GimpWireMessage *msg);
+static void gimp_plug_in_temp_proc_run (GimpPlugIn *plug_in,
+ GPProcRun *proc_run);
/* public functions */
@@ -65,6 +74,18 @@ _gimp_plug_in_quit (GimpPlugIn *plug_in)
GIMP_PLUG_IN_GET_CLASS (plug_in)->quit (plug_in);
}
+gboolean
+_gimp_plug_in_extension_read (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer data)
+{
+ GimpPlugIn *plug_in = data;
+
+ _gimp_plug_in_single_message (plug_in);
+
+ return G_SOURCE_CONTINUE;
+}
+
/* private functions */
@@ -130,3 +151,88 @@ gimp_plug_in_register (GimpPlugIn *plug_in,
branch->menu_label);
}
}
+
+void
+_gimp_plug_in_single_message (GimpPlugIn *plug_in)
+{
+ GimpWireMessage msg;
+
+ /* Run a temp function */
+ if (! gimp_wire_read_msg (_gimp_readchannel, &msg, NULL))
+ gimp_quit ();
+
+ gimp_plug_in_process_message (plug_in, &msg);
+
+ gimp_wire_destroy (&msg);
+}
+
+static void
+gimp_plug_in_process_message (GimpPlugIn *plug_in,
+ GimpWireMessage *msg)
+{
+ switch (msg->type)
+ {
+ case GP_QUIT:
+ gimp_quit ();
+ break;
+ case GP_CONFIG:
+ _gimp_config (msg->data);
+ break;
+ case GP_TILE_REQ:
+ case GP_TILE_ACK:
+ case GP_TILE_DATA:
+ g_warning ("unexpected tile message received (should not happen)");
+ break;
+ case GP_PROC_RUN:
+ g_warning ("unexpected proc run message received (should not happen)");
+ break;
+ case GP_PROC_RETURN:
+ g_warning ("unexpected proc return message received (should not happen)");
+ break;
+ case GP_TEMP_PROC_RUN:
+ gimp_plug_in_temp_proc_run (plug_in, msg->data);
+ break;
+ case GP_TEMP_PROC_RETURN:
+ g_warning ("unexpected temp proc return message received (should not happen)");
+ break;
+ case GP_PROC_INSTALL:
+ g_warning ("unexpected proc install message received (should not happen)");
+ break;
+ case GP_HAS_INIT:
+ g_warning ("unexpected has init message received (should not happen)");
+ break;
+ }
+}
+
+static void
+gimp_plug_in_temp_proc_run (GimpPlugIn *plug_in,
+ GPProcRun *proc_run)
+{
+ GPProcReturn proc_return;
+ GimpProcedure *procedure;
+
+ procedure = gimp_plug_in_get_temp_procedure (plug_in, proc_run->name);
+
+ if (procedure)
+ {
+ GimpValueArray *arguments;
+ GimpValueArray *return_values = NULL;
+
+ arguments = _gimp_gp_params_to_value_array (NULL, 0,
+ proc_run->params,
+ proc_run->nparams,
+ FALSE, FALSE);
+
+ return_values = gimp_procedure_run (procedure, arguments);
+ 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);
+ }
+
+ if (! gp_temp_proc_return_write (_gimp_writechannel, &proc_return, NULL))
+ gimp_quit ();
+}
diff --git a/libgimp/gimpplugin-private.h b/libgimp/gimpplugin-private.h
index af0ea851eb..910f0bc0d9 100644
--- a/libgimp/gimpplugin-private.h
+++ b/libgimp/gimpplugin-private.h
@@ -44,12 +44,19 @@ struct _GimpPlugInPrivate
GList *menu_branches;
GList *temp_procedures;
+
+ guint extension_source_id;
};
-void _gimp_plug_in_init (GimpPlugIn *plug_in);
-void _gimp_plug_in_query (GimpPlugIn *plug_in);
-void _gimp_plug_in_quit (GimpPlugIn *plug_in);
+void _gimp_plug_in_init (GimpPlugIn *plug_in);
+void _gimp_plug_in_query (GimpPlugIn *plug_in);
+void _gimp_plug_in_quit (GimpPlugIn *plug_in);
+
+gboolean _gimp_plug_in_extension_read (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer data);
+void _gimp_plug_in_single_message (GimpPlugIn *plug_in);
G_END_DECLS
diff --git a/libgimp/gimpplugin.c b/libgimp/gimpplugin.c
index df42f9b717..445b646d91 100644
--- a/libgimp/gimpplugin.c
+++ b/libgimp/gimpplugin.c
@@ -21,9 +21,14 @@
#include "config.h"
+#include <errno.h>
#include <string.h>
#include "gimp.h"
+
+#include "libgimpbase/gimpprotocol.h"
+
+#include "gimp-private.h"
#include "gimpplugin-private.h"
#include "gimpprocedure-private.h"
@@ -68,6 +73,12 @@ gimp_plug_in_finalize (GObject *object)
GimpPlugIn *plug_in = GIMP_PLUG_IN (object);
GList *list;
+ if (plug_in->priv->extension_source_id)
+ {
+ g_source_remove (plug_in->priv->extension_source_id);
+ plug_in->priv->extension_source_id = 0;
+ }
+
if (plug_in->priv->temp_procedures)
{
g_list_free_full (plug_in->priv->temp_procedures, g_object_unref);
@@ -250,9 +261,9 @@ gimp_plug_in_create_procedure (GimpPlugIn *plug_in,
* NOTE: Normally, plug-in communication is triggered by the plug-in
* and the GIMP core only responds to the plug-in's requests. You must
* explicitly enable receiving of temporary procedure run requests
- * using either gimp_extension_enable() or
- * gimp_extension_process(). See this functions' documentation for
- * details.
+ * using either gimp_plug_in_extension_enable() or
+ * gimp_plug_in_extension_process(). See this functions' documentation
+ * for details.
*
* Since: 3.0
**/
@@ -353,3 +364,126 @@ gimp_plug_in_get_temp_procedure (GimpPlugIn *plug_in,
return NULL;
}
+
+/**
+ * gimp_plug_in_extension_enable:
+ * @plug_in: A #GimpPlugIn
+ *
+ * Enables asynchronous processing of messages from the main GIMP
+ * application.
+ *
+ * Normally, a plug-in is not called by GIMP except for the call to
+ * the procedure it implements. All subsequent communication is
+ * triggered by the plug-in and all messages sent from GIMP to the
+ * plug-in are just answers to requests the plug-in made.
+ *
+ * If the plug-in however registered temporary procedures using
+ * gimp_plug_in_add_temp_procedure(), it needs to be able to receive
+ * requests to execute them. Usually this will be done by running
+ * gimp_plug_in_extension_process() in an endless loop.
+ *
+ * If the plug-in cannot use gimp_plug_in_extension_process(), i.e. if
+ * it has a GUI and is hanging around in a #GMainLoop, it must call
+ * gimp_plug_in_extension_enable().
+ *
+ * Note that the plug-in does not need to be a #GIMP_EXTENSION to
+ * register temporary procedures.
+ *
+ * See also: gimp_plug_in_add_temp_procedure().
+ *
+ * Since: 3.0
+ **/
+void
+gimp_plug_in_extension_enable (GimpPlugIn *plug_in)
+{
+ g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
+
+ if (! plug_in->priv->extension_source_id)
+ {
+ plug_in->priv->extension_source_id =
+ g_io_add_watch (_gimp_readchannel, G_IO_IN | G_IO_PRI,
+ _gimp_plug_in_extension_read,
+ plug_in);
+ }
+}
+
+/**
+ * gimp_plug_in_extension_process:
+ * @plug_in: A #GimpPlugIn.
+ * @timeout: The timeout (in ms) to use for the select() call.
+ *
+ * Processes one message sent by GIMP and returns.
+ *
+ * Call this function in an endless loop after calling
+ * gimp_plug_in_extension_ready() to process requests for running
+ * temporary procedures.
+ *
+ * See gimp_plug_in_extension_enable() for an asynchronous way of
+ * doing the same if running an endless loop is not an option.
+ *
+ * See also: gimp_plug_in_add_temp_procedure().
+ *
+ * Since: 3.0
+ **/
+void
+gimp_plug_in_extension_process (GimpPlugIn *plug_in,
+ guint timeout)
+{
+#ifndef G_OS_WIN32
+
+ gint select_val;
+
+ g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
+
+ do
+ {
+ fd_set readfds;
+ struct timeval tv;
+ struct timeval *tvp;
+
+ if (timeout)
+ {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tvp = &tv;
+ }
+ else
+ tvp = NULL;
+
+ FD_ZERO (&readfds);
+ FD_SET (g_io_channel_unix_get_fd (_gimp_readchannel), &readfds);
+
+ if ((select_val = select (FD_SETSIZE, &readfds, NULL, NULL, tvp)) > 0)
+ {
+ _gimp_plug_in_single_message (plug_in);
+ }
+ else if (select_val == -1 && errno != EINTR)
+ {
+ perror ("gimp_plug_in_extension_process");
+ gimp_quit ();
+ }
+ }
+ while (select_val == -1 && errno == EINTR);
+
+#else
+
+ /* Zero means infinite wait for us, but g_poll and
+ * g_io_channel_win32_poll use -1 to indicate
+ * infinite wait.
+ */
+ GPollFD pollfd;
+
+ g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
+
+ if (timeout == 0)
+ timeout = -1;
+
+ g_io_channel_win32_make_pollfd (_gimp_readchannel, G_IO_IN, &pollfd);
+
+ if (g_io_channel_win32_poll (&pollfd, 1, timeout) == 1)
+ {
+ _gimp_plug_in_single_message (plug_in);
+ }
+
+#endif
+}
diff --git a/libgimp/gimpplugin.h b/libgimp/gimpplugin.h
index c373770b44..3ae9fb44d9 100644
--- a/libgimp/gimpplugin.h
+++ b/libgimp/gimpplugin.h
@@ -159,6 +159,10 @@ GList * gimp_plug_in_get_temp_procedures (GimpPlugIn *plug_in);
GimpProcedure * gimp_plug_in_get_temp_procedure (GimpPlugIn *plug_in,
const gchar *name);
+void gimp_plug_in_extension_enable (GimpPlugIn *plug_in);
+void gimp_plug_in_extension_process (GimpPlugIn *plug_in,
+ guint timeout);
+
G_END_DECLS
diff --git a/plug-ins/common/goat-exercise.c b/plug-ins/common/goat-exercise.c
index 712fc55696..e78e782bde 100644
--- a/plug-ins/common/goat-exercise.c
+++ b/plug-ins/common/goat-exercise.c
@@ -19,6 +19,8 @@
#include "config.h"
+#define GIMP_DISABLE_COMPAR_CRUFT
+
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
diff --git a/plug-ins/help/help.c b/plug-ins/help/help.c
index 7d697d2f90..0f557669fc 100644
--- a/plug-ins/help/help.c
+++ b/plug-ins/help/help.c
@@ -26,6 +26,8 @@
#include <glib.h>
+#define GIMP_DISABLE_COMPAT_CRUFT
+
#include "libgimp/gimp.h"
#include "gimphelp.h"
@@ -206,7 +208,7 @@ help_run (GimpProcedure *procedure,
help_temp_proc_install (plug_in);
gimp_procedure_extension_ready (procedure);
- gimp_extension_enable ();
+ gimp_plug_in_extension_enable (plug_in);
g_main_loop_run (main_loop);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]