~jbicha/hud/build-depend-on-valac-not-gir

« back to all changes in this revision

Viewing changes to libhud-client/connection.c

  • Committer: Tarmac
  • Author(s): Ted Gould, Pete Woods, Antti Kaijanmäki, Ted Gould, Albert Astals, Ryan Lortie, Łukasz 'sil2100' Zemczak, Albert Astals Cid, Mathieu Trudel-Lapierre, Kaleo, Tarmac, Ricardo Salveti de Araujo, Michael Terry, Automatic PS uploader
  • Date: 2013-04-10 16:04:51 UTC
  • mfrom: (227.3.148 phablet)
  • Revision ID: tarmac-20130410160451-o3owpv3zaxulm5of
HUD 2.0 Merge.

Approved by PS Jenkins bot, Mathieu Trudel-Lapierre.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2012 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3, as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
 * PURPOSE.  See the GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Author: Ted Gould <ted@canonical.com>
 
17
 */
 
18
 
 
19
#ifdef HAVE_CONFIG_H
 
20
#include "config.h"
 
21
#endif
 
22
 
 
23
#include "connection.h"
 
24
#include "service-iface.h"
 
25
 
 
26
#include "shared-values.h"
 
27
 
 
28
struct _HudClientConnectionPrivate {
 
29
        _HudServiceComCanonicalHud * proxy;
 
30
        GDBusConnection * bus;
 
31
        gchar * address;
 
32
        gchar * path;
 
33
        gboolean connected;
 
34
        gulong name_owner_sig;
 
35
        GCancellable * cancellable;
 
36
};
 
37
 
 
38
#define HUD_CLIENT_CONNECTION_GET_PRIVATE(o) \
 
39
(G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_CLIENT_TYPE_CONNECTION, HudClientConnectionPrivate))
 
40
 
 
41
enum {
 
42
        PROP_0 = 0,
 
43
        PROP_ADDRESS,
 
44
        PROP_PATH,
 
45
};
 
46
 
 
47
#define PROP_ADDRESS_S  "address"
 
48
#define PROP_PATH_S     "path"
 
49
 
 
50
static void hud_client_connection_class_init (HudClientConnectionClass *klass);
 
51
static void hud_client_connection_init       (HudClientConnection *self);
 
52
static void hud_client_connection_constructed (GObject *object);
 
53
static void hud_client_connection_dispose    (GObject *object);
 
54
static void hud_client_connection_finalize   (GObject *object);
 
55
static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
 
56
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
 
57
static void name_owner_changed (GObject * object, GParamSpec * pspec, gpointer user_data);
 
58
 
 
59
G_DEFINE_TYPE (HudClientConnection, hud_client_connection, G_TYPE_OBJECT);
 
60
 
 
61
static guint signal_connection_status = 0;
 
62
 
 
63
static void
 
64
hud_client_connection_class_init (HudClientConnectionClass *klass)
 
65
{
 
66
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
67
 
 
68
        g_type_class_add_private (klass, sizeof (HudClientConnectionPrivate));
 
69
 
 
70
        object_class->dispose = hud_client_connection_dispose;
 
71
        object_class->finalize = hud_client_connection_finalize;
 
72
        object_class->constructed = hud_client_connection_constructed;
 
73
        object_class->set_property = set_property;
 
74
        object_class->get_property = get_property;
 
75
 
 
76
        g_object_class_install_property (object_class, PROP_ADDRESS,
 
77
                                         g_param_spec_string(PROP_ADDRESS_S, "Address on DBus for the HUD service",
 
78
                                                      "The DBus address of the HUD service we should connect to.",
 
79
                                                      DBUS_NAME,
 
80
                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
81
 
 
82
        g_object_class_install_property (object_class, PROP_PATH,
 
83
                                         g_param_spec_string(PROP_PATH_S, "Path on DBus for the HUD service",
 
84
                                                      "The DBus path of the HUD service we should connect to.",
 
85
                                                      DBUS_PATH,
 
86
                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
87
 
 
88
        /**
 
89
         * HudClientConnection::connection-status:
 
90
         *
 
91
         * Called when the connection status changes in some way.
 
92
         */
 
93
        signal_connection_status = g_signal_new (HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS,
 
94
                                                 HUD_CLIENT_TYPE_CONNECTION,
 
95
                                                 G_SIGNAL_RUN_LAST,
 
96
                                                 0, /* offset */
 
97
                                                 NULL, NULL, /* Collectors */
 
98
                                                 g_cclosure_marshal_VOID__BOOLEAN,
 
99
                                                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
100
 
 
101
 
 
102
        return;
 
103
}
 
104
 
 
105
static void
 
106
hud_client_connection_init (HudClientConnection *self)
 
107
{
 
108
        self->priv = HUD_CLIENT_CONNECTION_GET_PRIVATE(self);
 
109
        self->priv->connected = FALSE;
 
110
        self->priv->cancellable = g_cancellable_new();
 
111
 
 
112
        GError * error = NULL;
 
113
        self->priv->bus = g_bus_get_sync(G_BUS_TYPE_SESSION, self->priv->cancellable, &error);
 
114
 
 
115
        if (G_UNLIKELY(error != NULL)) { /* really should never happen */
 
116
                g_warning("Unable to get session bus: %s", error->message);
 
117
                g_error_free(error);
 
118
        }
 
119
 
 
120
        return;
 
121
}
 
122
 
 
123
static void
 
124
set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
 
125
{
 
126
        HudClientConnection * self = HUD_CLIENT_CONNECTION(obj);
 
127
 
 
128
        switch (id) {
 
129
        case PROP_ADDRESS:
 
130
                g_clear_pointer(&self->priv->address, g_free);
 
131
                self->priv->address = g_value_dup_string(value);
 
132
                break;
 
133
        case PROP_PATH:
 
134
                g_clear_pointer(&self->priv->path, g_free);
 
135
                self->priv->path = g_value_dup_string(value);
 
136
                break;
 
137
        default:
 
138
                g_warning("Unknown property %d.", id);
 
139
                return;
 
140
        }
 
141
 
 
142
        return;
 
143
}
 
144
 
 
145
static void
 
146
get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
 
147
{
 
148
        HudClientConnection * self = HUD_CLIENT_CONNECTION(obj);
 
149
 
 
150
        switch (id) {
 
151
        case PROP_ADDRESS:
 
152
                g_value_set_string(value, self->priv->address);
 
153
                break;
 
154
        case PROP_PATH:
 
155
                g_value_set_string(value, self->priv->path);
 
156
                break;
 
157
        default:
 
158
                g_warning("Unknown property %d.", id);
 
159
                return;
 
160
        }
 
161
 
 
162
        return;
 
163
}
 
164
 
 
165
static void
 
166
hud_client_connection_constructed (GObject * object)
 
167
{
 
168
        HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
 
169
 
 
170
        g_return_if_fail(self->priv->address != NULL);
 
171
        g_return_if_fail(self->priv->path != NULL);
 
172
 
 
173
        GError * error = NULL;
 
174
        self->priv->proxy = _hud_service_com_canonical_hud_proxy_new_for_bus_sync(
 
175
                G_BUS_TYPE_SESSION,
 
176
                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
 
177
                self->priv->address,
 
178
                self->priv->path,
 
179
                self->priv->cancellable,
 
180
                &error
 
181
        );
 
182
 
 
183
        if (error != NULL) {
 
184
                g_warning("Unable to get a HUD proxy: %s", error->message);
 
185
                self->priv->proxy = NULL;
 
186
                g_error_free(error); error = NULL;
 
187
        }
 
188
 
 
189
        self->priv->name_owner_sig = g_signal_connect(G_OBJECT(self->priv->proxy), "notify::g-name-owner", G_CALLBACK(name_owner_changed), self);
 
190
        name_owner_changed(G_OBJECT(self->priv->proxy), NULL, self);
 
191
 
 
192
        return;
 
193
}
 
194
 
 
195
static void
 
196
hud_client_connection_dispose (GObject *object)
 
197
{
 
198
        HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
 
199
 
 
200
        if (self->priv->cancellable != NULL) {
 
201
                g_cancellable_cancel(self->priv->cancellable);
 
202
                g_clear_object(&self->priv->cancellable);
 
203
        }
 
204
 
 
205
        if (self->priv->name_owner_sig != 0) {
 
206
                g_signal_handler_disconnect(self->priv->proxy, self->priv->name_owner_sig);
 
207
                self->priv->name_owner_sig = 0;
 
208
        }
 
209
 
 
210
        g_clear_object(&self->priv->proxy);
 
211
        g_clear_object(&self->priv->bus);
 
212
 
 
213
        G_OBJECT_CLASS (hud_client_connection_parent_class)->dispose (object);
 
214
        return;
 
215
}
 
216
 
 
217
static void
 
218
hud_client_connection_finalize (GObject *object)
 
219
{
 
220
        HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
 
221
 
 
222
        g_clear_pointer(&self->priv->address, g_free);
 
223
        g_clear_pointer(&self->priv->path, g_free);
 
224
 
 
225
        G_OBJECT_CLASS (hud_client_connection_parent_class)->finalize (object);
 
226
        return;
 
227
}
 
228
 
 
229
/* Called when the HUD service comes on or off the bus */
 
230
static void
 
231
name_owner_changed (GObject * object, GParamSpec * pspec, gpointer user_data)
 
232
{
 
233
        HudClientConnection * self = HUD_CLIENT_CONNECTION(user_data);
 
234
        gboolean connected = FALSE;
 
235
 
 
236
        gchar * owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(self->priv->proxy));
 
237
        if (owner != NULL) {
 
238
                connected = TRUE;
 
239
                g_free(owner);
 
240
        }
 
241
 
 
242
        /* Make sure we set the internal variable before signaling */
 
243
        gboolean change = (connected == self->priv->connected);
 
244
        self->priv->connected = connected;
 
245
 
 
246
        /* Cancel anything we had running */
 
247
        if (!self->priv->connected && self->priv->cancellable != NULL) {
 
248
                g_cancellable_cancel(self->priv->cancellable);
 
249
        }
 
250
 
 
251
        /* If there was a change, make sure others know about it */
 
252
        if (change) {
 
253
                g_signal_emit(self, signal_connection_status, 0, connected);
 
254
        }
 
255
 
 
256
        return;
 
257
}
 
258
 
 
259
/**
 
260
 * hud_client_connection_get_ref:
 
261
 *
 
262
 * Gets a reference to the default object that connects to the
 
263
 * default HUD service.
 
264
 *
 
265
 * Return value: (transfer full): Refence to a #HudClientConnection
 
266
 */
 
267
HudClientConnection *
 
268
hud_client_connection_get_ref (void)
 
269
{
 
270
        static HudClientConnection * global = NULL;
 
271
 
 
272
        if (global == NULL) {
 
273
                global = HUD_CLIENT_CONNECTION(g_object_new(HUD_CLIENT_TYPE_CONNECTION, NULL));
 
274
                g_object_add_weak_pointer(G_OBJECT(global), (gpointer *)&global);
 
275
                return global;
 
276
        } else {
 
277
                return g_object_ref(global);
 
278
        }
 
279
}
 
280
 
 
281
/**
 
282
 * hud_client_connection_new:
 
283
 * @dbus_address: Address on DBus for the HUD service
 
284
 * @dbus_path: Path to the object to create stuff
 
285
 *
 
286
 * Builds a HUD Connection object that can be used to connect to a
 
287
 * custom HUD service.  For the most part, this should only be used
 
288
 * in testing, though there might be other uses.  It is likely if you're
 
289
 * using this function you'd also be interested in
 
290
 * hud_client_query_new_for_connection()
 
291
 *
 
292
 * Return value: (transfer full): A new #HudClientConnection
 
293
 */
 
294
HudClientConnection *
 
295
hud_client_connection_new (gchar * dbus_address, gchar * dbus_path)
 
296
{
 
297
        return HUD_CLIENT_CONNECTION(g_object_new(HUD_CLIENT_TYPE_CONNECTION,
 
298
                        PROP_ADDRESS_S, dbus_address,
 
299
                        PROP_PATH_S, dbus_path,
 
300
                        NULL));
 
301
}
 
302
 
 
303
/* Data to handle the callback */
 
304
typedef struct _new_query_data_t new_query_data_t;
 
305
struct _new_query_data_t {
 
306
        HudClientConnection * con;
 
307
        HudClientConnectionNewQueryCallback cb;
 
308
        gpointer user_data;
 
309
};
 
310
 
 
311
/* Called when the new query call comes back */
 
312
static void
 
313
new_query_complete (GObject * object, GAsyncResult * res, gpointer user_data)
 
314
{
 
315
        new_query_data_t * data = (new_query_data_t *)user_data;
 
316
 
 
317
        gchar * query_object = NULL;
 
318
        gchar * results_name = NULL;
 
319
        gchar * appstack_name = NULL;
 
320
        gint revision = 0;
 
321
        GError * error = NULL;
 
322
 
 
323
        _hud_service_com_canonical_hud_call_create_query_finish((_HudServiceComCanonicalHud *)object,
 
324
                                                                &query_object,
 
325
                                                                &results_name,
 
326
                                                                &appstack_name,
 
327
                                                                &revision,
 
328
                                                                res,
 
329
                                                                &error);
 
330
 
 
331
        if (error != NULL) {
 
332
                if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && 
 
333
                                !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CLOSED)) {
 
334
                        g_warning("Unable to allocate query: %s", error->message);
 
335
                }
 
336
                g_error_free(error);
 
337
        }
 
338
 
 
339
        data->cb(data->con, query_object, results_name, appstack_name, data->user_data);
 
340
 
 
341
        g_free(data);
 
342
 
 
343
        return;
 
344
}
 
345
 
 
346
/**
 
347
 * hud_client_connection_new_query:
 
348
 * @connection: A #HudClientConnection
 
349
 * @query: The initial query string
 
350
 * @cb: Callback when we've got the query
 
351
 * @user_data: Data to pass to the callback
 
352
 *
 
353
 * Function to create a new query in the HUD service and pass back
 
354
 * the information needed to create a #HudClientQuery object.
 
355
 */
 
356
void
 
357
hud_client_connection_new_query (HudClientConnection * connection, const gchar * query, HudClientConnectionNewQueryCallback cb, gpointer user_data)
 
358
{
 
359
        g_return_if_fail(HUD_CLIENT_IS_CONNECTION(connection));
 
360
 
 
361
        new_query_data_t * data = g_new0(new_query_data_t, 1);
 
362
        data->con = connection;
 
363
        data->cb = cb;
 
364
        data->user_data = user_data;
 
365
 
 
366
        return _hud_service_com_canonical_hud_call_create_query(connection->priv->proxy,
 
367
                query,
 
368
                connection->priv->cancellable,
 
369
                new_query_complete,
 
370
                data);
 
371
}
 
372
 
 
373
/**
 
374
 * hud_client_connection_get_address:
 
375
 * @connection: A #HudClientConnection
 
376
 *
 
377
 * Accessor to get the address of the HUD service.
 
378
 *
 
379
 * Return value: A DBus address
 
380
 */
 
381
const gchar *
 
382
hud_client_connection_get_address (HudClientConnection * connection)
 
383
{
 
384
        g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), NULL);
 
385
 
 
386
        return connection->priv->address;
 
387
}
 
388
 
 
389
/**
 
390
 * hud_client_connection_connected:
 
391
 * @connection: A #HudClientConnection
 
392
 *
 
393
 * Accessor to get the connected status of the connection
 
394
 *
 
395
 * Return value: If we're connected or not
 
396
 */
 
397
gboolean
 
398
hud_client_connection_connected (HudClientConnection * connection)
 
399
{
 
400
        g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), FALSE);
 
401
        return connection->priv->connected;
 
402
}