gimpdbusservice.c 12.4 KB
Newer Older
1 2 3 4
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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 12 13 14 15 16 17 18
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 21 22 23
 */

#include "config.h"

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 34

#include "file/file-open.h"

35
#include "display/gimpdisplay.h"
36
#include "display/gimpdisplayshell.h"
37

38 39
#include "gimpdbusservice.h"

40

41 42
typedef struct
{
43
  GFile    *file;
44 45
  gboolean  as_new;

46 47 48
  gchar    *interpreter;
  gchar    *command;
} IdleData;
49

50
static void       gimp_dbus_service_ui_iface_init  (GimpDBusServiceUIIface *iface);
51

52 53
static void       gimp_dbus_service_dispose        (GObject               *object);
static void       gimp_dbus_service_finalize       (GObject               *object);
54

55 56 57 58 59
static gboolean   gimp_dbus_service_activate       (GimpDBusServiceUI     *service,
                                                    GDBusMethodInvocation *invocation);
static gboolean   gimp_dbus_service_open           (GimpDBusServiceUI     *service,
                                                    GDBusMethodInvocation *invocation,
                                                    const gchar           *uri);
60

61 62 63
static gboolean   gimp_dbus_service_open_as_new    (GimpDBusServiceUI     *service,
                                                    GDBusMethodInvocation *invocation,
                                                    const gchar           *uri);
Sven Neumann's avatar
Sven Neumann committed
64

65 66 67 68 69
static gboolean   gimp_dbus_service_batch_run      (GimpDBusServiceUI     *service,
                                                    GDBusMethodInvocation *invocation,
                                                    const gchar           *batch_interpreter,
                                                    const gchar           *batch_command);

70
static void       gimp_dbus_service_gimp_opened    (Gimp                  *gimp,
Jehan's avatar
Jehan committed
71 72
                                                    GFile                 *file,
                                                    GimpDBusService       *service);
73

74 75 76
static gboolean   gimp_dbus_service_queue_open     (GimpDBusService       *service,
                                                    const gchar           *uri,
                                                    gboolean               as_new);
77 78 79
static gboolean   gimp_dbus_service_queue_batch    (GimpDBusService       *service,
                                                    const gchar           *interpreter,
                                                    const gchar           *command);
80

81 82
static gboolean   gimp_dbus_service_process_idle   (GimpDBusService       *service);
static IdleData * gimp_dbus_service_open_data_new  (GimpDBusService       *service,
83 84
                                                    const gchar           *uri,
                                                    gboolean               as_new);
85 86 87 88
static IdleData * gimp_dbus_service_batch_data_new (GimpDBusService       *service,
                                                    const gchar           *interpreter,
                                                    const gchar           *command);
static void       gimp_dbus_service_idle_data_free (IdleData              *data);
89

90

91 92 93 94 95 96
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))

#define parent_class gimp_dbus_service_parent_class
97

98 99 100 101

static void
gimp_dbus_service_class_init (GimpDBusServiceClass *klass)
{
102 103 104 105
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose  = gimp_dbus_service_dispose;
  object_class->finalize = gimp_dbus_service_finalize;
106 107 108 109 110
}

static void
gimp_dbus_service_init (GimpDBusService *service)
{
111
  service->queue = g_queue_new ();
112 113
}

114 115 116 117 118 119
static void
gimp_dbus_service_ui_iface_init (GimpDBusServiceUIIface *iface)
{
  iface->handle_activate    = gimp_dbus_service_activate;
  iface->handle_open        = gimp_dbus_service_open;
  iface->handle_open_as_new = gimp_dbus_service_open_as_new;
120
  iface->handle_batch_run   = gimp_dbus_service_batch_run;
121 122
}

123 124 125 126 127 128 129 130 131 132 133
GObject *
gimp_dbus_service_new (Gimp *gimp)
{
  GimpDBusService *service;

  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);

  service = g_object_new (GIMP_TYPE_DBUS_SERVICE, NULL);

  service->gimp = gimp;

134
  g_signal_connect_object (gimp, "image-opened",
Jehan's avatar
Jehan committed
135 136
                           G_CALLBACK (gimp_dbus_service_gimp_opened),
                           service, 0);
137

138 139 140
  return G_OBJECT (service);
}

