libgimp: separate legacy from GimpPlugIn wire communication

Move all old wire code to gimplegacy.c and add wire code to
GimpPlugIn, which now talks with the GIMP core all by itself.

Add some more ASSERT_NO_PLUG_IN_EXISTS assertions to gimplegacy.c and
fix new code that was still using legacy API.
This commit is contained in:
Michael Natterer 2019-08-06 22:21:50 +02:00
parent caa61eef4f
commit 3c001a6123
9 changed files with 311 additions and 166 deletions

View file

@ -24,15 +24,14 @@
G_BEGIN_DECLS
extern GIOChannel *_gimp_readchannel;
extern GIOChannel *_gimp_writechannel;
void _gimp_config (GPConfig *config);
void _gimp_legacy_init (GIOChannel *read_channel,
GIOChannel *write_channel);
void _gimp_legacy_quit (void);
void _gimp_loop (GimpRunProc run_proc);
void _gimp_read_expect_msg (GimpWireMessage *msg,
gint type);
void _gimp_set_pdb_error (GimpValueArray *return_vals);
void _gimp_set_pdb_error (GimpValueArray *return_vals);
G_END_DECLS

View file

@ -108,9 +108,6 @@
#include "libgimp-intl.h"
#define WRITE_BUFFER_SIZE 1024
static gint gimp_main_internal (GType plug_in_type,
const GimpPlugInInfo *info,
gint argc,
@ -132,15 +129,6 @@ static LONG WINAPI gimp_plugin_sigfatal_handler (PEXCEPTION_POINTERS pExceptionI
#else
static void gimp_plugin_sigfatal_handler (gint sig_num);
#endif
static gboolean gimp_plugin_io_error_handler (GIOChannel *channel,
GIOCondition cond,
gpointer data);
static gboolean gimp_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data);
static gboolean gimp_flush (GIOChannel *channel,
gpointer user_data);
#if defined G_OS_WIN32 && defined HAVE_EXCHNDL
@ -148,9 +136,6 @@ static LPTOP_LEVEL_EXCEPTION_FILTER _prevExceptionFilter = NULL;
static gchar *plug_in_backtrace_path = NULL;
#endif
GIOChannel *_gimp_readchannel = NULL;
GIOChannel *_gimp_writechannel = NULL;
static gint _tile_width = -1;
static gint _tile_height = -1;
static gboolean _show_help_button = TRUE;
@ -168,9 +153,6 @@ static guint32 _timestamp = 0;
static gchar *_icon_theme_dir = NULL;
static const gchar *progname = NULL;
static gchar write_buffer[WRITE_BUFFER_SIZE];
static gulong write_buffer_index = 0;
static GimpStackTraceMode stack_trace_mode = GIMP_STACK_TRACE_NEVER;
static GimpPlugIn *PLUG_IN = NULL;
@ -241,8 +223,10 @@ gimp_main_internal (GType plug_in_type,
N_ARGS
};
gchar *basename;
gint protocol_version;
GIOChannel *read_channel;
GIOChannel *write_channel;
gchar *basename;
gint protocol_version;
#ifdef G_OS_WIN32
gint i, j, k;
@ -460,26 +444,21 @@ gimp_main_internal (GType plug_in_type,
#endif
#ifdef G_OS_WIN32
_gimp_readchannel = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
_gimp_writechannel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
readc_hannel = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
write_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
#else
_gimp_readchannel = g_io_channel_unix_new (atoi (argv[ARG_READ_FD]));
_gimp_writechannel = g_io_channel_unix_new (atoi (argv[ARG_WRITE_FD]));
read_channel = g_io_channel_unix_new (atoi (argv[ARG_READ_FD]));
write_channel = g_io_channel_unix_new (atoi (argv[ARG_WRITE_FD]));
#endif
g_io_channel_set_encoding (_gimp_readchannel, NULL, NULL);
g_io_channel_set_encoding (_gimp_writechannel, NULL, NULL);
g_io_channel_set_encoding (read_channel, NULL, NULL);
g_io_channel_set_encoding (write_channel, NULL, NULL);
g_io_channel_set_buffered (_gimp_readchannel, FALSE);
g_io_channel_set_buffered (_gimp_writechannel, FALSE);
g_io_channel_set_buffered (read_channel, FALSE);
g_io_channel_set_buffered (write_channel, FALSE);
g_io_channel_set_close_on_unref (_gimp_readchannel, TRUE);
g_io_channel_set_close_on_unref (_gimp_writechannel, TRUE);
gp_init ();
gimp_wire_set_writer (gimp_write);
gimp_wire_set_flusher (gimp_flush);
g_io_channel_set_close_on_unref (read_channel, TRUE);
g_io_channel_set_close_on_unref (write_channel, TRUE);
/* initialize GTypes, they need to be known to g_type_from_name() */
{
@ -604,8 +583,8 @@ gimp_main_internal (GType plug_in_type,
if (plug_in_type != G_TYPE_NONE)
{
PLUG_IN = g_object_new (plug_in_type,
"read-channel", _gimp_readchannel,
"write-channel", _gimp_writechannel,
"read-channel", read_channel,
"write-channel", write_channel,
NULL);
g_assert (GIMP_IS_PLUG_IN (PLUG_IN));
@ -613,6 +592,9 @@ gimp_main_internal (GType plug_in_type,
else
{
PLUG_IN_INFO = *info;
_gimp_legacy_init (read_channel,
write_channel);
}
if (strcmp (argv[ARG_MODE], "-query") == 0)
@ -627,7 +609,7 @@ gimp_main_internal (GType plug_in_type,
else
{
if (PLUG_IN_INFO.init_proc)
gp_has_init_write (_gimp_writechannel, NULL);
gp_has_init_write (write_channel, NULL);
if (PLUG_IN_INFO.query_proc)
PLUG_IN_INFO.query_proc ();
@ -669,11 +651,6 @@ gimp_main_internal (GType plug_in_type,
}
else
{
g_io_add_watch (_gimp_readchannel,
G_IO_ERR | G_IO_HUP,
gimp_plugin_io_error_handler,
NULL);
_gimp_loop (PLUG_IN_INFO.run_proc);
}
@ -1080,9 +1057,7 @@ gimp_close (void)
if (PLUG_IN_INFO.quit_proc)
PLUG_IN_INFO.quit_proc ();
_gimp_shm_close ();
gp_quit_write (_gimp_writechannel, NULL);
_gimp_legacy_quit ();
}
}
@ -1252,100 +1227,6 @@ gimp_plugin_sigfatal_handler (gint sig_num)
}
#endif
static gboolean
gimp_plugin_io_error_handler (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
g_printerr ("%s: fatal error: GIMP crashed\n", progname);
gimp_quit ();
/* never reached */
return TRUE;
}
static gboolean
gimp_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data)
{
gulong bytes;
while (count > 0)
{
if ((write_buffer_index + count) >= WRITE_BUFFER_SIZE)
{
bytes = WRITE_BUFFER_SIZE - write_buffer_index;
memcpy (&write_buffer[write_buffer_index], buf, bytes);
write_buffer_index += bytes;
if (! gimp_wire_flush (channel, NULL))
return FALSE;
}
else
{
bytes = count;
memcpy (&write_buffer[write_buffer_index], buf, bytes);
write_buffer_index += bytes;
}
buf += bytes;
count -= bytes;
}
return TRUE;
}
static gboolean
gimp_flush (GIOChannel *channel,
gpointer user_data)
{
GIOStatus status;
GError *error = NULL;
gsize count;
gsize bytes;
if (write_buffer_index > 0)
{
count = 0;
while (count != write_buffer_index)
{
do
{
bytes = 0;
status = g_io_channel_write_chars (channel,
&write_buffer[count],
(write_buffer_index - count),
&bytes,
&error);
}
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
{
if (error)
{
g_warning ("%s: gimp_flush(): error: %s",
g_get_prgname (), error->message);
g_error_free (error);
}
else
{
g_warning ("%s: gimp_flush(): error", g_get_prgname ());
}
return FALSE;
}
count += bytes;
}
write_buffer_index = 0;
}
return TRUE;
}
void
_gimp_config (GPConfig *config)
{

View file

@ -626,6 +626,8 @@ EXPORTS
gimp_pdb_procedure_exists
gimp_pdb_query
gimp_pdb_run_procedure
gimp_pdb_run_procedure_array
gimp_pdb_run_procedure_valist
gimp_pdb_set_data
gimp_pdb_temp_name
gimp_pencil

View file

@ -27,6 +27,7 @@
#include "libgimpbase/gimpprotocol.h"
#include "libgimpbase/gimpwire.h"
#include "gimp-shm.h"
#include "gimp-private.h"
#include "gimpgpcompat.h"
#include "gimpgpparams.h"
@ -43,6 +44,9 @@
**/
#define WRITE_BUFFER_SIZE 1024
#define ASSERT_NO_PLUG_IN_EXISTS(strfunc) \
if (gimp_get_plug_in ()) \
{ \
@ -64,9 +68,24 @@ static void gimp_temp_proc_run (GPProcRun *proc_run);
static void gimp_proc_run_internal (GPProcRun *proc_run,
GimpRunProc run_proc,
GPProcReturn *proc_return);
static gboolean gimp_plugin_io_error_handler (GIOChannel *channel,
GIOCondition cond,
gpointer data);
static gboolean gimp_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data);
static gboolean gimp_flush (GIOChannel *channel,
gpointer user_data);
static GHashTable *gimp_temp_proc_ht = NULL;
GIOChannel *_gimp_readchannel = NULL;
GIOChannel *_gimp_writechannel = NULL;
static gchar write_buffer[WRITE_BUFFER_SIZE];
static gulong write_buffer_index = 0;
static GHashTable *gimp_temp_proc_ht = NULL;
/**
@ -752,11 +771,11 @@ gimp_run_procedure_array (const gchar *name,
GimpWireMessage msg;
GimpValueArray *return_values;
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (arguments != NULL, NULL);
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
proc_run.name = (gchar *) name;
proc_run.nparams = gimp_value_array_length (arguments);
proc_run.params = _gimp_value_array_to_gp_params (arguments, FALSE);
@ -892,6 +911,27 @@ gimp_destroy_paramdefs (GimpParamDef *paramdefs,
g_free (paramdefs);
}
void
_gimp_legacy_init (GIOChannel *read_channel,
GIOChannel *write_channel)
{
_gimp_readchannel = read_channel;
_gimp_writechannel = write_channel;
gp_init ();
gimp_wire_set_writer (gimp_write);
gimp_wire_set_flusher (gimp_flush);
}
void
_gimp_legacy_quit (void)
{
_gimp_shm_close ();
gp_quit_write (_gimp_writechannel, NULL);
}
void
_gimp_loop (GimpRunProc run_proc)
{
@ -901,6 +941,11 @@ _gimp_loop (GimpRunProc run_proc)
gimp_temp_proc_ht = g_hash_table_new (g_str_hash, g_str_equal);
g_io_add_watch (_gimp_readchannel,
G_IO_ERR | G_IO_HUP,
gimp_plugin_io_error_handler,
NULL);
while (TRUE)
{
if (! gimp_wire_read_msg (_gimp_readchannel, &msg, NULL))
@ -976,6 +1021,8 @@ gboolean
gimp_plugin_domain_register (const gchar *domain_name,
const gchar *domain_path)
{
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
return _gimp_plugin_domain_register (domain_name, domain_path);
}
@ -998,6 +1045,8 @@ gboolean
gimp_plugin_help_register (const gchar *domain_name,
const gchar *domain_uri)
{
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
return _gimp_plugin_help_register (domain_name, domain_uri);
}
@ -1021,6 +1070,8 @@ gboolean
gimp_plugin_menu_branch_register (const gchar *menu_path,
const gchar *menu_name)
{
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
return _gimp_plugin_menu_branch_register (menu_path, menu_name);
}
@ -1042,6 +1093,8 @@ gboolean
gimp_plugin_menu_register (const gchar *procedure_name,
const gchar *menu_path)
{
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
return _gimp_plugin_menu_register (procedure_name, menu_path);
}
@ -1069,6 +1122,8 @@ gimp_plugin_icon_register (const gchar *procedure_name,
g_return_val_if_fail (procedure_name != NULL, FALSE);
g_return_val_if_fail (icon_data != NULL, FALSE);
ASSERT_NO_PLUG_IN_EXISTS (G_STRFUNC);
switch (icon_type)
{
case GIMP_ICON_TYPE_ICON_NAME:
@ -1230,3 +1285,98 @@ gimp_proc_run_internal (GPProcRun *proc_run,
gimp_value_array_unref (return_values);
}
static gboolean
gimp_plugin_io_error_handler (GIOChannel *channel,
GIOCondition cond,
gpointer data)
{
g_printerr ("%s: fatal error: GIMP crashed\n",
gimp_get_progname ());
gimp_quit ();
/* never reached */
return TRUE;
}
static gboolean
gimp_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data)
{
gulong bytes;
while (count > 0)
{
if ((write_buffer_index + count) >= WRITE_BUFFER_SIZE)
{
bytes = WRITE_BUFFER_SIZE - write_buffer_index;
memcpy (&write_buffer[write_buffer_index], buf, bytes);
write_buffer_index += bytes;
if (! gimp_wire_flush (channel, NULL))
return FALSE;
}
else
{
bytes = count;
memcpy (&write_buffer[write_buffer_index], buf, bytes);
write_buffer_index += bytes;
}
buf += bytes;
count -= bytes;
}
return TRUE;
}
static gboolean
gimp_flush (GIOChannel *channel,
gpointer user_data)
{
GIOStatus status;
GError *error = NULL;
gsize count;
gsize bytes;
if (write_buffer_index > 0)
{
count = 0;
while (count != write_buffer_index)
{
do
{
bytes = 0;
status = g_io_channel_write_chars (channel,
&write_buffer[count],
(write_buffer_index - count),
&bytes,
&error);
}
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
{
if (error)
{
g_warning ("%s: gimp_flush(): error: %s",
g_get_prgname (), error->message);
g_error_free (error);
}
else
{
g_warning ("%s: gimp_flush(): error", g_get_prgname ());
}
return FALSE;
}
count += bytes;
}
write_buffer_index = 0;
}
return TRUE;
}

View file

@ -199,8 +199,8 @@ gimp_plug_in_register (GimpPlugIn *plug_in,
{
gchar *path = g_file_get_path (plug_in->priv->translation_domain_path);
gimp_plugin_domain_register (plug_in->priv->translation_domain_name,
path);
_gimp_plugin_domain_register (plug_in->priv->translation_domain_name,
path);
g_free (path);
}
@ -209,8 +209,8 @@ gimp_plug_in_register (GimpPlugIn *plug_in,
{
gchar *uri = g_file_get_uri (plug_in->priv->help_domain_uri);
gimp_plugin_domain_register (plug_in->priv->help_domain_name,
uri);
_gimp_plugin_help_register (plug_in->priv->help_domain_name,
uri);
g_free (uri);
}
@ -219,8 +219,8 @@ gimp_plug_in_register (GimpPlugIn *plug_in,
{
GimpPlugInMenuBranch *branch = list->data;
gimp_plugin_menu_branch_register (branch->menu_path,
branch->menu_label);
_gimp_plugin_menu_branch_register (branch->menu_path,
branch->menu_label);
}
}

View file

@ -25,6 +25,9 @@
G_BEGIN_DECLS
#define WRITE_BUFFER_SIZE 1024
typedef struct _GimpPlugInMenuBranch GimpPlugInMenuBranch;
struct _GimpPlugInMenuBranch
@ -37,6 +40,10 @@ struct _GimpPlugInPrivate
{
GIOChannel *read_channel;
GIOChannel *write_channel;
gchar write_buffer[WRITE_BUFFER_SIZE];
gulong write_buffer_index;
guint extension_source_id;
gchar *translation_domain_name;

View file

@ -55,16 +55,23 @@ enum
};
static void gimp_plug_in_constructed (GObject *object);
static void gimp_plug_in_finalize (GObject *object);
static void gimp_plug_in_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_plug_in_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_plug_in_constructed (GObject *object);
static void gimp_plug_in_finalize (GObject *object);
static void gimp_plug_in_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_plug_in_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static gboolean gimp_plug_in_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data);
static gboolean gimp_plug_in_flush (GIOChannel *channel,
gpointer user_data);
G_DEFINE_TYPE_WITH_PRIVATE (GimpPlugIn, gimp_plug_in, G_TYPE_OBJECT)
@ -116,6 +123,11 @@ gimp_plug_in_constructed (GObject *object)
g_assert (plug_in->priv->read_channel != NULL);
g_assert (plug_in->priv->write_channel != NULL);
gp_init ();
gimp_wire_set_writer (gimp_plug_in_write);
gimp_wire_set_flusher (gimp_plug_in_flush);
}
static void
@ -587,3 +599,94 @@ gimp_plug_in_extension_process (GimpPlugIn *plug_in,
#endif
}
/* private functions */
static gboolean
gimp_plug_in_write (GIOChannel *channel,
const guint8 *buf,
gulong count,
gpointer user_data)
{
GimpPlugIn *plug_in = user_data;
gulong bytes;
while (count > 0)
{
if ((plug_in->priv->write_buffer_index + count) >= WRITE_BUFFER_SIZE)
{
bytes = WRITE_BUFFER_SIZE - plug_in->priv->write_buffer_index;
memcpy (&plug_in->priv->write_buffer[plug_in->priv->write_buffer_index],
buf, bytes);
plug_in->priv->write_buffer_index += bytes;
if (! gimp_wire_flush (channel, plug_in))
return FALSE;
}
else
{
bytes = count;
memcpy (&plug_in->priv->write_buffer[plug_in->priv->write_buffer_index],
buf, bytes);
plug_in->priv->write_buffer_index += bytes;
}
buf += bytes;
count -= bytes;
}
return TRUE;
}
static gboolean
gimp_plug_in_flush (GIOChannel *channel,
gpointer user_data)
{
GimpPlugIn *plug_in = user_data;
GIOStatus status;
GError *error = NULL;
gsize count;
gsize bytes;
if (plug_in->priv->write_buffer_index > 0)
{
count = 0;
while (count != plug_in->priv->write_buffer_index)
{
do
{
bytes = 0;
status = g_io_channel_write_chars (channel,
&plug_in->priv->write_buffer[count],
(plug_in->priv->write_buffer_index - count),
&bytes,
&error);
}
while (status == G_IO_STATUS_AGAIN);
if (status != G_IO_STATUS_NORMAL)
{
if (error)
{
g_warning ("%s: gimp_flush(): error: %s",
g_get_prgname (), error->message);
g_error_free (error);
}
else
{
g_warning ("%s: gimp_flush(): error", g_get_prgname ());
}
return FALSE;
}
count += bytes;
}
plug_in->priv->write_buffer_index = 0;
}
return TRUE;
}

View file

@ -99,8 +99,8 @@ _gimp_procedure_register (GimpProcedure *procedure)
list;
list = g_list_next (list))
{
gimp_plugin_menu_register (gimp_procedure_get_name (procedure),
list->data);
_gimp_plugin_menu_register (gimp_procedure_get_name (procedure),
list->data);
}
}

View file

@ -97,6 +97,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (GimpTileBackendPlugin, _gimp_tile_backend_plugin,
#define parent_class _gimp_tile_backend_plugin_parent_class
extern GIOChannel *_gimp_readchannel;
extern GIOChannel *_gimp_writechannel;
static GMutex backend_plugin_mutex;