]> git.0d.be Git - empathy.git/blob - libempathy/empathy-connectivity.c
empathy-connectivity: be sure to get the initial presence on init
[empathy.git] / libempathy / empathy-connectivity.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /*
3  * Copyright (C) 2009 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk>
20  */
21
22 #include "config.h"
23 #include "empathy-connectivity.h"
24
25 #ifdef HAVE_NM
26 #include <nm-client.h>
27 #endif
28
29 #include "empathy-utils.h"
30 #include "empathy-marshal.h"
31
32 #define DEBUG_FLAG EMPATHY_DEBUG_CONNECTIVITY
33 #include "empathy-debug.h"
34
35 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectivity)
36
37 typedef struct {
38 #ifdef HAVE_NM
39   NMClient *nm_client;
40 #endif
41
42   gboolean connected;
43   gboolean use_conn;
44   gboolean dispose_run;
45 } EmpathyConnectivityPriv;
46
47 enum {
48   STATE_CHANGE,
49   LAST_SIGNAL
50 };
51
52 enum {
53   PROP_0,
54   PROP_USE_CONN,
55 };
56
57 static guint signals[LAST_SIGNAL];
58 static EmpathyConnectivity *connectivity_singleton = NULL;
59
60 G_DEFINE_TYPE (EmpathyConnectivity, empathy_connectivity, G_TYPE_OBJECT);
61
62 #ifdef HAVE_NM
63 static void
64 connectivity_nm_state_change_cb (NMClient *client,
65     const GParamSpec *pspec,
66     EmpathyConnectivity *connectivity)
67 {
68   EmpathyConnectivityPriv *priv;
69   gboolean old_nm_connected;
70   gboolean new_nm_connected;
71   NMState state;
72
73   priv = GET_PRIV (connectivity);
74
75   if (!priv->use_conn)
76     return;
77
78   state = nm_client_get_state (priv->nm_client);
79   old_nm_connected = priv->connected;
80   new_nm_connected = !(state == NM_STATE_CONNECTING
81       || state == NM_STATE_DISCONNECTED);
82
83   DEBUG ("New NetworkManager network state %d", state);
84
85   priv->connected = new_nm_connected;
86
87   g_signal_emit (connectivity, signals[STATE_CHANGE], 0,
88       old_nm_connected, new_nm_connected);
89 }
90 #endif
91
92 static void
93 empathy_connectivity_init (EmpathyConnectivity *connectivity)
94 {
95   EmpathyConnectivityPriv *priv;
96
97   priv = G_TYPE_INSTANCE_GET_PRIVATE (connectivity,
98       EMPATHY_TYPE_CONNECTIVITY, EmpathyConnectivityPriv);
99
100   connectivity->priv = priv;
101   priv->dispose_run = FALSE;
102
103   priv->use_conn = TRUE;
104
105 #ifdef HAVE_NM
106   priv->nm_client = nm_client_new ();
107   if (priv->nm_client != NULL)
108     {
109       g_signal_connect (priv->nm_client, "notify::" NM_CLIENT_STATE,
110           G_CALLBACK (connectivity_nm_state_change_cb), connectivity);
111
112       connectivity_nm_state_change_cb (priv->nm_client, NULL, connectivity);
113     }
114   else
115     {
116       DEBUG ("Failed to get NetworkManager proxy");
117     }
118 #else
119   priv->connected = TRUE;
120 #endif
121 }
122
123 static void
124 connectivity_finalize (GObject *object)
125 {
126 #ifdef HAVE_NM
127   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
128   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
129
130   if (priv->nm_client != NULL)
131     {
132       g_signal_handlers_disconnect_by_func (priv->nm_client,
133           connectivity_nm_state_change_cb, connectivity);
134       g_object_unref (priv->nm_client);
135       priv->nm_client = NULL;
136     }
137 #endif
138
139   G_OBJECT_CLASS (empathy_connectivity_parent_class)->finalize (object);
140 }
141
142 static void
143 connectivity_dispose (GObject *object)
144 {
145   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
146   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
147
148   if (priv->dispose_run)
149     return;
150
151   priv->dispose_run = TRUE;
152
153   G_OBJECT_CLASS (empathy_connectivity_parent_class)->dispose (object);
154 }
155
156 static GObject *
157 connectivity_constructor (GType type,
158     guint n_construct_params,
159     GObjectConstructParam *construct_params)
160 {
161   GObject *retval;
162
163   if (!connectivity_singleton)
164     {
165       retval = G_OBJECT_CLASS (empathy_connectivity_parent_class)->constructor
166         (type, n_construct_params, construct_params);
167
168       connectivity_singleton = EMPATHY_CONNECTIVITY (retval);
169       g_object_add_weak_pointer (retval, (gpointer) &connectivity_singleton);
170     }
171   else
172     {
173       retval = g_object_ref (connectivity_singleton);
174     }
175
176   return retval;
177 }
178
179 static void
180 connectivity_get_property (GObject *object,
181     guint param_id,
182     GValue *value,
183     GParamSpec *pspec)
184 {
185   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
186
187   switch (param_id)
188     {
189     case PROP_USE_CONN:
190       g_value_set_boolean (value, empathy_connectivity_get_use_conn (
191               connectivity));
192       break;
193     default:
194       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
195       break;
196     };
197 }
198
199 static void
200 connectivity_set_property (GObject *object,
201     guint param_id,
202     const GValue *value,
203     GParamSpec *pspec)
204 {
205   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
206
207   switch (param_id)
208     {
209     case PROP_USE_CONN:
210       empathy_connectivity_set_use_conn (connectivity,
211           g_value_get_boolean (value));
212       break;
213     default:
214       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
215       break;
216     };
217 }
218
219 static void
220 empathy_connectivity_class_init (EmpathyConnectivityClass *klass)
221 {
222   GObjectClass *oclass = G_OBJECT_CLASS (klass);
223
224   oclass->finalize = connectivity_finalize;
225   oclass->dispose = connectivity_dispose;
226   oclass->constructor = connectivity_constructor;
227   oclass->get_property = connectivity_get_property;
228   oclass->set_property = connectivity_set_property;
229
230   signals[STATE_CHANGE] =
231     g_signal_new ("state-change",
232         G_TYPE_FROM_CLASS (klass),
233         G_SIGNAL_RUN_LAST,
234         0,
235         NULL, NULL,
236         _empathy_marshal_VOID__BOOLEAN_BOOLEAN,
237         G_TYPE_NONE,
238         2, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, NULL);
239
240   g_object_class_install_property (oclass,
241       PROP_USE_CONN,
242       g_param_spec_boolean ("use-conn",
243           "Use connectivity managers",
244           "Set presence according to connectivity managers",
245           TRUE,
246           G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
247
248   g_type_class_add_private (oclass, sizeof (EmpathyConnectivityPriv));
249 }
250
251 /* public methods */
252
253 EmpathyConnectivity *
254 empathy_connectivity_dup_singleton (void)
255 {
256   return g_object_new (EMPATHY_TYPE_CONNECTIVITY, NULL);
257 }
258
259 gboolean
260 empathy_connectivity_is_online (EmpathyConnectivity *connectivity)
261 {
262   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
263
264   if (priv->use_conn)
265     {
266       return priv->connected;
267     }
268   else
269     {
270       return TRUE;
271     }
272 }
273
274 gboolean
275 empathy_connectivity_get_use_conn (EmpathyConnectivity *connectivity)
276 {
277   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
278
279   return priv->use_conn;
280 }
281
282 void
283 empathy_connectivity_set_use_conn (EmpathyConnectivity *connectivity,
284     gboolean use_conn)
285 {
286   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
287
288   if (use_conn == priv->use_conn)
289     return;
290
291   DEBUG ("use_conn gconf key changed; new value = %s",
292       use_conn ? "true" : "false");
293
294   priv->use_conn = use_conn;
295
296 #ifdef HAVE_NM
297   if (use_conn)
298     {
299       connectivity_nm_state_change_cb (priv->nm_client, NULL, connectivity);
300 #else
301   if (FALSE)
302     {
303 #endif
304     }
305   else
306     {
307       g_signal_emit (connectivity, signals[STATE_CHANGE], 0,
308           FALSE, TRUE);
309     }
310
311   g_object_notify (G_OBJECT (connectivity), "use-conn");
312 }