2
* Copyright Ā© 2012 Canonical Ltd.
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.
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.
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/>.
16
* Author: Ted Gould <ted@canonical.com>
23
#include "connection.h"
24
#include "service-iface.h"
26
#include "shared-values.h"
28
struct _HudClientConnectionPrivate {
29
_HudServiceComCanonicalHud * proxy;
30
GDBusConnection * bus;
34
gulong name_owner_sig;
35
GCancellable * cancellable;
38
#define HUD_CLIENT_CONNECTION_GET_PRIVATE(o) \
39
(G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_CLIENT_TYPE_CONNECTION, HudClientConnectionPrivate))
47
#define PROP_ADDRESS_S "address"
48
#define PROP_PATH_S "path"
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);
59
G_DEFINE_TYPE (HudClientConnection, hud_client_connection, G_TYPE_OBJECT);
61
static guint signal_connection_status = 0;
64
hud_client_connection_class_init (HudClientConnectionClass *klass)
66
GObjectClass *object_class = G_OBJECT_CLASS (klass);
68
g_type_class_add_private (klass, sizeof (HudClientConnectionPrivate));
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;
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.",
80
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
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.",
86
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
89
* HudClientConnection::connection-status:
91
* Called when the connection status changes in some way.
93
signal_connection_status = g_signal_new (HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS,
94
HUD_CLIENT_TYPE_CONNECTION,
97
NULL, NULL, /* Collectors */
98
g_cclosure_marshal_VOID__BOOLEAN,
99
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
106
hud_client_connection_init (HudClientConnection *self)
108
self->priv = HUD_CLIENT_CONNECTION_GET_PRIVATE(self);
109
self->priv->connected = FALSE;
110
self->priv->cancellable = g_cancellable_new();
112
GError * error = NULL;
113
self->priv->bus = g_bus_get_sync(G_BUS_TYPE_SESSION, self->priv->cancellable, &error);
115
if (G_UNLIKELY(error != NULL)) { /* really should never happen */
116
g_warning("Unable to get session bus: %s", error->message);
124
set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
126
HudClientConnection * self = HUD_CLIENT_CONNECTION(obj);
130
g_clear_pointer(&self->priv->address, g_free);
131
self->priv->address = g_value_dup_string(value);
134
g_clear_pointer(&self->priv->path, g_free);
135
self->priv->path = g_value_dup_string(value);
138
g_warning("Unknown property %d.", id);
146
get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
148
HudClientConnection * self = HUD_CLIENT_CONNECTION(obj);
152
g_value_set_string(value, self->priv->address);
155
g_value_set_string(value, self->priv->path);
158
g_warning("Unknown property %d.", id);
166
hud_client_connection_constructed (GObject * object)
168
HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
170
g_return_if_fail(self->priv->address != NULL);
171
g_return_if_fail(self->priv->path != NULL);
173
GError * error = NULL;
174
self->priv->proxy = _hud_service_com_canonical_hud_proxy_new_for_bus_sync(
176
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
179
self->priv->cancellable,
184
g_warning("Unable to get a HUD proxy: %s", error->message);
185
self->priv->proxy = NULL;
186
g_error_free(error); error = NULL;
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);
196
hud_client_connection_dispose (GObject *object)
198
HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
200
if (self->priv->cancellable != NULL) {
201
g_cancellable_cancel(self->priv->cancellable);
202
g_clear_object(&self->priv->cancellable);
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;
210
g_clear_object(&self->priv->proxy);
211
g_clear_object(&self->priv->bus);
213
G_OBJECT_CLASS (hud_client_connection_parent_class)->dispose (object);
218
hud_client_connection_finalize (GObject *object)
220
HudClientConnection * self = HUD_CLIENT_CONNECTION(object);
222
g_clear_pointer(&self->priv->address, g_free);
223
g_clear_pointer(&self->priv->path, g_free);
225
G_OBJECT_CLASS (hud_client_connection_parent_class)->finalize (object);
229
/* Called when the HUD service comes on or off the bus */
231
name_owner_changed (GObject * object, GParamSpec * pspec, gpointer user_data)
233
HudClientConnection * self = HUD_CLIENT_CONNECTION(user_data);
234
gboolean connected = FALSE;
236
gchar * owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(self->priv->proxy));
242
/* Make sure we set the internal variable before signaling */
243
gboolean change = (connected == self->priv->connected);
244
self->priv->connected = connected;
246
/* Cancel anything we had running */
247
if (!self->priv->connected && self->priv->cancellable != NULL) {
248
g_cancellable_cancel(self->priv->cancellable);
251
/* If there was a change, make sure others know about it */
253
g_signal_emit(self, signal_connection_status, 0, connected);
260
* hud_client_connection_get_ref:
262
* Gets a reference to the default object that connects to the
263
* default HUD service.
265
* Return value: (transfer full): Refence to a #HudClientConnection
267
HudClientConnection *
268
hud_client_connection_get_ref (void)
270
static HudClientConnection * global = NULL;
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);
277
return g_object_ref(global);
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
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()
292
* Return value: (transfer full): A new #HudClientConnection
294
HudClientConnection *
295
hud_client_connection_new (gchar * dbus_address, gchar * dbus_path)
297
return HUD_CLIENT_CONNECTION(g_object_new(HUD_CLIENT_TYPE_CONNECTION,
298
PROP_ADDRESS_S, dbus_address,
299
PROP_PATH_S, dbus_path,
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;
311
/* Called when the new query call comes back */
313
new_query_complete (GObject * object, GAsyncResult * res, gpointer user_data)
315
new_query_data_t * data = (new_query_data_t *)user_data;
317
gchar * query_object = NULL;
318
gchar * results_name = NULL;
319
gchar * appstack_name = NULL;
321
GError * error = NULL;
323
_hud_service_com_canonical_hud_call_create_query_finish((_HudServiceComCanonicalHud *)object,
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);
339
data->cb(data->con, query_object, results_name, appstack_name, data->user_data);
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
353
* Function to create a new query in the HUD service and pass back
354
* the information needed to create a #HudClientQuery object.
357
hud_client_connection_new_query (HudClientConnection * connection, const gchar * query, HudClientConnectionNewQueryCallback cb, gpointer user_data)
359
g_return_if_fail(HUD_CLIENT_IS_CONNECTION(connection));
361
new_query_data_t * data = g_new0(new_query_data_t, 1);
362
data->con = connection;
364
data->user_data = user_data;
366
return _hud_service_com_canonical_hud_call_create_query(connection->priv->proxy,
368
connection->priv->cancellable,
374
* hud_client_connection_get_address:
375
* @connection: A #HudClientConnection
377
* Accessor to get the address of the HUD service.
379
* Return value: A DBus address
382
hud_client_connection_get_address (HudClientConnection * connection)
384
g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), NULL);
386
return connection->priv->address;
390
* hud_client_connection_connected:
391
* @connection: A #HudClientConnection
393
* Accessor to get the connected status of the connection
395
* Return value: If we're connected or not
398
hud_client_connection_connected (HudClientConnection * connection)
400
g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), FALSE);
401
return connection->priv->connected;
405
* hud_client_connection_get_bus:
406
* @connection: A #HudClientConnection
408
* Grab the bus being used by the connection.
410
* Return value: (transfer none): Our bus if we have one
413
hud_client_connection_get_bus (HudClientConnection * connection)
415
g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), NULL);
416
return connection->priv->bus;