1
/* GIMP - The GNU 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"
39
#include "pdb/gimppdb.h"
40
#include "pdb/gimp-pdb-compat.h"
42
#include "gimpplugin.h"
43
#include "gimpplugin-message.h"
44
#include "gimppluginmanager.h"
45
#include "gimpplugindef.h"
46
#include "gimppluginshm.h"
47
#include "gimptemporaryprocedure.h"
48
#include "plug-in-params.h"
51
/* local function prototypes */
53
static void gimp_plug_in_handle_quit (GimpPlugIn *plug_in);
54
static void gimp_plug_in_handle_tile_req (GimpPlugIn *plug_in,
56
static void gimp_plug_in_handle_proc_run (GimpPlugIn *plug_in,
58
static void gimp_plug_in_handle_proc_return (GimpPlugIn *plug_in,
59
GPProcReturn *proc_return);
60
static void gimp_plug_in_handle_temp_proc_return (GimpPlugIn *plug_in,
61
GPProcReturn *proc_return);
62
static void gimp_plug_in_handle_proc_install (GimpPlugIn *plug_in,
63
GPProcInstall *proc_install);
64
static void gimp_plug_in_handle_proc_uninstall (GimpPlugIn *plug_in,
65
GPProcUninstall *proc_uninstall);
66
static void gimp_plug_in_handle_extension_ack (GimpPlugIn *plug_in);
67
static void gimp_plug_in_handle_has_init (GimpPlugIn *plug_in);
70
/* public functions */
73
gimp_plug_in_handle_message (GimpPlugIn *plug_in,
76
g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
77
g_return_if_fail (plug_in->open == TRUE);
78
g_return_if_fail (msg != NULL);
83
gimp_plug_in_handle_quit (plug_in);
87
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
88
"Plug-In \"%s\"\n(%s)\n\n"
89
"sent a CONFIG message. This should not happen.",
90
gimp_object_get_name (GIMP_OBJECT (plug_in)),
91
gimp_filename_to_utf8 (plug_in->prog));
92
gimp_plug_in_close (plug_in, TRUE);
96
gimp_plug_in_handle_tile_req (plug_in, msg->data);
100
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
101
"Plug-In \"%s\"\n(%s)\n\n"
102
"sent a TILE_ACK message. This should not happen.",
103
gimp_object_get_name (GIMP_OBJECT (plug_in)),
104
gimp_filename_to_utf8 (plug_in->prog));
105
gimp_plug_in_close (plug_in, TRUE);
109
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
110
"Plug-In \"%s\"\n(%s)\n\n"
111
"sent a TILE_DATA message. This should not happen.",
112
gimp_object_get_name (GIMP_OBJECT (plug_in)),
113
gimp_filename_to_utf8 (plug_in->prog));
114
gimp_plug_in_close (plug_in, TRUE);
118
gimp_plug_in_handle_proc_run (plug_in, msg->data);
122
gimp_plug_in_handle_proc_return (plug_in, msg->data);
125
case GP_TEMP_PROC_RUN:
126
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
127
"Plug-In \"%s\"\n(%s)\n\n"
128
"sent a TEMP_PROC_RUN message. This should not happen.",
129
gimp_object_get_name (GIMP_OBJECT (plug_in)),
130
gimp_filename_to_utf8 (plug_in->prog));
131
gimp_plug_in_close (plug_in, TRUE);
134
case GP_TEMP_PROC_RETURN:
135
gimp_plug_in_handle_temp_proc_return (plug_in, msg->data);
138
case GP_PROC_INSTALL:
139
gimp_plug_in_handle_proc_install (plug_in, msg->data);
142
case GP_PROC_UNINSTALL:
143
gimp_plug_in_handle_proc_uninstall (plug_in, msg->data);
146
case GP_EXTENSION_ACK:
147
gimp_plug_in_handle_extension_ack (plug_in);
151
gimp_plug_in_handle_has_init (plug_in);
157
/* private functions */
160
gimp_plug_in_handle_quit (GimpPlugIn *plug_in)
162
gimp_plug_in_close (plug_in, FALSE);
166
gimp_plug_in_handle_tile_req (GimpPlugIn *plug_in,
169
GPTileData tile_data;
170
GPTileData *tile_info;
172
GimpDrawable *drawable;
176
if (tile_req->drawable_ID == -1)
178
/* this branch communicates with libgimp/gimptile.c:gimp_tile_put() */
180
tile_data.drawable_ID = -1;
181
tile_data.tile_num = 0;
182
tile_data.shadow = 0;
185
tile_data.height = 0;
186
tile_data.use_shm = (plug_in->manager->shm != NULL);
187
tile_data.data = NULL;
189
if (! gp_tile_data_write (plug_in->my_write, &tile_data, plug_in))
191
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
192
"plug_in_handle_tile_req: ERROR");
193
gimp_plug_in_close (plug_in, TRUE);
197
if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
199
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
200
"plug_in_handle_tile_req: ERROR");
201
gimp_plug_in_close (plug_in, TRUE);
205
if (msg.type != GP_TILE_DATA)
207
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
208
"expected tile data and received: %d", msg.type);
209
gimp_plug_in_close (plug_in, TRUE);
213
tile_info = msg.data;
215
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->manager->gimp,
216
tile_info->drawable_ID);
218
if (! GIMP_IS_DRAWABLE (drawable))
220
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
221
"Plug-In \"%s\"\n(%s)\n\n"
222
"requested invalid drawable (killing)",
223
gimp_object_get_name (GIMP_OBJECT (plug_in)),
224
gimp_filename_to_utf8 (plug_in->prog));
225
gimp_plug_in_close (plug_in, TRUE);
229
if (tile_info->shadow)
230
tm = gimp_drawable_get_shadow_tiles (drawable);
232
tm = gimp_drawable_get_tiles (drawable);
234
tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
238
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
239
"Plug-In \"%s\"\n(%s)\n\n"
240
"requested invalid tile (killing)",
241
gimp_object_get_name (GIMP_OBJECT (plug_in)),
242
gimp_filename_to_utf8 (plug_in->prog));
243
gimp_plug_in_close (plug_in, TRUE);
247
if (tile_data.use_shm)
248
memcpy (tile_data_pointer (tile, 0, 0),
249
gimp_plug_in_shm_get_addr (plug_in->manager->shm),
252
memcpy (tile_data_pointer (tile, 0, 0),
256
tile_release (tile, TRUE);
257
gimp_wire_destroy (&msg);
259
if (! gp_tile_ack_write (plug_in->my_write, plug_in))
261
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
262
"plug_in_handle_tile_req: ERROR");
263
gimp_plug_in_close (plug_in, TRUE);
269
/* this branch communicates with libgimp/gimptile.c:gimp_tile_get() */
271
drawable = (GimpDrawable *) gimp_item_get_by_ID (plug_in->manager->gimp,
272
tile_req->drawable_ID);
274
if (! GIMP_IS_DRAWABLE (drawable))
276
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
277
"Plug-In \"%s\"\n(%s)\n\n"
278
"requested invalid drawable (killing)",
279
gimp_object_get_name (GIMP_OBJECT (plug_in)),
280
gimp_filename_to_utf8 (plug_in->prog));
281
gimp_plug_in_close (plug_in, TRUE);
285
if (tile_req->shadow)
286
tm = gimp_drawable_get_shadow_tiles (drawable);
288
tm = gimp_drawable_get_tiles (drawable);
290
tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
294
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
295
"Plug-In \"%s\"\n(%s)\n\n"
296
"requested invalid tile (killing)",
297
gimp_object_get_name (GIMP_OBJECT (plug_in)),
298
gimp_filename_to_utf8 (plug_in->prog));
299
gimp_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 = (plug_in->manager->shm != NULL);
311
if (tile_data.use_shm)
312
memcpy (gimp_plug_in_shm_get_addr (plug_in->manager->shm),
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
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
321
"plug_in_handle_tile_req: ERROR");
322
gimp_plug_in_close (plug_in, TRUE);
326
tile_release (tile, FALSE);
328
if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
330
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
331
"plug_in_handle_tile_req: ERROR");
332
gimp_plug_in_close (plug_in, TRUE);
336
if (msg.type != GP_TILE_ACK)
338
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
339
"expected tile ack and received: %d", msg.type);
340
gimp_plug_in_close (plug_in, TRUE);
344
gimp_wire_destroy (&msg);
349
gimp_plug_in_handle_proc_run (GimpPlugIn *plug_in,
352
GimpPlugInProcFrame *proc_frame;
354
const gchar *proc_name = NULL;
355
GimpProcedure *procedure;
356
GValueArray *args = NULL;
357
GValueArray *return_vals = NULL;
359
canonical = gimp_canonicalize_identifier (proc_run->name);
361
proc_frame = gimp_plug_in_get_proc_frame (plug_in);
363
procedure = gimp_pdb_lookup_procedure (plug_in->manager->gimp->pdb,
368
proc_name = gimp_pdb_lookup_compat_proc_name (plug_in->manager->gimp->pdb,
373
procedure = gimp_pdb_lookup_procedure (plug_in->manager->gimp->pdb,
376
if (plug_in->manager->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
378
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
379
"Plug-In \"%s\"\n(%s)\n"
380
"called deprecated procedure '%s'.\n"
381
"It should call '%s' instead!",
382
gimp_object_get_name (GIMP_OBJECT (plug_in)),
383
gimp_filename_to_utf8 (plug_in->prog),
384
canonical, proc_name);
388
else if (procedure->deprecated)
390
if (plug_in->manager->gimp->pdb_compat_mode == GIMP_PDB_COMPAT_WARN)
392
if (! strcmp (procedure->deprecated, "NONE"))
394
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
395
"Plug-In \"%s\"\n(%s)\n"
396
"called deprecated procedure '%s'.",
397
gimp_object_get_name (GIMP_OBJECT (plug_in)),
398
gimp_filename_to_utf8 (plug_in->prog),
403
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
404
"WARNING: Plug-In \"%s\"\n(%s)\n"
405
"called deprecated procedure '%s'.\n"
406
"It should call '%s' instead!",
407
gimp_object_get_name (GIMP_OBJECT (plug_in)),
408
gimp_filename_to_utf8 (plug_in->prog),
409
canonical, procedure->deprecated);
415
proc_name = canonical;
417
args = plug_in_params_to_args (procedure ? procedure->args : NULL,
418
procedure ? procedure->num_args : 0,
419
proc_run->params, proc_run->nparams,
422
/* Execute the procedure even if gimp_pdb_lookup_procedure()
423
* returned NULL, gimp_pdb_execute_procedure_by_name_args() will
424
* return appropriate error return_vals.
426
gimp_plug_in_manager_plug_in_push (plug_in->manager, plug_in);
427
return_vals = gimp_pdb_execute_procedure_by_name_args (plug_in->manager->gimp->pdb,
428
proc_frame->context_stack ?
429
proc_frame->context_stack->data :
430
proc_frame->main_context,
431
proc_frame->progress,
434
gimp_plug_in_manager_plug_in_pop (plug_in->manager);
436
g_value_array_free (args);
439
/* Don't bother to send the return value if executing the procedure
440
* closed the plug-in (e.g. if the procedure is gimp-quit)
444
GPProcReturn proc_return;
446
/* Return the name we got called with, *not* proc_name or canonical,
447
* since proc_name may have been remapped by gimp->procedural_compat_ht
448
* and canonical may be different too.
450
proc_return.name = proc_run->name;
451
proc_return.nparams = return_vals->n_values;
452
proc_return.params = plug_in_args_to_params (return_vals, FALSE);
454
if (! gp_proc_return_write (plug_in->my_write, &proc_return, plug_in))
456
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
457
"plug_in_handle_proc_run: ERROR");
458
gimp_plug_in_close (plug_in, TRUE);
461
g_free (proc_return.params);
464
g_value_array_free (return_vals);
468
gimp_plug_in_handle_proc_return (GimpPlugIn *plug_in,
469
GPProcReturn *proc_return)
471
GimpPlugInProcFrame *proc_frame = &plug_in->main_proc_frame;
473
if (proc_frame->main_loop)
475
proc_frame->return_vals =
476
plug_in_params_to_args (proc_frame->procedure->values,
477
proc_frame->procedure->num_values,
479
proc_return->nparams,
482
g_main_loop_quit (proc_frame->main_loop);
485
gimp_plug_in_close (plug_in, FALSE);
489
gimp_plug_in_handle_temp_proc_return (GimpPlugIn *plug_in,
490
GPProcReturn *proc_return)
492
if (plug_in->temp_proc_frames)
494
GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
496
proc_frame->return_vals =
497
plug_in_params_to_args (proc_frame->procedure->values,
498
proc_frame->procedure->num_values,
500
proc_return->nparams,
503
gimp_plug_in_main_loop_quit (plug_in);
504
gimp_plug_in_proc_frame_pop (plug_in);
508
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
509
"Plug-In \"%s\"\n(%s)\n\n"
510
"sent a TEMP_PROC_RETURN message while not running "
511
"a temporary procedure. This should not happen.",
512
gimp_object_get_name (GIMP_OBJECT (plug_in)),
513
gimp_filename_to_utf8 (plug_in->prog));
514
gimp_plug_in_close (plug_in, TRUE);
519
gimp_plug_in_handle_proc_install (GimpPlugIn *plug_in,
520
GPProcInstall *proc_install)
522
GimpPlugInProcedure *proc = NULL;
523
GimpProcedure *procedure = NULL;
525
gboolean valid_utf8 = FALSE;
528
canonical = gimp_canonicalize_identifier (proc_install->name);
530
/* Sanity check for array arguments */
532
for (i = 1; i < proc_install->nparams; i++)
534
if ((proc_install->params[i].type == GIMP_PDB_INT32ARRAY ||
535
proc_install->params[i].type == GIMP_PDB_INT8ARRAY ||
536
proc_install->params[i].type == GIMP_PDB_FLOATARRAY ||
537
proc_install->params[i].type == GIMP_PDB_STRINGARRAY)
539
proc_install->params[i - 1].type != GIMP_PDB_INT32)
541
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
542
"Plug-In \"%s\"\n(%s)\n\n"
543
"attempted to install procedure \"%s\" "
544
"which fails to comply with the array parameter "
545
"passing standard. Argument %d is noncompliant.",
546
gimp_object_get_name (GIMP_OBJECT (plug_in)),
547
gimp_filename_to_utf8 (plug_in->prog),
554
/* Sanity check strings for UTF-8 validity */
556
if ((proc_install->menu_path == NULL ||
557
g_utf8_validate (proc_install->menu_path, -1, NULL)) &&
558
(g_utf8_validate (canonical, -1, NULL)) &&
559
(proc_install->blurb == NULL ||
560
g_utf8_validate (proc_install->blurb, -1, NULL)) &&
561
(proc_install->help == NULL ||
562
g_utf8_validate (proc_install->help, -1, NULL)) &&
563
(proc_install->author == NULL ||
564
g_utf8_validate (proc_install->author, -1, NULL)) &&
565
(proc_install->copyright == NULL ||
566
g_utf8_validate (proc_install->copyright, -1, NULL)) &&
567
(proc_install->date == NULL ||
568
g_utf8_validate (proc_install->date, -1, NULL)))
572
for (i = 0; i < proc_install->nparams && valid_utf8; i++)
574
if (! (g_utf8_validate (proc_install->params[i].name, -1, NULL) &&
575
(proc_install->params[i].description == NULL ||
576
g_utf8_validate (proc_install->params[i].description, -1, NULL))))
580
for (i = 0; i < proc_install->nreturn_vals && valid_utf8; i++)
582
if (! (g_utf8_validate (proc_install->return_vals[i].name, -1, NULL) &&
583
(proc_install->return_vals[i].description == NULL ||
584
g_utf8_validate (proc_install->return_vals[i].description, -1, NULL))))
591
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
592
"Plug-In \"%s\"\n(%s)\n\n"
593
"attempted to install a procedure with invalid UTF-8 strings.",
594
gimp_object_get_name (GIMP_OBJECT (plug_in)),
595
gimp_filename_to_utf8 (plug_in->prog));
600
/* Create the procedure object */
602
switch (proc_install->type)
606
procedure = gimp_plug_in_procedure_new (proc_install->type,
611
procedure = gimp_temporary_procedure_new (plug_in);
615
proc = GIMP_PLUG_IN_PROCEDURE (procedure);
617
proc->mtime = time (NULL);
618
proc->installed_during_init = (plug_in->call_mode == GIMP_PLUG_IN_CALL_INIT);
620
gimp_plug_in_procedure_set_image_types (proc, proc_install->image_types);
622
gimp_object_take_name (GIMP_OBJECT (procedure), canonical);
623
gimp_procedure_set_strings (procedure,
627
proc_install->author,
628
proc_install->copyright,
632
for (i = 0; i < proc_install->nparams; i++)
635
gimp_pdb_compat_param_spec (plug_in->manager->gimp,
636
proc_install->params[i].type,
637
proc_install->params[i].name,
638
proc_install->params[i].description);
640
gimp_procedure_add_argument (procedure, pspec);
643
for (i = 0; i < proc_install->nreturn_vals; i++)
646
gimp_pdb_compat_param_spec (plug_in->manager->gimp,
647
proc_install->return_vals[i].type,
648
proc_install->return_vals[i].name,
649
proc_install->return_vals[i].description);
651
gimp_procedure_add_return_value (procedure, pspec);
654
/* Sanity check menu path */
656
if (proc_install->menu_path)
658
if (proc_install->menu_path[0] == '<')
660
GError *error = NULL;
662
if (! gimp_plug_in_procedure_add_menu_path (proc,
663
proc_install->menu_path,
666
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_WARNING,
667
"%s", error->message);
668
g_clear_error (&error);
673
proc->menu_label = g_strdup (proc_install->menu_path);
677
/* Install the procedure */
679
switch (proc_install->type)
683
gimp_plug_in_def_add_procedure (plug_in->plug_in_def, proc);
687
gimp_plug_in_add_temp_proc (plug_in, GIMP_TEMPORARY_PROCEDURE (proc));
691
g_object_unref (proc);
695
gimp_plug_in_handle_proc_uninstall (GimpPlugIn *plug_in,
696
GPProcUninstall *proc_uninstall)
698
GimpPlugInProcedure *proc;
701
canonical = gimp_canonicalize_identifier (proc_uninstall->name);
703
proc = gimp_plug_in_procedure_find (plug_in->temp_procedures, canonical);
706
gimp_plug_in_remove_temp_proc (plug_in, GIMP_TEMPORARY_PROCEDURE (proc));
712
gimp_plug_in_handle_extension_ack (GimpPlugIn *plug_in)
714
if (plug_in->ext_main_loop)
716
g_main_loop_quit (plug_in->ext_main_loop);
720
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
721
"Plug-In \"%s\"\n(%s)\n\n"
722
"sent an EXTENSION_ACK message while not being started "
723
"as an extension. This should not happen.",
724
gimp_object_get_name (GIMP_OBJECT (plug_in)),
725
gimp_filename_to_utf8 (plug_in->prog));
726
gimp_plug_in_close (plug_in, TRUE);
731
gimp_plug_in_handle_has_init (GimpPlugIn *plug_in)
733
if (plug_in->call_mode == GIMP_PLUG_IN_CALL_QUERY)
735
gimp_plug_in_def_set_has_init (plug_in->plug_in_def, TRUE);
739
gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
740
"Plug-In \"%s\"\n(%s)\n\n"
741
"sent an HAS_INIT message while not in query(). "
742
"This should not happen.",
743
gimp_object_get_name (GIMP_OBJECT (plug_in)),
744
gimp_filename_to_utf8 (plug_in->prog));
745
gimp_plug_in_close (plug_in, TRUE);