1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
3 * Copyright (C) 2009 Collabora Ltd.
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.
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.
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
19 * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk>
23 #include "empathy-connectivity.h"
26 #include <nm-client.h>
30 #include <dbus/dbus-glib.h>
33 #include <telepathy-glib/util.h>
35 #include "empathy-utils.h"
36 #include "empathy-marshal.h"
38 #define DEBUG_FLAG EMPATHY_DEBUG_CONNECTIVITY
39 #include "empathy-debug.h"
41 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectivity)
46 gulong state_change_signal_id
;
55 } EmpathyConnectivityPriv
;
67 static guint signals
[LAST_SIGNAL
];
68 static EmpathyConnectivity
*connectivity_singleton
= NULL
;
70 G_DEFINE_TYPE (EmpathyConnectivity
, empathy_connectivity
, G_TYPE_OBJECT
);
73 connectivity_change_state (EmpathyConnectivity
*connectivity
,
76 EmpathyConnectivityPriv
*priv
;
78 priv
= GET_PRIV (connectivity
);
80 if (priv
->connected
== new_state
)
83 priv
->connected
= new_state
;
85 g_signal_emit (connectivity
, signals
[STATE_CHANGE
], 0,
91 #if !defined(NM_CHECK_VERSION)
92 #define NM_CHECK_VERSION(x,y,z) 0
96 connectivity_nm_state_change_cb (NMClient
*client
,
97 const GParamSpec
*pspec
,
98 EmpathyConnectivity
*connectivity
)
100 EmpathyConnectivityPriv
*priv
;
101 gboolean new_nm_connected
;
104 priv
= GET_PRIV (connectivity
);
109 state
= nm_client_get_state (priv
->nm_client
);
110 new_nm_connected
= !(state
== NM_STATE_CONNECTING
111 #if NM_CHECK_VERSION(0,8,992)
112 || state
== NM_STATE_DISCONNECTING
114 || state
== NM_STATE_ASLEEP
115 || state
== NM_STATE_DISCONNECTED
);
117 DEBUG ("New NetworkManager network state %d (connected: %s)", state
,
118 new_nm_connected
? "true" : "false");
120 connectivity_change_state (connectivity
, new_nm_connected
);
126 connectivity_connman_state_changed_cb (DBusGProxy
*proxy
,
127 const gchar
*new_state
,
128 EmpathyConnectivity
*connectivity
)
130 EmpathyConnectivityPriv
*priv
;
131 gboolean new_connected
;
133 priv
= GET_PRIV (connectivity
);
138 new_connected
= !tp_strdiff (new_state
, "online");
140 DEBUG ("New ConnMan network state %s", new_state
);
142 connectivity_change_state (connectivity
, new_connected
);
146 connectivity_connman_check_state_cb (DBusGProxy
*proxy
,
147 DBusGProxyCall
*call_id
,
150 EmpathyConnectivity
*connectivity
= (EmpathyConnectivity
*) user_data
;
151 GError
*error
= NULL
;
154 if (dbus_g_proxy_end_call (proxy
, call_id
, &error
,
155 G_TYPE_STRING
, &state
, G_TYPE_INVALID
))
157 connectivity_connman_state_changed_cb (proxy
, state
,
163 DEBUG ("Failed to call GetState: %s", error
->message
);
164 connectivity_connman_state_changed_cb (proxy
, "offline",
170 connectivity_connman_check_state (EmpathyConnectivity
*connectivity
)
172 EmpathyConnectivityPriv
*priv
;
174 priv
= GET_PRIV (connectivity
);
176 dbus_g_proxy_begin_call (priv
->proxy
, "GetState",
177 connectivity_connman_check_state_cb
, connectivity
, NULL
,
183 empathy_connectivity_init (EmpathyConnectivity
*connectivity
)
185 EmpathyConnectivityPriv
*priv
;
187 DBusGConnection
*connection
;
188 GError
*error
= NULL
;
191 priv
= G_TYPE_INSTANCE_GET_PRIVATE (connectivity
,
192 EMPATHY_TYPE_CONNECTIVITY
, EmpathyConnectivityPriv
);
194 connectivity
->priv
= priv
;
196 priv
->use_conn
= TRUE
;
199 priv
->nm_client
= nm_client_new ();
200 if (priv
->nm_client
!= NULL
)
202 priv
->state_change_signal_id
= g_signal_connect (priv
->nm_client
,
203 "notify::" NM_CLIENT_STATE
,
204 G_CALLBACK (connectivity_nm_state_change_cb
), connectivity
);
206 connectivity_nm_state_change_cb (priv
->nm_client
, NULL
, connectivity
);
210 DEBUG ("Failed to get NetworkManager proxy");
215 connection
= dbus_g_bus_get (DBUS_BUS_SYSTEM
, &error
);
216 if (connection
!= NULL
)
218 priv
->proxy
= dbus_g_proxy_new_for_name (connection
,
220 "net.connman.Manager");
222 dbus_g_object_register_marshaller (
223 _empathy_marshal_VOID__STRING
,
224 G_TYPE_NONE
, G_TYPE_STRING
, G_TYPE_INVALID
);
226 dbus_g_proxy_add_signal (priv
->proxy
, "StateChanged",
227 G_TYPE_STRING
, G_TYPE_INVALID
);
229 dbus_g_proxy_connect_signal (priv
->proxy
, "StateChanged",
230 G_CALLBACK (connectivity_connman_state_changed_cb
),
233 connectivity_connman_check_state (connectivity
);
237 DEBUG ("Failed to get system bus connection: %s", error
->message
);
238 g_error_free (error
);
242 #if !defined(HAVE_NM) && !defined(HAVE_CONNMAN)
243 priv
->connected
= TRUE
;
248 connectivity_finalize (GObject
*object
)
251 EmpathyConnectivity
*connectivity
= EMPATHY_CONNECTIVITY (object
);
252 EmpathyConnectivityPriv
*priv
= GET_PRIV (connectivity
);
254 if (priv
->nm_client
!= NULL
)
256 g_signal_handler_disconnect (priv
->nm_client
,
257 priv
->state_change_signal_id
);
258 priv
->state_change_signal_id
= 0;
259 g_object_unref (priv
->nm_client
);
260 priv
->nm_client
= NULL
;
265 EmpathyConnectivity
*connectivity
= EMPATHY_CONNECTIVITY (object
);
266 EmpathyConnectivityPriv
*priv
= GET_PRIV (connectivity
);
268 if (priv
->proxy
!= NULL
)
270 dbus_g_proxy_disconnect_signal (priv
->proxy
, "StateChanged",
271 G_CALLBACK (connectivity_connman_state_changed_cb
), connectivity
);
273 g_object_unref (priv
->proxy
);
278 G_OBJECT_CLASS (empathy_connectivity_parent_class
)->finalize (object
);
282 connectivity_dispose (GObject
*object
)
284 G_OBJECT_CLASS (empathy_connectivity_parent_class
)->dispose (object
);
288 connectivity_constructor (GType type
,
289 guint n_construct_params
,
290 GObjectConstructParam
*construct_params
)
294 if (!connectivity_singleton
)
296 retval
= G_OBJECT_CLASS (empathy_connectivity_parent_class
)->constructor
297 (type
, n_construct_params
, construct_params
);
299 connectivity_singleton
= EMPATHY_CONNECTIVITY (retval
);
300 g_object_add_weak_pointer (retval
, (gpointer
) &connectivity_singleton
);
304 retval
= g_object_ref (connectivity_singleton
);
311 connectivity_get_property (GObject
*object
,
316 EmpathyConnectivity
*connectivity
= EMPATHY_CONNECTIVITY (object
);
321 g_value_set_boolean (value
, empathy_connectivity_get_use_conn (
325 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
331 connectivity_set_property (GObject
*object
,
336 EmpathyConnectivity
*connectivity
= EMPATHY_CONNECTIVITY (object
);
341 empathy_connectivity_set_use_conn (connectivity
,
342 g_value_get_boolean (value
));
345 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
351 empathy_connectivity_class_init (EmpathyConnectivityClass
*klass
)
353 GObjectClass
*oclass
= G_OBJECT_CLASS (klass
);
355 oclass
->finalize
= connectivity_finalize
;
356 oclass
->dispose
= connectivity_dispose
;
357 oclass
->constructor
= connectivity_constructor
;
358 oclass
->get_property
= connectivity_get_property
;
359 oclass
->set_property
= connectivity_set_property
;
361 signals
[STATE_CHANGE
] =
362 g_signal_new ("state-change",
363 G_TYPE_FROM_CLASS (klass
),
367 _empathy_marshal_VOID__BOOLEAN
,
369 1, G_TYPE_BOOLEAN
, NULL
);
371 g_object_class_install_property (oclass
,
373 g_param_spec_boolean ("use-conn",
374 "Use connectivity managers",
375 "Set presence according to connectivity managers",
377 G_PARAM_CONSTRUCT
| G_PARAM_READWRITE
));
379 g_type_class_add_private (oclass
, sizeof (EmpathyConnectivityPriv
));
384 EmpathyConnectivity
*
385 empathy_connectivity_dup_singleton (void)
387 return g_object_new (EMPATHY_TYPE_CONNECTIVITY
, NULL
);
391 empathy_connectivity_is_online (EmpathyConnectivity
*connectivity
)
393 EmpathyConnectivityPriv
*priv
= GET_PRIV (connectivity
);
395 return priv
->connected
;
399 empathy_connectivity_get_use_conn (EmpathyConnectivity
*connectivity
)
401 EmpathyConnectivityPriv
*priv
= GET_PRIV (connectivity
);
403 return priv
->use_conn
;
407 empathy_connectivity_set_use_conn (EmpathyConnectivity
*connectivity
,
410 EmpathyConnectivityPriv
*priv
= GET_PRIV (connectivity
);
412 if (use_conn
== priv
->use_conn
)
415 DEBUG ("use_conn GSetting key changed; new value = %s",
416 use_conn
? "true" : "false");
418 priv
->use_conn
= use_conn
;
420 #if defined(HAVE_NM) || defined(HAVE_CONNMAN)
424 connectivity_nm_state_change_cb (priv
->nm_client
, NULL
, connectivity
);
425 #elif defined(HAVE_CONNMAN)
426 connectivity_connman_check_state (connectivity
);
432 connectivity_change_state (connectivity
, TRUE
);
435 g_object_notify (G_OBJECT (connectivity
), "use-conn");