141 142
static void
gimp_dbus_service_dispose (GObject *object)
143
{
144
  GimpDBusService *service = GIMP_DBUS_SERVICE (object);
145

146 147 148 149 150
  if (service->source)
    {
      g_source_remove (g_source_get_id (service->source));
      service->source = NULL;
    }
151

152 153
  while (! g_queue_is_empty (service->queue))
    {
154
      gimp_dbus_service_idle_data_free (g_queue_pop_head (service->queue));
155
    }
156

157
  G_OBJECT_CLASS (parent_class)->dispose (object);
158 159 160
}

static void
161
gimp_dbus_service_finalize (GObject *object)
162
{
163
  GimpDBusService *service = GIMP_DBUS_SERVICE (object);
164

165 166 167 168 169
  if (service->queue)
    {
      g_queue_free (service->queue);
      service->queue = NULL;
    }
170

171
  G_OBJECT_CLASS (parent_class)->finalize (object);
172 173
}

174
gboolean
175 176
gimp_dbus_service_activate (GimpDBusServiceUI     *service,
                            GDBusMethodInvocation *invocation)
177
{
178
  Gimp *gimp = GIMP_DBUS_SERVICE (service)->gimp;
179

180 181 182 183 184 185 186 187 188 189 190 191 192 193
  /*  We want to be called again later in case that GIMP is not fully
   *  started yet.
   */
  if (gimp_is_restored (gimp))
    {
      GimpObject *display;

      display = gimp_container_get_first_child (gimp->displays);

      if (display)
        gimp_display_shell_present (gimp_display_get_shell (GIMP_DISPLAY (display)));
    }

  gimp_dbus_service_ui_complete_activate (service, invocation);
194 195 196 197 198

  return TRUE;
}

gboolean
199 200 201
gimp_dbus_service_open (GimpDBusServiceUI     *service,
                        GDBusMethodInvocation *invocation,
                        const gchar           *uri)
202
{
203 204 205 206
  gboolean success;

  success = gimp_dbus_service_queue_open (GIMP_DBUS_SERVICE (service),
                                          uri, FALSE);
207

208
  gimp_dbus_service_ui_complete_open (service, invocation, success);
209 210 211 212

  return TRUE;
}

Sven Neumann's avatar
Sven Neumann committed
213
gboolean
214 215 216
gimp_dbus_service_open_as_new (GimpDBusServiceUI     *service,
                               GDBusMethodInvocation *invocation,
                               const gchar           *uri)
Sven Neumann's avatar
Sven Neumann committed
217
{
218
  gboolean success;
Sven Neumann's avatar
Sven Neumann committed
219

220 221
  success = gimp_dbus_service_queue_open (GIMP_DBUS_SERVICE (service),
                                          uri, TRUE);
222

223
  gimp_dbus_service_ui_complete_open_as_new (service, invocation, success);
Sven Neumann's avatar
Sven Neumann committed
224 225 226

  return TRUE;
}
227

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
gboolean
gimp_dbus_service_batch_run (GimpDBusServiceUI     *service,
                             GDBusMethodInvocation *invocation,
                             const gchar           *batch_interpreter,
                             const gchar           *batch_command)
{
  gboolean success;

  success = gimp_dbus_service_queue_batch (GIMP_DBUS_SERVICE (service),
                                           batch_interpreter,
                                           batch_command);

  gimp_dbus_service_ui_complete_batch_run (service, invocation, success);

  return TRUE;
}

245 246
static void
gimp_dbus_service_gimp_opened (Gimp            *gimp,
Jehan's avatar
Jehan committed
247 248
                               GFile           *file,
                               GimpDBusService *service)
249
{
250 251
  gchar *uri = g_file_get_uri (file);

252
  g_signal_emit_by_name (service, "opened", uri);
253 254

  g_free (uri);
255 256
}

Sven Neumann's avatar
Sven Neumann committed
257 258 259 260 261 262 263 264
/*
 * Adds a request to open a file to the end of the queue and
 * starts an idle source if it is not already running.
 */
static gboolean
gimp_dbus_service_queue_open (GimpDBusService *service,
                              const gchar     *uri,
                              gboolean         as_new)
