~ubuntu-branches/ubuntu/precise/libzeitgeist/precise

« back to all changes in this revision

Viewing changes to src/zeitgeist-log.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-06-24 20:38:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100624203823-7a6qwx798gz257mj
Tags: upstream-0.2.2
ImportĀ upstreamĀ versionĀ 0.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010 Canonical, Ltd.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU Lesser General Public License
 
6
 * version 3.0 as published by the Free Software Foundation.
 
7
 *
 
8
 * This library is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU Lesser General Public License version 3.0 for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public
 
14
 * License along with this library. If not, see
 
15
 * <http://www.gnu.org/licenses/>.
 
16
 *
 
17
 * Authored by
 
18
 *             Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
 
19
 */
 
20
 
 
21
#if HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#include "zeitgeist-log.h"
 
26
#include "zeitgeist-simple-result-set.h"
 
27
#include "zeitgeist-eggdbusconversions.h"
 
28
#include "eggzeitgeistbindings.h"
 
29
 
 
30
/**
 
31
 * SECTION:zeitgeist-log
 
32
 * @short_description: Primary access point for talking to the Zeitgeist daemon
 
33
 * @include: zeitgeist.h
 
34
 *
 
35
 * #ZeitgeistLog encapsulates the low level access to the Zeitgeist daemon.
 
36
 * You can use it to manage the log by inserting and deleting entries as well
 
37
 * as do queries on the logged data.
 
38
 *
 
39
 * It's important to realize that the #ZeitgeistLog class does not expose
 
40
 * any API that does synchronous communications with the message bus - 
 
41
 * everything is asynchronous. To ease development some of the methods have
 
42
 * variants that are "fire and forget" ignoring the normal return value, so
 
43
 * that callbacks does not have to be set up.
 
44
 */
 
45
 
 
46
G_DEFINE_TYPE (ZeitgeistLog, zeitgeist_log, G_TYPE_OBJECT);
 
47
#define ZEITGEIST_LOG_GET_PRIVATE(obj) \
 
48
  (G_TYPE_INSTANCE_GET_PRIVATE(obj, ZEITGEIST_TYPE_LOG, ZeitgeistLogPrivate))
 
49
 
 
50
typedef struct
 
51
{
 
52
  /* The connection to the ZG daemon
 
53
   * Note: The EggZeitgeistLog is owned by the EggDBusObjectProxy! */
 
54
  EggDBusObjectProxy *log_proxy;
 
55
  EggZeitgeistLog    *log;
 
56
 
 
57
  /* Hash set of ZeitgeistMonitors we've installed. We actually store
 
58
   * a map of (monitor, log) because this is most convenient for use with
 
59
   * _zeitgeist_monitor_weak_unref() casted to a GHFunc */
 
60
  GHashTable         *monitors;
 
61
} ZeitgeistLogPrivate;
 
62
 
 
63
/* Property ids */
 
64
enum
 
65
{
 
66
        PROP_0,
 
67
 
 
68
        LAST_PROPERTY
 
69
};
 
70
 
 
71
static void    _zeitgeist_log_on_name_owner_changed    (ZeitgeistLog    *self);
 
72
 
 
73
static void    _zeitgeist_log_on_monitor_destroyed     (ZeitgeistLog     *self,
 
74
                                                        ZeitgeistMonitor *monitor);
 
75
 
 
76
static void    _zeitgeist_monitor_weak_unref           (ZeitgeistMonitor *monitor,
 
77
                                                        ZeitgeistLog     *log);
 
78
 
 
79
/* Signature of egg_zeitgeist variants of find_events() and find_event_ids() */
 
80
typedef guint (*FindEventsFunc) (EggZeitgeistLog          *instance,
 
81
                                 EggDBusCallFlags          call_flags,
 
82
                                 EggZeitgeistTimeRange    *time_range,
 
83
                                 EggDBusArraySeq          *event_templates,
 
84
                                 EggZeitgeistStorageState  storage_state,
 
85
                                 guint                     num_events,
 
86
                                 EggZeitgeistResultType    result_type,
 
87
                                 GCancellable             *cancellable,
 
88
                                 GAsyncReadyCallback       callback,
 
89
                                 gpointer                  user_data);
 
90
 
 
91
/* Signature for egg_zeitgeist_log functions that send an array of event ids */
 
92
typedef guint (*SendEventIdsFunc) (EggZeitgeistLog          *instance,
 
93
                                   EggDBusCallFlags          call_flags,
 
94
                                   EggDBusArraySeq          *event_ids,
 
95
                                   GCancellable             *cancellable,
 
96
                                   GAsyncReadyCallback       callback,
 
97
                                   gpointer                  user_data);
 
98
 
 
99
/* Signature for egg_zeitgeist_log functions that does not have arguments  */
 
100
typedef guint (*SendVoidFunc) (EggZeitgeistLog          *instance,
 
101
                               EggDBusCallFlags          call_flags,
 
102
                               GCancellable             *cancellable,
 
103
                               GAsyncReadyCallback       callback,
 
104
                               gpointer                  user_data);
 
105
 
 
106
typedef gboolean (*CollectEventsFunc) (EggZeitgeistLog          *instance,
 
107
                                       EggDBusArraySeq         **out_events,
 
108
                                       GAsyncResult             *res,
 
109
                                       GError                  **error);
 
110
 
 
111
typedef gboolean (*CollectIdsFunc) (EggZeitgeistLog          *instance,
 
112
                                    EggDBusArraySeq         **out_event_ids,
 
113
                                    GAsyncResult             *res,
 
114
                                    GError                  **error);
 
115
 
 
116
typedef gboolean (*CollectVoidFunc) (EggZeitgeistLog          *instance,
 
117
                                     GAsyncResult             *res,
 
118
                                     GError                  **error);
 
119
 
 
120
static void
 
121
zeitgeist_log_init (ZeitgeistLog *self)
 
