*/
#include "config.h"
+#include "empathy-connectivity.h"
-#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
-#include <libempathy/empathy-debug.h>
+#ifdef HAVE_NM
+#include <nm-client.h>
+#endif
+
+#ifdef HAVE_CONNMAN
+#include <dbus/dbus-glib.h>
+#endif
+
+#include <telepathy-glib/util.h>
+
+#include "empathy-utils.h"
+#include "empathy-marshal.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_CONNECTIVITY
+#include "empathy-debug.h"
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectivity)
typedef struct {
- gboolean dispose_run;
+#ifdef HAVE_NM
+ NMClient *nm_client;
+ gulong state_change_signal_id;
+#endif
+
+#ifdef HAVE_CONNMAN
+ DBusGProxy *proxy;
+#endif
+
+ gboolean connected;
+ gboolean use_conn;
} EmpathyConnectivityPriv;
enum {
LAST_SIGNAL
};
+enum {
+ PROP_0,
+ PROP_USE_CONN,
+};
+
static guint signals[LAST_SIGNAL];
static EmpathyConnectivity *connectivity_singleton = NULL;
G_DEFINE_TYPE (EmpathyConnectivity, empathy_connectivity, G_TYPE_OBJECT);
+static void
+connectivity_change_state (EmpathyConnectivity *connectivity,
+ gboolean new_state)
+{
+ EmpathyConnectivityPriv *priv;
+
+ priv = GET_PRIV (connectivity);
+
+ if (priv->connected == new_state)
+ return;
+
+ priv->connected = new_state;
+
+ g_signal_emit (connectivity, signals[STATE_CHANGE], 0,
+ priv->connected);
+}
+
+#ifdef HAVE_NM
+static void
+connectivity_nm_state_change_cb (NMClient *client,
+ const GParamSpec *pspec,
+ EmpathyConnectivity *connectivity)
+{
+ EmpathyConnectivityPriv *priv;
+ gboolean new_nm_connected;
+ NMState state;
+
+ priv = GET_PRIV (connectivity);
+
+ if (!priv->use_conn)
+ return;
+
+ state = nm_client_get_state (priv->nm_client);
+ new_nm_connected = !(state == NM_STATE_CONNECTING
+ || state == NM_STATE_DISCONNECTED);
+
+ DEBUG ("New NetworkManager network state %d (connected: %s)", state,
+ new_nm_connected ? "true" : "false");
+
+ connectivity_change_state (connectivity, new_nm_connected);
+}
+#endif
+
+#ifdef HAVE_CONNMAN
+static void
+connectivity_connman_state_changed_cb (DBusGProxy *proxy,
+ const gchar *new_state,
+ EmpathyConnectivity *connectivity)
+{
+ EmpathyConnectivityPriv *priv;
+ gboolean new_connected;
+
+ priv = GET_PRIV (connectivity);
+
+ if (!priv->use_conn)
+ return;
+
+ new_connected = !tp_strdiff (new_state, "online");
+
+ DEBUG ("New ConnMan network state %s", new_state);
+
+ connectivity_change_state (connectivity, new_connected);
+}
+
+static void
+connectivity_connman_check_state_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call_id,
+ gpointer user_data)
+{
+ EmpathyConnectivity *connectivity = (EmpathyConnectivity *) user_data;
+ GError *error = NULL;
+ gchar *state;
+
+ if (dbus_g_proxy_end_call (proxy, call_id, &error,
+ G_TYPE_STRING, &state, G_TYPE_INVALID))
+ {
+ connectivity_connman_state_changed_cb (proxy, state,
+ connectivity);
+ g_free (state);
+ }
+ else
+ {
+ DEBUG ("Failed to call GetState: %s", error->message);
+ connectivity_connman_state_changed_cb (proxy, "offline",
+ connectivity);
+ }
+}
+
+static void
+connectivity_connman_check_state (EmpathyConnectivity *connectivity)
+{
+ EmpathyConnectivityPriv *priv;
+
+ priv = GET_PRIV (connectivity);
+
+ dbus_g_proxy_begin_call (priv->proxy, "GetState",
+ connectivity_connman_check_state_cb, connectivity, NULL,
+ G_TYPE_INVALID);
+}
+#endif
+
static void
empathy_connectivity_init (EmpathyConnectivity *connectivity)
{
EmpathyConnectivityPriv *priv;
+#ifdef HAVE_CONNMAN
+ DBusGConnection *connection;
+ GError *error = NULL;
+#endif
priv = G_TYPE_INSTANCE_GET_PRIVATE (connectivity,
EMPATHY_TYPE_CONNECTIVITY, EmpathyConnectivityPriv);
connectivity->priv = priv;
- priv->dispose_run = FALSE;
+
+ priv->use_conn = TRUE;
+
+#ifdef HAVE_NM
+ priv->nm_client = nm_client_new ();
+ if (priv->nm_client != NULL)
+ {
+ priv->state_change_signal_id = g_signal_connect (priv->nm_client,
+ "notify::" NM_CLIENT_STATE,
+ G_CALLBACK (connectivity_nm_state_change_cb), connectivity);
+
+ connectivity_nm_state_change_cb (priv->nm_client, NULL, connectivity);
+ }
+ else
+ {
+ DEBUG ("Failed to get NetworkManager proxy");
+ }
+#endif
+
+#ifdef HAVE_CONNMAN
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (connection != NULL)
+ {
+ priv->proxy = dbus_g_proxy_new_for_name (connection,
+ "org.moblin.connman", "/",
+ "org.moblin.connman.Manager");
+
+ dbus_g_object_register_marshaller (
+ _empathy_marshal_VOID__STRING,
+ G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID);
+
+ dbus_g_proxy_add_signal (priv->proxy, "StateChanged",
+ G_TYPE_STRING, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (priv->proxy, "StateChanged",
+ G_CALLBACK (connectivity_connman_state_changed_cb),
+ connectivity, NULL);
+
+ connectivity_connman_check_state (connectivity);
+ }
+ else
+ {
+ DEBUG ("Failed to get system bus connection: %s", error->message);
+ g_error_free (error);
+ }
+#endif
+
+#if !defined(HAVE_NM) && !defined(HAVE_CONNMAN)
+ priv->connected = TRUE;
+#endif
}
static void
connectivity_finalize (GObject *object)
{
- EmpathyConnectivity *manager = EMPATHY_CONNECTIVITY (obj);
- EmpathyConnectivityPriv *priv = GET_PRIV (manager);
+#ifdef HAVE_NM
+ EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
+ EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
- G_OBJECT_CLASS (empathy_connectivity_parent_class)->finalize (obj);
+ if (priv->nm_client != NULL)
+ {
+ g_signal_handler_disconnect (priv->nm_client,
+ priv->state_change_signal_id);
+ priv->state_change_signal_id = 0;
+ g_object_unref (priv->nm_client);
+ priv->nm_client = NULL;
+ }
+#endif
+
+#ifdef HAVE_CONNMAN
+ EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
+ EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
+
+ if (priv->proxy != NULL)
+ {
+ dbus_g_proxy_disconnect_signal (priv->proxy, "StateChanged",
+ G_CALLBACK (connectivity_connman_state_changed_cb), connectivity);
+
+ g_object_unref (priv->proxy);
+ priv->proxy = NULL;
+ }
+#endif
+
+ G_OBJECT_CLASS (empathy_connectivity_parent_class)->finalize (object);
}
static void
connectivity_dispose (GObject *object)
{
- EmpathyConnectivity *manager = EMPATHY_CONNECTIVITY (obj);
- EmpathyConnectivityPriv *priv = GET_PRIV (manager);
-
- if (priv->dispose_run)
- return;
-
- priv->dispose_run = TRUE;
-
- G_OBJECT_CLASS (empathy_connectivity_parent_class)->dispose (obj);
+ G_OBJECT_CLASS (empathy_connectivity_parent_class)->dispose (object);
}
static GObject *
{
GObject *retval;
- if (!manager_singleton)
+ if (!connectivity_singleton)
{
retval = G_OBJECT_CLASS (empathy_connectivity_parent_class)->constructor
(type, n_construct_params, construct_params);
- manager_singleton = EMPATHY_CONNECTIVITY (retval);
- g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
+ connectivity_singleton = EMPATHY_CONNECTIVITY (retval);
+ g_object_add_weak_pointer (retval, (gpointer) &connectivity_singleton);
}
else
{
- retval = g_object_ref (manager_singleton);
+ retval = g_object_ref (connectivity_singleton);
}
return retval;
}
+static void
+connectivity_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
+
+ switch (param_id)
+ {
+ case PROP_USE_CONN:
+ g_value_set_boolean (value, empathy_connectivity_get_use_conn (
+ connectivity));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
+static void
+connectivity_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyConnectivity *connectivity = EMPATHY_CONNECTIVITY (object);
+
+ switch (param_id)
+ {
+ case PROP_USE_CONN:
+ empathy_connectivity_set_use_conn (connectivity,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ };
+}
+
static void
empathy_connectivity_class_init (EmpathyConnectivityClass *klass)
{
oclass->finalize = connectivity_finalize;
oclass->dispose = connectivity_dispose;
oclass->constructor = connectivity_constructor;
+ oclass->get_property = connectivity_get_property;
+ oclass->set_property = connectivity_set_property;
signals[STATE_CHANGE] =
g_signal_new ("state-change",
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT, /* TODO */
+ _empathy_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
- 0, NULL);
+ 1, G_TYPE_BOOLEAN, NULL);
+
+ g_object_class_install_property (oclass,
+ PROP_USE_CONN,
+ g_param_spec_boolean ("use-conn",
+ "Use connectivity managers",
+ "Set presence according to connectivity managers",
+ TRUE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_type_class_add_private (oclass, sizeof (EmpathyConnectivityPriv));
}
{
return g_object_new (EMPATHY_TYPE_CONNECTIVITY, NULL);
}
+
+gboolean
+empathy_connectivity_is_online (EmpathyConnectivity *connectivity)
+{
+ EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
+
+ return priv->connected;
+}
+
+gboolean
+empathy_connectivity_get_use_conn (EmpathyConnectivity *connectivity)
+{
+ EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
+
+ return priv->use_conn;
+}
+
+void
+empathy_connectivity_set_use_conn (EmpathyConnectivity *connectivity,
+ gboolean use_conn)
+{
+ EmpathyConnectivityPriv *priv = GET_PRIV (connectivity);
+
+ if (use_conn == priv->use_conn)
+ return;
+
+ DEBUG ("use_conn gconf key changed; new value = %s",
+ use_conn ? "true" : "false");
+
+ priv->use_conn = use_conn;
+
+#if defined(HAVE_NM) || defined(HAVE_CONNMAN)
+ if (use_conn)
+ {
+#if defined(HAVE_NM)
+ connectivity_nm_state_change_cb (priv->nm_client, NULL, connectivity);
+#elif defined(HAVE_CONNMAN)
+ connectivity_connman_check_state (connectivity);
+#endif
+ }
+ else
+#endif
+ {
+ connectivity_change_state (connectivity, TRUE);
+ }
+
+ g_object_notify (G_OBJECT (connectivity), "use-conn");
+}