Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-daemon.c File Reference
#include "config.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "ev-daemon-gdbus-generated.h"
+ Include dependency graph for ev-daemon.c:

Go to the source code of this file.

Data Structures

struct  _EvDaemonApplicationClass
 
struct  _EvDaemonApplication
 
struct  EvDoc
 

Macros

#define G_LOG_DOMAIN   "EvinceDaemon"
 
#define EV_DBUS_DAEMON_NAME   "org.gnome.evince.Daemon"
 
#define EV_DBUS_DAEMON_INTERFACE_NAME   "org.gnome.evince.Daemon"
 
#define EV_DBUS_DAEMON_OBJECT_PATH   "/org/gnome/evince/Daemon"
 
#define EV_DBUS_WINDOW_INTERFACE_NAME   "org.gnome.evince.Window"
 
#define DAEMON_TIMEOUT   (30) /* seconds */
 
#define LOG   g_debug
 
#define EV_TYPE_DAEMON_APPLICATION   (ev_daemon_application_get_type ())
 
#define EV_DAEMON_APPLICATION(object)   (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication))
 
#define EV_DAEMON_APPLICATION_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))
 
#define EV_IS_DAEMON_APPLICATION(object)   (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_DAEMON_APPLICATION))
 
#define EV_IS_DAEMON_APPLICATION_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_DAEMON_APPLICATION))
 
#define EV_DAEMON_APPLICATION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))
 

Typedefs

typedef struct _EvDaemonApplication EvDaemonApplication
 
typedef struct
_EvDaemonApplicationClass 
EvDaemonApplicationClass
 

Functions

static GType ev_daemon_application_get_type (void)
 
static void ev_doc_free (EvDoc *doc)
 
static EvDocev_daemon_application_find_doc (EvDaemonApplication *application, const gchar *uri)
 
static gboolean spawn_evince (const gchar *uri)
 
static void name_appeared_cb (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data)
 
static void name_vanished_cb (GDBusConnection *connection, const gchar *name, gpointer user_data)
 
static void process_pending_invocations (EvDaemonApplication *application, const gchar *uri, const gchar *dbus_name)
 