122
{
 
123
  ZeitgeistLogPrivate *priv;
 
124
  EggDBusConnection   *conn;
 
125
 
 
126
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
127
  
 
128
  /* Reset hash set of monitors */
 
129
  priv->monitors = g_hash_table_new (g_direct_hash, g_direct_equal);
 
130
  
 
131
  /* Set up the connection to the ZG daemon */  
 
132
  conn = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SESSION);
 
133
  priv->log_proxy = 
 
134
    egg_dbus_connection_get_object_proxy (conn,
 
135
                                          "org.gnome.zeitgeist.Engine",
 
136
                                          "/org/gnome/zeitgeist/log/activity");
 
137
  
 
138
  priv->log = EGG_ZEITGEIST_QUERY_INTERFACE_LOG (priv->log_proxy);
 
139
  g_object_unref (conn);
 
140
 
 
141
  /* We need to detect if the Zeitgeist daemon leaves/enters the bus */
 
142
  g_signal_connect_swapped (priv->log_proxy, "notify::name-owner",
 
143
                            G_CALLBACK (_zeitgeist_log_on_name_owner_changed),
 
144
                            self);
 
145
}
 
146
 
 
147
static void
 
148
zeitgeist_log_finalize (GObject *object)
 
149
{
 
150
  ZeitgeistLog *log = ZEITGEIST_LOG (object);
 
151
  ZeitgeistLogPrivate *priv;
 
152
  
 
153
  priv = ZEITGEIST_LOG_GET_PRIVATE (log);
 
154
 
 
155
  /* Note: priv->log is owned by priv->log_proxy */
 
156
  if (priv->log_proxy)
 
157
    {
 
158
      g_object_unref (priv->log_proxy);
 
159
    }
 
160
  
 
161
  /* Out list of monitors only holds weak refs to the monitors */
 
162
  if (priv->monitors)
 
163
    {
 
164
      g_hash_table_foreach (priv->monitors,
 
165
                            (GHFunc) _zeitgeist_monitor_weak_unref,
 
166
                            NULL);
 
167
      g_hash_table_unref (priv->monitors);
 
168
    }
 
169
  
 
170
  G_OBJECT_CLASS (zeitgeist_log_parent_class)->finalize (object); 
 
171
}
 
172
 
 
173
static void
 
174
zeitgeist_log_get_property (GObject    *object,
 
175
                            guint       prop_id,
 
176
                            GValue     *value,
 
177
                            GParamSpec *pspec)
 
178
{
 
179
  ZeitgeistLogPrivate *priv = ZEITGEIST_LOG_GET_PRIVATE (object);
 
180
 
 
181
  switch (prop_id)
 
182
    {
 
183
      default:
 
184
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
185
        return;
 
186
        break;
 
187
    }
 
188
}
 
189
 
 
190
static void
 
191
zeitgeist_log_set_property (GObject      *object,
 
192
                            guint         prop_id,
 
193
                            const GValue *value,
 
194
                            GParamSpec   *pspec)
 
195
{
 
196
  ZeitgeistLogPrivate *priv = ZEITGEIST_LOG_GET_PRIVATE (object);
 
197
 
 
198
  switch (prop_id)
 
199
    {
 
200
      default:
 
201
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
202
        return;
 
203
        break;
 
204
    }
 
205
}
 
206
 
 
207
 
 
208
static void
 
209
zeitgeist_log_class_init (ZeitgeistLogClass *klass)
 
210
{
 
211
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
212
  GParamSpec   *pspec;
 
213
  
 
214
  object_class->finalize     = zeitgeist_log_finalize;
 
215
  object_class->get_property = zeitgeist_log_get_property;
 
216
  object_class->set_property = zeitgeist_log_set_property;
 
217
  
 
218
  g_type_class_add_private (object_class, sizeof (ZeitgeistLogPrivate));
 
219
}
 
220
 
 
221
/* Used to marshal the async callbacks from EggDBus into ones
 
222
 * coming from this Log instance */
 
223
static void
 
224
dispatch_async_callback (GObject      *source_object,
 
225
                         GAsyncResult *res,
 
226
                         gpointer      user_data)
 
227
 
228
  gpointer            *data = (gpointer*) user_data;
 
229
  ZeitgeistLog        *self = ZEITGEIST_LOG (data[0]);
 
230
  GAsyncReadyCallback  callback = (GAsyncReadyCallback) data[1];
 
231
  gpointer             _user_data = data[2];
 
232
 
 
233
  if (callback != NULL)
 
234
    {
 
235
      callback (G_OBJECT (self), res, _user_data);
 
236
    }
 
237
  
 
238
  g_object_unref (self);
 
239
  g_free (user_data);
 
240
}
 
241
 
 
242
/*
 
243
 * API BELOW HERE
 
244
 */
 
245
 
 
246
/**
 
247
 * zeitgeist_log_new:
 
248
 * Create a new log that interfaces with the default event log of the Zeitgeist
 
249
 * daemon.
 
250
 *
 
251
 * Log instances are not overly expensive for neither client or the Zeitgeist
 
252
 * daemon so there's no need to go to lenghts to keep singleton instances
 
253
 * around.
 
254
 *
 
255
 * Returns: A reference to a newly allocated log.
 
256
 */
 
257
ZeitgeistLog*
 
258
zeitgeist_log_new (void)
 
259
{
 
260
  ZeitgeistLog        *log;
 
261
 
 
262
  log = (ZeitgeistLog*) g_object_new (ZEITGEIST_TYPE_LOG,
 
263
                                      NULL);
 
264
 
 
265
  return log;
 
266
}
 
267
 
 
268
/* Helper for _finish() functions that returns a GArray of event ids */
 
269
static gboolean
 
270
_zeitgeist_log_collect_event_ids (CollectIdsFunc       collect_ids_func,
 
271
                                  ZeitgeistLog        *self,
 
272
                                  GArray             **out_event_ids,
 
273
                                  GAsyncResult        *res,
 
274
                                  GError             **error)
 