265
{
Sven Neumann's avatar
Sven Neumann committed
266 267
  g_queue_push_tail (service->queue,
                     gimp_dbus_service_open_data_new (service, uri, as_new));
268

Sven Neumann's avatar
Sven Neumann committed
269 270 271
  if (! service->source)
    {
      service->source = g_idle_source_new ();
272

273
      g_source_set_priority (service->source, G_PRIORITY_LOW);
Sven Neumann's avatar
Sven Neumann committed
274
      g_source_set_callback (service->source,
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
                             (GSourceFunc) gimp_dbus_service_process_idle,
                             service,
                             NULL);
      g_source_attach (service->source, NULL);
      g_source_unref (service->source);
    }

  /*  The call always succeeds as it is handled in one way or another.
   *  Even presenting an error message is considered success ;-)
   */
  return TRUE;
}

/*
 * Adds a request to run a batch command to the end of the queue and
 * starts an idle source if it is not already running.
 */
static gboolean
gimp_dbus_service_queue_batch (GimpDBusService *service,
                               const gchar     *interpreter,
                               const gchar     *command)
{
  g_queue_push_tail (service->queue,
                     gimp_dbus_service_batch_data_new (service,
                                                       interpreter,
                                                       command));

  if (! service->source)
    {
      service->source = g_idle_source_new ();

      g_source_set_priority (service->source, G_PRIORITY_LOW);
      g_source_set_callback (service->source,
                             (GSourceFunc) gimp_dbus_service_process_idle,
                             service,
Sven Neumann's avatar
Sven Neumann committed
310 311 312 313
                             NULL);
      g_source_attach (service->source, NULL);
      g_source_unref (service->source);
    }
314

Sven Neumann's avatar
Sven Neumann committed
315 316 317 318
  /*  The call always succeeds as it is handled in one way or another.
   *  Even presenting an error message is considered success ;-)
   */
  return TRUE;
319 320
}

Sven Neumann's avatar
Sven Neumann committed
321 322 323 324 325
/*
 * Idle callback that removes the first request from the queue and
 * handles it. If there are no more requests, the idle source is
 * removed.
 */
326
static gboolean
327
gimp_dbus_service_process_idle (GimpDBusService *service)
328
{
329
  IdleData *data;
330 331 332 333 334

  if (! service->gimp->restored)
    return TRUE;

  data = g_queue_pop_tail (service->queue);
335 336 337

  if (data)
    {
338

339 340 341 342 343 344 345 346
      if (data->file)
        file_open_from_command_line (service->gimp, data->file, data->as_new,
                                     NULL, /* FIXME monitor */
                                     0 /* FIXME monitor */);
      if (data->command)
        {
          const gchar *commands[2] = {data->command, 0};

347 348
          gimp_batch_run (service->gimp, data->interpreter,
                          commands);
349 350 351
        }

      gimp_dbus_service_idle_data_free (data);
352 353 354 355

      return TRUE;
    }

356 357
  service->source = NULL;

358 359 360
  return FALSE;
}

361
static IdleData *
Sven Neumann's avatar
Sven Neumann committed
362 363 364
gimp_dbus_service_open_data_new (GimpDBusService *service,
                                 const gchar     *uri,
                                 gboolean         as_new)
365
{
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
  IdleData *data    = g_slice_new (IdleData);

  data->file        = g_file_new_for_uri (uri);
  data->as_new      = as_new;
  data->interpreter = NULL;
  data->command     = NULL;

  return data;
}

static IdleData *
gimp_dbus_service_batch_data_new (GimpDBusService *service,
                                  const gchar     *interpreter,
                                  const gchar     *command)
{
  IdleData *data = g_slice_new (IdleData);

  data->file     = NULL;
  data->as_new   = FALSE;
385

386 387 388 389 390 391
  data->command  = g_strdup (command);

  if (g_strcmp0 (interpreter, "") == 0)
    data->interpreter = NULL;
  else
    data->interpreter = g_strdup (interpreter);
392

Sven Neumann's avatar
Sven Neumann committed
393
  return data;
394
}
395

Sven Neumann's avatar
Sven Neumann committed
396
static void
397
gimp_dbus_service_idle_data_free (IdleData *data)
Sven Neumann's avatar
Sven Neumann committed
398
{
399 400 401 402 403 404 405 406 407
  if (data->file)
    g_object_unref (data->file);

  if (data->command)
    g_free (data->command);
  if (data->interpreter)
    g_free (data->interpreter);

  g_slice_free (IdleData, data);
Sven Neumann's avatar
Sven Neumann committed
408
}