1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimppluginmanager-call.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 #include <gdk-pixbuf/gdk-pixbuf.h>
23 #include <gegl.h>
24
25 #ifdef G_OS_WIN32
26 #include <windows.h>
27 #endif
28
29 #include "libgimpbase/gimpbase.h"
30 #include "libgimpbase/gimpprotocol.h"
31 #include "libgimpbase/gimpwire.h"
32
33 #include "plug-in-types.h"
34
35 #include "config/gimpguiconfig.h"
36
37 #include "core/gimp.h"
38 #include "core/gimpprogress.h"
39
40 #include "pdb/gimppdbcontext.h"
41
42 #include "gimpplugin.h"
43 #include "gimpplugin-message.h"
44 #include "gimpplugindef.h"
45 #include "gimppluginerror.h"
46 #include "gimppluginmanager.h"
47 #define __YES_I_NEED_GIMP_PLUG_IN_MANAGER_CALL__
48 #include "gimppluginmanager-call.h"
49 #include "gimppluginshm.h"
50 #include "gimptemporaryprocedure.h"
51 #include "plug-in-params.h"
52
53 #include "gimp-intl.h"
54
55
56 static void
gimp_allow_set_foreground_window(GimpPlugIn * plug_in)57 gimp_allow_set_foreground_window (GimpPlugIn *plug_in)
58 {
59 #ifdef G_OS_WIN32
60 AllowSetForegroundWindow (GetProcessId (plug_in->pid));
61 #endif
62 }
63
64 /* public functions */
65
66 void
gimp_plug_in_manager_call_query(GimpPlugInManager * manager,GimpContext * context,GimpPlugInDef * plug_in_def)67 gimp_plug_in_manager_call_query (GimpPlugInManager *manager,
68 GimpContext *context,
69 GimpPlugInDef *plug_in_def)
70 {
71 GimpPlugIn *plug_in;
72
73 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
74 g_return_if_fail (GIMP_IS_PDB_CONTEXT (context));
75 g_return_if_fail (GIMP_IS_PLUG_IN_DEF (plug_in_def));
76
77 plug_in = gimp_plug_in_new (manager, context, NULL,
78 NULL, plug_in_def->file);
79
80 if (plug_in)
81 {
82 plug_in->plug_in_def = plug_in_def;
83
84 if (gimp_plug_in_open (plug_in, GIMP_PLUG_IN_CALL_QUERY, TRUE))
85 {
86 while (plug_in->open)
87 {
88 GimpWireMessage msg;
89
90 if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
91 {
92 gimp_plug_in_close (plug_in, TRUE);
93 }
94 else
95 {
96 gimp_plug_in_handle_message (plug_in, &msg);
97 gimp_wire_destroy (&msg);
98 }
99 }
100 }
101
102 g_object_unref (plug_in);
103 }
104 }
105
106 void
gimp_plug_in_manager_call_init(GimpPlugInManager * manager,GimpContext * context,GimpPlugInDef * plug_in_def)107 gimp_plug_in_manager_call_init (GimpPlugInManager *manager,
108 GimpContext *context,
109 GimpPlugInDef *plug_in_def)
110 {
111 GimpPlugIn *plug_in;
112
113 g_return_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager));
114 g_return_if_fail (GIMP_IS_PDB_CONTEXT (context));
115 g_return_if_fail (GIMP_IS_PLUG_IN_DEF (plug_in_def));
116
117 plug_in = gimp_plug_in_new (manager, context, NULL,
118 NULL, plug_in_def->file);
119
120 if (plug_in)
121 {
122 plug_in->plug_in_def = plug_in_def;
123
124 if (gimp_plug_in_open (plug_in, GIMP_PLUG_IN_CALL_INIT, TRUE))
125 {
126 while (plug_in->open)
127 {
128 GimpWireMessage msg;
129
130 if (! gimp_wire_read_msg (plug_in->my_read, &msg, plug_in))
131 {
132 gimp_plug_in_close (plug_in, TRUE);
133 }
134 else
135 {
136 gimp_plug_in_handle_message (plug_in, &msg);
137 gimp_wire_destroy (&msg);
138 }
139 }
140 }
141
142 g_object_unref (plug_in);
143 }
144 }
145
146 GimpValueArray *
gimp_plug_in_manager_call_run(GimpPlugInManager * manager,GimpContext * context,GimpProgress * progress,GimpPlugInProcedure * procedure,GimpValueArray * args,gboolean synchronous,GimpObject * display)147 gimp_plug_in_manager_call_run (GimpPlugInManager *manager,
148 GimpContext *context,
149 GimpProgress *progress,
150 GimpPlugInProcedure *procedure,
151 GimpValueArray *args,
152 gboolean synchronous,
153 GimpObject *display)
154 {
155 GimpValueArray *return_vals = NULL;
156 GimpPlugIn *plug_in;
157
158 g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
159 g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
160 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
161 g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (procedure), NULL);
162 g_return_val_if_fail (args != NULL, NULL);
163 g_return_val_if_fail (display == NULL || GIMP_IS_OBJECT (display), NULL);
164
165 plug_in = gimp_plug_in_new (manager, context, progress, procedure, NULL);
166
167 if (plug_in)
168 {
169 GimpCoreConfig *core_config = manager->gimp->config;
170 GimpGeglConfig *gegl_config = GIMP_GEGL_CONFIG (core_config);
171 GimpDisplayConfig *display_config = GIMP_DISPLAY_CONFIG (core_config);
172 GimpGuiConfig *gui_config = GIMP_GUI_CONFIG (core_config);
173 GPConfig config;
174 GPProcRun proc_run;
175 gint display_ID;
176 GObject *screen;
177 gint monitor;
178 GFile *icon_theme_dir;
179
180 if (! gimp_plug_in_open (plug_in, GIMP_PLUG_IN_CALL_RUN, FALSE))
181 {
182 const gchar *name = gimp_object_get_name (plug_in);
183 GError *error = g_error_new (GIMP_PLUG_IN_ERROR,
184 GIMP_PLUG_IN_EXECUTION_FAILED,
185 _("Failed to run plug-in \"%s\""),
186 name);
187
188 g_object_unref (plug_in);
189
190 return_vals = gimp_procedure_get_return_values (GIMP_PROCEDURE (procedure),
191 FALSE, error);
192 g_error_free (error);
193
194 return return_vals;
195 }
196
197 display_ID = display ? gimp_get_display_ID (manager->gimp, display) : -1;
198
199 icon_theme_dir = gimp_get_icon_theme_dir (manager->gimp);
200
201 config.version = GIMP_PROTOCOL_VERSION;
202 config.tile_width = GIMP_PLUG_IN_TILE_WIDTH;
203 config.tile_height = GIMP_PLUG_IN_TILE_HEIGHT;
204 config.shm_ID = (manager->shm ?
205 gimp_plug_in_shm_get_ID (manager->shm) : -1);
206 config.check_size = display_config->transparency_size;
207 config.check_type = display_config->transparency_type;
208 config.show_help_button = (gui_config->use_help &&
209 gui_config->show_help_button);
210 config.use_cpu_accel = manager->gimp->use_cpu_accel;
211 config.use_opencl = gegl_config->use_opencl;
212 config.export_profile = core_config->export_color_profile;
213 config.export_exif = core_config->export_metadata_exif;
214 config.export_xmp = core_config->export_metadata_xmp;
215 config.export_iptc = core_config->export_metadata_iptc;
216 config.show_tooltips = gui_config->show_tooltips;
217 config.min_colors = 144;
218 config.gdisp_ID = display_ID;
219 config.app_name = (gchar *) g_get_application_name ();
220 config.wm_class = (gchar *) gimp_get_program_class (manager->gimp);
221 config.display_name = gimp_get_display_name (manager->gimp,
222 display_ID,
223 &screen, &monitor);
224 config.monitor_number = monitor;
225 config.timestamp = gimp_get_user_time (manager->gimp);
226 config.icon_theme_dir = icon_theme_dir ?
227 g_file_get_path (icon_theme_dir) :
228 NULL;
229 config.tile_cache_size = gegl_config->tile_cache_size;
230 config.swap_path = gegl_config->swap_path;
231 config.num_processors = gegl_config->num_processors;
232 config.swap_compression = gegl_config->swap_compression;
233
234 proc_run.name = GIMP_PROCEDURE (procedure)->original_name;
235 proc_run.nparams = gimp_value_array_length (args);
236 proc_run.params = plug_in_args_to_params (args, FALSE);
237
238 if (! gp_config_write (plug_in->my_write, &config, plug_in) ||
239 ! gp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
240 ! gimp_wire_flush (plug_in->my_write, plug_in))
241 {
242 const gchar *name = gimp_object_get_name (plug_in);
243 GError *error = g_error_new (GIMP_PLUG_IN_ERROR,
244 GIMP_PLUG_IN_EXECUTION_FAILED,
245 _("Failed to run plug-in \"%s\""),
246 name);
247
248 g_free (config.display_name);
249 g_free (config.icon_theme_dir);
250 g_free (proc_run.params);
251
252 g_object_unref (plug_in);
253
254 return_vals = gimp_procedure_get_return_values (GIMP_PROCEDURE (procedure),
255 FALSE, error);
256 g_error_free (error);
257
258 return return_vals;
259 }
260
261 g_free (config.display_name);
262 g_free (config.icon_theme_dir);
263 g_free (proc_run.params);
264
265 /* If this is an extension,
266 * wait for an installation-confirmation message
267 */
268 if (GIMP_PROCEDURE (procedure)->proc_type == GIMP_EXTENSION)
269 {
270 plug_in->ext_main_loop = g_main_loop_new (NULL, FALSE);
271
272 gimp_threads_leave (manager->gimp);
273 g_main_loop_run (plug_in->ext_main_loop);
274 gimp_threads_enter (manager->gimp);
275
276 /* main_loop is quit in gimp_plug_in_handle_extension_ack() */
277
278 g_clear_pointer (&plug_in->ext_main_loop, g_main_loop_unref);
279 }
280
281 /* If this plug-in is requested to run synchronously,
282 * wait for its return values
283 */
284 if (synchronous)
285 {
286 GimpPlugInProcFrame *proc_frame = &plug_in->main_proc_frame;
287
288 proc_frame->main_loop = g_main_loop_new (NULL, FALSE);
289
290 gimp_threads_leave (manager->gimp);
291 g_main_loop_run (proc_frame->main_loop);
292 gimp_threads_enter (manager->gimp);
293
294 /* main_loop is quit in gimp_plug_in_handle_proc_return() */
295
296 g_clear_pointer (&proc_frame->main_loop, g_main_loop_unref);
297
298 return_vals = gimp_plug_in_proc_frame_get_return_values (proc_frame);
299 }
300
301 g_object_unref (plug_in);
302 }
303
304 return return_vals;
305 }
306
307 GimpValueArray *
gimp_plug_in_manager_call_run_temp(GimpPlugInManager * manager,GimpContext * context,GimpProgress * progress,GimpTemporaryProcedure * procedure,GimpValueArray * args)308 gimp_plug_in_manager_call_run_temp (GimpPlugInManager *manager,
309 GimpContext *context,
310 GimpProgress *progress,
311 GimpTemporaryProcedure *procedure,
312 GimpValueArray *args)
313 {
314 GimpValueArray *return_vals = NULL;
315 GimpPlugIn *plug_in;
316
317 g_return_val_if_fail (GIMP_IS_PLUG_IN_MANAGER (manager), NULL);
318 g_return_val_if_fail (GIMP_IS_PDB_CONTEXT (context), NULL);
319 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
320 g_return_val_if_fail (GIMP_IS_TEMPORARY_PROCEDURE (procedure), NULL);
321 g_return_val_if_fail (args != NULL, NULL);
322
323 plug_in = procedure->plug_in;
324
325 if (plug_in)
326 {
327 GimpPlugInProcFrame *proc_frame;
328 GPProcRun proc_run;
329
330 proc_frame = gimp_plug_in_proc_frame_push (plug_in, context, progress,
331 procedure);
332
333 proc_run.name = GIMP_PROCEDURE (procedure)->original_name;
334 proc_run.nparams = gimp_value_array_length (args);
335 proc_run.params = plug_in_args_to_params (args, FALSE);
336
337 if (! gp_temp_proc_run_write (plug_in->my_write, &proc_run, plug_in) ||
338 ! gimp_wire_flush (plug_in->my_write, plug_in))
339 {
340 const gchar *name = gimp_object_get_name (plug_in);
341 GError *error = g_error_new (GIMP_PLUG_IN_ERROR,
342 GIMP_PLUG_IN_EXECUTION_FAILED,
343 _("Failed to run plug-in \"%s\""),
344 name);
345
346 g_free (proc_run.params);
347 gimp_plug_in_proc_frame_pop (plug_in);
348
349 return_vals = gimp_procedure_get_return_values (GIMP_PROCEDURE (procedure),
350 FALSE, error);
351 g_error_free (error);
352
353 return return_vals;
354 }
355 gimp_allow_set_foreground_window (plug_in);
356
357 g_free (proc_run.params);
358
359 g_object_ref (plug_in);
360 gimp_plug_in_proc_frame_ref (proc_frame);
361
362 gimp_plug_in_main_loop (plug_in);
363
364 /* main_loop is quit and proc_frame is popped in
365 * gimp_plug_in_handle_temp_proc_return()
366 */
367
368 return_vals = gimp_plug_in_proc_frame_get_return_values (proc_frame);
369
370 gimp_plug_in_proc_frame_unref (proc_frame, plug_in);
371 g_object_unref (plug_in);
372 }
373
374 return return_vals;
375 }
376