275
{
 
276
  ZeitgeistLogPrivate   *priv;
 
277
  EggDBusArraySeq       *event_ids;
 
278
  gint                   len, i;
 
279
  guint32                event_id;
 
280
  gboolean               result;
 
281
 
 
282
  g_return_val_if_fail (ZEITGEIST_IS_LOG (self), FALSE);
 
283
  g_return_val_if_fail (out_event_ids != NULL, FALSE);
 
284
  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
 
285
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
286
 
 
287
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
288
 
 
289
  result = collect_ids_func (priv->log,
 
290
                             &event_ids,
 
291
                             res,
 
292
                             error);
 
293
  
 
294
  if (!result)
 
295
    {
 
296
      return FALSE;
 
297
    }
 
298
 
 
299
  len = egg_dbus_array_seq_get_size (event_ids);
 
300
  *out_event_ids = g_array_sized_new (FALSE, FALSE, sizeof (guint32), len);
 
301
  for (i = 0; i < len; i++)
 
302
    {
 
303
      event_id = egg_dbus_array_seq_get_fixed (event_ids, i);
 
304
      g_array_append_val (*out_event_ids, event_id);
 
305
                                
 
306
    }
 
307
  
 
308
  g_object_unref (event_ids);
 
309
  return TRUE;  
 
310
}
 
311
 
 
312
/* Helper for _finish() functions returning an array of events.
 
313
 * Set the free_func on @out_events to g_object_unref() */
 
314
static gboolean
 
315
_zeitgeist_log_collect_events (CollectEventsFunc    collect_events_func,
 
316
                               ZeitgeistLog        *self,
 
317
                               GPtrArray          **out_events,
 
318
                               GAsyncResult        *res,
 
319
                               GError             **error)
 
320
{
 
321
  ZeitgeistLogPrivate   *priv;
 
322
  EggDBusArraySeq       *events;
 
323
  gboolean               result;
 
324
 
 
325
  g_return_val_if_fail (ZEITGEIST_IS_LOG (self), FALSE);
 
326
  g_return_val_if_fail (out_events != NULL, FALSE);
 
327
  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
 
328
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
329
 
 
330
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
331
 
 
332
  result = collect_events_func (priv->log,
 
333
                                &events,
 
334
                                res,
 
335
                                error);
 
336
 
 
337
  if (!result)
 
338
    {
 
339
      return FALSE;
 
340
    }
 
341
 
 
342
  *out_events = _egg_zeitgeist_events_to_zeitgeist_events (events);
 
343
  g_ptr_array_set_free_func (*out_events, (GDestroyNotify) g_object_unref);
 
344
  
 
345
  g_object_unref (events);
 
346
  return TRUE;
 
347
}
 
348
 
 
349
/* Helper for _finish() functions without a return value */
 
350
static gboolean
 
351
_zeitgeist_log_collect_void (CollectVoidFunc collect_void,
 
352
                             ZeitgeistLog        *self,
 
353
                             GAsyncResult        *res,
 
354
                             GError             **error)
 
355
{
 
356
  ZeitgeistLogPrivate   *priv;
 
357
  EggDBusArraySeq       *events;
 
358
  gboolean               result;
 
359
 
 
360
  g_return_val_if_fail (ZEITGEIST_IS_LOG (self), FALSE);
 
361
  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
 
362
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
363
 
 
364
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
365
 
 
366
  return collect_void (priv->log, res, error);
 
367
}
 
368
 
 
369
/**
 
370
 * zeitgeist_log_insert_events:
 
371
 * @self: The log logging the events
 
372
 * @cancellable: To cancel the operation or %NULL
 
373
 * @callback: #GAsyncReadyCallback to invoke once the logging operation has
 
374
 *            completed. Set to %NULL to ignore the result. In this callback
 
375
 *            you can invoke zeitgeist_log_insert_events_finish() to collect
 
376
 *            the event ids of the inserted events
 
377
 * @user_data: Any user data to pass back to @callback
 
378
 * @VarArgs: A list of #ZeitgeistEvent<!-- -->s terminated by a %NULL
 
379
 *
 
380
 * Asynchrnously send a set of events to the Zeitgeist daemon, requesting they
 
381
 * be inserted into the log.
 
382
 */
 
383
void
 
384
zeitgeist_log_insert_events (ZeitgeistLog        *self,
 
385
                             GCancellable        *cancellable,
 
386
                             GAsyncReadyCallback  callback,
 
387
                             gpointer             user_data,
 
388
                             ...)
 
389
{
 
390
  va_list                events;
 
391
 
 
392
  va_start (events, user_data);
 
393
  zeitgeist_log_insert_events_valist (self, cancellable,
 
394
                                      callback, user_data, events);
 
395
  va_end (events);
 
396
}
 
397
 
 
398
/**
 
399
 * zeitgeist_log_insert_events_no_reply:
 
400
 * @self: The log logging the events
 
401
 * @VarArgs: A list of #ZeitgeistEvent<!-- -->s terminated by a %NULL
 
402
 *
 
403
 * Asynchrnously send a set of events to the Zeitgeist daemon, requesting they
 
404
 * be inserted into the log. This method is &quot;fire and forget&quot; and the
 
405
 * caller will never know whether the events was succesfully inserted or not.
 
406
 *
 
407
 * This method is exactly equivalent to calling zeitgeist_log_insert_events()
 
408
 * with %NULL set as @cancellable, @callback, and @user_data.
 
409
 */
 
410
void
 
411
zeitgeist_log_insert_events_no_reply (ZeitgeistLog *self,
 
412
                                      ...)
 
413
{
 
414
  va_list                events;
 
415
 
 
416
  va_start (events, self);
 
417
  zeitgeist_log_insert_events_valist (self, NULL, NULL, NULL, events);
 
418
  va_end (events);
 
419
}
 
420
 
 
421
/**
 
422
 * zeitgeist_log_insert_events_valist:
 
423
 * @self: The log logging the events
 
424
 * @cancellable: To cancel the operation or %NULL
 
425
 * @callback: #GAsyncReadyCallback to invoke once the logging operation has
 
426
 *            completed. Set to %NULL to ignore the result. In this callback
 
427
 *            you can invoke zeitgeist_log_insert_events_finish() to collect
 
428
 *            the event ids of the inserted events
 
429
 * @user_data: Any user data to pass back to @callback
 
430
 * @events: A #GPtrArray of #ZeitgeistEvent<!-- -->s to insert. This method
 
431
 *          steals the reference to @events and consumes all floating refs
 
432
 *          on the event members. It is assumed that the free_func on @events
 
433
 *          is set to g_object_unref().
 
434
 *
 
435
 * This method is intended for language bindings. If calling this function
 
436
 * from C code it's generally more handy to use zeitgeist_log_insert_events()
 
437
 * or zeitgeist_log_insert_events_from_ptrarray().
 
438
 * 
 
439
 * Asynchrnously send a set of events to the Zeitgeist daemon, requesting they
 
440
 * be inserted into the log.
 
441
 */
 
442
void
 
443
zeitgeist_log_insert_events_valist (ZeitgeistLog        *self,
 
444
                                    GCancellable        *cancellable,
 
445
                                    GAsyncReadyCallback  callback,
 
446
                                    gpointer             user_data,
 
447
                                    va_list              events)
 
448
{
 
449
  GPtrArray *_events;
 
450
 
 
451
  _events = _zeitgeist_events_from_valist (events);
 
452
  zeitgeist_log_insert_events_from_ptrarray (self, _events, cancellable,
 
453
                                             callback, user_data);
 
454
}
 
455
 
 
456
/**
 
457
 * zeitgeist_log_insert_events_from_ptrarray:
 
458
 * @self: The log logging the events
 
459
 * @events: A #GPtrArray of #ZeitgeistEvent<!-- -->s to insert. This method
 
460
 *          steals the reference to @events and consumes all floating refs
 
461
 *          on the event members. It is assumed that the free_func on @events
 
462
 *          is set to g_object_unref().
 
463
 * @cancellable: To cancel the operation or %NULL
 
464
 * @callback: #GAsyncReadyCallback to invoke once the logging operation has
 
465
 *            completed. Set to %NULL to ignore the result. In this callback
 
466
 *            you can invoke zeitgeist_log_insert_events_finish() to collect
 
467
 *            the event ids of the inserted events
 
468
 * @user_data: Any user data to pass back to @callback
 
469
 *
 
470
 * Asynchrnously send a set of events to the Zeitgeist daemon, requesting they
 
471
 * be inserted into the log.
 
472
 */
 
473
void
 
474
zeitgeist_log_insert_events_from_ptrarray (ZeitgeistLog        *self,
 
475
                                           GPtrArray           *events,
 
476
                                           GCancellable        *cancellable,
 
477
                                           GAsyncReadyCallback  callback,
 
478
                                           gpointer             user_data)
 
479
{
 
480
  ZeitgeistLogPrivate   *priv;
 
481
  EggDBusArraySeq       *_events;
 
482
  gpointer              *dispatch_data;
 
483
 
 
484
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
485
  g_return_if_fail (events != NULL);
 
486
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
487
 
 
488
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
489
 
 
490
  /* Own all floating refs on the events */
 
491
  g_ptr_array_foreach (events, (GFunc) g_object_ref_sink, NULL);
 
492
  
 
493
  _events = _zeitgeist_events_to_egg_zeitgeist_events (events);
 
494
 
 
495
  dispatch_data = g_new (gpointer, 3);
 
496
  dispatch_data[0] = g_object_ref (self);
 
497
  dispatch_data[1] = callback;
 
498
  dispatch_data[2] = user_data;
 
499
 
 
500
  egg_zeitgeist_log_insert_events (priv->log,
 
501
                                   EGG_DBUS_CALL_FLAGS_NONE,
 
502
                                   _events,
 
503
                                   cancellable,
 
504
                                   dispatch_async_callback,
 
505
                                   dispatch_data);
 
506
                                 
 
507
  /* Release the events */
 
508
  g_ptr_array_unref (events);
 
509
  g_object_unref (_events);
 
510
 
 
511
}
 
512
 
 
513
GArray*
 
514
zeitgeist_log_insert_events_finish (ZeitgeistLog        *self,
 
515
                                    GAsyncResult        *res,
 
516
                                    GError             **error)
 
517
{
 
518
  GArray *event_ids;
 
519
 
 
520
  _zeitgeist_log_collect_event_ids (egg_zeitgeist_log_insert_events_finish,
 
521
                                    self, &event_ids, res, error);
 
522
  return event_ids;
 
523
}
 
524
 
 
525
/* Shared helper for dispatching find_events() and find_event_ids() */
 
526
static void
 
527
_zeitgeist_log_find_events_with_func (FindEventsFunc       find_events_func,
 
528
                                      ZeitgeistLog        *self,
 
529
                                      ZeitgeistTimeRange  *time_range,
 
530
                                      GPtrArray           *event_templates,
 
531
                                      ZeitgeistStorageState storage_state,
 
532
                                      guint32              num_events,
 
533
                                      ZeitgeistResultType  result_type,
 
534
                                      GCancellable        *cancellable,
 
535
                                      GAsyncReadyCallback  callback,
 
536
                                      gpointer             user_data)                                      
 
537
{
 
538
  ZeitgeistLogPrivate   *priv;
 
539
  EggZeitgeistTimeRange *_time_range;
 
540
  EggDBusArraySeq       *_event_templates;
 
541
  gpointer              *dispatch_data;
 
542
 
 
543
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
544
  g_return_if_fail (ZEITGEIST_IS_TIME_RANGE (time_range));
 
545
  g_return_if_fail (event_templates != NULL);
 
546
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
547
 
 
548
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
549
 
 
550
  /* Own all floating refs on the events and the time_range */
 
551
  g_ptr_array_foreach (event_templates, (GFunc) g_object_ref_sink, NULL);
 
552
  g_object_ref_sink (time_range);
 
553
  
 
554
  _time_range = _zeitgeist_time_range_to_egg_zeitgeist_time_range (time_range);
 
555
  _event_templates = _zeitgeist_events_to_egg_zeitgeist_events (event_templates);
 
556
 
 
557
  dispatch_data = g_new (gpointer, 3);
 
558
  dispatch_data[0] = g_object_ref (self);
 
559
  dispatch_data[1] = callback;
 
560
  dispatch_data[2] = user_data;
 
561
 
 
562
  find_events_func (priv->log,
 
563
                    EGG_DBUS_CALL_FLAGS_NONE,
 
564
                    _time_range,
 
565
                    _event_templates,
 
566
                    (EggZeitgeistStorageState) storage_state,
 
567
                    num_events,
 
568
                    (EggZeitgeistResultType) result_type,
 
569
                    cancellable,
 
570
                    dispatch_async_callback,
 
571
                    dispatch_data);
 
572
                                 
 
573
  /* Release the event templates */
 
574
  g_ptr_array_foreach (event_templates, (GFunc) g_object_unref, NULL);
 
575
  g_ptr_array_unref (event_templates);
 
576
  g_object_unref (time_range);
 
577
  g_object_unref (_event_templates);
 
578
  g_object_unref (_time_range);
 
579
}
 
580
 
 
581
void
 
582
zeitgeist_log_find_events (ZeitgeistLog        *self,
 
583
                           ZeitgeistTimeRange  *time_range,
 
584
                           GPtrArray           *event_templates,
 
585
                           ZeitgeistStorageState storage_state,
 
586
                           guint32              num_events,
 
587
                           ZeitgeistResultType  result_type,
 
588
                           GCancellable        *cancellable,
 
589
                           GAsyncReadyCallback  callback,
 
590
                           gpointer             user_data)
 
591
{
 
592
  _zeitgeist_log_find_events_with_func (egg_zeitgeist_log_find_events,
 
593
                                        self,
 
594
                                        time_range,
 
595
                                        event_templates,
 
596
                                        storage_state,
 
597
                                        num_events,
 
598
                                        result_type,
 
599
                                        cancellable,
 
600
                                        callback,
 
601
                                        user_data);
 
602
}
 
603
 
 
604
/**
 
605
 * zeitgeist_log_find_events_finish:
 
606
 * @self:
 
607
 * @res:
 
608
 * @error:
 
609
 *
 
610
 * Retrieve the result from an asynchronous query started with
 
611
 * zeitgeist_log_find_events().
 
612
 *
 
613
 * Returns: (transfer-full): A newly allocated #ZeitgeistResultSet containing
 
614
 *          the #ZeitgeistEvent<!-- -->s
 
615
 *          matching the query. You must free the result set with
 
616
 *          g_object_unref(). The events held in the result set will
 
617
 *          automatically be unreffed when the result set is finalized.
 
618
 */
 
619
ZeitgeistResultSet*
 
620
zeitgeist_log_find_events_finish (ZeitgeistLog        *self,
 
621
                                  GAsyncResult        *res,
 
622
                                  GError             **error)
 
623
{
 
624
  GPtrArray *events;
 
625
  
 
626
  _zeitgeist_log_collect_events (egg_zeitgeist_log_find_events_finish,
 
627
                                 self, &events, res, error);
 
628
  return _zeitgeist_simple_result_set_new (events, events->len);
 
629
}
 
630
 
 
631
void
 
632
zeitgeist_log_find_event_ids (ZeitgeistLog        *self,
 
633
                              ZeitgeistTimeRange  *time_range,
 
634
                              GPtrArray           *event_templates,
 
635
                              ZeitgeistStorageState storage_state,
 
636
                              guint32              num_events,
 
637
                              ZeitgeistResultType  result_type,
 
638
                              GCancellable        *cancellable,
 
639
                              GAsyncReadyCallback  callback,
 
640
                              gpointer             user_data)
 
641
{
 
642
  _zeitgeist_log_find_events_with_func (egg_zeitgeist_log_find_event_ids,
 
643
                                        self,
 
644
                                        time_range,
 
645
                                        event_templates,
 
646
                                        storage_state,
 
647
                                        num_events,
 
648
                                        result_type,
 
649
                                        cancellable,
 
650
                                        callback,
 
651
                                        user_data);
 
652
}
 
653
 
 
654
GArray*
 
655
zeitgeist_log_find_event_ids_finish (ZeitgeistLog        *self,
 
656
                                     GAsyncResult        *res,
 
657
                                     GError             **error)
 
658
{
 
659
  GArray *event_ids;
 
660
  
 
661
  _zeitgeist_log_collect_event_ids (egg_zeitgeist_log_find_event_ids_finish,
 
662
                                    self, &event_ids, res, error);
 
663
  return event_ids;
 
664
}
 
665
 
 
666
static void
 
667
_zeitgeist_log_send_event_ids (SendEventIdsFunc     send_event_ids,
 
668
                               ZeitgeistLog        *self,
 
669
                               GArray              *event_ids,
 
670
                               GCancellable        *cancellable,
 
671
                               GAsyncReadyCallback  callback,
 
672
                               gpointer             user_data)
 
673
{
 
674
  ZeitgeistLogPrivate   *priv;
 
675
  EggDBusArraySeq       *_event_ids;
 
676
  gpointer              *dispatch_data;
 
677
  gint                   i;
 
678
 
 
679
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
680
  g_return_if_fail (event_ids != NULL);
 
681
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
682
 
 
683
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
684
 
 
685
  /* Convert GArray<guint32> to EggDBusArraySeq<guint> */
 
686
  _event_ids = egg_dbus_array_seq_new (G_TYPE_UINT, NULL, NULL, NULL);
 
687
  for (i = 0; i < event_ids->len; i++)
 
688
    {
 
689
      egg_dbus_array_seq_add_fixed (_event_ids,
 
690
                                    g_array_index (event_ids, guint32, i));
 
691
    }
 
692
 
 
693
  dispatch_data = g_new (gpointer, 3);
 
694
  dispatch_data[0] = g_object_ref (self);
 
695
  dispatch_data[1] = callback;
 
696
  dispatch_data[2] = user_data;
 
697
 
 
698
  send_event_ids (priv->log,
 
699
                  EGG_DBUS_CALL_FLAGS_NONE,
 
700
                  _event_ids,
 
701
                  cancellable,
 
702
                  dispatch_async_callback,
 
703
                  dispatch_data);
 
704
                                 
 
705
  /* Release the event ids */
 
706
  g_array_unref (event_ids);
 
707
  g_object_unref (_event_ids);
 
708
}
 
709
 
 
710
void
 
711
zeitgeist_log_get_events (ZeitgeistLog        *self,
 
712
                          GArray              *event_ids,
 
713
                          GCancellable        *cancellable,
 
714
                          GAsyncReadyCallback  callback,
 
715
                          gpointer             user_data)
 
716
{
 
717
  _zeitgeist_log_send_event_ids (egg_zeitgeist_log_get_events,
 
718
                                 self, event_ids, cancellable,
 
719
                                 callback, user_data);
 
720
}
 
721
 
 
722
ZeitgeistResultSet*
 
723
zeitgeist_log_get_events_finish (ZeitgeistLog        *self,
 
724
                                 GAsyncResult        *res,
 
725
                                 GError             **error)
 
726
{
 
727
  GPtrArray *events;
 
728
  
 
729
  _zeitgeist_log_collect_events (egg_zeitgeist_log_get_events_finish,
 
730
                                 self, &events, res, error);
 
731
  return _zeitgeist_simple_result_set_new (events, events->len);
 
732
}                          
 
733
 
 
734
void
 
735
zeitgeist_log_delete_events (ZeitgeistLog        *self,
 
736
                             GArray              *event_ids,
 
737
                             GCancellable        *cancellable,
 
738
                             GAsyncReadyCallback  callback,
 
739
                             gpointer             user_data)
 
740
{
 
741
  _zeitgeist_log_send_event_ids (egg_zeitgeist_log_delete_events,
 
742
                                 self, event_ids, cancellable,
 
743
                                 callback, user_data);
 
744
}
 
745
 
 
746
gboolean
 
747
zeitgeist_log_delete_events_finish (ZeitgeistLog        *self,
 
748
                                    GAsyncResult        *res,
 
749
                                    GError             **error)
 
750
{
 
751
  return _zeitgeist_log_collect_void (egg_zeitgeist_log_delete_events_finish,
 
752
                                      self, res, error);
 
753
}
 
754
 
 
755
void
 
756
zeitgeist_log_find_related_uris (ZeitgeistLog        *self,
 
757
                                 ZeitgeistTimeRange  *time_range,
 
758
                                 GPtrArray           *event_templates,
 
759
                                 GPtrArray           *result_event_templates,
 
760
                                 ZeitgeistStorageState storage_state,
 
761
                                 guint32              num_events,
 
762
                                 ZeitgeistResultType  result_type,
 
763
                                 GCancellable        *cancellable,
 
764
                                 GAsyncReadyCallback  callback,
 
765
                                 gpointer             user_data)
 
766
{
 
767
  ZeitgeistLogPrivate   *priv;
 
768
  EggZeitgeistTimeRange *_time_range;
 
769
  EggDBusArraySeq       *_event_templates, *_result_event_templates;
 
770
  gpointer              *dispatch_data;
 
771
 
 
772
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
773
  g_return_if_fail (ZEITGEIST_IS_TIME_RANGE (time_range));
 
774
  g_return_if_fail (event_templates != NULL);
 
775
  g_return_if_fail (result_event_templates != NULL);
 
776
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
777
 
 
778
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
779
 
 
780
  /* Own all floating refs on the events and the time_range */
 
781
  g_ptr_array_foreach (event_templates, (GFunc) g_object_ref_sink, NULL);
 
782
  g_ptr_array_foreach (result_event_templates, (GFunc) g_object_ref_sink, NULL);
 
783
  g_object_ref_sink (time_range);
 
784
  
 
785
  _time_range = _zeitgeist_time_range_to_egg_zeitgeist_time_range (time_range);
 
786
  _event_templates = _zeitgeist_events_to_egg_zeitgeist_events (event_templates);
 
787
  _result_event_templates = _zeitgeist_events_to_egg_zeitgeist_events (event_templates);
 
788
 
 
789
  dispatch_data = g_new (gpointer, 3);
 
790
  dispatch_data[0] = g_object_ref (self);
 
791
  dispatch_data[1] = callback;
 
792
  dispatch_data[2] = user_data;
 
793
 
 
794
  egg_zeitgeist_log_find_related_uris (priv->log,
 
795
                                       EGG_DBUS_CALL_FLAGS_NONE,
 
796
                                       _time_range,
 
797
                                       _event_templates,
 
798
                                       _result_event_templates,
 
799
                                       (EggZeitgeistStorageState) storage_state,
 
800
                                       num_events,
 
801
                                       (EggZeitgeistResultType) result_type,
 
802
                                       cancellable,
 
803
                                       dispatch_async_callback,
 
804
                                       dispatch_data);
 
805
                                 
 
806
  /* Release the event templates */
 
807
  g_ptr_array_foreach (event_templates, (GFunc) g_object_unref, NULL);
 
808
  g_ptr_array_foreach (result_event_templates, (GFunc) g_object_unref, NULL);
 
809
  g_ptr_array_unref (event_templates);
 
810
  g_ptr_array_unref (result_event_templates);
 
811
  g_object_unref (time_range);
 
812
  g_object_unref (_event_templates);
 
813
  g_object_unref (_result_event_templates);
 
814
  g_object_unref (_time_range);
 
815
}
 
816
 
 
817
gchar**
 
818
zeitgeist_log_find_related_uris_finish (ZeitgeistLog    *self,
 
819
                                        GAsyncResult    *res,
 
820
                                        GError         **error)
 
821
{
 
822
  ZeitgeistLogPrivate   *priv;
 
823
  gboolean               result;
 
824
  gchar                **uris;
 
825
 
 
826
  g_return_val_if_fail (ZEITGEIST_IS_LOG (self), FALSE);
 
827
  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
 
828
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
829
 
 
830
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
831
 
 
832
  egg_zeitgeist_log_find_related_uris_finish (priv->log,
 
833
                                              &uris,
 
834
                                              res,
 
835
                                              error);
 
836
 
 
837
  return uris;
 
838
}
 
839
 
 
840
static void
 
841
_zeitgeist_log_send_void (SendVoidFunc send_void,
 
842
                          ZeitgeistLog        *self,
 
843
                          GCancellable        *cancellable,
 
844
                          GAsyncReadyCallback  callback,
 
845
                          gpointer             user_data)
 
846
{
 
847
  ZeitgeistLogPrivate   *priv;
 
848
  gpointer              *dispatch_data;
 
849
 
 
850
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
851
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
852
 
 
853
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
854
 
 
855
  dispatch_data = g_new (gpointer, 3);
 
856
  dispatch_data[0] = g_object_ref (self);
 
857
  dispatch_data[1] = callback;
 
858
  dispatch_data[2] = user_data;
 
859
 
 
860
  send_void (priv->log,
 
861
             EGG_DBUS_CALL_FLAGS_NONE,
 
862
             cancellable,
 
863
             dispatch_async_callback,
 
864
             dispatch_data);
 
865
}
 
866
 
 
867
void
 
868
zeitgeist_log_delete_log (ZeitgeistLog        *self,
 
869
                          GCancellable        *cancellable,
 
870
                          GAsyncReadyCallback  callback,
 
871
                          gpointer             user_data)
 
872
{
 
873
  _zeitgeist_log_send_void (egg_zeitgeist_log_delete_log,
 
874
                            self, cancellable, callback, user_data);
 
875
}
 
876
 
 
877
gboolean
 
878
zeitgeist_log_delete_log_finish (ZeitgeistLog        *self,
 
879
                                 GAsyncResult        *res,
 
880
                                 GError             **error)
 
881
{
 
882
  _zeitgeist_log_collect_void (egg_zeitgeist_log_delete_log_finish,
 
883
                               self, res, error);
 
884
}
 
885
 
 
886
void
 
887
zeitgeist_log_quit (ZeitgeistLog        *self,
 
888
                    GCancellable        *cancellable,
 
889
                    GAsyncReadyCallback  callback,
 
890
                    gpointer             user_data)
 
891
{
 
892
  _zeitgeist_log_send_void (egg_zeitgeist_log_quit,
 
893
                            self, cancellable, callback, user_data);
 
894
}
 
895
 
 
896
gboolean
 
897
zeitgeist_log_quit_finish (ZeitgeistLog        *self,
 
898
                           GAsyncResult        *res,
 
899
                           GError             **error)
 
900
{
 
901
  _zeitgeist_log_collect_void (egg_zeitgeist_log_quit_finish,
 
902
                               self, res, error);
 
903
}
 
904
 
 
905
static void
 
906
_zeitgeist_log_install_monitor (ZeitgeistLog        *self,
 
907
                                ZeitgeistMonitor    *monitor,
 
908
                                GCancellable        *cancellable,
 
909
                                GAsyncReadyCallback  callback,
 
910
                                gpointer             user_data)
 
911
{
 
912
  ZeitgeistLogPrivate   *priv;
 
913
  EggZeitgeistTimeRange *_time_range;
 
914
  EggDBusArraySeq       *_event_templates;
 
915
  EggDBusConnection     *connection;
 
916
  gpointer              *dispatch_data;
 
917
 
 
918
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
919
 
 
920
  /* Export the monitor, client side, on the session bus. Once the last
 
921
   * ref to the monitor is dropped eggdbus will automatically unregister it */
 
922
  connection = egg_dbus_object_proxy_get_connection (priv->log_proxy);
 
923
  egg_dbus_connection_register_interface (connection,
 
924
                                          zeitgeist_monitor_get_path (monitor),
 
925
                                          EGG_ZEITGEIST_TYPE_MONITOR,
 
926
                                          monitor,
 
927
                                          G_TYPE_INVALID);
 
928
  
 
929
  /* Register the monitor with the ZG daemon */
 
930
  _time_range = _zeitgeist_time_range_to_egg_zeitgeist_time_range (
 
931
                                    zeitgeist_monitor_get_time_range (monitor));
 
932
  _event_templates = _zeitgeist_events_to_egg_zeitgeist_events (
 
933
                                     zeitgeist_monitor_get_templates (monitor));
 
934
 
 
935
  dispatch_data = g_new (gpointer, 3);
 
936
  dispatch_data[0] = g_object_ref (self);
 
937
  dispatch_data[1] = callback;
 
938
  dispatch_data[2] = user_data;
 
939
 
 
940
  egg_zeitgeist_log_install_monitor (priv->log,
 
941
                                     EGG_DBUS_CALL_FLAGS_NONE,
 
942
                                     zeitgeist_monitor_get_path (monitor),
 
943
                                     _time_range,
 
944
                                     _event_templates,
 
945
                                     cancellable,
 
946
                                     dispatch_async_callback,
 
947
                                     dispatch_data);
 
948
                                 
 
949
  /* Release the event templates */
 
950
  g_object_unref (_event_templates);
 
951
  g_object_unref (_time_range);
 
952
}
 
953
 
 
954
void
 
955
zeitgeist_log_install_monitor (ZeitgeistLog        *self,
 
956
                               ZeitgeistMonitor    *monitor,
 
957
                               GCancellable        *cancellable,
 
958
                               GAsyncReadyCallback  callback,
 
959
                               gpointer             user_data)
 
