1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * GimpDBusService
5 * Copyright (C) 2007, 2008 Sven Neumann <sven@gimp.org>
6 * Copyright (C) 2013 Michael Natterer <mitch@gimp.org>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <gegl.h>
25 #include <gtk/gtk.h>
26
27 #include "gui-types.h"
28
29 #include "core/gimp.h"
30 #include "core/gimp-batch.h"
31 #include "core/gimpcontainer.h"
32
33 #include "file/file-open.h"
34
35 #include "display/gimpdisplay.h"
36 #include "display/gimpdisplayshell.h"
37
38 #include "gimpdbusservice.h"
39
40
41 typedef struct
42 {
43 GFile *file;
44 gboolean as_new;
45
46 gchar *interpreter;
47 gchar *command;
48 } IdleData;
49
50 static void gimp_dbus_service_ui_iface_init (GimpDBusServiceUIIface *iface);
51
52 static void gimp_dbus_service_dispose (GObject *object);
53 static void gimp_dbus_service_finalize (GObject *object);
54
55 static gboolean gimp_dbus_service_activate (GimpDBusServiceUI *service,
56 GDBusMethodInvocation *invocation);
57 static gboolean gimp_dbus_service_open (GimpDBusServiceUI *service,
58 GDBusMethodInvocation *invocation,
59 const gchar *uri);
60
61 static gboolean gimp_dbus_service_open_as_new (GimpDBusServiceUI *service,
62 GDBusMethodInvocation *invocation,
63 const gchar *uri);
64
65 static gboolean gimp_dbus_service_batch_run (GimpDBusServiceUI *service,
66 GDBusMethodInvocation *invocation,
67 const gchar *batch_interpreter,
68 const gchar *batch_command);
69
70 static void gimp_dbus_service_gimp_opened (Gimp *gimp,
71 GFile *file,
72 GimpDBusService *service);
73
74 static gboolean gimp_dbus_service_queue_open (GimpDBusService *service,
75 const gchar *uri,
76 gboolean as_new);
77 static gboolean gimp_dbus_service_queue_batch (GimpDBusService *service,
78 const gchar *interpreter,
79 const gchar *command);
80
81 static gboolean gimp_dbus_service_process_idle (GimpDBusService *service);
82 static IdleData * gimp_dbus_service_open_data_new (GimpDBusService *service,
83 const gchar *uri,
84 gboolean as_new);
85 static IdleData * gimp_dbus_service_batch_data_new (GimpDBusService *service,
86 const gchar *interpreter,
87 const gchar *command);
88 static void gimp_dbus_service_idle_data_free (IdleData *data);
89
90
G_DEFINE_TYPE_WITH_CODE(GimpDBusService,gimp_dbus_service,GIMP_DBUS_SERVICE_TYPE_UI_SKELETON,G_IMPLEMENT_INTERFACE (GIMP_DBUS_SERVICE_TYPE_UI,gimp_dbus_service_ui_iface_init))91 G_DEFINE_TYPE_WITH_CODE (GimpDBusService, gimp_dbus_service,
92 GIMP_DBUS_SERVICE_TYPE_UI_SKELETON,
93 G_IMPLEMENT_INTERFACE (GIMP_DBUS_SERVICE_TYPE_UI,
94 gimp_dbus_service_ui_iface_init))
95
96 #define parent_class gimp_dbus_service_parent_class
97
98
99 static void
100 gimp_dbus_service_class_init (GimpDBusServiceClass *klass)
101 {
102 GObjectClass *object_class = G_OBJECT_CLASS (klass);
103
104 object_class->dispose = gimp_dbus_service_dispose;
105 object_class->finalize = gimp_dbus_service_finalize;
106 }
107
108 static void
gimp_dbus_service_init(GimpDBusService * service)109 gimp_dbus_service_init (GimpDBusService *service)
110 {
111 service->queue = g_queue_new ();
112 }
113
114 static void
gimp_dbus_service_ui_iface_init(GimpDBusServiceUIIface * iface)115 gimp_dbus_service_ui_iface_init (GimpDBusServiceUIIface *iface)
116 {
117 iface->handle_activate = gimp_dbus_service_activate;
118 iface->handle_open = gimp_dbus_service_open;
119 iface->handle_open_as_new = gimp_dbus_service_open_as_new;
120 iface->handle_batch_run = gimp_dbus_service_batch_run;
121 }
122
123 GObject *
gimp_dbus_service_new(Gimp * gimp)124 gimp_dbus_service_new (Gimp *gimp)
125 {
126 GimpDBusService *service;
127
128 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
129
130 service = g_object_new (GIMP_TYPE_DBUS_SERVICE, NULL);
131
132 service->gimp = gimp;
133
134 g_signal_connect_object (gimp, "image-opened",
135 G_CALLBACK (gimp_dbus_service_gimp_opened),
136 service, 0);
137
138 return G_OBJECT (service);
139 }
140
141 static void
gimp_dbus_service_dispose(GObject * object)142 gimp_dbus_service_dispose (GObject *object)
143 {
144 GimpDBusService *service = GIMP_DBUS_SERVICE (object);
145
146 if (service->source)
147 {
148 g_source_remove (g_source_get_id (service->source));
149 service->source = NULL;
150 service->timeout_source = FALSE;
151 }
152
153 while (! g_queue_is_empty (service->queue))
154 {
155 gimp_dbus_service_idle_data_free (g_queue_pop_head (service->queue));
156 }
157
158 G_OBJECT_CLASS (parent_class)->dispose (object);
159 }
160
161 static void
gimp_dbus_service_finalize(GObject * object)162 gimp_dbus_service_finalize (GObject *object)
163 {
164 GimpDBusService *service = GIMP_DBUS_SERVICE (object);
165
166 if (service->queue)
167 {
168 g_queue_free (service->queue);
169 service->queue = NULL;
170 }
171
172 G_OBJECT_CLASS (parent_class)->finalize (object);
173 }
174
175 gboolean
gimp_dbus_service_activate(GimpDBusServiceUI * service,GDBusMethodInvocation * invocation)176 gimp_dbus_service_activate (GimpDBusServiceUI *service,
177 GDBusMethodInvocation *invocation)
178 {
179 Gimp *gimp = GIMP_DBUS_SERVICE (service)->gimp;
180
181 /* We want to be called again later in case that GIMP is not fully
182 * started yet.
183 */
184 if (gimp_is_restored (gimp))
185 {
186 GimpObject *display;
187
188 display = gimp_container_get_first_child (gimp->displays);
189
190 if (display)
191 gimp_display_shell_present (gimp_display_get_shell (GIMP_DISPLAY (display)));
192 }
193
194 gimp_dbus_service_ui_complete_activate (service, invocation);
195
196 return TRUE;
197 }
198
199 gboolean
gimp_dbus_service_open(GimpDBusServiceUI * service,GDBusMethodInvocation * invocation,const gchar * uri)200 gimp_dbus_service_open (GimpDBusServiceUI *service,
201 GDBusMethodInvocation *invocation,
202 const gchar *uri)
203 {
204 gboolean success;
205
206 success = gimp_dbus_service_queue_open (GIMP_DBUS_SERVICE (service),
207 uri, FALSE);
208
209 gimp_dbus_service_ui_complete_open (service, invocation, success);
210
211 return TRUE;
212 }
213
214 gboolean
gimp_dbus_service_open_as_new(GimpDBusServiceUI * service,GDBusMethodInvocation * invocation,const gchar * uri)215 gimp_dbus_service_open_as_new (GimpDBusServiceUI *service,
216 GDBusMethodInvocation *invocation,
217 const gchar *uri)
218 {
219 gboolean success;
220
221 success = gimp_dbus_service_queue_open (GIMP_DBUS_SERVICE (service),
222 uri, TRUE);
223
224 gimp_dbus_service_ui_complete_open_as_new (service, invocation, success);
225
226 return TRUE;
227 }
228
229 gboolean
gimp_dbus_service_batch_run(GimpDBusServiceUI * service,GDBusMethodInvocation * invocation,const gchar * batch_interpreter,const gchar * batch_command)230 gimp_dbus_service_batch_run (GimpDBusServiceUI *service,
231 GDBusMethodInvocation *invocation,
232 const gchar *batch_interpreter,
233 const gchar *batch_command)
234 {
235 gboolean success;
236
237 success = gimp_dbus_service_queue_batch (GIMP_DBUS_SERVICE (service),
238 batch_interpreter,
239 batch_command);
240
241 gimp_dbus_service_ui_complete_batch_run (service, invocation, success);
242
243 return TRUE;
244 }
245
246 static void
gimp_dbus_service_gimp_opened(Gimp * gimp,GFile * file,GimpDBusService * service)247 gimp_dbus_service_gimp_opened (Gimp *gimp,
248 GFile *file,
249 GimpDBusService *service)
250 {
251 gchar *uri = g_file_get_uri (file);
252
253 g_signal_emit_by_name (service, "opened", uri);
254
255 g_free (uri);
256 }
257
258 /*
259 * Adds a request to open a file to the end of the queue and
260 * starts an idle source if it is not already running.
261 */
262 static gboolean
gimp_dbus_service_queue_open(GimpDBusService * service,const gchar * uri,gboolean as_new)263 gimp_dbus_service_queue_open (GimpDBusService *service,
264 const gchar *uri,
265 gboolean as_new)
266 {
267 g_queue_push_tail (service->queue,
268 gimp_dbus_service_open_data_new (service, uri, as_new));
269
270 if (! service->source)
271 {
272 service->source = g_idle_source_new ();
273 service->timeout_source = FALSE;
274
275 g_source_set_priority (service->source, G_PRIORITY_LOW);
276 g_source_set_callback (service->source,
277 (GSourceFunc) gimp_dbus_service_process_idle,
278 service,
279 NULL);
280 g_source_attach (service->source, NULL);
281 g_source_unref (service->source);
282 }
283
284 /* The call always succeeds as it is handled in one way or another.
285 * Even presenting an error message is considered success ;-)
286 */
287 return TRUE;
288 }
289
290 /*
291 * Adds a request to run a batch command to the end of the queue and
292 * starts an idle source if it is not already running.
293 */
294 static gboolean
gimp_dbus_service_queue_batch(GimpDBusService * service,const gchar * interpreter,const gchar * command)295 gimp_dbus_service_queue_batch (GimpDBusService *service,
296 const gchar *interpreter,
297 const gchar *command)
298 {
299 g_queue_push_tail (service->queue,
300 gimp_dbus_service_batch_data_new (service,
301 interpreter,
302 command));
303
304 if (! service->source)
305 {
306 service->source = g_idle_source_new ();
307 service->timeout_source = FALSE;
308
309 g_source_set_priority (service->source, G_PRIORITY_LOW);
310 g_source_set_callback (service->source,
311 (GSourceFunc) gimp_dbus_service_process_idle,
312 service,
313 NULL);
314 g_source_attach (service->source, NULL);
315 g_source_unref (service->source);
316 }
317
318 /* The call always succeeds as it is handled in one way or another.
319 * Even presenting an error message is considered success ;-)
320 */
321 return TRUE;
322 }
323
324 /*
325 * Idle callback that removes the first request from the queue and
326 * handles it. If there are no more requests, the idle source is
327 * removed.
328 */
329 static gboolean
gimp_dbus_service_process_idle(GimpDBusService * service)330 gimp_dbus_service_process_idle (GimpDBusService *service)
331 {
332 IdleData *data;
333
334 if (! service->gimp->initialized || ! service->gimp->restored)
335 {
336 if (! service->timeout_source)
337 {
338 /* We are probably starting the program. No need to spam GIMP with
339 * an idle handler (which might make GIMP slower to start even
340 * with low priority).
341 * Instead let's add a timeout of half a second.
342 */
343 service->source = g_timeout_source_new (500);
344 service->timeout_source = TRUE;
345
346 g_source_set_priority (service->source, G_PRIORITY_LOW);
347 g_source_set_callback (service->source,
348 (GSourceFunc) gimp_dbus_service_process_idle,
349 service,
350 NULL);
351 g_source_attach (service->source, NULL);
352 g_source_unref (service->source);
353
354 return G_SOURCE_REMOVE;
355 }
356 else
357 {
358 return G_SOURCE_CONTINUE;
359 }
360 }
361
362 /* Process data as a FIFO. */
363 data = g_queue_pop_head (service->queue);
364
365 if (data)
366 {
367 if (data->file)
368 file_open_from_command_line (service->gimp, data->file, data->as_new,
369 NULL, /* FIXME monitor */
370 0 /* FIXME monitor */);
371 if (data->command)
372 {
373 const gchar *commands[2] = {data->command, 0};
374
375 gimp_batch_run (service->gimp, data->interpreter,
376 commands);
377 }
378
379 gimp_dbus_service_idle_data_free (data);
380
381 if (service->timeout_source)
382 {
383 /* Now GIMP is fully functional and can respond quickly to
384 * DBus calls. Switch to a usual idle source.
385 */
386 service->source = g_idle_source_new ();
387 service->timeout_source = FALSE;
388
389 g_source_set_priority (service->source, G_PRIORITY_LOW);
390 g_source_set_callback (service->source,
391 (GSourceFunc) gimp_dbus_service_process_idle,
392 service,
393 NULL);
394 g_source_attach (service->source, NULL);
395 g_source_unref (service->source);
396
397 return G_SOURCE_REMOVE;
398 }
399 else
400 {
401 return G_SOURCE_CONTINUE;
402 }
403 }
404
405 service->source = NULL;
406
407 return G_SOURCE_REMOVE;
408 }
409
410 static IdleData *
gimp_dbus_service_open_data_new(GimpDBusService * service,const gchar * uri,gboolean as_new)411 gimp_dbus_service_open_data_new (GimpDBusService *service,
412 const gchar *uri,
413 gboolean as_new)
414 {
415 IdleData *data = g_slice_new (IdleData);
416
417 data->file = g_file_new_for_uri (uri);
418 data->as_new = as_new;
419 data->interpreter = NULL;
420 data->command = NULL;
421
422 return data;
423 }
424
425 static IdleData *
gimp_dbus_service_batch_data_new(GimpDBusService * service,const gchar * interpreter,const gchar * command)426 gimp_dbus_service_batch_data_new (GimpDBusService *service,
427 const gchar *interpreter,
428 const gchar *command)
429 {
430 IdleData *data = g_slice_new (IdleData);
431
432 data->file = NULL;
433 data->as_new = FALSE;
434
435 data->command = g_strdup (command);
436
437 if (g_strcmp0 (interpreter, "") == 0)
438 data->interpreter = NULL;
439 else
440 data->interpreter = g_strdup (interpreter);
441
442 return data;
443 }
444
445 static void
gimp_dbus_service_idle_data_free(IdleData * data)446 gimp_dbus_service_idle_data_free (IdleData *data)
447 {
448 if (data->file)
449 g_object_unref (data->file);
450
451 if (data->command)
452 g_free (data->command);
453 if (data->interpreter)
454 g_free (data->interpreter);
455
456 g_slice_free (IdleData, data);
457 }
458