void gimp_plug_in_enable_precision (GimpPlugIn *plug_in) { g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); plug_in->precision = TRUE; }
void gimp_plug_in_progress_end (GimpPlugIn *plug_in, GimpPlugInProcFrame *proc_frame) { g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (proc_frame != NULL); if (proc_frame->progress) { if (proc_frame->progress_cancel_id) { g_signal_handler_disconnect (proc_frame->progress, proc_frame->progress_cancel_id); proc_frame->progress_cancel_id = 0; } if (gimp_plug_in_progress_detach (proc_frame->progress) < 1 && gimp_progress_is_active (proc_frame->progress)) { gimp_progress_end (proc_frame->progress); } if (proc_frame->progress_created) { gimp_free_progress (plug_in->manager->gimp, proc_frame->progress); g_object_unref (proc_frame->progress); proc_frame->progress = NULL; } } }
gboolean gimp_plug_in_precision_enabled (GimpPlugIn *plug_in) { g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); return plug_in->precision; }
gboolean gimp_plug_in_cleanup_undo_group_start (GimpPlugIn *plug_in, GimpImage *image) { GimpPlugInProcFrame *proc_frame; GimpPlugInCleanupImage *cleanup; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); proc_frame = gimp_plug_in_get_proc_frame (plug_in); cleanup = gimp_plug_in_cleanup_image_get (proc_frame, image); if (! cleanup) { cleanup = gimp_plug_in_cleanup_image_new (image); cleanup->undo_group_count = gimp_image_get_undo_group_count (image); proc_frame->image_cleanups = g_list_prepend (proc_frame->image_cleanups, cleanup); } return TRUE; }
gboolean gimp_plug_in_cleanup_remove_shadow (GimpPlugIn *plug_in, GimpDrawable *drawable) { GimpPlugInProcFrame *proc_frame; GimpPlugInCleanupItem *cleanup; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); proc_frame = gimp_plug_in_get_proc_frame (plug_in); cleanup = gimp_plug_in_cleanup_item_get (proc_frame, GIMP_ITEM (drawable)); if (! cleanup) return FALSE; if (! cleanup->shadow_buffer) return FALSE; proc_frame->item_cleanups = g_list_remove (proc_frame->item_cleanups, cleanup); gimp_plug_in_cleanup_item_free (cleanup); return TRUE; }
gboolean gimp_plug_in_cleanup_add_shadow (GimpPlugIn *plug_in, GimpDrawable *drawable) { GimpPlugInProcFrame *proc_frame; GimpPlugInCleanupItem *cleanup; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); proc_frame = gimp_plug_in_get_proc_frame (plug_in); cleanup = gimp_plug_in_cleanup_item_get (proc_frame, GIMP_ITEM (drawable)); if (! cleanup) { cleanup = gimp_plug_in_cleanup_item_new (GIMP_ITEM (drawable)); proc_frame->item_cleanups = g_list_prepend (proc_frame->item_cleanups, cleanup); } cleanup->shadow_tiles = TRUE; return TRUE; }
void gimp_plug_in_add_temp_proc (GimpPlugIn *plug_in, GimpTemporaryProcedure *proc) { GimpPlugInProcedure *overridden; const gchar *locale_domain; const gchar *help_domain; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc)); overridden = gimp_plug_in_procedure_find (plug_in->temp_procedures, gimp_object_get_name (proc)); if (overridden) gimp_plug_in_remove_temp_proc (plug_in, GIMP_TEMPORARY_PROCEDURE (overridden)); locale_domain = gimp_plug_in_manager_get_locale_domain (plug_in->manager, plug_in->prog, NULL); help_domain = gimp_plug_in_manager_get_help_domain (plug_in->manager, plug_in->prog, NULL); gimp_plug_in_procedure_set_locale_domain (GIMP_PLUG_IN_PROCEDURE (proc), locale_domain); gimp_plug_in_procedure_set_help_domain (GIMP_PLUG_IN_PROCEDURE (proc), help_domain); plug_in->temp_procedures = g_slist_prepend (plug_in->temp_procedures, g_object_ref (proc)); gimp_plug_in_manager_add_temp_proc (plug_in->manager, proc); }
gboolean gimp_plug_in_progress_cancel (GimpPlugIn *plug_in, const gchar *progress_callback) { g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (progress_callback != NULL, FALSE); return FALSE; }
GimpPlugInProcFrame * gimp_plug_in_get_proc_frame (GimpPlugIn *plug_in) { g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); if (plug_in->temp_proc_frames) return plug_in->temp_proc_frames->data; else return &plug_in->main_proc_frame; }
void gimp_plug_in_remove_temp_proc (GimpPlugIn *plug_in, GimpTemporaryProcedure *proc) { g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (proc)); plug_in->temp_procedures = g_slist_remove (plug_in->temp_procedures, proc); gimp_plug_in_manager_remove_temp_proc (plug_in->manager, proc); g_object_unref (proc); }
void gimp_plug_in_set_error_handler (GimpPlugIn *plug_in, GimpPDBErrorHandler handler) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame) proc_frame->error_handler = handler; }
void gimp_plug_in_progress_set_text (GimpPlugIn *plug_in, const gchar *message) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame->progress) gimp_progress_set_text_literal (proc_frame->progress, message); }
void gimp_plug_in_progress_start (GimpPlugIn *plug_in, const gchar *message, GimpObject *display) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (display == NULL || GIMP_IS_OBJECT (display)); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (! proc_frame->progress) { proc_frame->progress = gimp_new_progress (plug_in->manager->gimp, display); if (proc_frame->progress) { proc_frame->progress_created = TRUE; g_object_ref (proc_frame->progress); gimp_plug_in_progress_attach (proc_frame->progress); } } if (proc_frame->progress) { if (! proc_frame->progress_cancel_id) proc_frame->progress_cancel_id = g_signal_connect (proc_frame->progress, "cancel", G_CALLBACK (gimp_plug_in_progress_cancel_callback), plug_in); if (gimp_progress_is_active (proc_frame->progress)) { if (message) gimp_progress_set_text (proc_frame->progress, message); if (gimp_progress_get_value (proc_frame->progress) > 0.0) gimp_progress_set_value (proc_frame->progress, 0.0); } else { gimp_progress_start (proc_frame->progress, message ? message : "", TRUE); } } }
void gimp_plug_in_main_loop_quit (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (plug_in->temp_proc_frames != NULL); proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data; g_return_if_fail (proc_frame->main_loop != NULL); g_main_loop_quit (proc_frame->main_loop); }
guint32 gimp_plug_in_progress_get_window_id (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), 0); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame->progress) return gimp_progress_get_window_id (proc_frame->progress); return 0; }
void gimp_plug_in_proc_frame_pop (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (plug_in->temp_proc_frames != NULL); proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data; gimp_plug_in_proc_frame_unref (proc_frame, plug_in); plug_in->temp_proc_frames = g_list_remove (plug_in->temp_proc_frames, proc_frame); }
GimpPDBErrorHandler gimp_plug_in_get_error_handler (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), GIMP_PDB_ERROR_HANDLER_INTERNAL); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame) return proc_frame->error_handler; return GIMP_PDB_ERROR_HANDLER_INTERNAL; }
GimpProcedure * gimp_temporary_procedure_new (GimpPlugIn *plug_in) { GimpTemporaryProcedure *proc; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); proc = g_object_new (GIMP_TYPE_TEMPORARY_PROCEDURE, NULL); proc->plug_in = plug_in; GIMP_PLUG_IN_PROCEDURE (proc)->file = g_file_new_for_path ("none"); return GIMP_PROCEDURE (proc); }
gboolean gimp_plug_in_progress_install (GimpPlugIn *plug_in, const gchar *progress_callback) { GimpPlugInProcFrame *proc_frame; GimpProcedure *procedure; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (progress_callback != NULL, FALSE); procedure = gimp_pdb_lookup_procedure (plug_in->manager->gimp->pdb, progress_callback); if (! GIMP_IS_TEMPORARY_PROCEDURE (procedure) || GIMP_TEMPORARY_PROCEDURE (procedure)->plug_in != plug_in || procedure->num_args != 3 || ! GIMP_IS_PARAM_SPEC_INT32 (procedure->args[0]) || ! G_IS_PARAM_SPEC_STRING (procedure->args[1]) || ! G_IS_PARAM_SPEC_DOUBLE (procedure->args[2])) { return FALSE; } proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame->progress) { gimp_plug_in_progress_end (plug_in, proc_frame); if (proc_frame->progress) { g_object_unref (proc_frame->progress); proc_frame->progress = NULL; } } proc_frame->progress = g_object_new (GIMP_TYPE_PDB_PROGRESS, "pdb", plug_in->manager->gimp->pdb, "context", proc_frame->main_context, "callback-name", progress_callback, NULL); gimp_plug_in_progress_attach (proc_frame->progress); return TRUE; }
void gimp_plug_in_cleanup (GimpPlugIn *plug_in, GimpPlugInProcFrame *proc_frame) { GList *list; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (proc_frame != NULL); for (list = proc_frame->cleanups; list; list = g_list_next (list)) { GimpPlugInCleanupImage *cleanup = list->data; GimpImage *image = cleanup->image; if (! gimp_container_have (plug_in->manager->gimp->images, (GimpObject *) image)) continue; if (image->pushing_undo_group == GIMP_UNDO_GROUP_NONE) continue; if (cleanup->undo_group_count != image->group_count) { GimpProcedure *proc = proc_frame->procedure; g_message ("Plug-In '%s' left image undo in inconsistent state, " "closing open undo groups.", gimp_plug_in_procedure_get_label (GIMP_PLUG_IN_PROCEDURE (proc))); while (image->pushing_undo_group != GIMP_UNDO_GROUP_NONE && cleanup->undo_group_count < image->group_count) { if (! gimp_image_undo_group_end (image)) break; } } g_slice_free (GimpPlugInCleanupImage, cleanup); } g_list_free (proc_frame->cleanups); proc_frame->cleanups = NULL; }
void gimp_plug_in_progress_pulse (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (! proc_frame->progress || ! gimp_progress_is_active (proc_frame->progress) || ! proc_frame->progress_cancel_id) { gimp_plug_in_progress_start (plug_in, NULL, NULL); } if (proc_frame->progress && gimp_progress_is_active (proc_frame->progress)) gimp_progress_pulse (proc_frame->progress); }
void gimp_plug_in_cleanup (GimpPlugIn *plug_in, GimpPlugInProcFrame *proc_frame) { GList *list; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (proc_frame != NULL); for (list = proc_frame->image_cleanups; list; list = g_list_next (list)) { GimpPlugInCleanupImage *cleanup = list->data; if (gimp_image_get_by_ID (plug_in->manager->gimp, cleanup->image_ID) == cleanup->image) { gimp_plug_in_cleanup_image (proc_frame, cleanup); } gimp_plug_in_cleanup_image_free (cleanup); } g_list_free (proc_frame->image_cleanups); proc_frame->image_cleanups = NULL; for (list = proc_frame->item_cleanups; list; list = g_list_next (list)) { GimpPlugInCleanupItem *cleanup = list->data; if (gimp_item_get_by_ID (plug_in->manager->gimp, cleanup->item_ID) == cleanup->item) { gimp_plug_in_cleanup_item (proc_frame, cleanup); } gimp_plug_in_cleanup_item_free (cleanup); } g_list_free (proc_frame->item_cleanups); proc_frame->item_cleanups = NULL; }
void gimp_plug_in_main_loop (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (plug_in->temp_proc_frames != NULL); proc_frame = (GimpPlugInProcFrame *) plug_in->temp_proc_frames->data; g_return_if_fail (proc_frame->main_loop == NULL); proc_frame->main_loop = g_main_loop_new (NULL, FALSE); gimp_threads_leave (plug_in->manager->gimp); g_main_loop_run (proc_frame->main_loop); gimp_threads_enter (plug_in->manager->gimp); g_main_loop_unref (proc_frame->main_loop); proc_frame->main_loop = NULL; }
GimpPlugInProcFrame * gimp_plug_in_proc_frame_push (GimpPlugIn *plug_in, GimpContext *context, GimpProgress *progress, GimpTemporaryProcedure *procedure) { GimpPlugInProcFrame *proc_frame; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure), NULL); proc_frame = gimp_plug_in_proc_frame_new (context, progress, GIMP_PLUG_IN_PROCEDURE (procedure)); plug_in->temp_proc_frames = g_list_prepend (plug_in->temp_proc_frames, proc_frame); return proc_frame; }
gboolean gimp_plug_in_progress_uninstall (GimpPlugIn *plug_in, const gchar *progress_callback) { GimpPlugInProcFrame *proc_frame; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (progress_callback != NULL, FALSE); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (GIMP_IS_PDB_PROGRESS (proc_frame->progress)) { gimp_plug_in_progress_end (plug_in, proc_frame); g_object_unref (proc_frame->progress); proc_frame->progress = NULL; return TRUE; } return FALSE; }
const gchar * gimp_plug_in_get_undo_desc (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; const gchar *undo_desc = NULL; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame) { GimpPlugInProcedure *proc; proc = GIMP_PLUG_IN_PROCEDURE (proc_frame->procedure); if (proc) undo_desc = gimp_plug_in_procedure_get_label (proc); } return undo_desc ? undo_desc : gimp_object_get_name (plug_in); }
gboolean gimp_plug_in_cleanup_undo_group_end (GimpPlugIn *plug_in, GimpImage *image) { GimpPlugInProcFrame *proc_frame; GimpPlugInCleanupImage *cleanup; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); proc_frame = gimp_plug_in_get_proc_frame (plug_in); cleanup = gimp_plug_in_cleanup_get_image (proc_frame, image); if (! cleanup) return FALSE; if (cleanup->undo_group_count == image->group_count - 1) { proc_frame->cleanups = g_list_remove (proc_frame->cleanups, cleanup); g_slice_free (GimpPlugInCleanupImage, cleanup); } return TRUE; }
/* called from the PDB (gimp_plugin_menu_register) */ gboolean gimp_plug_in_menu_register (GimpPlugIn *plug_in, const gchar *proc_name, const gchar *menu_path) { GimpPlugInProcedure *proc = NULL; GError *error = NULL; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (proc_name != NULL, FALSE); g_return_val_if_fail (menu_path != NULL, FALSE); if (plug_in->plug_in_def) proc = gimp_plug_in_procedure_find (plug_in->plug_in_def->procedures, proc_name); if (! proc) proc = gimp_plug_in_procedure_find (plug_in->temp_procedures, proc_name); if (! proc) { gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, "Plug-in \"%s\"\n(%s)\n" "attempted to register the menu item \"%s\" " "for the procedure \"%s\".\n" "It has however not installed that procedure. This " "is not allowed.", gimp_object_get_name (plug_in), gimp_filename_to_utf8 (plug_in->prog), menu_path, proc_name); return FALSE; } switch (GIMP_PROCEDURE (proc)->proc_type) { case GIMP_INTERNAL: return FALSE; case GIMP_PLUGIN: case GIMP_EXTENSION: if (plug_in->call_mode != GIMP_PLUG_IN_CALL_QUERY && plug_in->call_mode != GIMP_PLUG_IN_CALL_INIT) return FALSE; case GIMP_TEMPORARY: break; } if (! proc->menu_label) { gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, "Plug-in \"%s\"\n(%s)\n" "attempted to register the menu item \"%s\" " "for procedure \"%s\".\n" "The menu label given in gimp_install_procedure() " "already contained a path. To make this work, " "pass just the menu's label to " "gimp_install_procedure().", gimp_object_get_name (plug_in), gimp_filename_to_utf8 (plug_in->prog), menu_path, proc_name); return FALSE; } if (! strlen (proc->menu_label)) { gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, "Plug-in \"%s\"\n(%s)\n" "attempted to register the procedure \"%s\" " "in the menu \"%s\", but the procedure has no label. " "This is not allowed.", gimp_object_get_name (plug_in), gimp_filename_to_utf8 (plug_in->prog), proc_name, menu_path); return FALSE; } if (! gimp_plug_in_procedure_add_menu_path (proc, menu_path, &error)) { gimp_message_literal (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); g_clear_error (&error); return FALSE; } return TRUE; }
gboolean gimp_plug_in_open (GimpPlugIn *plug_in, GimpPlugInCallMode call_mode, gboolean synchronous) { gint my_read[2]; gint my_write[2]; gchar **envp; const gchar *args[9]; gchar **argv; gint argc; gchar *interp, *interp_arg; gchar *read_fd, *write_fd; const gchar *mode; gchar *stm; GError *error = NULL; gboolean debug; guint debug_flag; guint spawn_flags; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE); g_return_val_if_fail (plug_in->call_mode == GIMP_PLUG_IN_CALL_NONE, FALSE); /* Open two pipes. (Bidirectional communication). */ if ((pipe (my_read) == -1) || (pipe (my_write) == -1)) { gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, "Unable to run plug-in \"%s\"\n(%s)\n\npipe() failed: %s", gimp_object_get_name (plug_in), gimp_filename_to_utf8 (plug_in->prog), g_strerror (errno)); return FALSE; } #if defined(G_WITH_CYGWIN) /* Set to binary mode */ setmode (my_read[0], _O_BINARY); setmode (my_write[0], _O_BINARY); setmode (my_read[1], _O_BINARY); setmode (my_write[1], _O_BINARY); #endif #ifdef G_OS_WIN32 /* Prevent the plug-in from inheriting our ends of the pipes */ SetHandleInformation ((HANDLE) _get_osfhandle (my_read[0]), HANDLE_FLAG_INHERIT, 0); SetHandleInformation ((HANDLE) _get_osfhandle (my_write[1]), HANDLE_FLAG_INHERIT, 0); #endif plug_in->my_read = g_io_channel_unix_new (my_read[0]); plug_in->my_write = g_io_channel_unix_new (my_write[1]); plug_in->his_read = g_io_channel_unix_new (my_write[0]); plug_in->his_write = g_io_channel_unix_new (my_read[1]); g_io_channel_set_encoding (plug_in->my_read, NULL, NULL); g_io_channel_set_encoding (plug_in->my_write, NULL, NULL); g_io_channel_set_encoding (plug_in->his_read, NULL, NULL); g_io_channel_set_encoding (plug_in->his_write, NULL, NULL); g_io_channel_set_buffered (plug_in->my_read, FALSE); g_io_channel_set_buffered (plug_in->my_write, FALSE); g_io_channel_set_buffered (plug_in->his_read, FALSE); g_io_channel_set_buffered (plug_in->his_write, FALSE); g_io_channel_set_close_on_unref (plug_in->my_read, TRUE); g_io_channel_set_close_on_unref (plug_in->my_write, TRUE); g_io_channel_set_close_on_unref (plug_in->his_read, TRUE); g_io_channel_set_close_on_unref (plug_in->his_write, TRUE); /* Remember the file descriptors for the pipes. */ read_fd = g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read)); write_fd = g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write)); switch (call_mode) { case GIMP_PLUG_IN_CALL_QUERY: mode = "-query"; debug_flag = GIMP_DEBUG_WRAP_QUERY; break; case GIMP_PLUG_IN_CALL_INIT: mode = "-init"; debug_flag = GIMP_DEBUG_WRAP_INIT; break; case GIMP_PLUG_IN_CALL_RUN: mode = "-run"; debug_flag = GIMP_DEBUG_WRAP_RUN; break; default: g_assert_not_reached (); } stm = g_strdup_printf ("%d", plug_in->manager->gimp->stack_trace_mode); interp = gimp_interpreter_db_resolve (plug_in->manager->interpreter_db, plug_in->prog, &interp_arg); argc = 0; if (interp) args[argc++] = interp; if (interp_arg) args[argc++] = interp_arg; args[argc++] = plug_in->prog; args[argc++] = "-gimp"; args[argc++] = read_fd; args[argc++] = write_fd; args[argc++] = mode; args[argc++] = stm; args[argc++] = NULL; argv = (gchar **) args; envp = gimp_environ_table_get_envp (plug_in->manager->environ_table); spawn_flags = (G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_CHILD_INHERITS_STDIN); debug = FALSE; if (plug_in->manager->debug) { gchar **debug_argv = gimp_plug_in_debug_argv (plug_in->manager->debug, plug_in->prog, debug_flag, args); if (debug_argv) { debug = TRUE; argv = debug_argv; spawn_flags |= G_SPAWN_SEARCH_PATH; } } /* Fork another process. We'll remember the process id so that we * can later use it to kill the filter if necessary. */ if (! g_spawn_async (NULL, argv, envp, spawn_flags, gimp_plug_in_prep_for_exec, plug_in, &plug_in->pid, &error)) { gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR, "Unable to run plug-in \"%s\"\n(%s)\n\n%s", gimp_object_get_name (plug_in), gimp_filename_to_utf8 (plug_in->prog), error->message); g_error_free (error); goto cleanup; } g_io_channel_unref (plug_in->his_read); plug_in->his_read = NULL; g_io_channel_unref (plug_in->his_write); plug_in->his_write = NULL; if (! synchronous) { GSource *source; source = g_io_create_watch (plug_in->my_read, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP); g_source_set_callback (source, (GSourceFunc) gimp_plug_in_recv_message, plug_in, NULL); g_source_set_can_recurse (source, TRUE); plug_in->input_id = g_source_attach (source, NULL); g_source_unref (source); } plug_in->open = TRUE; plug_in->call_mode = call_mode; gimp_plug_in_manager_add_open_plug_in (plug_in->manager, plug_in); cleanup: if (debug) g_free (argv); g_free (read_fd); g_free (write_fd); g_free (stm); g_free (interp); g_free (interp_arg); return plug_in->open; }
void gimp_plug_in_close (GimpPlugIn *plug_in, gboolean kill_it) { g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (plug_in->open); plug_in->open = FALSE; if (plug_in->pid) { #ifndef G_OS_WIN32 gint status; #endif /* Ask the filter to exit gracefully, but not if it is closed because of a broken pipe. */ if (kill_it && ! plug_in->hup) { gp_quit_write (plug_in->my_write, plug_in); /* give the plug-in some time (10 ms) */ g_usleep (10000); } /* If necessary, kill the filter. */ #ifndef G_OS_WIN32 if (kill_it) { if (plug_in->manager->gimp->be_verbose) g_print ("Terminating plug-in: '%s'\n", gimp_filename_to_utf8 (plug_in->prog)); /* If the plug-in opened a process group, kill the group instead * of only the plug-in, so we kill the plug-in's children too */ if (getpgid (0) != getpgid (plug_in->pid)) status = kill (- plug_in->pid, SIGKILL); else status = kill (plug_in->pid, SIGKILL); } /* Wait for the process to exit. This will happen * immediately if it was just killed. */ waitpid (plug_in->pid, &status, 0); #else /* G_OS_WIN32 */ if (kill_it) { /* Trying to avoid TerminateProcess (does mostly work). * Otherwise some of our needed DLLs may get into an * unstable state (see Win32 API docs). */ DWORD dwExitCode = STILL_ACTIVE; DWORD dwTries = 10; while (dwExitCode == STILL_ACTIVE && GetExitCodeProcess ((HANDLE) plug_in->pid, &dwExitCode) && (dwTries > 0)) { Sleep (10); dwTries--; } if (dwExitCode == STILL_ACTIVE) { if (plug_in->manager->gimp->be_verbose) g_print ("Terminating plug-in: '%s'\n", gimp_filename_to_utf8 (plug_in->prog)); TerminateProcess ((HANDLE) plug_in->pid, 0); } } #endif /* G_OS_WIN32 */ g_spawn_close_pid (plug_in->pid); plug_in->pid = 0; } /* Remove the input handler. */ if (plug_in->input_id) { g_source_remove (plug_in->input_id); plug_in->input_id = 0; } /* Close the pipes. */ if (plug_in->my_read != NULL) { g_io_channel_unref (plug_in->my_read); plug_in->my_read = NULL; } if (plug_in->my_write != NULL) { g_io_channel_unref (plug_in->my_write); plug_in->my_write = NULL; } if (plug_in->his_read != NULL) { g_io_channel_unref (plug_in->his_read); plug_in->his_read = NULL; } if (plug_in->his_write != NULL) { g_io_channel_unref (plug_in->his_write); plug_in->his_write = NULL; } gimp_wire_clear_error (); while (plug_in->temp_proc_frames) { GimpPlugInProcFrame *proc_frame = plug_in->temp_proc_frames->data; #ifdef GIMP_UNSTABLE g_printerr ("plug-in '%s' aborted before sending its " "temporary procedure return values\n", gimp_object_get_name (plug_in)); #endif if (proc_frame->main_loop && g_main_loop_is_running (proc_frame->main_loop)) { g_main_loop_quit (proc_frame->main_loop); } /* pop the frame here, because normally this only happens in * gimp_plug_in_handle_temp_proc_return(), which can't * be called after plug_in_close() */ gimp_plug_in_proc_frame_pop (plug_in); } if (plug_in->main_proc_frame.main_loop && g_main_loop_is_running (plug_in->main_proc_frame.main_loop)) { #ifdef GIMP_UNSTABLE g_printerr ("plug-in '%s' aborted before sending its " "procedure return values\n", gimp_object_get_name (plug_in)); #endif g_main_loop_quit (plug_in->main_proc_frame.main_loop); } if (plug_in->ext_main_loop && g_main_loop_is_running (plug_in->ext_main_loop)) { #ifdef GIMP_UNSTABLE g_printerr ("extension '%s' aborted before sending its " "extension_ack message\n", gimp_object_get_name (plug_in)); #endif g_main_loop_quit (plug_in->ext_main_loop); } /* Unregister any temporary procedures. */ while (plug_in->temp_procedures) gimp_plug_in_remove_temp_proc (plug_in, plug_in->temp_procedures->data); gimp_plug_in_manager_remove_open_plug_in (plug_in->manager, plug_in); }