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