static void document_loaded_cb (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
 
static gboolean handle_register_document_cb (EvDaemon *object, GDBusMethodInvocation *invocation, const gchar *uri, EvDaemonApplication *application)
 
static gboolean handle_unregister_document_cb (EvDaemon *object, GDBusMethodInvocation *invocation, const gchar *uri, EvDaemonApplication *application)
 
static gboolean handle_find_document_cb (EvDaemon *object, GDBusMethodInvocation *invocation, const gchar *uri, gboolean spawn, EvDaemonApplication *application)
 
static gboolean ev_daemon_application_dbus_register (GApplication *gapplication, GDBusConnection *connection, const gchar *object_path, GError **error)
 
static void ev_daemon_application_dbus_unregister (GApplication *gapplication, GDBusConnection *connection, const gchar *object_path)
 
static void ev_daemon_application_init (EvDaemonApplication *application)
 
static void ev_daemon_application_finalize (GObject *object)
 
static void ev_daemon_application_class_init (EvDaemonApplicationClass *klass)
 
gint main (gint argc, gchar **argv)
 

Macro Definition Documentation

#define DAEMON_TIMEOUT   (30) /* seconds */

Definition at line 42 of file ev-daemon.c.

#define EV_DAEMON_APPLICATION (   object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication))

Definition at line 47 of file ev-daemon.c.

#define EV_DAEMON_APPLICATION_CLASS (   klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))

Definition at line 48 of file ev-daemon.c.

#define EV_DAEMON_APPLICATION_GET_CLASS (   obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))

Definition at line 51 of file ev-daemon.c.

#define EV_DBUS_DAEMON_INTERFACE_NAME   "org.gnome.evince.Daemon"

Definition at line 37 of file ev-daemon.c.

#define EV_DBUS_DAEMON_NAME   "org.gnome.evince.Daemon"

Definition at line 36 of file ev-daemon.c.

#define EV_DBUS_DAEMON_OBJECT_PATH   "/org/gnome/evince/Daemon"

Definition at line 38 of file ev-daemon.c.

#define EV_DBUS_WINDOW_INTERFACE_NAME   "org.gnome.evince.Window"

Definition at line 40 of file ev-daemon.c.

#define EV_IS_DAEMON_APPLICATION (   object)    (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_DAEMON_APPLICATION))

Definition at line 49 of file ev-daemon.c.

#define EV_IS_DAEMON_APPLICATION_CLASS (   klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_DAEMON_APPLICATION))

Definition at line 50 of file ev-daemon.c.

#define EV_TYPE_DAEMON_APPLICATION   (ev_daemon_application_get_type ())

Definition at line 46 of file ev-daemon.c.

#define G_LOG_DOMAIN   "EvinceDaemon"

Definition at line 24 of file ev-daemon.c.

#define LOG   g_debug

Definition at line 44 of file ev-daemon.c.

Typedef Documentation

Definition at line 53 of file ev-daemon.c.

Definition at line 54 of file ev-daemon.c.

Function Documentation

static void document_loaded_cb ( GDBusConnection *  connection,
const gchar *  sender_name,
const gchar *  object_path,
const gchar *  interface_name,
const gchar *  signal_name,
GVariant *  parameters,
gpointer  user_data 
)
static

Definition at line 192 of file ev-daemon.c.

199 {
200  EvDaemonApplication *application = EV_DAEMON_APPLICATION (user_data);
201  const gchar *uri;
202  EvDoc *doc;
203 
204  g_variant_get (parameters, "(&s)", &uri);
205  doc = ev_daemon_application_find_doc (application, uri);
206 
207  if (doc == NULL)
208  return;
209  if (strcmp (uri, doc->uri) == 0) {
210  process_pending_invocations (application, uri, sender_name);
211  }
212 
213  g_dbus_connection_signal_unsubscribe (connection, doc->loaded_id);
214  doc->loaded_id = 0;
215 }

+ Here is the caller graph for this function:

static void ev_daemon_application_class_init ( EvDaemonApplicationClass klass)
static

Definition at line 442 of file ev-daemon.c.

443 {
444  GObjectClass *object_class = G_OBJECT_CLASS (klass);
445  GApplicationClass *g_application_class = G_APPLICATION_CLASS (klass);
446 
447  object_class->finalize = ev_daemon_application_finalize;
448 
449  g_application_class->dbus_register = ev_daemon_application_dbus_register;
450  g_application_class->dbus_unregister = ev_daemon_application_dbus_unregister;
451 }
static gboolean ev_daemon_application_dbus_register ( GApplication *  gapplication,
GDBusConnection *  connection,
const gchar *  object_path,
GError **  error 
)
static

Definition at line 368 of file ev-daemon.c.

372 {
373  EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication);
374  EvDaemon *skeleton;
375 
376  if (!G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_register (gapplication,
377  connection,
378  object_path,
379  error))
380  return FALSE;
381 
382  skeleton = ev_daemon_skeleton_new ();
383  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
384  connection,
386  error)) {
387  g_object_unref (skeleton);
388  return FALSE;
389  }
390 
391  application->daemon = skeleton;
392  g_signal_connect (skeleton, "handle-register-document",
393  G_CALLBACK (handle_register_document_cb), application);
394  g_signal_connect (skeleton, "handle-unregister-document",
395  G_CALLBACK (handle_unregister_document_cb), application);
396  g_signal_connect (skeleton, "handle-find-document",
397  G_CALLBACK (handle_find_document_cb), application);
398  return TRUE;
399 }

+ Here is the caller graph for this function:

static void ev_daemon_application_dbus_unregister ( GApplication *  gapplication,
GDBusConnection *  connection,
const gchar *  object_path 
)
static

Definition at line 402 of file ev-daemon.c.

405 {
406  EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication);
407 
408  if (application->daemon) {
409  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (application->daemon));
410  g_object_unref (application->daemon);
411  application->daemon = NULL;
412  }
413 
414  G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_unregister (gapplication,
415  connection,
416  object_path);
417 }

+ Here is the caller graph for this function:

static void ev_daemon_application_finalize ( GObject *  object)
static

Definition at line 429 of file ev-daemon.c.

430 {
431  EvDaemonApplication *application = EV_DAEMON_APPLICATION (object);
432 
433  g_warn_if_fail (g_hash_table_size (application->pending_invocations) == 0);
434  g_hash_table_destroy (application->pending_invocations);
435 
436  g_list_free_full (application->docs, (GDestroyNotify) ev_doc_free);
437 
438  G_OBJECT_CLASS (ev_daemon_application_parent_class)->finalize (object);
439 }

+ Here is the caller graph for this function:

static EvDoc* ev_daemon_application_find_doc ( EvDaemonApplication application,
const gchar *  uri 
)
static

Definition at line 94 of file ev-daemon.c.

96 {
97  GList *l;
98 
99  for (l = application->docs; l != NULL; l = l->next) {
100  EvDoc *doc = (EvDoc *)l->data;
101 
102  if (strcmp (doc->uri, uri) == 0)
103  return doc;
104  }
105 
106  return NULL;
107 }

+ Here is the caller graph for this function:

static GType ev_daemon_application_get_type ( void  )
static
static void ev_daemon_application_init ( EvDaemonApplication application)
static

