1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpplugin.c
5 *
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 3 of the License, or
9 * (at your option) any later version.
10 *
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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "config.h"
21
22 #ifndef _WIN32
23 #define _GNU_SOURCE
24 #endif
25
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #ifdef HAVE_SYS_WAIT_H
36 #include <sys/wait.h>
37 #endif
38
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif
42
43 #include <gdk-pixbuf/gdk-pixbuf.h>
44 #include <gegl.h>
45
46 #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
47
48 #define STRICT
49 #include <windows.h>
50 #include <process.h>
51
52 #ifdef G_OS_WIN32
53 #include <fcntl.h>
54 #include <io.h>
55
56 #ifndef pipe
57 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
58 #endif
59
60 #endif
61
62 #ifdef G_WITH_CYGWIN
63 #define O_TEXT 0x0100 /* text file */
64 #define _O_TEXT 0x0100 /* text file */
65 #define O_BINARY 0x0200 /* binary file */
66 #define _O_BINARY 0x0200 /* binary file */
67 #endif
68
69 #endif /* G_OS_WIN32 || G_WITH_CYGWIN */
70
71 #include "libgimpbase/gimpbase.h"
72 #include "libgimpbase/gimpprotocol.h"
73 #include "libgimpbase/gimpwire.h"
74
75 #include "plug-in-types.h"
76
77 #include "core/gimp.h"
78 #include "core/gimp-spawn.h"
79 #include "core/gimpprogress.h"
80
81 #include "pdb/gimppdbcontext.h"
82
83 #include "gimpenvirontable.h"
84 #include "gimpinterpreterdb.h"
85 #include "gimpplugin.h"
86 #include "gimpplugin-message.h"
87 #include "gimpplugin-progress.h"
88 #include "gimpplugindebug.h"
89 #include "gimpplugindef.h"
90 #include "gimppluginmanager.h"
91 #include "gimppluginmanager-help-domain.h"
92 #include "gimppluginmanager-locale-domain.h"
93 #include "gimptemporaryprocedure.h"
94 #include "plug-in-params.h"
95
96 #include "gimp-intl.h"
97
98
99 static void gimp_plug_in_finalize (GObject *object);
100
101 static gboolean gimp_plug_in_recv_message (GIOChannel *channel,
102 GIOCondition cond,
103 gpointer data);
104 static gboolean gimp_plug_in_write (GIOChannel *channel,
105 const guint8 *buf,
106 gulong count,
107 gpointer data);
108 static gboolean gimp_plug_in_flush (GIOChannel *channel,
109 gpointer data);
110
111 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
112 static void gimp_plug_in_set_dll_directory (const gchar *path);
113 #endif
114
115
116
G_DEFINE_TYPE(GimpPlugIn,gimp_plug_in,GIMP_TYPE_OBJECT)117 G_DEFINE_TYPE (GimpPlugIn, gimp_plug_in, GIMP_TYPE_OBJECT)
118
119 #define parent_class gimp_plug_in_parent_class
120
121
122 static void
123 gimp_plug_in_class_init (GimpPlugInClass *klass)
124 {
125 GObjectClass *object_class = G_OBJECT_CLASS (klass);
126
127 object_class->finalize = gimp_plug_in_finalize;
128
129 /* initialize the gimp protocol library and set the read and
130 * write handlers.
131 */
132 gp_init ();
133 gimp_wire_set_writer (gimp_plug_in_write);
134 gimp_wire_set_flusher (gimp_plug_in_flush);
135 }
136
137 static void
gimp_plug_in_init(GimpPlugIn * plug_in)138 gimp_plug_in_init (GimpPlugIn *plug_in)
139 {
140 plug_in->manager = NULL;
141 plug_in->file = NULL;
142
143 plug_in->call_mode = GIMP_PLUG_IN_CALL_NONE;
144 plug_in->open = FALSE;
145 plug_in->hup = FALSE;
146 plug_in->pid = 0;
147
148 plug_in->my_read = NULL;
149 plug_in->my_write = NULL;
150 plug_in->his_read = NULL;
151 plug_in->his_write = NULL;
152
153 plug_in->input_id = 0;
154 plug_in->write_buffer_index = 0;
155
156 plug_in->temp_procedures = NULL;
157
158 plug_in->ext_main_loop = NULL;
159
160 plug_in->temp_proc_frames = NULL;
161
162 plug_in->plug_in_def = NULL;
163 }
164
165 static void
gimp_plug_in_finalize(GObject * object)166 gimp_plug_in_finalize (GObject *object)
167 {
168 GimpPlugIn *plug_in = GIMP_PLUG_IN (object);
169
170 g_clear_object (&plug_in->file);
171
172 gimp_plug_in_proc_frame_dispose (&plug_in->main_proc_frame, plug_in);
173
174 G_OBJECT_CLASS (parent_class)->finalize (object);
175 }
176
177 static gboolean
gimp_plug_in_recv_message(GIOChannel * channel,GIOCondition cond,gpointer data)178 gimp_plug_in_recv_message (GIOChannel *channel,
179 GIOCondition cond,
180 gpointer data)
181 {
182 GimpPlugIn *plug_in = data;
183 gboolean got_message = FALSE;
184
185 #ifdef G_OS_WIN32
186 /* Workaround for GLib bug #137968: sometimes we are called for no
187 * reason...
188 */
189 if (cond == 0)
190 return TRUE;
191 #endif
192
193 if (plug_in->my_read == NULL)
194 return TRUE;
195
196 g_object_ref (plug_in);
197
198 if (cond & (G_IO_IN | G_IO_PRI))
199 {
200 GimpWireMessage msg;
201
202 memset (&msg, 0, sizeof (GimpWireMessage));
203
204 if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
205 {
206 gimp_plug_in_close (plug_in, TRUE);
207 }
208 else
209 {
210 gimp_plug_in_handle_message (plug_in, &msg);
211 gimp_wire_destroy (&msg);
212 got_message = TRUE;
213 }
214 }
215
216 if (cond & (G_IO_ERR | G_IO_HUP))
217 {
218 if (cond & G_IO_HUP)
219 plug_in->hup = TRUE;
220
221 if (plug_in->open)
222 gimp_plug_in_close (plug_in, TRUE);
223 }
224
225 if (! got_message)
226 {
227 GimpPlugInProcFrame *frame = gimp_plug_in_get_proc_frame (plug_in);
228 GimpProgress *progress = frame ? frame->progress : NULL;
229
230 gimp_message (plug_in->manager->gimp, G_OBJECT (progress),
231 GIMP_MESSAGE_ERROR,
232 _("Plug-in crashed: \"%s\"\n(%s)\n\n"
233 "The dying plug-in may have messed up GIMP's internal "
234 "state. You may want to save your images and restart "
235 "GIMP to be on the safe side."),
236 gimp_object_get_name (plug_in),
237 gimp_file_get_utf8_name (plug_in->file));
238 }
239
240 g_object_unref (plug_in);
241
242 return TRUE;
243 }
244
245 static gboolean
gimp_plug_in_write(GIOChannel * channel,const guint8 * buf,gulong count,gpointer data)246 gimp_plug_in_write (GIOChannel *channel,
247 const guint8 *buf,
248 gulong count,
249 gpointer data)
250 {
251 GimpPlugIn *plug_in = data;
252 gulong bytes;
253
254 while (count > 0)
255 {
256 if ((plug_in->write_buffer_index + count) >= WRITE_BUFFER_SIZE)
257 {
258 bytes = WRITE_BUFFER_SIZE - plug_in->write_buffer_index;
259 memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
260 buf, bytes);
261 plug_in->write_buffer_index += bytes;
262 if (! gimp_wire_flush (channel, plug_in))
263 return FALSE;
264 }
265 else
266 {
267 bytes = count;
268 memcpy (&plug_in->write_buffer[plug_in->write_buffer_index],
269 buf, bytes);
270 plug_in->write_buffer_index += bytes;
271 }
272
273 buf += bytes;
274 count -= bytes;
275 }
276
277 return TRUE;
278 }
279
280 static gboolean
gimp_plug_in_flush(GIOChannel * channel,gpointer data)281 gimp_plug_in_flush (GIOChannel *channel,
282 gpointer data)
283 {
284 GimpPlugIn *plug_in = data;
285
286 if (plug_in->write_buffer_index > 0)
287 {
288 GIOStatus status;
289 GError *error = NULL;
290 gint count;
291 gsize bytes;
292
293 count = 0;
294 while (count != plug_in->write_buffer_index)
295 {
296 do
297 {
298 bytes = 0;
299 status = g_io_channel_write_chars (channel,
300 &plug_in->write_buffer[count],
301 (plug_in->write_buffer_index - count),
302 &bytes,
303 &error);
304 }
305 while (status == G_IO_STATUS_AGAIN);
306
307 if (status != G_IO_STATUS_NORMAL)
308 {
309 if (error)
310 {
311 g_warning ("%s: plug_in_flush(): error: %s",
312 gimp_filename_to_utf8 (g_get_prgname ()),
313 error->message);
314 g_error_free (error);
315 }
316 else
317 {
318 g_warning ("%s: plug_in_flush(): error",
319 gimp_filename_to_utf8 (g_get_prgname ()));
320 }
321
322 return FALSE;
323 }
324
325 count += bytes;
326 }
327
328 plug_in->write_buffer_index = 0;
329 }
330
331 return TRUE;
332 }
333
334 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
335 static void
gimp_plug_in_set_dll_directory(const gchar * path)336 gimp_plug_in_set_dll_directory (const gchar *path)
337 {
338 const gchar *install_dir;
339 gchar *bin_dir;
340 LPWSTR w_bin_dir;
341 DWORD BinaryType;
342 int n;
343
344 w_bin_dir = NULL;
345 install_dir = gimp_installation_directory ();
346 if (path &&
347 GetBinaryTypeA (path, &BinaryType) &&
348 BinaryType == SCS_32BIT_BINARY)
349 bin_dir = g_build_filename (install_dir, WIN32_32BIT_DLL_FOLDER, NULL);
350 else
351 bin_dir = g_build_filename (install_dir, "bin", NULL);
352
353 n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
354 bin_dir, -1, NULL, 0);
355 if (n == 0)
356 goto out;
357
358 w_bin_dir = g_malloc_n (n + 1, sizeof (wchar_t));
359 n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
360 bin_dir, -1,
361 w_bin_dir, (n + 1) * sizeof (wchar_t));
362 if (n == 0)
363 goto out;
364
365 SetDllDirectoryW (w_bin_dir);
366
367 out:
368 if (w_bin_dir)
369 g_free ((void*) w_bin_dir);
370 g_free (bin_dir);
371 }
372 #endif
373
374
375 /* public functions */
376
377 GimpPlugIn *
gimp_plug_in_new(GimpPlugInManager * manager,GimpContext * context,GimpProgress * progress,GimpPlugInProcedure * procedure,GFile * file)378 gimp_plug_in_new (GimpPlugInManager *manager,
379 GimpContext *context,
380 GimpProgress *progress,
381 GimpPlugInProcedure *procedure,
382 GFile *file)
383 {
384 GimpPlugIn *plug_in;
385
386 g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
387 g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
388 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
389 g_return_val_if_fail (procedure == NULL ||
390 GIMP_IS_PLUG_IN_PROCEDURE (procedure), NULL);
391 g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
392 g_return_val_if_fail ((procedure != NULL || file != NULL) &&
393 ! (procedure != NULL && file != NULL), NULL);
394
395 plug_in = g_object_new (GIMP_TYPE_PLUG_IN, NULL);
396
397 if (! file)
398 file = gimp_plug_in_procedure_get_file (procedure);
399
400 gimp_object_take_name (GIMP_OBJECT (plug_in),
401 g_path_get_basename (gimp_file_get_utf8_name (file)));
402
403 plug_in->manager = manager;
404 plug_in->file = g_object_ref (file);
405
406 gimp_plug_in_proc_frame_init (&plug_in->main_proc_frame,
407 context, progress, procedure);
408
409 return plug_in;
410 }
411
412 gboolean
gimp_plug_in_open(GimpPlugIn * plug_in,GimpPlugInCallMode call_mode,gboolean synchronous)413 gimp_plug_in_open (GimpPlugIn *plug_in,
414 GimpPlugInCallMode call_mode,
415 gboolean synchronous)
416 {
417 gchar *progname;
418 gint my_read[2];
419 gint my_write[2];
420 gchar **envp;
421 const gchar *args[9];
422 gchar **argv;
423 gint argc;
424 gchar *interp, *interp_arg;
425 gchar *his_read_fd, *his_write_fd;
426 const gchar *mode;
427 gchar *stm;
428 GError *error = NULL;
429 gboolean debug;
430 guint debug_flag;
431 guint spawn_flags;
432
433 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
434 g_return_val_if_fail (plug_in->call_mode == GIMP_PLUG_IN_CALL_NONE, FALSE);
435
436 /* Open two pipes. (Bidirectional communication).
437 */
438 if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
439 {
440 gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
441 "Unable to run plug-in \"%s\"\n(%s)\n\npipe() failed: %s",
442 gimp_object_get_name (plug_in),
443 gimp_file_get_utf8_name (plug_in->file),
444 g_strerror (errno));
445 return FALSE;
446 }
447
448 #if defined(G_WITH_CYGWIN)
449 /* Set to binary mode */
450 setmode (my_read[0], _O_BINARY);
451 setmode (my_write[0], _O_BINARY);
452 setmode (my_read[1], _O_BINARY);
453 setmode (my_write[1], _O_BINARY);
454 #endif
455
456 /* Prevent the plug-in from inheriting our end of the pipes */
457 gimp_spawn_set_cloexec (my_read[0]);
458 gimp_spawn_set_cloexec (my_write[1]);
459
460 #ifdef G_OS_WIN32
461 plug_in->my_read = g_io_channel_win32_new_fd (my_read[0]);
462 plug_in->my_write = g_io_channel_win32_new_fd (my_write[1]);
463 plug_in->his_read = g_io_channel_win32_new_fd (my_write[0]);
464 plug_in->his_write = g_io_channel_win32_new_fd (my_read[1]);
465 #else
466 plug_in->my_read = g_io_channel_unix_new (my_read[0]);
467 plug_in->my_write = g_io_channel_unix_new (my_write[1]);
468 plug_in->his_read = g_io_channel_unix_new (my_write[0]);
469 plug_in->his_write = g_io_channel_unix_new (my_read[1]);
470 #endif
471
472 g_io_channel_set_encoding (plug_in->my_read, NULL, NULL);
473 g_io_channel_set_encoding (plug_in->my_write, NULL, NULL);
474 g_io_channel_set_encoding (plug_in->his_read, NULL, NULL);
475 g_io_channel_set_encoding (plug_in->his_write, NULL, NULL);
476
477 g_io_channel_set_buffered (plug_in->my_read, FALSE);
478 g_io_channel_set_buffered (plug_in->my_write, FALSE);
479 g_io_channel_set_buffered (plug_in->his_read, FALSE);
480 g_io_channel_set_buffered (plug_in->his_write, FALSE);
481
482 g_io_channel_set_close_on_unref (plug_in->my_read, TRUE);
483 g_io_channel_set_close_on_unref (plug_in->my_write, TRUE);
484 g_io_channel_set_close_on_unref (plug_in->his_read, TRUE);
485 g_io_channel_set_close_on_unref (plug_in->his_write, TRUE);
486
487 /* Remember the file descriptors for the pipes.
488 */
489 his_read_fd = g_strdup_printf ("%d",
490 g_io_channel_unix_get_fd (plug_in->his_read));
491 his_write_fd = g_strdup_printf ("%d",
492 g_io_channel_unix_get_fd (plug_in->his_write));
493
494 switch (call_mode)
495 {
496 case GIMP_PLUG_IN_CALL_QUERY:
497 mode = "-query";
498 debug_flag = GIMP_DEBUG_WRAP_QUERY;
499 break;
500
501 case GIMP_PLUG_IN_CALL_INIT:
502 mode = "-init";
503 debug_flag = GIMP_DEBUG_WRAP_INIT;
504 break;
505
506 case GIMP_PLUG_IN_CALL_RUN:
507 mode = "-run";
508 debug_flag = GIMP_DEBUG_WRAP_RUN;
509 break;
510
511 default:
512 gimp_assert_not_reached ();
513 }
514
515 stm = g_strdup_printf ("%d", plug_in->manager->gimp->stack_trace_mode);
516
517 progname = g_file_get_path (plug_in->file);
518
519 interp = gimp_interpreter_db_resolve (plug_in->manager->interpreter_db,
520 progname, &interp_arg);
521
522 argc = 0;
523
524 if (interp)
525 args[argc++] = interp;
526
527 if (interp_arg)
528 args[argc++] = interp_arg;
529
530 args[argc++] = progname;
531 args[argc++] = "-gimp";
532 args[argc++] = his_read_fd;
533 args[argc++] = his_write_fd;
534 args[argc++] = mode;
535 args[argc++] = stm;
536 args[argc++] = NULL;
537
538 argv = (gchar **) args;
539 envp = gimp_environ_table_get_envp (plug_in->manager->environ_table);
540 spawn_flags = (G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
541 G_SPAWN_DO_NOT_REAP_CHILD |
542 G_SPAWN_CHILD_INHERITS_STDIN);
543
544 debug = FALSE;
545
546 if (plug_in->manager->debug)
547 {
548 gchar **debug_argv = gimp_plug_in_debug_argv (plug_in->manager->debug,
549 progname,
550 debug_flag, args);
551
552 if (debug_argv)
553 {
554 debug = TRUE;
555 argv = debug_argv;
556 spawn_flags |= G_SPAWN_SEARCH_PATH;
557 }
558 }
559
560 /* Fork another process. We'll remember the process id so that we
561 * can later use it to kill the filter if necessary.
562 */
563 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
564 gimp_plug_in_set_dll_directory (argv[0]);
565 #endif
566 if (! gimp_spawn_async (argv, envp, spawn_flags, &plug_in->pid, &error))
567 {
568 gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
569 "Unable to run plug-in \"%s\"\n(%s)\n\n%s",
570 gimp_object_get_name (plug_in),
571 gimp_file_get_utf8_name (plug_in->file),
572 error->message);
573 g_clear_error (&error);
574 goto cleanup;
575 }
576
577 g_clear_pointer (&plug_in->his_read, g_io_channel_unref);
578 g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
579
580 if (! synchronous)
581 {
582 GSource *source;
583
584 source = g_io_create_watch (plug_in->my_read,
585 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP);
586
587 g_source_set_callback (source,
588 (GSourceFunc) gimp_plug_in_recv_message, plug_in,
589 NULL);
590
591 g_source_set_can_recurse (source, TRUE);
592
593 plug_in->input_id = g_source_attach (source, NULL);
594 g_source_unref (source);
595 }
596
597 plug_in->open = TRUE;
598 plug_in->call_mode = call_mode;
599
600 gimp_plug_in_manager_add_open_plug_in (plug_in->manager, plug_in);
601
602 cleanup:
603
604 #if defined G_OS_WIN32 && defined WIN32_32BIT_DLL_FOLDER
605 gimp_plug_in_set_dll_directory (NULL);
606 #endif
607
608 if (debug)
609 g_free (argv);
610
611 g_free (his_read_fd);
612 g_free (his_write_fd);
613 g_free (stm);
614 g_free (interp);
615 g_free (interp_arg);
616 g_free (progname);
617
618 return plug_in->open;
619 }
620
621 void
gimp_plug_in_close(GimpPlugIn * plug_in,gboolean kill_it)622 gimp_plug_in_close (GimpPlugIn *plug_in,
623 gboolean kill_it)
624 {
625 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
626 g_return_if_fail (plug_in->open);
627
628 plug_in->open = FALSE;
629
630 if (plug_in->pid)
631 {
632 #ifndef G_OS_WIN32
633 gint status;
634 #endif
635
636 /* Ask the filter to exit gracefully,
637 but not if it is closed because of a broken pipe. */
638 if (kill_it && ! plug_in->hup)
639 {
640 gp_quit_write (plug_in->my_write, plug_in);
641
642 /* give the plug-in some time (10 ms) */
643 g_usleep (10000);
644 }
645
646 /* If necessary, kill the filter. */
647
648 #ifndef G_OS_WIN32
649
650 if (kill_it)
651 {
652 if (plug_in->manager->gimp->be_verbose)
653 g_print ("Terminating plug-in: '%s'\n",
654 gimp_file_get_utf8_name (plug_in->file));
655
656 /* If the plug-in opened a process group, kill the group instead
657 * of only the plug-in, so we kill the plug-in's children too
658 */
659 if (getpgid (0) != getpgid (plug_in->pid))
660 status = kill (- plug_in->pid, SIGKILL);
661 else
662 status = kill (plug_in->pid, SIGKILL);
663 }
664
665 /* Wait for the process to exit. This will happen
666 * immediately if it was just killed.
667 */
668 waitpid (plug_in->pid, &status, 0);
669
670 #else /* G_OS_WIN32 */
671
672 if (kill_it)
673 {
674 /* Trying to avoid TerminateProcess (does mostly work).
675 * Otherwise some of our needed DLLs may get into an
676 * unstable state (see Win32 API docs).
677 */
678 DWORD dwExitCode = STILL_ACTIVE;
679 DWORD dwTries = 10;
680
681 while (dwExitCode == STILL_ACTIVE &&
682 GetExitCodeProcess ((HANDLE) plug_in->pid, &dwExitCode) &&
683 (dwTries > 0))
684 {
685 Sleep (10);
686 dwTries--;
687 }
688
689 if (dwExitCode == STILL_ACTIVE)
690 {
691 if (plug_in->manager->gimp->be_verbose)
692 g_print ("Terminating plug-in: '%s'\n",
693 gimp_file_get_utf8_name (plug_in->file));
694
695 TerminateProcess ((HANDLE) plug_in->pid, 0);
696 }
697 }
698
699 #endif /* G_OS_WIN32 */
700
701 g_spawn_close_pid (plug_in->pid);
702 plug_in->pid = 0;
703 }
704
705 /* Remove the input handler. */
706 if (plug_in->input_id)
707 {
708 g_source_remove (plug_in->input_id);
709 plug_in->input_id = 0;
710 }
711
712 /* Close the pipes. */
713 g_clear_pointer (&plug_in->my_read, g_io_channel_unref);
714 g_clear_pointer (&plug_in->my_write, g_io_channel_unref);
715 g_clear_pointer (&plug_in->his_read, g_io_channel_unref);
716 g_clear_pointer (&plug_in->his_write, g_io_channel_unref);
717
718 gimp_wire_clear_error ();
719
720 while (plug_in->temp_proc_frames)
721 {
722 GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data;
723
724 #ifdef GIMP_UNSTABLE
725 g_printerr ("plug-in '%s' aborted before sending its "
726 "temporary procedure return values\n",
727 gimp_object_get_name (plug_in));
728 #endif
729
730 if (proc_frame->main_loop &&
731 g_main_loop_is_running (proc_frame->main_loop))
732 {
733 g_main_loop_quit (proc_frame->main_loop);
734 }
735
736 /* pop the frame here, because normally this only happens in
737 * gimp_plug_in_handle_temp_proc_return(), which can't
738 * be called after plug_in_close()
739 */
740 gimp_plug_in_proc_frame_pop (plug_in);
741 }
742
743 if (plug_in->main_proc_frame.main_loop &&
744 g_main_loop_is_running (plug_in->main_proc_frame.main_loop))
745 {
746 #ifdef GIMP_UNSTABLE
747 g_printerr ("plug-in '%s' aborted before sending its "
748 "procedure return values\n",
749 gimp_object_get_name (plug_in));
750 #endif
751
752 g_main_loop_quit (plug_in->main_proc_frame.main_loop);
753 }
754
755 if (plug_in->ext_main_loop &&
756 g_main_loop_is_running (plug_in->ext_main_loop))
757 {
758 #ifdef GIMP_UNSTABLE
759 g_printerr ("extension '%s' aborted before sending its "
760 "extension_ack message\n",
761 gimp_object_get_name (plug_in));
762 #endif
763
764 g_main_loop_quit (plug_in->ext_main_loop);
765 }
766
767 /* Unregister any temporary procedures. */
768 while (plug_in->temp_procedures)
769 gimp_plug_in_remove_temp_proc (plug_in, plug_in->temp_procedures->data);
770
771 gimp_plug_in_manager_remove_open_plug_in (plug_in->manager, plug_in);
772 }
773
774 GimpPlugInProcFrame *
gimp_plug_in_get_proc_frame(GimpPlugIn * plug_in)775 gimp_plug_in_get_proc_frame (GimpPlugIn *plug_in)
776 {
777 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
778
779 if (plug_in->temp_proc_frames)
780 return plug_in->temp_proc_frames->data;
781 else
782 return &plug_in->main_proc_frame;
783 }
784
785 GimpPlugInProcFrame *
gimp_plug_in_proc_frame_push(GimpPlugIn * plug_in,GimpContext * context,GimpProgress * progress,GimpTemporaryProcedure * procedure)786 gimp_plug_in_proc_frame_push (GimpPlugIn *plug_in,
787 GimpContext *context,
788 GimpProgress *progress,
789 GimpTemporaryProcedure *procedure)
790 {
791 GimpPlugInProcFrame *proc_frame;
792
793 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
794 g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
795 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
796 g_return_val_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure), NULL);
797
798 proc_frame = gimp_plug_in_proc_frame_new (context, progress,
799 GIMP_PLUG_IN_PROCEDURE (procedure));
800
801 plug_in->temp_proc_frames = g_list_prepend (plug_in->temp_proc_frames,
802 proc_frame);
803
804 return proc_frame;
805 }
806
807 void
gimp_plug_in_proc_frame_pop(GimpPlugIn * plug_in)808 gimp_plug_in_proc_frame_pop (GimpPlugIn *plug_in)
809 {
810 GimpPlugInProcFrame *proc_frame;
811
812 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
813 g_return_if_fail (plug_in->temp_proc_frames != NULL);
814
815 proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
816
817 gimp_plug_in_proc_frame_unref (proc_frame, plug_in);
818
819 plug_in->temp_proc_frames = g_list_remove (plug_in->temp_proc_frames,
820 proc_frame);
821 }
822
823 void
gimp_plug_in_main_loop(GimpPlugIn * plug_in)824 gimp_plug_in_main_loop (GimpPlugIn *plug_in)
825 {
826 GimpPlugInProcFrame *proc_frame;
827
828 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
829 g_return_if_fail (plug_in->temp_proc_frames != NULL);
830
831 proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
832
833 g_return_if_fail (proc_frame->main_loop == NULL);
834
835 proc_frame->main_loop = g_main_loop_new (NULL, FALSE);
836
837 gimp_threads_leave (plug_in->manager->gimp);
838 g_main_loop_run (proc_frame->main_loop);
839 gimp_threads_enter (plug_in->manager->gimp);
840
841 g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
842 }
843
844 void
gimp_plug_in_main_loop_quit(GimpPlugIn * plug_in)845 gimp_plug_in_main_loop_quit (GimpPlugIn *plug_in)
846 {
847 GimpPlugInProcFrame *proc_frame;
848
849 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
850 g_return_if_fail (plug_in->temp_proc_frames != NULL);
851
852 proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data;
853
854 g_return_if_fail (proc_frame->main_loop != NULL);
855
856 g_main_loop_quit (proc_frame->main_loop);
857 }
858
859 const gchar *
gimp_plug_in_get_undo_desc(GimpPlugIn * plug_in)860 gimp_plug_in_get_undo_desc (GimpPlugIn *plug_in)
861 {
862 GimpPlugInProcFrame *proc_frame;
863 const gchar *undo_desc = NULL;
864
865 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
866
867 proc_frame = gimp_plug_in_get_proc_frame (plug_in);
868
869 if (proc_frame && proc_frame->procedure)
870 undo_desc = gimp_procedure_get_label (proc_frame->procedure);
871
872 return undo_desc ? undo_desc : gimp_object_get_name (plug_in);
873 }
874
875 /* called from the PDB (gimp_plugin_menu_register) */
876 gboolean
gimp_plug_in_menu_register(GimpPlugIn * plug_in,const gchar * proc_name,const gchar * menu_path)877 gimp_plug_in_menu_register (GimpPlugIn *plug_in,
878 const gchar *proc_name,
879 const gchar *menu_path)
880 {
881 GimpPlugInProcedure *proc = NULL;
882 GError *error = NULL;
883
884 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
885 g_return_val_if_fail (proc_name != NULL, FALSE);
886 g_return_val_if_fail (menu_path != NULL, FALSE);
887
888 if (plug_in->plug_in_def)
889 proc = gimp_plug_in_procedure_find (plug_in->plug_in_def->procedures,
890 proc_name);
891
892 if (! proc)
893 proc = gimp_plug_in_procedure_find (plug_in->temp_procedures, proc_name);
894
895 if (! proc)
896 {
897 gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
898 "Plug-in \"%s\"\n(%s)\n"
899 "attempted to register the menu item \"%s\" "
900 "for the procedure \"%s\".\n"
901 "It has however not installed that procedure. This "
902 "is not allowed.",
903 gimp_object_get_name (plug_in),
904 gimp_file_get_utf8_name (plug_in->file),
905 menu_path, proc_name);
906
907 return FALSE;
908 }
909
910 switch (GIMP_PROCEDURE (proc)->proc_type)
911 {
912 case GIMP_INTERNAL:
913 return FALSE;
914
915 case GIMP_PLUGIN:
916 case GIMP_EXTENSION:
917 if (plug_in->call_mode != GIMP_PLUG_IN_CALL_QUERY &&
918 plug_in->call_mode != GIMP_PLUG_IN_CALL_INIT)
919 return FALSE;
920
921 case GIMP_TEMPORARY:
922 break;
923 }
924
925 if (! proc->menu_label)
926 {
927 gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
928 "Plug-in \"%s\"\n(%s)\n"
929 "attempted to register the menu item \"%s\" "
930 "for procedure \"%s\".\n"
931 "The menu label given in gimp_install_procedure() "
932 "already contained a path. To make this work, "
933 "pass just the menu's label to "
934 "gimp_install_procedure().",
935 gimp_object_get_name (plug_in),
936 gimp_file_get_utf8_name (plug_in->file),
937 menu_path, proc_name);
938
939 return FALSE;
940 }
941
942 if (! strlen (proc->menu_label))
943 {
944 gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
945 "Plug-in \"%s\"\n(%s)\n"
946 "attempted to register the procedure \"%s\" "
947 "in the menu \"%s\", but the procedure has no label. "
948 "This is not allowed.",
949 gimp_object_get_name (plug_in),
950 gimp_file_get_utf8_name (plug_in->file),
951 proc_name, menu_path);
952
953 return FALSE;
954 }
955
956 if (! gimp_plug_in_procedure_add_menu_path (proc, menu_path, &error))
957 {
958 gimp_message_literal (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
959 error->message);
960 g_clear_error (&error);
961
962 return FALSE;
963 }
964
965 return TRUE;
966 }
967
968 void
gimp_plug_in_add_temp_proc(GimpPlugIn * plug_in,GimpTemporaryProcedure * proc)969 gimp_plug_in_add_temp_proc (GimpPlugIn *plug_in,
970 GimpTemporaryProcedure *proc)
971 {
972 GimpPlugInProcedure *overridden;
973 const gchar *locale_domain;
974 const gchar *help_domain;
975
976 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
977 g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc));
978
979 overridden = gimp_plug_in_procedure_find (plug_in->temp_procedures,
980 gimp_object_get_name (proc));
981
982 if (overridden)
983 gimp_plug_in_remove_temp_proc (plug_in,
984 GIMP_TEMPORARY_PROCEDURE (overridden));
985
986 locale_domain = gimp_plug_in_manager_get_locale_domain (plug_in->manager,
987 plug_in->file,
988 NULL);
989 help_domain = gimp_plug_in_manager_get_help_domain (plug_in->manager,
990 plug_in->file,
991 NULL);
992
993 gimp_plug_in_procedure_set_locale_domain (GIMP_PLUG_IN_PROCEDURE (proc),
994 locale_domain);
995 gimp_plug_in_procedure_set_help_domain (GIMP_PLUG_IN_PROCEDURE (proc),
996 help_domain);
997
998 plug_in->temp_procedures = g_slist_prepend (plug_in->temp_procedures,
999 g_object_ref (proc));
1000 gimp_plug_in_manager_add_temp_proc (plug_in->manager, proc);
1001 }
1002
1003 void
gimp_plug_in_remove_temp_proc(GimpPlugIn * plug_in,GimpTemporaryProcedure * proc)1004 gimp_plug_in_remove_temp_proc (GimpPlugIn *plug_in,
1005 GimpTemporaryProcedure *proc)
1006 {
1007 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1008 g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc));
1009
1010 plug_in->temp_procedures = g_slist_remove (plug_in->temp_procedures, proc);
1011
1012 gimp_plug_in_manager_remove_temp_proc (plug_in->manager, proc);
1013 g_object_unref (proc);
1014 }
1015
1016 void
gimp_plug_in_set_error_handler(GimpPlugIn * plug_in,GimpPDBErrorHandler handler)1017 gimp_plug_in_set_error_handler (GimpPlugIn *plug_in,
1018 GimpPDBErrorHandler handler)
1019 {
1020 GimpPlugInProcFrame *proc_frame;
1021
1022 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1023
1024 proc_frame = gimp_plug_in_get_proc_frame (plug_in);
1025
1026 if (proc_frame)
1027 proc_frame->error_handler = handler;
1028 }
1029
1030 GimpPDBErrorHandler
gimp_plug_in_get_error_handler(GimpPlugIn * plug_in)1031 gimp_plug_in_get_error_handler (GimpPlugIn *plug_in)
1032 {
1033 GimpPlugInProcFrame *proc_frame;
1034
1035 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in),
1036 GIMP_PDB_ERROR_HANDLER_INTERNAL);
1037
1038 proc_frame = gimp_plug_in_get_proc_frame (plug_in);
1039
1040 if (proc_frame)
1041 return proc_frame->error_handler;
1042
1043 return GIMP_PDB_ERROR_HANDLER_INTERNAL;
1044 }
1045
1046 void
gimp_plug_in_enable_precision(GimpPlugIn * plug_in)1047 gimp_plug_in_enable_precision (GimpPlugIn *plug_in)
1048 {
1049 g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
1050
1051 plug_in->precision = TRUE;
1052 }
1053
1054 gboolean
gimp_plug_in_precision_enabled(GimpPlugIn * plug_in)1055 gimp_plug_in_precision_enabled (GimpPlugIn *plug_in)
1056 {
1057 g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
1058
1059 return plug_in->precision;
1060 }
1061