1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
#include <glib-object.h>
27
#include "libgimpbase/gimpbase.h"
28
#include "libgimpbase/gimpprotocol.h"
29
#include "libgimpbase/gimpwire.h"
31
#include "plug-in-types.h"
33
#include "base/tile.h"
34
#include "base/tile-manager.h"
36
#include "core/gimp.h"
37
#include "core/gimpdrawable.h"
41
#include "plug-in-def.h"
42
#include "plug-in-params.h"
43
#include "plug-in-proc-def.h"
44
#include "plug-in-shm.h"
47
typedef struct _PlugInBlocked PlugInBlocked;
56
/* local function prototypes */
58
static void plug_in_handle_quit (PlugIn *plug_in);
59
static void plug_in_handle_tile_req (PlugIn *plug_in,
61
static void plug_in_handle_proc_run (PlugIn *plug_in,
63
static void plug_in_handle_proc_return_priv (PlugIn *plug_in,
64
GPProcReturn *proc_return,
66
static void plug_in_handle_proc_return (PlugIn *plug_in,
67
GPProcReturn *proc_return);
68
static void plug_in_handle_temp_proc_return (PlugIn *plug_in,
69
GPProcReturn *proc_return);
70
static void plug_in_handle_proc_install (PlugIn *plug_in,
71
GPProcInstall *proc_install);
72
static void plug_in_handle_proc_uninstall (PlugIn *plug_in,
73
GPProcUninstall *proc_uninstall);
74
static void plug_in_handle_extension_ack (PlugIn *plug_in);
75
static void plug_in_handle_has_init (PlugIn *plug_in);
78
/* private variables */
80
static GSList *blocked_plug_ins = NULL;
83
/* public functions */
86
plug_in_handle_message (PlugIn *plug_in,
92
plug_in_handle_quit (plug_in);
96
g_message ("Plug-In \"%s\"\n(%s)\n\n"
97
"sent a CONFIG message (should not happen)",
98
gimp_filename_to_utf8 (plug_in->name),
99
gimp_filename_to_utf8 (plug_in->prog));
100
plug_in_close (plug_in, TRUE);
104
plug_in_handle_tile_req (plug_in, msg->data);
108
g_message ("Plug-In \"%s\"\n(%s)\n\n"
109
"sent a TILE_ACK message (should not happen)",
110
gimp_filename_to_utf8 (plug_in->name),
111
gimp_filename_to_utf8 (plug_in->prog));
112
plug_in_close (plug_in, TRUE);
116
g_message ("Plug-In \"%s\"\n(%s)\n\n"
117
"sent a TILE_DATA message (should not happen)",
118
gimp_filename_to_utf8 (plug_in->name),
119
gimp_filename_to_utf8 (plug_in->prog));
120
plug_in_close (plug_in, TRUE);
124
plug_in_handle_proc_run (plug_in, msg->data);
128
plug_in_handle_proc_return (plug_in, msg->data);
131
case GP_TEMP_PROC_RUN:
132
g_message ("Plug-In \"%s\"\n(%s)\n\n"
133
"sent a TEMP_PROC_RUN message (should not happen)",
134
gimp_filename_to_utf8 (plug_in->name),
135
gimp_filename_to_utf8 (plug_in->prog));
136
plug_in_close (plug_in, TRUE);
139
case GP_TEMP_PROC_RETURN:
140
plug_in_handle_temp_proc_return (plug_in, msg->data);
143
case GP_PROC_INSTALL:
144
plug_in_handle_proc_install (plug_in, msg->data);
147
case GP_PROC_UNINSTALL:
148
plug_in_handle_proc_uninstall (plug_in, msg->data);
151
case GP_EXTENSION_ACK:
152
plug_in_handle_extension_ack (plug_in);
156
plug_in_handle_has_init (plug_in);
162
/* private functions */
165
plug_in_handle_quit (PlugIn *plug_in)
167
plug_in_close (plug_in, FALSE);
171
plug_in_handle_tile_req (PlugIn *plug_in,
174
GPTileData tile_data;
175
GPTileData *tile_info;
177
GimpDrawable *drawable;
182
shm_ID = plug_in_shm_get_ID (plug_in->gimp);
184
if (tile_req->drawable_ID == -1)
186
/* this branch communicates with libgimp/gimptile.c:gimp_tile_put() */
188
tile_data.drawable_ID = -1;
189
tile_data.tile_num = 0;
190
tile_data.shadow = 0;
193
tile_data.height = 0;
194
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
195
tile_data.data = NULL;
197
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
199
g_warning ("plug_in_handle_tile_req: ERROR");
200
plug_in_close (plug_in, TRUE);
204
if (! wire_read_msg (plug_in->my_read, &msg, plug_in))
206
g_warning ("plug_in_handle_tile_req: ERROR");
207
plug_in_close (plug_in, TRUE);
211
if (msg.type != GP_TILE_DATA)
213
g_warning ("expected tile data and received: %d", msg.type);
214
plug_in_close (plug_in, TRUE);
218
tile_info = msg.data;
220
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->gimp,
221
tile_info->drawable_ID);
225
g_message ("Plug-In \"%s\"\n(%s)\n\n"
226
"requested invalid drawable (killing)",
227
gimp_filename_to_utf8 (plug_in->name),
228
gimp_filename_to_utf8 (plug_in->prog));
229
plug_in_close (plug_in, TRUE);
233
if (tile_info->shadow)
234
tm = gimp_drawable_shadow (drawable);
236
tm = gimp_drawable_data (drawable);
238
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
242
g_message ("Plug-In \"%s\"\n(%s)\n\n"
243
"requested invalid tile (killing)",
244
gimp_filename_to_utf8 (plug_in->name),
245
gimp_filename_to_utf8 (plug_in->prog));
246
plug_in_close (plug_in, TRUE);
250
if (tile_data.use_shm)
251
memcpy (tile_data_pointer (tile, 0, 0),
252
plug_in_shm_get_addr (plug_in->gimp),
255
memcpy (tile_data_pointer (tile, 0, 0),
259
tile_release (tile, TRUE);
262
if (! gp_tile_ack_write (plug_in->my_write, plug_in))
264
g_warning ("plug_in_handle_tile_req: ERROR");
265
plug_in_close (plug_in, TRUE);
271
/* this branch communicates with libgimp/gimptile.c:gimp_tile_get() */
273
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->gimp,
274
tile_req->drawable_ID);
278
g_message ("Plug-In \"%s\"\n(%s)\n\n"
279
"requested invalid drawable (killing)",
280
gimp_filename_to_utf8 (plug_in->name),
281
gimp_filename_to_utf8 (plug_in->prog));
282
plug_in_close (plug_in, TRUE);
286
if (tile_req->shadow)
287
tm = gimp_drawable_shadow (drawable);
289
tm = gimp_drawable_data (drawable);
291
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
295
g_message ("Plug-In \"%s\"\n(%s)\n\n"
296
"requested invalid tile (killing)",
297
gimp_filename_to_utf8 (plug_in->name),
298
gimp_filename_to_utf8 (plug_in->prog));
299
plug_in_close (plug_in, TRUE);
303
tile_data.drawable_ID = tile_req->drawable_ID;
304
tile_data.tile_num = tile_req->tile_num;
305
tile_data.shadow = tile_req->shadow;
306
tile_data.bpp = tile_bpp (tile);
307
tile_data.width = tile_ewidth (tile);
308
tile_data.height = tile_eheight (tile);
309
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
311
if (tile_data.use_shm)
312
memcpy (plug_in_shm_get_addr (plug_in->gimp),
313
tile_data_pointer (tile, 0, 0),
316
tile_data.data = tile_data_pointer (tile, 0, 0);
318
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
320
g_message ("plug_in_handle_tile_req: ERROR");
321
plug_in_close (plug_in, TRUE);
325
tile_release (tile, FALSE);
327
if (! wire_read_msg (plug_in->my_read, &msg, plug_in))
329
g_message ("plug_in_handle_tile_req: ERROR");
330
plug_in_close (plug_in, TRUE);
334
if (msg.type != GP_TILE_ACK)
336
g_warning ("expected tile ack and received: %d", msg.type);
337
plug_in_close (plug_in, TRUE);
346
plug_in_handle_proc_run (PlugIn *plug_in,
349
PlugInProcFrame *proc_frame;
350
const gchar *proc_name = NULL;
351
ProcRecord *proc_rec;
353
Argument *return_vals;
355
proc_frame = plug_in_get_proc_frame (plug_in);
357
proc_rec = procedural_db_lookup (plug_in->gimp, proc_run->name);
361
proc_name = g_hash_table_lookup (plug_in->gimp->procedural_compat_ht,
366
proc_rec = procedural_db_lookup (plug_in->gimp, proc_name);
368
if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
370
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
371
"called deprecated procedure '%s'.\n"
372
"It should call '%s' instead!",
373
gimp_filename_to_utf8 (plug_in->name),
374
gimp_filename_to_utf8 (plug_in->prog),
375
proc_run->name, proc_name);
379
else if (proc_rec->deprecated)
381
if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
383
if (! strcmp (proc_rec->deprecated, "NONE"))
385
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
386
"called deprecated procedure '%s'.",
387
gimp_filename_to_utf8 (plug_in->name),
388
gimp_filename_to_utf8 (plug_in->prog),
393
g_message ("WARNING: Plug-In \"%s\"\n(%s)\n"
394
"called deprecated procedure '%s'.\n"
395
"It should call '%s' instead!",
396
gimp_filename_to_utf8 (plug_in->name),
397
gimp_filename_to_utf8 (plug_in->prog),
398
proc_run->name, proc_rec->deprecated);
401
else if (plug_in->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_OFF)
408
proc_name = proc_run->name;
410
args = plug_in_params_to_args (proc_run->params, proc_run->nparams, FALSE);
412
plug_in_push (plug_in->gimp, plug_in);
414
/* Execute the procedure even if procedural_db_lookup() returned NULL,
415
* procedural_db_execute() will return appropriate error return_vals.
417
return_vals = procedural_db_execute (plug_in->gimp,
418
proc_frame->context_stack ?
419
proc_frame->context_stack->data :
420
proc_frame->main_context,
421
proc_frame->progress,
424
plug_in_pop (plug_in->gimp);
428
GPProcReturn proc_return;
430
/* Return the name we got called with, *not* proc_name, since
431
* proc_name may have been remapped by gimp->procedural_compat_ht
433
proc_return.name = proc_run->name;
437
proc_return.nparams = proc_rec->num_values + 1;
438
proc_return.params = plug_in_args_to_params (return_vals,
444
proc_return.nparams = 1;
445
proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
448
if (! gp_proc_return_write (plug_in->my_write, &proc_return, plug_in))
450
g_warning ("plug_in_handle_proc_run: ERROR");
451
plug_in_close (plug_in, TRUE);
455
plug_in_args_destroy (args, proc_run->nparams, FALSE);
458
plug_in_args_destroy (return_vals, proc_rec->num_values + 1, TRUE);
460
plug_in_args_destroy (return_vals, 1, TRUE);
462
plug_in_params_destroy (proc_return.params, proc_return.nparams, FALSE);
466
PlugInBlocked *blocked;
468
g_warning ("%s: EEEEEEEEEK! \n"
469
"You managed to trigger a code path that \n"
470
"should be dead. Please report this to bugs.gimp.org.",
473
blocked = g_new0 (PlugInBlocked, 1);
475
blocked->plug_in = plug_in;
476
blocked->proc_name = g_strdup (proc_run->name);
478
blocked_plug_ins = g_slist_prepend (blocked_plug_ins, blocked);
483
plug_in_handle_proc_return_priv (PlugIn *plug_in,
484
GPProcReturn *proc_return,
487
PlugInProcFrame *proc_frame;
490
proc_frame = plug_in->temp_proc_frames->data;
492
proc_frame = &plug_in->main_proc_frame;
494
if (proc_frame->main_loop)
496
proc_frame->return_vals = plug_in_params_to_args (proc_return->params,
497
proc_return->nparams,
499
proc_frame->n_return_vals = proc_return->nparams;
505
for (list = blocked_plug_ins; list; list = g_slist_next (list))
507
PlugInBlocked *blocked;
509
blocked = (PlugInBlocked *) list->data;
511
if (blocked->proc_name && proc_return->name &&
512
strcmp (blocked->proc_name, proc_return->name) == 0)
514
if (! gp_proc_return_write (blocked->plug_in->my_write,
518
g_message ("plug_in_handle_proc_run: ERROR");
519
plug_in_close (blocked->plug_in, TRUE);
523
blocked_plug_ins = g_slist_remove (blocked_plug_ins, blocked);
524
g_free (blocked->proc_name);
533
plug_in_handle_proc_return (PlugIn *plug_in,
534
GPProcReturn *proc_return)
536
plug_in_handle_proc_return_priv (plug_in, proc_return, FALSE);
538
if (plug_in->main_proc_frame.main_loop)
539
g_main_loop_quit (plug_in->main_proc_frame.main_loop);
541
plug_in_close (plug_in, FALSE);
545
plug_in_handle_temp_proc_return (PlugIn *plug_in,
546
GPProcReturn *proc_return)
548
if (plug_in->temp_proc_frames)
550
plug_in_handle_proc_return_priv (plug_in, proc_return, TRUE);
552
plug_in_main_loop_quit (plug_in);
553
plug_in_proc_frame_pop (plug_in);
557
g_message ("Plug-In \"%s\"\n(%s)\n\n"
558
"sent a TEMP_PROC_RETURN message while not running "
559
"a temp proc (should not happen)",
560
gimp_filename_to_utf8 (plug_in->name),
561
gimp_filename_to_utf8 (plug_in->prog));
562
plug_in_close (plug_in, TRUE);
567
plug_in_handle_proc_install (PlugIn *plug_in,
568
GPProcInstall *proc_install)
570
PlugInDef *plug_in_def = NULL;
571
PlugInProcDef *proc_def = NULL;
572
ProcRecord *proc = NULL;
575
gboolean valid_utf8 = FALSE;
579
* --only sanity check arguments when the procedure requests a menu path
582
if (proc_install->menu_path && proc_install->menu_path[0] == '<')
584
GError *error = NULL;
586
if (! plug_in_param_defs_check (plug_in->name,
589
proc_install->menu_path,
590
proc_install->params,
591
proc_install->nparams,
592
proc_install->return_vals,
593
proc_install->nreturn_vals,
596
g_message (error->message);
597
g_clear_error (&error);
603
/* Sanity check for array arguments */
605
for (i = 1; i < proc_install->nparams; i++)
607
if ((proc_install->params[i].type == GIMP_PDB_INT32ARRAY ||
608
proc_install->params[i].type == GIMP_PDB_INT8ARRAY ||
609
proc_install->params[i].type == GIMP_PDB_FLOATARRAY ||
610
proc_install->params[i].type == GIMP_PDB_STRINGARRAY)
612
proc_install->params[i-1].type != GIMP_PDB_INT32)
614
g_message ("Plug-In \"%s\"\n(%s)\n\n"
615
"attempted to install procedure \"%s\" "
616
"which fails to comply with the array parameter "
617
"passing standard. Argument %d is noncompliant.",
618
gimp_filename_to_utf8 (plug_in->name),
619
gimp_filename_to_utf8 (plug_in->prog),
620
proc_install->name, i);
625
/* Sanity check strings for UTF-8 validity */
627
if ((proc_install->menu_path == NULL ||
628
g_utf8_validate (proc_install->menu_path, -1, NULL)) &&
629
(g_utf8_validate (proc_install->name, -1, NULL)) &&
630
(proc_install->blurb == NULL ||
631
g_utf8_validate (proc_install->blurb, -1, NULL)) &&
632
(proc_install->help == NULL ||
633
g_utf8_validate (proc_install->help, -1, NULL)) &&
634
(proc_install->author == NULL ||
635
g_utf8_validate (proc_install->author, -1, NULL)) &&
636
(proc_install->copyright == NULL ||
637
g_utf8_validate (proc_install->copyright, -1, NULL)) &&
638
(proc_install->date == NULL ||
639
g_utf8_validate (proc_install->date, -1, NULL)))
643
for (i = 0; i < proc_install->nparams && valid_utf8; i++)
645
if (! (g_utf8_validate (proc_install->params[i].name, -1, NULL) &&
646
(proc_install->params[i].description == NULL ||
647
g_utf8_validate (proc_install->params[i].description, -1, NULL))))
651
for (i = 0; i < proc_install->nreturn_vals && valid_utf8; i++)
653
if (! (g_utf8_validate (proc_install->return_vals[i].name, -1, NULL) &&
654
(proc_install->return_vals[i].description == NULL ||
655
g_utf8_validate (proc_install->return_vals[i].description, -1, NULL))))
662
g_message ("Plug-In \"%s\"\n(%s)\n\n"
663
"attempted to install a procedure with invalid UTF-8 strings.",
664
gimp_filename_to_utf8 (plug_in->name),
665
gimp_filename_to_utf8 (plug_in->prog));
671
switch (proc_install->type)
675
plug_in_def = plug_in->plug_in_def;
676
prog = plug_in_def->prog;
678
tmp = plug_in_def->proc_defs;
685
tmp = plug_in->temp_proc_defs;
691
proc_def = tmp->data;
694
if (strcmp (proc_def->db_info.name, proc_install->name) == 0)
696
switch (proc_install->type)
700
plug_in_def->proc_defs = g_slist_remove (plug_in_def->proc_defs,
702
plug_in_proc_def_free (proc_def);
706
plug_in->temp_proc_defs = g_slist_remove (plug_in->temp_proc_defs,
708
plug_ins_temp_proc_def_remove (plug_in->gimp, proc_def);
716
proc_def = plug_in_proc_def_new ();
718
if (proc_install->menu_path)
720
if (proc_install->menu_path[0] == '<')
721
proc_def->menu_paths =
722
g_list_append (proc_def->menu_paths,
723
g_strdup (proc_install->menu_path));
725
proc_def->menu_label = g_strdup (proc_install->menu_path);
728
proc_def->prog = g_strdup (prog);
729
proc_def->extensions = NULL;
730
proc_def->prefixes = NULL;
731
proc_def->magics = NULL;
732
proc_def->image_types = g_strdup (proc_install->image_types);
733
proc_def->image_types_val = plug_ins_image_types_parse (proc_def->image_types);
734
/* Install temp one use todays time */
735
proc_def->mtime = time (NULL);
737
/* Remember if this proc was installed while initing a plug-in */
738
proc_def->installed_during_init = plug_in->init;
740
/* The procedural database procedure */
742
proc = &proc_def->db_info;
744
proc->name = g_strdup (proc_install->name);
745
proc->blurb = g_strdup (proc_install->blurb);
746
proc->help = g_strdup (proc_install->help);
747
proc->author = g_strdup (proc_install->author);
748
proc->copyright = g_strdup (proc_install->copyright);
749
proc->date = g_strdup (proc_install->date);
750
proc->proc_type = proc_install->type;
752
proc->num_args = proc_install->nparams;
753
proc->num_values = proc_install->nreturn_vals;
755
proc->args = g_new0 (ProcArg, proc->num_args);
756
proc->values = g_new0 (ProcArg, proc->num_values);
758
for (i = 0; i < proc->num_args; i++)
760
proc->args[i].arg_type = proc_install->params[i].type;
761
proc->args[i].name = g_strdup (proc_install->params[i].name);
762
proc->args[i].description = g_strdup (proc_install->params[i].description);
765
for (i = 0; i < proc->num_values; i++)
767
proc->values[i].arg_type = proc_install->return_vals[i].type;
768
proc->values[i].name = g_strdup (proc_install->return_vals[i].name);
769
proc->values[i].description = g_strdup (proc_install->return_vals[i].description);
772
switch (proc_install->type)
776
plug_in_def->proc_defs = g_slist_prepend (plug_in_def->proc_defs,
781
plug_in->temp_proc_defs = g_slist_prepend (plug_in->temp_proc_defs,
784
proc->exec_method.temporary.plug_in = plug_in;
786
plug_ins_temp_proc_def_add (plug_in->gimp, proc_def);
792
plug_in_handle_proc_uninstall (PlugIn *plug_in,
793
GPProcUninstall *proc_uninstall)
797
for (tmp = plug_in->temp_proc_defs; tmp; tmp = g_slist_next (tmp))
799
PlugInProcDef *proc_def;
801
proc_def = tmp->data;
803
if (! strcmp (proc_def->db_info.name, proc_uninstall->name))
805
plug_in->temp_proc_defs = g_slist_remove (plug_in->temp_proc_defs,
807
plug_ins_temp_proc_def_remove (plug_in->gimp, proc_def);
814
plug_in_handle_extension_ack (PlugIn *plug_in)
816
if (plug_in->ext_main_loop)
818
g_main_loop_quit (plug_in->ext_main_loop);
822
g_message ("Plug-In \"%s\"\n(%s)\n\n"
823
"sent an EXTENSION_ACK message while not being started "
824
"as extension (should not happen)",
825
gimp_filename_to_utf8 (plug_in->name),
826
gimp_filename_to_utf8 (plug_in->prog));
827
plug_in_close (plug_in, TRUE);
832
plug_in_handle_has_init (PlugIn *plug_in)
836
plug_in_def_set_has_init (plug_in->plug_in_def, TRUE);
840
g_message ("Plug-In \"%s\"\n(%s)\n\n"
841
"sent an HAS_INIT message while not in query() "
842
"(should not happen)",
843
gimp_filename_to_utf8 (plug_in->name),
844
gimp_filename_to_utf8 (plug_in->prog));
845
plug_in_close (plug_in, TRUE);