Definition at line 420 of file ev-daemon.c.

421 {
422  application->pending_invocations = g_hash_table_new_full (g_str_hash,
423  g_str_equal,
424  (GDestroyNotify) g_free,
425  NULL);
426 }
static void ev_doc_free ( EvDoc doc)
static

Definition at line 80 of file ev-daemon.c.

81 {
82  if (!doc)
83  return;
84 
85  g_free (doc->dbus_name);
86  g_free (doc->uri);
87 
88  g_bus_unwatch_name (doc->watch_id);
89 
90  g_free (doc);
91 }

+ Here is the caller graph for this function:

static gboolean handle_find_document_cb ( EvDaemon *  object,
GDBusMethodInvocation *  invocation,
const gchar *  uri,
gboolean  spawn,
EvDaemonApplication application 
)
static

Definition at line 320 of file ev-daemon.c.

325 {
326  EvDoc *doc;
327 
328  LOG ("FindDocument URI '%s'", uri);
329 
330  doc = ev_daemon_application_find_doc (application, uri);
331  if (doc != NULL) {
332  ev_daemon_complete_find_document (object, invocation, doc->dbus_name);
333 
334  return TRUE;
335  }
336 
337  if (spawn) {
338  GList *uri_invocations;
339  gboolean ret_val = TRUE;
340 
341  uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);
342 
343  if (uri_invocations == NULL) {
344  /* Only spawn once. */
345  ret_val = spawn_evince (uri);
346  }
347 
348  if (ret_val) {
349  /* Only defer DBUS answer if evince was succesfully spawned */
350  uri_invocations = g_list_prepend (uri_invocations, invocation);
351  g_hash_table_insert (application->pending_invocations,
352  g_strdup (uri),
353  uri_invocations);
354  return TRUE;
355  }
356  }
357 
358  LOG ("FindDocument URI '%s' was not registered!", uri);
359  // FIXME: shouldn't this return an error then?
360  ev_daemon_complete_find_document (object, invocation, "");
361 
362  return TRUE;
363 }

+ Here is the caller graph for this function:

static gboolean handle_register_document_cb ( EvDaemon *  object,
GDBusMethodInvocation *  invocation,
const gchar *  uri,
EvDaemonApplication application 
)
static

Definition at line 218 of file ev-daemon.c.

222 {
223  GDBusConnection *connection;
224  const char *sender;
225  EvDoc *doc;
226 
227  doc = ev_daemon_application_find_doc (application, uri);
228  if (doc != NULL) {
229  LOG ("RegisterDocument found owner '%s' for URI '%s'", doc->dbus_name, uri);
230  ev_daemon_complete_register_document (object, invocation, doc->dbus_name);
231 
232  return TRUE;
233  }
234 
235  sender = g_dbus_method_invocation_get_sender (invocation);
236  connection = g_dbus_method_invocation_get_connection (invocation);
237 
238  LOG ("RegisterDocument registered owner '%s' for URI '%s'", sender, uri);
239 
240  doc = g_new (EvDoc, 1);
241  doc->dbus_name = g_strdup (sender);
242  doc->uri = g_strdup (uri);
243 
244  application->docs = g_list_prepend (application->docs, doc);
245 
246  doc->loaded_id = g_dbus_connection_signal_subscribe (connection,
247  doc->dbus_name,
249  "DocumentLoaded",
250  NULL,
251  NULL,
252  0,
254  application, NULL);
255  doc->watch_id = g_bus_watch_name_on_connection (connection,
256  sender,
257  G_BUS_NAME_WATCHER_FLAGS_NONE,
260  application, NULL);
261 
262  ev_daemon_complete_register_document (object, invocation, "");
263 
264  g_application_hold (G_APPLICATION (application));
265 
266  return TRUE;
267 }

+ Here is the caller graph for this function:

static gboolean handle_unregister_document_cb ( EvDaemon *  object,
GDBusMethodInvocation *  invocation,
const gchar *  uri,
EvDaemonApplication application 
)
static

Definition at line 270 of file ev-daemon.c.

