mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
19fbb1d9a8
commit
5f8d0ef27b
|
@ -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);
|
||||
|
||||
|
|
249
libgimp/gimp.c
249
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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#define GIMP_DISABLE_COMPAR_CRUFT
|
||||
|
||||
#include <libgimp/gimp.h>
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue