~noskcaj/ubuntu/saucy/xfce4-power-manager/1.2.0-2ubuntu1

« back to all changes in this revision

Viewing changes to libdbus/xfpm-dbus-monitor.c

  • Committer: Bazaar Package Importer
  • Author(s): Lionel Le Folgoc
  • Date: 2010-12-09 18:28:34 UTC
  • mfrom: (2.3.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20101209182834-efb7dinmf9ssp3es
Tags: 1.0.1-0ubuntu1
Upload to natty (pkg-xfce svn r4665), no Ubuntu changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* * * Copyright (C) 2009 Ali <aliov@xfce.org>
 
2
 *
 
3
 * Licensed under the GNU General Public License Version 2
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include <config.h>
 
22
#endif
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
 
 
28
#include <glib.h>
 
29
 
 
30
#include <dbus/dbus.h>
 
31
#include <dbus/dbus-glib-lowlevel.h>
 
32
#include <dbus/dbus-glib.h>
 
33
 
 
34
#include <libxfce4util/libxfce4util.h>
 
35
 
 
36
#include "xfpm-dbus.h"
 
37
 
 
38
#include "xfpm-dbus-monitor.h"
 
39
#include "xfpm-dbus-marshal.h"
 
40
 
 
41
static void xfpm_dbus_monitor_finalize   (GObject *object);
 
42
 
 
43
#define XFPM_DBUS_MONITOR_GET_PRIVATE(o) \
 
44
(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_DBUS_MONITOR, XfpmDBusMonitorPrivate))
 
45
 
 
46
struct XfpmDBusMonitorPrivate
 
47
{
 
48
    DBusGConnection *system_bus;
 
49
    DBusGConnection *session_bus;
 
50
 
 
51
    DBusGProxy      *system_proxy;
 
52
    DBusGProxy      *session_proxy;
 
53
    
 
54
    GPtrArray       *names_array;
 
55
    GPtrArray       *services_array;
 
56
};
 
57
 
 
58
typedef struct
 
59
{
 
60
    gchar       *name;
 
61
    DBusBusType  bus_type;
 
62
    
 
63
} XfpmWatchData;
 
64
 
 
65
enum
 
66
{
 
67
    UNIQUE_NAME_LOST,
 
68
    SERVICE_CONNECTION_CHANGED,
 
69
    SYSTEM_BUS_CONNECTION_CHANGED,
 
70
    LAST_SIGNAL
 
71
};
 
72
 
 
73
static guint signals [LAST_SIGNAL] = { 0 };
 
74
 
 
75
G_DEFINE_TYPE (XfpmDBusMonitor, xfpm_dbus_monitor, G_TYPE_OBJECT)
 
76
 
 
77
static void
 
78
xfpm_dbus_monitor_free_watch_data (XfpmWatchData *data)
 
79
{
 
80
    g_free (data->name);
 
81
    g_free (data);
 
82
}
 
83
 
 
84
static XfpmWatchData *
 
85
xfpm_dbus_monitor_get_watch_data (GPtrArray *array, const gchar *name, DBusBusType bus_type)
 
86
{
 
87
    XfpmWatchData *data;
 
88
    guint i;
 
89
    
 
90
    for ( i = 0; i < array->len; i++)
 
91
    {
 
92
        data = g_ptr_array_index (array, i);
 
93
        if ( !g_strcmp0 (data->name, name) && data->bus_type == bus_type )
 
94
            return data;
 
95
    }
 
96
    return NULL;
 
97
}
 
98
 
 
99
static void
 
100
xfpm_dbus_monitor_unique_connection_name_lost (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *name)
 
101
{
 
102
    XfpmWatchData *watch;
 
103
    guint i = 0;
 
104
    
 
105
    for ( i = 0; i < monitor->priv->names_array->len; i++ )
 
106
    {
 
107
        watch = g_ptr_array_index (monitor->priv->names_array, i);
 
108
        
 
109
        if ( !g_strcmp0 (watch->name, name) && bus_type == watch->bus_type )
 
110
        {
 
111
            g_signal_emit (G_OBJECT(monitor), signals [UNIQUE_NAME_LOST], 0, 
 
112
                           watch->name, bus_type == DBUS_BUS_SESSION ? TRUE : FALSE);
 
113
            g_ptr_array_remove (monitor->priv->names_array, watch);
 
114
            xfpm_dbus_monitor_free_watch_data (watch);
 
115
        }
 
116
    }
 
117
}
 
118
 
 
119
static void
 
120
xfpm_dbus_monitor_service_connection_changed (XfpmDBusMonitor *monitor, DBusBusType bus_type, 
 
121
                                              const gchar *name, gboolean connected)
 
122
{
 
123
    XfpmWatchData *watch;
 
124
    guint i;
 
125
    
 
126
    for ( i = 0; i < monitor->priv->services_array->len; i++)
 
127
    {
 
128
        watch = g_ptr_array_index (monitor->priv->services_array, i);
 
129
        
 
130
        if ( !g_strcmp0 (watch->name, name) && watch->bus_type == bus_type)
 
131
        {
 
132
            g_signal_emit (G_OBJECT (monitor), signals [SERVICE_CONNECTION_CHANGED], 0,
 
133
                           name, connected, bus_type == DBUS_BUS_SESSION ? TRUE : FALSE);
 
134
        }
 
135
    }
 
136
}
 
137
 
 
138
static void
 
139
xfpm_dbus_monitor_name_owner_changed (XfpmDBusMonitor *monitor, const gchar *name,
 
140
                                      const gchar *prev, const gchar *new, DBusBusType bus_type)
 
141
{
 
142
    if ( strlen (prev) != 0 )
 
143
    {
 
144
        xfpm_dbus_monitor_unique_connection_name_lost (monitor, bus_type, prev);
 
145
        
 
146
        /* Connection has name */
 
147
        if ( strlen (name) != 0 )
 
148
            xfpm_dbus_monitor_service_connection_changed (monitor, bus_type, name, FALSE);
 
149
    }
 
150
    else if ( strlen (name) != 0 && strlen (new) != 0)
 
151
    {
 
152
        xfpm_dbus_monitor_service_connection_changed (monitor, bus_type, name, TRUE);
 
153
    }
 
154
}
 
155
 
 
156
static void
 
157
xfpm_dbus_monitor_session_name_owner_changed_cb (DBusGProxy *proxy, const gchar *name,
 
158
                                                 const gchar *prev, const gchar *new,
 
159
                                                 XfpmDBusMonitor *monitor)
 
160
{
 
161
    xfpm_dbus_monitor_name_owner_changed (monitor, name, prev, new, DBUS_BUS_SESSION);
 
162
}
 
163
 
 
164
static void
 
165
xfpm_dbus_monitor_system_name_owner_changed_cb  (DBusGProxy *proxy, const gchar *name,
 
166
                                                 const gchar *prev, const gchar *new,
 
167
                                                 XfpmDBusMonitor *monitor)
 
168
{
 
169
    xfpm_dbus_monitor_name_owner_changed (monitor, name, prev, new, DBUS_BUS_SYSTEM);
 
170
}
 
171
 
 
172
static gboolean
 
173
xfpm_dbus_monitor_query_system_bus_idle (gpointer data)
 
174
{
 
175
    XfpmDBusMonitor *monitor;
 
176
    DBusGConnection *bus;
 
177
    GError *error = NULL;
 
178
 
 
179
    bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 
180
    
 
181
    if ( error )
 
182
    {
 
183
        TRACE ("System bus is not connected  %s:", error->message);
 
184
        g_error_free (error);
 
185
        return TRUE;
 
186
    }
 
187
    
 
188
    monitor = XFPM_DBUS_MONITOR (data);
 
189
    g_signal_emit (G_OBJECT (monitor), signals [SYSTEM_BUS_CONNECTION_CHANGED], 0, TRUE);
 
190
    
 
191
    return FALSE;
 
192
}
 
193
 
 
194
static void
 
195
xfpm_dbus_monitor_setup_system_watch (XfpmDBusMonitor *monitor)
 
196
{
 
197
    g_timeout_add_seconds (2, (GSourceFunc) xfpm_dbus_monitor_query_system_bus_idle, monitor);
 
198
}
 
199
 
 
200
static DBusHandlerResult
 
201
xfpm_dbus_monitor_system_bus_filter (DBusConnection *bus, DBusMessage *message, void *data)
 
202
{
 
203
    XfpmDBusMonitor *monitor;
 
204
    
 
205
    if ( dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") )
 
206
    {
 
207
        TRACE ("System bus is disconnected");
 
208
        monitor = XFPM_DBUS_MONITOR (data);
 
209
        g_signal_emit (G_OBJECT (monitor), signals [SYSTEM_BUS_CONNECTION_CHANGED], 0, FALSE);
 
210
        
 
211
        xfpm_dbus_monitor_setup_system_watch (monitor);
 
212
        
 
213
        return DBUS_HANDLER_RESULT_HANDLED;
 
214
    }
 
215
    
 
216
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
217
}
 
218
 
 
219
static void
 
220
xfpm_dbus_monitor_session (XfpmDBusMonitor *monitor)
 
221
{
 
222
    monitor->priv->session_proxy = dbus_g_proxy_new_for_name_owner (monitor->priv->session_bus,
 
223
                                                                    "org.freedesktop.DBus",
 
224
                                                                    "/org/freedesktop/DBus",
 
225
                                                                    "org.freedesktop.DBus",
 
226
                                                                    NULL);
 
227
    if ( !monitor->priv->session_proxy )
 
228
    {
 
229
        g_critical ("Unable to create proxy on /org/freedesktop/DBus");
 
230
        return;
 
231
    }
 
232
    
 
233
    dbus_g_proxy_add_signal (monitor->priv->session_proxy, "NameOwnerChanged", 
 
234
                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 
235
                             
 
236
    dbus_g_proxy_connect_signal (monitor->priv->session_proxy, "NameOwnerChanged",
 
237
                                 G_CALLBACK (xfpm_dbus_monitor_session_name_owner_changed_cb), monitor, NULL);
 
238
}
 
239
 
 
240
static void
 
241
xfpm_dbus_monitor_system (XfpmDBusMonitor *monitor)
 
242
{
 
243
    monitor->priv->system_proxy = dbus_g_proxy_new_for_name_owner (monitor->priv->system_bus,
 
244
                                                                   "org.freedesktop.DBus",
 
245
                                                                   "/org/freedesktop/DBus",
 
246
                                                                   "org.freedesktop.DBus",
 
247
                                                                   NULL);
 
248
    if ( !monitor->priv->system_proxy )
 
249
    {
 
250
        g_critical ("Unable to create proxy on /org/freedesktop/DBus");
 
251
        return;
 
252
    }
 
253
    
 
254
    dbus_g_proxy_add_signal (monitor->priv->system_proxy, "NameOwnerChanged", 
 
255
                             G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 
256
                             
 
257
    dbus_g_proxy_connect_signal (monitor->priv->system_proxy, "NameOwnerChanged",
 
258
                                 G_CALLBACK (xfpm_dbus_monitor_system_name_owner_changed_cb), monitor, NULL);
 
259
}
 
260
 
 
261
static void
 
262
xfpm_dbus_monitor_class_init (XfpmDBusMonitorClass *klass)
 
263
{
 
264
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
265
 
 
266
    signals [UNIQUE_NAME_LOST] =
 
267
        g_signal_new ("unique-name-lost",
 
268
                      XFPM_TYPE_DBUS_MONITOR,
 
269
                      G_SIGNAL_RUN_LAST,
 
270
                      G_STRUCT_OFFSET (XfpmDBusMonitorClass, unique_name_lost),
 
271
                      NULL, NULL,
 
272
                      _xfpm_dbus_marshal_VOID__STRING_BOOLEAN,
 
273
                      G_TYPE_NONE, 2, 
 
274
                      G_TYPE_STRING, G_TYPE_BOOLEAN);
 
275
                     
 
276
    signals [SERVICE_CONNECTION_CHANGED] =
 
277
        g_signal_new ("service-connection-changed",
 
278
                      XFPM_TYPE_DBUS_MONITOR,
 
279
                      G_SIGNAL_RUN_LAST,
 
280
                      G_STRUCT_OFFSET (XfpmDBusMonitorClass, service_connection_changed),
 
281
                      NULL, NULL,
 
282
                      _xfpm_dbus_marshal_VOID__STRING_BOOLEAN_BOOLEAN,
 
283
                      G_TYPE_NONE, 3, G_TYPE_STRING,
 
284
                      G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
 
285
                      
 
286
    signals [SYSTEM_BUS_CONNECTION_CHANGED] =
 
287
        g_signal_new ("system-bus-connection-changed",
 
288
                      XFPM_TYPE_DBUS_MONITOR,
 
289
                      G_SIGNAL_RUN_LAST,
 
290
                      G_STRUCT_OFFSET (XfpmDBusMonitorClass, system_bus_connection_changed),
 
291
                      NULL, NULL,
 
292
                      g_cclosure_marshal_VOID__BOOLEAN,
 
293
                      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
294
                     
 
295
    object_class->finalize = xfpm_dbus_monitor_finalize;
 
296
 
 
297
    g_type_class_add_private (klass, sizeof (XfpmDBusMonitorPrivate));
 
298
}
 
299
 
 
300
static void
 
301
xfpm_dbus_monitor_init (XfpmDBusMonitor *monitor)
 
302
{
 
303
    monitor->priv = XFPM_DBUS_MONITOR_GET_PRIVATE (monitor);
 
304
    
 
305
    monitor->priv->session_proxy = NULL;
 
306
    monitor->priv->system_proxy  = NULL;
 
307
    
 
308
    monitor->priv->names_array = g_ptr_array_new ();
 
309
    monitor->priv->services_array = g_ptr_array_new ();
 
310
         
 
311
    monitor->priv->session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
 
312
    monitor->priv->system_bus  = dbus_g_bus_get (DBUS_BUS_SYSTEM,  NULL);
 
313
    
 
314
    xfpm_dbus_monitor_session (monitor);
 
315
    xfpm_dbus_monitor_system  (monitor);
 
316
    
 
317
    dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (monitor->priv->system_bus), 
 
318
                                            FALSE);
 
319
    
 
320
    dbus_connection_add_filter (dbus_g_connection_get_connection (monitor->priv->system_bus),
 
321
                                xfpm_dbus_monitor_system_bus_filter,
 
322
                                monitor, 
 
323
                                NULL);
 
324
}
 
325
 
 
326
static void
 
327
xfpm_dbus_monitor_finalize (GObject *object)
 
328
{
 
329
    XfpmDBusMonitor *monitor;
 
330
 
 
331
    monitor = XFPM_DBUS_MONITOR (object);
 
332
    
 
333
    if ( monitor->priv->session_proxy )
 
334
    {
 
335
        dbus_g_proxy_disconnect_signal (monitor->priv->session_proxy, "NameOwnerChanged",
 
336
                                        G_CALLBACK (xfpm_dbus_monitor_session_name_owner_changed_cb), monitor);
 
337
        g_object_unref (monitor->priv->session_proxy);
 
338
    }
 
339
 
 
340
    if ( monitor->priv->system_proxy )
 
341
    {
 
342
        dbus_g_proxy_disconnect_signal (monitor->priv->system_proxy, "NameOwnerChanged",
 
343
                                        G_CALLBACK (xfpm_dbus_monitor_system_name_owner_changed_cb), monitor);
 
344
        g_object_unref (monitor->priv->system_proxy);
 
345
    }
 
346
 
 
347
    dbus_connection_remove_filter (dbus_g_connection_get_connection (monitor->priv->system_bus),
 
348
                                   xfpm_dbus_monitor_system_bus_filter,
 
349
                                   monitor);
 
350
 
 
351
    dbus_g_connection_unref (monitor->priv->system_bus);
 
352
    dbus_g_connection_unref (monitor->priv->session_bus);
 
353
 
 
354
    g_ptr_array_foreach (monitor->priv->names_array, (GFunc) xfpm_dbus_monitor_free_watch_data, NULL);
 
355
    g_ptr_array_foreach (monitor->priv->services_array, (GFunc) xfpm_dbus_monitor_free_watch_data, NULL);
 
356
 
 
357
    g_ptr_array_free (monitor->priv->names_array, TRUE);
 
358
    g_ptr_array_free (monitor->priv->services_array, TRUE);
 
359
 
 
360
    G_OBJECT_CLASS (xfpm_dbus_monitor_parent_class)->finalize (object);
 
361
}
 
362
 
 
363
XfpmDBusMonitor *
 
364
xfpm_dbus_monitor_new (void)
 
365
{
 
366
    static gpointer xfpm_dbus_monitor_object = NULL;
 
367
    
 
368
    if ( G_LIKELY (xfpm_dbus_monitor_object != NULL) )
 
369
    {
 
370
        g_object_ref (xfpm_dbus_monitor_object);
 
371
    }
 
372
    else
 
373
    {
 
374
        xfpm_dbus_monitor_object = g_object_new (XFPM_TYPE_DBUS_MONITOR, NULL);
 
375
        g_object_add_weak_pointer (xfpm_dbus_monitor_object, &xfpm_dbus_monitor_object);
 
376
    }
 
377
    
 
378
    return XFPM_DBUS_MONITOR (xfpm_dbus_monitor_object);
 
379
}
 
380
 
 
381
gboolean xfpm_dbus_monitor_add_unique_name (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *unique_name)
 
382
{
 
383
    XfpmWatchData *watch;
 
384
    
 
385
    g_return_val_if_fail (XFPM_IS_DBUS_MONITOR (monitor), FALSE);
 
386
    g_return_val_if_fail (unique_name != NULL, FALSE);
 
387
    
 
388
    /* We have it already */
 
389
    if ( xfpm_dbus_monitor_get_watch_data (monitor->priv->names_array, unique_name, bus_type) )
 
390
        return FALSE;
 
391
        
 
392
    watch = g_new0 (XfpmWatchData , 1);
 
393
    watch->name = g_strdup (unique_name);
 
394
    watch->bus_type = bus_type;
 
395
    
 
396
    g_ptr_array_add (monitor->priv->names_array, watch);
 
397
    return TRUE;
 
398
}
 
399
 
 
400
void xfpm_dbus_monitor_remove_unique_name (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *unique_name)
 
401
{
 
402
    XfpmWatchData *watch;
 
403
    
 
404
    g_return_if_fail (XFPM_IS_DBUS_MONITOR (monitor));
 
405
 
 
406
    watch = xfpm_dbus_monitor_get_watch_data (monitor->priv->names_array, unique_name, bus_type);
 
407
    
 
408
    if ( watch )
 
409
    {
 
410
        g_ptr_array_remove (monitor->priv->names_array, watch);
 
411
        xfpm_dbus_monitor_free_watch_data (watch);
 
412
    }
 
413
}
 
414
 
 
415
gboolean xfpm_dbus_monitor_add_service (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *service_name)
 
416
{
 
417
    XfpmWatchData *watch;
 
418
    
 
419
    g_return_val_if_fail (XFPM_IS_DBUS_MONITOR (monitor), FALSE);
 
420
    
 
421
    if ( xfpm_dbus_monitor_get_watch_data (monitor->priv->services_array, service_name, bus_type ) )
 
422
        return FALSE;
 
423
        
 
424
    watch = g_new0 (XfpmWatchData , 1);
 
425
    watch->name = g_strdup (service_name);
 
426
    watch->bus_type = bus_type;
 
427
    
 
428
    g_ptr_array_add (monitor->priv->services_array, watch);
 
429
    
 
430
    return TRUE;
 
431
}
 
432
 
 
433
void xfpm_dbus_monitor_remove_service (XfpmDBusMonitor *monitor, DBusBusType bus_type, const gchar *service_name)
 
434
{
 
435
    XfpmWatchData *watch;
 
436
    
 
437
    g_return_if_fail (XFPM_IS_DBUS_MONITOR (monitor));
 
438
    
 
439
    watch = xfpm_dbus_monitor_get_watch_data (monitor->priv->services_array, service_name, bus_type);
 
440
    
 
441
    if ( watch )
 
442
    {
 
443
        g_ptr_array_remove (monitor->priv->services_array, watch);
 
444
        xfpm_dbus_monitor_free_watch_data (watch);
 
445
    }
 
446
}