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 #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 #include #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 #include 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 +#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);