]> git.0d.be Git - empathy.git/blob - libempathy/empathy-connection-managers.c
Add singleton to cache TpConnectionManagers
[empathy.git] / libempathy / empathy-connection-managers.c
1 /*
2  * empathy-connection-managers.c - Source for EmpathyConnectionManagers
3  * Copyright (C) 2009 Collabora Ltd.
4  * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <telepathy-glib/connection-manager.h>
26 #include <telepathy-glib/util.h>
27
28 #include "empathy-connection-managers.h"
29 #include "empathy-utils.h"
30
31 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
32 #include <libempathy/empathy-debug.h>
33
34 static GObject *managers = NULL;
35
36 G_DEFINE_TYPE(EmpathyConnectionManagers, empathy_connection_managers,
37     G_TYPE_OBJECT)
38
39 /* signal enum */
40 enum
41 {
42     UPDATED,
43     LAST_SIGNAL
44 };
45
46 static guint signals[LAST_SIGNAL] = {0};
47
48 /* properties */
49 enum {
50   PROP_READY = 1
51 };
52
53 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectionManagers)
54
55
56 /* private structure */
57 typedef struct _EmpathyConnectionManagersPriv
58   EmpathyConnectionManagersPriv;
59
60 struct _EmpathyConnectionManagersPriv
61 {
62   gboolean dispose_has_run;
63   gboolean ready;
64
65   GList *cms;
66
67   TpDBusDaemon *dbus;
68 };
69
70 #define EMPATHY_CONNECTION_MANAGERS_GET_PRIVATE(o) \
71   (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
72   EMPATHY_TYPE_CONNECTION_MANAGERS, EmpathyConnectionManagersPriv))
73
74 static void
75 empathy_connection_managers_init (EmpathyConnectionManagers *obj)
76 {
77   EmpathyConnectionManagersPriv *priv =
78       EMPATHY_CONNECTION_MANAGERS_GET_PRIVATE (obj);
79
80   priv->dbus = tp_dbus_daemon_dup (NULL);
81   g_assert (priv->dbus != NULL);
82
83   empathy_connection_managers_update (obj);
84
85   /* allocate any data required by the object here */
86 }
87
88 static void empathy_connection_managers_dispose (GObject *object);
89 static void empathy_connection_managers_finalize (GObject *object);
90
91 static GObject *
92 empathy_connection_managers_constructor (GType type,
93                         guint n_construct_params,
94                         GObjectConstructParam *construct_params)
95 {
96   if (managers != NULL)
97     return g_object_ref (managers);
98
99   managers =
100       G_OBJECT_CLASS (empathy_connection_managers_parent_class)->constructor
101           (type, n_construct_params, construct_params);
102
103   g_object_add_weak_pointer (managers, (gpointer) &managers);
104
105   return managers;
106 }
107
108
109
110 static void
111 empathy_connection_managers_get_property (GObject *object,
112     guint prop_id,
113     GValue *value,
114     GParamSpec *pspec)
115 {
116   EmpathyConnectionManagers *managers = EMPATHY_CONNECTION_MANAGERS (object);
117   EmpathyConnectionManagersPriv *priv = GET_PRIV (managers);
118
119   switch (prop_id)
120     {
121       case PROP_READY:
122         g_value_set_boolean (value, priv->ready);
123         break;
124       default:
125         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
126         break;
127     }
128 }
129
130 static void
131 empathy_connection_managers_class_init (
132     EmpathyConnectionManagersClass *empathy_connection_managers_class)
133 {
134   GObjectClass *object_class =
135       G_OBJECT_CLASS (empathy_connection_managers_class);
136
137   g_type_class_add_private (empathy_connection_managers_class, sizeof
138       (EmpathyConnectionManagersPriv));
139
140   object_class->constructor = empathy_connection_managers_constructor;
141   object_class->dispose = empathy_connection_managers_dispose;
142   object_class->finalize = empathy_connection_managers_finalize;
143   object_class->get_property = empathy_connection_managers_get_property;
144
145   g_object_class_install_property (object_class, PROP_READY,
146     g_param_spec_boolean ("ready",
147       "Ready",
148       "Whether the connection manager information is ready to be used",
149       FALSE,
150       G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
151
152   signals[UPDATED] = g_signal_new ("updated",
153     G_TYPE_FROM_CLASS (object_class),
154     G_SIGNAL_RUN_LAST,
155     0, NULL, NULL,
156     g_cclosure_marshal_VOID__VOID,
157     G_TYPE_NONE, 0);
158 }
159
160 static void
161 empathy_connection_managers_free_cm_list (EmpathyConnectionManagers *self)
162 {
163   EmpathyConnectionManagersPriv *priv = GET_PRIV (self);
164   GList *l;
165
166   for (l = priv->cms ; l != NULL ; l = g_list_next (l))
167     {
168       g_object_unref (l->data);
169     }
170   g_list_free (priv->cms);
171
172   priv->cms = NULL;
173 }
174
175 static void
176 empathy_connection_managers_dispose (GObject *object)
177 {
178   EmpathyConnectionManagers *self = EMPATHY_CONNECTION_MANAGERS (object);
179   EmpathyConnectionManagersPriv *priv = GET_PRIV (self);
180
181   if (priv->dispose_has_run)
182     return;
183
184   priv->dispose_has_run = TRUE;
185
186   if (priv->dbus != NULL)
187     g_object_unref (priv->dbus);
188   priv->dbus = NULL;
189
190   empathy_connection_managers_free_cm_list (self);
191
192   /* release any references held by the object here */
193
194   if (G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose)
195     G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose (object);
196 }
197
198 void
199 empathy_connection_managers_finalize (GObject *object)
200 {
201 #if 0
202   EmpathyConnectionManagers *self = EMPATHY_CONNECTION_MANAGERS (object);
203   EmpathyConnectionManagersPriv *priv =
204     EMPATHY_CONNECTION_MANAGERS_GET_PRIVATE (self);
205
206   /* free any data held directly by the object here */
207
208   G_OBJECT_CLASS (empathy_connection_managers_parent_class)->finalize (object);
209 #endif
210 }
211
212 EmpathyConnectionManagers *
213 empathy_connection_managers_dup_singleton (void)
214 {
215   return EMPATHY_CONNECTION_MANAGERS (
216       g_object_new (EMPATHY_TYPE_CONNECTION_MANAGERS, NULL));
217 }
218
219 gboolean
220 empathy_connection_managers_is_ready (EmpathyConnectionManagers *managers)
221 {
222   EmpathyConnectionManagersPriv *priv = GET_PRIV (managers);
223   return priv->ready;
224 }
225
226 static void
227 empathy_connection_managers_listed_cb (TpConnectionManager * const *cms,
228     gsize n_cms,
229     const GError *error,
230     gpointer user_data,
231     GObject *weak_object)
232 {
233   EmpathyConnectionManagers *self =
234     EMPATHY_CONNECTION_MANAGERS (weak_object);
235   EmpathyConnectionManagersPriv *priv = GET_PRIV (self);
236   TpConnectionManager * const *iter;
237
238   empathy_connection_managers_free_cm_list (self);
239
240   if (error != NULL)
241     {
242       DEBUG ("Failed to get connection managers: %s", error->message);
243       goto out;
244     }
245
246   for (iter = cms ; iter != NULL && *iter != NULL; iter++)
247     {
248       /* only list cms that didn't hit errors */
249       if (tp_connection_manager_is_ready(*iter))
250         priv->cms = g_list_prepend (priv->cms, g_object_ref (*iter));
251     }
252
253 out:
254   if (!priv->ready)
255     {
256       priv->ready = TRUE;
257       g_object_notify (weak_object, "ready");
258     }
259   g_signal_emit (weak_object, signals[UPDATED], 0);
260 }
261
262 void
263 empathy_connection_managers_update (EmpathyConnectionManagers *managers)
264 {
265   EmpathyConnectionManagersPriv *priv = GET_PRIV (managers);
266
267   tp_list_connection_managers (priv->dbus,
268     empathy_connection_managers_listed_cb,
269     NULL, NULL, G_OBJECT (managers));
270 }
271
272 GList *
273 empathy_connection_managers_get_cms (EmpathyConnectionManagers *managers)
274 {
275   EmpathyConnectionManagersPriv *priv = GET_PRIV (managers);
276
277   return priv->cms;
278 }
279
280 TpConnectionManager *
281 empathy_connection_managers_get_cm (EmpathyConnectionManagers *managers,
282   const gchar *cm)
283 {
284   EmpathyConnectionManagersPriv *priv = GET_PRIV (managers);
285   GList *l;
286
287   for (l = priv->cms ; l != NULL; l = g_list_next (l))
288     {
289       TpConnectionManager *c = TP_CONNECTION_MANAGER (l->data);
290
291       if (!tp_strdiff (c->name, cm))
292         return c;
293     }
294
295   return NULL;
296 }