960
{
 
961
  ZeitgeistLogPrivate   *priv;
 
962
  
 
963
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
964
  g_return_if_fail (ZEITGEIST_IS_MONITOR (monitor));
 
965
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
966
 
 
967
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
968
  
 
969
  /* Track the monitor so we can reinstate it if the Zeitgeist daemon
 
970
   * leaves and reappears on the bus */
 
971
  g_object_weak_ref (G_OBJECT (monitor),
 
972
                     (GWeakNotify) _zeitgeist_log_on_monitor_destroyed,
 
973
                     self);
 
974
  g_hash_table_insert (priv->monitors, monitor, monitor);
 
975
 
 
976
  _zeitgeist_log_install_monitor (self, monitor,
 
977
                                  cancellable, callback, user_data);
 
978
}
 
979
 
 
980
gboolean
 
981
zeitgeist_log_install_monitor_finish (ZeitgeistLog      *self,
 
982
                                      GAsyncResult      *res,
 
983
                                      GError           **error)
 
984
{
 
985
  return _zeitgeist_log_collect_void (egg_zeitgeist_log_install_monitor_finish,
 
986
                                      self, res, error);
 
987
}
 
988
 
 
989
void
 
990
zeitgeist_log_remove_monitor (ZeitgeistLog        *self,
 
991
                              ZeitgeistMonitor    *monitor,
 
992
                              GCancellable        *cancellable,
 
993
                              GAsyncReadyCallback  callback,
 
994
                              gpointer             user_data)
 
995
{
 
996
  ZeitgeistLogPrivate   *priv;
 
997
  EggDBusConnection     *connection;
 
998
  gpointer              *dispatch_data;
 
999
 
 
1000
  g_return_if_fail (ZEITGEIST_IS_LOG (self));
 
1001
  g_return_if_fail (ZEITGEIST_IS_MONITOR (monitor));
 
1002
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE(cancellable));
 
1003
 
 
1004
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
1005
 
 
1006
  /* Retract the monitor from the session bus */
 
1007
  connection = egg_dbus_object_proxy_get_connection (priv->log_proxy);
 
1008
  egg_dbus_connection_unregister_interface (connection,
 
1009
                                            zeitgeist_monitor_get_path (monitor),
 
1010
                                            EGG_ZEITGEIST_TYPE_MONITOR,
 
1011
                                            G_TYPE_INVALID);
 
1012
  
 
1013
  dispatch_data = g_new (gpointer, 3);
 
1014
  dispatch_data[0] = g_object_ref (self);
 
1015
  dispatch_data[1] = callback;
 
1016
  dispatch_data[2] = user_data;
 
1017
 
 
1018
  egg_zeitgeist_log_remove_monitor (priv->log,
 
1019
                                    EGG_DBUS_CALL_FLAGS_NONE,
 
1020
                                    zeitgeist_monitor_get_path (monitor),
 
1021
                                    cancellable,
 
1022
                                    dispatch_async_callback,
 
1023
                                    dispatch_data);
 
1024
}
 
1025
 
 
1026
gboolean
 
1027
zeitgeist_log_remove_monitor_finish (ZeitgeistLog       *self,
 
1028
                                     GAsyncResult       *res,
 
1029
                                     GError            **error)
 
1030
{
 
1031
  return _zeitgeist_log_collect_void (egg_zeitgeist_log_remove_monitor_finish,
 
1032
                                      self, res, error);
 
1033
}
 
1034
 
 
1035
/* Helper for dropping a weak ref from a log on a monitor. The method
 
1036
 * signature makes it suitable for casting to a GHFunc */
 
1037
static void
 
1038
_zeitgeist_monitor_weak_unref (ZeitgeistMonitor *monitor,
 
1039
                               ZeitgeistLog     *log)
 
1040
{
 
1041
  g_object_weak_unref (G_OBJECT (monitor),
 
1042
                       (GWeakNotify) _zeitgeist_log_on_monitor_destroyed,
 
1043
                       log);
 
1044
}
 
1045
 
 
1046
/* Called when a monitor is finalized, by virtue of our weak ref */
 
1047
static void
 
1048
_zeitgeist_log_on_monitor_destroyed (ZeitgeistLog     *self,
 
1049
                                     ZeitgeistMonitor *monitor)
 
1050
{
 
1051
  ZeitgeistLogPrivate *priv;
 
1052
  
 
1053
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
1054
  g_hash_table_remove (priv->monitors, monitor);
 
1055
}
 
1056
 
 
1057
/* Called when the Zeitgeist daemon enters/leaves the bus */
 
1058
static void
 
1059
_zeitgeist_log_on_name_owner_changed (ZeitgeistLog *self)
 
1060
{
 
1061
  ZeitgeistLogPrivate *priv;
 
1062
  gchar               *name_owner;
 
1063
  
 
1064
  priv = ZEITGEIST_LOG_GET_PRIVATE (self);
 
1065
  g_object_get (priv->log_proxy, "name-owner", &name_owner, NULL);
 
1066
  
 
1067
  if (name_owner == NULL)
 
1068
    {
 
1069
      /* The Zeitgeist daemon disconnected. Do nothing */
 
1070
    }
 
1071
  else
 
1072
    {
 
1073
      /* The Zeitgeist daemon entered the bus. Reinstate all active monitors */
 
1074
      GHashTableIter iter;
 
1075
      gpointer monitor, dummy;
 
1076
 
 
1077
      g_hash_table_iter_init (&iter, priv->monitors);
 
1078
      while (g_hash_table_iter_next (&iter, &monitor, &dummy)) 
 
1079
        {
 
1080
          _zeitgeist_log_install_monitor (self, ZEITGEIST_MONITOR (monitor), 
 
1081
                                          NULL, NULL, NULL);
 
1082
        }
 
1083
      g_free (name_owner);
 
1084
    }    
 
1085
}
 
 
b'\\ No newline at end of file'