274 {
275  EvDoc *doc;
276  const char *sender;
277 
278  LOG ("UnregisterDocument URI '%s'", uri);
279 
280  doc = ev_daemon_application_find_doc (application, uri);
281  if (doc == NULL) {
282  LOG ("UnregisterDocument URI was not registered!");
283  g_dbus_method_invocation_return_error_literal (invocation,
284  G_DBUS_ERROR,
285  G_DBUS_ERROR_INVALID_ARGS,
286  "URI not registered");
287  return TRUE;
288  }
289 
290  sender = g_dbus_method_invocation_get_sender (invocation);
291  if (strcmp (doc->dbus_name, sender) != 0) {
292  LOG ("UnregisterDocument called by non-owner (owner '%s' sender '%s')",
293  doc->dbus_name, sender);
294 
295  g_dbus_method_invocation_return_error_literal (invocation,
296  G_DBUS_ERROR,
297  G_DBUS_ERROR_BAD_ADDRESS,
298  "Only owner can call this method");
299  return TRUE;
300  }
301 
302  application->docs = g_list_remove (application->docs, doc);
303 
304  if (doc->loaded_id != 0) {
305  g_dbus_connection_signal_unsubscribe (g_dbus_method_invocation_get_connection (invocation),
306  doc->loaded_id);
307  doc->loaded_id = 0;
308  }
309 
310  ev_doc_free (doc);
311 
312  ev_daemon_complete_unregister_document (object, invocation);
313 
314  g_application_release (G_APPLICATION (application));
315 
316  return TRUE;
317 }

+ Here is the caller graph for this function:

gint main ( gint  argc,
gchar **  argv 
)

Definition at line 456 of file ev-daemon.c.

457 {
458  GApplication *application;
459  const GApplicationFlags flags = G_APPLICATION_IS_SERVICE;
460  GError *error = NULL;
461  int status;
462 
463  g_set_prgname ("evince-daemon");
464 
465  application = g_object_new (EV_TYPE_DAEMON_APPLICATION,
466  "application-id", EV_DBUS_DAEMON_NAME,
467  "flags", flags,
468  NULL);
469  g_application_set_inactivity_timeout (application, DAEMON_TIMEOUT);
470 
471  if (!g_application_register (application, NULL, &error)) {
472  g_printerr ("Failed to register: %s\n", error->message);
473  g_error_free (error);
474  g_object_unref (application);
475 
476  return 1;
477  }
478 
479  status = g_application_run (application, 0, NULL);
480  g_object_unref (application);
481 
482  return status;
483 }
static void name_appeared_cb ( GDBusConnection *  connection,
const gchar *  name,
const gchar *  name_owner,
gpointer  user_data 
)
static

Definition at line 133 of file ev-daemon.c.

137 {
138  LOG ("Watch name'%s' appeared with owner '%s'", name, name_owner);
139 }

+ Here is the caller graph for this function:

static void name_vanished_cb ( GDBusConnection *  connection,
const gchar *  name,
gpointer  user_data 
)
static

Definition at line 142 of file ev-daemon.c.

145 {
146  EvDaemonApplication *application = EV_DAEMON_APPLICATION (user_data);
147  GList *l;
148 
149  LOG ("Watch name'%s' disappeared", name);
150 
151  for (l = application->docs; l != NULL; l = l->next) {
152  EvDoc *doc = (EvDoc *) l->data;
153 
154  if (strcmp (doc->dbus_name, name) != 0)
155  continue;
156 
157  LOG ("Watch found URI '%s' for name; removing", doc->uri);
158 
159  application->docs = g_list_delete_link (application->docs, l);
160  ev_doc_free (doc);
161 
162  g_application_release (G_APPLICATION (application));
163 
164  return;
165  }
166 }

+ Here is the caller graph for this function:

static void process_pending_invocations ( EvDaemonApplication application,
const gchar *  uri,
const gchar *  dbus_name 
)
static

Definition at line 169 of file ev-daemon.c.

172 {
173  GList *l;
174  GList *uri_invocations;
175 
176  LOG ("RegisterDocument process pending invocations for URI %s", uri);
177  uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);
178 
179  for (l = uri_invocations; l != NULL; l = l->next) {
180  GDBusMethodInvocation *invocation;
181 
182  invocation = (GDBusMethodInvocation *)l->data;
183  g_dbus_method_invocation_return_value (invocation,
184  g_variant_new ("(s)", dbus_name));
185  }
186 
187  g_list_free (uri_invocations);
188  g_hash_table_remove (application->pending_invocations, uri);
189 }

+ Here is the caller graph for this function:

static gboolean spawn_evince ( const gchar *  uri)
static

Definition at line 110 of file ev-daemon.c.

111 {
112  gchar *argv[3];
113  gboolean retval;
114  GError *error = NULL;
115 
116  /* TODO Check that the uri exists */
117  argv[0] = g_build_filename (BINDIR, "evince", NULL);
118  argv[1] = (gchar *) uri;
119  argv[2] = NULL;
120 
121  retval = g_spawn_async (NULL /* wd */, argv, NULL /* env */,
122  0, NULL, NULL, NULL, &error);
123  if (!retval) {
124  g_printerr ("Error spawning evince for uri %s: %s\n", uri, error->message);
125  g_error_free (error);
126  }
127  g_free (argv[0]);
128 
129  return retval;
130 }

+ Here is the caller graph for this function: