]> git.0d.be Git - empathy.git/blob - libempathy/empathy-connectivity.c
empathy-connectivity: only unref the NM client if we're using NM
[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_CONNECTED;
81   new_nm_connected = !(state == NM_STATE_CONNECTING
82       || state == NM_STATE_DISCONNECTED);
83
84   DEBUG ("New NetworkManager network state %d", state);
85
86   priv->connected = new_nm_connected;
87
88   g_signal_emit (connectivity, signals[STATE_CHANGE], 0,
89       old_nm_connected, new_nm_connected);
90 }
91 #endif
92
93 static void
94 empathy_connectivity_init (EmpathyConnectivity *connectivity)
95 {
96   EmpathyConnectivityPriv *priv;
97
98   priv = G_TYPE_INSTANCE_GET_PRIVATE (connectivity,
99       EMPATHY_TYPE_CONNECTIVITY, EmpathyConnectivityPriv);
100
101   connectivity->priv = priv;
102   priv->dispose_run = FALSE;
103
104 #ifdef HAVE_NM
105   priv->nm_client = nm_client_new ();
106   if (priv->nm_client != NULL)
107     {
108       g_signal_connect (priv->nm_client, "notify::" NM_CLIENT_STATE,
109           G_CALLBACK (connectivity_nm_state_change_cb), connectivity);
110     }
111   else
112     {
113       DEBUG ("Failed to get NetworkManager proxy");
114     }
115 #endif
116 }
117
118 static void
119 connectivity_finalize (GObject *object)
120 {
121 #ifdef HAVE_NM
122   EmpathyConnectivity *manager = EMPATHY_CONNECTIVITY (object);
123   EmpathyConnectivityPriv *priv = GET_PRIV (manager);
124
125   if (priv->nm_client != NULL)
126     {
127       g_object_unref (priv->nm_client);
128       priv->nm_client = NULL;
129     }
130 #endif
131
132   G_OBJECT_CLASS (empathy_connectivity_parent_class)->finalize (object);
133 }
134
135 static void
136 connectivity_dispose (GObject *object)
137 {
138   EmpathyConnectivity *manager = EMPATHY_CONNECTIVITY (object);
139   EmpathyConnectivityPriv *priv = GET_PRIV (manager);
140
141   if (priv->dispose_run)
142     return;
143
144   priv->dispose_run = TRUE;
145
146   G_OBJECT_CLASS (empathy_connectivity_parent_class)->dispose (object);
147 }
148
149 static GObject *
150 connectivity_constructor (GType type,
151     guint n_construct_params,
152     GObjectConstructParam *construct_params)
153 {
154   GObject *retval;
155
156   if (!connectivity_singleton)
157     {
158       retval = G_OBJECT_CLASS (empathy_connectivity_parent_class)->constructor
159         (type, n_construct_params, construct_params);
160
161       connectivity_singleton = EMPATHY_CONNECTIVITY (retval);
162       g_object_add_weak_pointer (retval, (gpointer) &connectivity_singleton);
163     }
164   else
165     {
166       retval = g_object_ref (connectivity_singleton);
167     }
168
169   return retval;
170 }
171
172 static void
173 connectivity_get_property (GObject *object,
174     guint param_id,
175     GValue *value,
176     GParamSpec *pspec)
177 {
178   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
179
180   switch (param_id)
181     {
182     case PROP_USE_CONN:
183       g_value_set_boolean (value, empathy_connectivity_get_use_conn (
184               connectivity));
185       break;
186     default:
187       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
188       break;
189     };
190 }
191
192 static void
193 connectivity_set_property (GObject *object,
194     guint param_id,
195     const GValue *value,
196     GParamSpec *pspec)
197 {
198   EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
199
200   switch (param_id)
201     {
202     case PROP_USE_CONN:
203       empathy_connectivity_set_use_conn (connectivity,
204           g_value_get_boolean (value));
205       break;
206     default:
207       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
208       break;
209     };
210 }
211
212 static void
213 empathy_connectivity_class_init (EmpathyConnectivityClass *klass)
214 {
215   GObjectClass *oclass = G_OBJECT_CLASS (klass);
216
217   oclass->finalize = connectivity_finalize;
218   oclass->dispose = connectivity_dispose;
219   oclass->constructor = connectivity_constructor;
220   oclass->get_property = connectivity_get_property;
221   oclass->set_property = connectivity_set_property;
222
223   signals[STATE_CHANGE] =
224     g_signal_new ("state-change",
225         G_TYPE_FROM_CLASS (klass),
226         G_SIGNAL_RUN_LAST,
227         0,
228         NULL, NULL,
229         _empathy_marshal_VOID__BOOLEAN_BOOLEAN,
230         G_TYPE_NONE,
231         2, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, NULL);
232
233   g_object_class_install_property (oclass,
234       PROP_USE_CONN,
235       g_param_spec_boolean ("use-conn",
236           "Use connectivity managers",
237           "Set presence according to connectivity managers",
238           TRUE,
239           G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
240
241   g_type_class_add_private (oclass, sizeof (EmpathyConnectivityPriv));
242 }
243
244 /* public methods */
245
246 EmpathyConnectivity *
247 empathy_connectivity_dup_singleton (void)
248 {
249   return g_object_new (EMPATHY_TYPE_CONNECTIVITY, NULL);
250 }
251
252 gboolean
253 empathy_connectivity_is_online (EmpathyConnectivity *connectivity)
254 {
255   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
256
257   if (priv->use_conn)
258     {
259 #ifdef HAVE_NM
260       return priv->connected;
261 #else
262       return TRUE;
263 #endif
264     }
265   else
266     {
267       return TRUE;
268     }
269 }
270
271 gboolean
272 empathy_connectivity_get_use_conn (EmpathyConnectivity *connectivity)
273 {
274   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
275
276   return priv->use_conn;
277 }
278
279 void
280 empathy_connectivity_set_use_conn (EmpathyConnectivity *connectivity,
281     gboolean use_conn)
282 {
283   EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
284
285   if (use_conn == priv->use_conn)
286     return;
287
288   DEBUG ("use_conn gconf key changed; new value = %s",
289       use_conn ? "true" : "false");
290
291   priv->use_conn = use_conn;
292
293 #ifdef HAVE_NM
294   if (use_conn)
295     {
296       connectivity_nm_state_change_cb (priv->nm_client, NULL, connectivity);
297 #else
298   if (FALSE)
299     {
300 #endif
301     }
302   else
303     {
304       g_signal_emit (connectivity, signals[STATE_CHANGE], 0,
305           FALSE, TRUE);
306     }
307
308   g_object_notify (G_OBJECT (connectivity), "use-conn");
309 }