From 796c6e95ecab316f927092391affe35d6b01e99f Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Wed, 14 Sep 2011 16:24:55 +0100 Subject: Import EmpathyConnectivity as McdConnectivityMonitor I'll wrap this up in the hateful McdTransport[Plugin] API forthwith. --- src/Makefile.am | 8 +- src/connectivity-monitor.c | 438 +++++++++++++++++++++++++++++++++++++++++++++ src/connectivity-monitor.h | 74 ++++++++ 3 files changed, 519 insertions(+), 1 deletion(-) create mode 100644 src/connectivity-monitor.c create mode 100644 src/connectivity-monitor.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 7b13de59..9a91ba16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,8 @@ INCLUDES = \ $(TELEPATHY_CFLAGS) \ $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ + $(NETWORK_MANAGER_CFLAGS) \ + $(CONNMAN_CFLAGS) \ -DG_LOG_DOMAIN=\"mcd\" \ -DMCD_PLUGIN_LOADER_DIR=\"@libdir@/mission-control-plugins.@MCP_ABI_VERSION@\" \ -DMC_DISABLE_DEPRECATED -I$(top_srcdir) @@ -97,7 +99,9 @@ libmcd_convenience_la_LIBADD = \ $(top_builddir)/mission-control-plugins/libmission-control-plugins.la \ $(TELEPATHY_LIBS) \ $(DBUS_LIBS) \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(NETWORK_MANAGER_LIBS) \ + $(CONNMAN_LIBS) if ENABLE_GNOME_KEYRING libmcd_convenience_la_LIBADD += $(GNOME_KEYRING_LIBS) @@ -168,6 +172,8 @@ libmcd_convenience_la_SOURCES = \ channel-utils.h \ client-registry.c \ client-registry.h \ + connectivity-monitor.c \ + connectivity-monitor.h \ gtypes.c \ mcd-dbusprop.c \ mcd-dbusprop.h \ diff --git a/src/connectivity-monitor.c b/src/connectivity-monitor.c new file mode 100644 index 00000000..3235f776 --- /dev/null +++ b/src/connectivity-monitor.c @@ -0,0 +1,438 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* + * Copyright © 2009–2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Jonny Lamb + * Will Thompson + */ + +#include "config.h" +#include "connectivity-monitor.h" + + +#ifdef HAVE_NM +# ifdef HAVE_CONNMAN +# error tried to build both Network Manager and ConnMan support simultaneously! +/* I mean, we could support both one day, but not for now. */ +# endif +/* Moving swiftly on… */ +#include +#endif + +#ifdef HAVE_CONNMAN +#include +#endif + +#include + +#include "mcd-debug.h" + +struct _McdConnectivityMonitorPrivate { +#ifdef HAVE_NM + NMClient *nm_client; + gulong state_change_signal_id; +#endif + +#ifdef HAVE_CONNMAN + DBusGProxy *proxy; +#endif + + gboolean connected; + gboolean use_conn; +}; + +enum { + STATE_CHANGE, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_USE_CONN, +}; + +static guint signals[LAST_SIGNAL]; +static McdConnectivityMonitor *connectivity_monitor_singleton = NULL; + +G_DEFINE_TYPE (McdConnectivityMonitor, mcd_connectivity_monitor, G_TYPE_OBJECT); + +static void +connectivity_monitor_change_state (McdConnectivityMonitor *connectivity_monitor, + gboolean new_state) +{ + McdConnectivityMonitorPrivate *priv; + + priv = connectivity_monitor->priv; + + if (priv->connected == new_state) + return; + + priv->connected = new_state; + + g_signal_emit (connectivity_monitor, signals[STATE_CHANGE], 0, + priv->connected); +} + +#ifdef HAVE_NM + +#if !defined(NM_CHECK_VERSION) +#define NM_CHECK_VERSION(x,y,z) 0 +#endif + +static void +connectivity_monitor_nm_state_change_cb (NMClient *client, + const GParamSpec *pspec, + McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv; + gboolean new_nm_connected; + NMState state; + + priv = connectivity_monitor->priv; + + if (!priv->use_conn) + return; + + state = nm_client_get_state (priv->nm_client); + new_nm_connected = !(state == NM_STATE_CONNECTING +#if NM_CHECK_VERSION(0,8,992) + || state == NM_STATE_DISCONNECTING +#endif + || state == NM_STATE_ASLEEP + || state == NM_STATE_DISCONNECTED); + + DEBUG ("New NetworkManager network state %d (connected: %s)", state, + new_nm_connected ? "true" : "false"); + + connectivity_monitor_change_state (connectivity_monitor, new_nm_connected); +} +#endif + +#ifdef HAVE_CONNMAN +static void +connectivity_monitor_connman_state_changed_cb (DBusGProxy *proxy, + const gchar *new_state, + McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv; + gboolean new_connected; + + priv = connectivity_monitor->priv; + + if (!priv->use_conn) + return; + + new_connected = !tp_strdiff (new_state, "online"); + + DEBUG ("New ConnMan network state %s", new_state); + + connectivity_monitor_change_state (connectivity_monitor, new_connected); +} + +static void +connectivity_monitor_connman_check_state_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) +{ + McdConnectivityMonitor *connectivity_monitor = (McdConnectivityMonitor *) 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_monitor_connman_state_changed_cb (proxy, state, + connectivity_monitor); + g_free (state); + } + else + { + DEBUG ("Failed to call GetState: %s", error->message); + connectivity_monitor_connman_state_changed_cb (proxy, "offline", + connectivity_monitor); + } +} + +static void +connectivity_monitor_connman_check_state (McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv; + + priv = connectivity_monitor->priv; + + dbus_g_proxy_begin_call (priv->proxy, "GetState", + connectivity_monitor_connman_check_state_cb, connectivity_monitor, NULL, + G_TYPE_INVALID); +} +#endif + +static void +mcd_connectivity_monitor_init (McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv; +#ifdef HAVE_CONNMAN + DBusGConnection *connection; + GError *error = NULL; +#endif + + priv = G_TYPE_INSTANCE_GET_PRIVATE (connectivity_monitor, + MCD_TYPE_CONNECTIVITY_MONITOR, McdConnectivityMonitorPrivate); + + connectivity_monitor->priv = priv; + + 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_monitor_nm_state_change_cb), connectivity_monitor); + + connectivity_monitor_nm_state_change_cb (priv->nm_client, NULL, connectivity_monitor); + } + 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, + "net.connman", "/", + "net.connman.Manager"); + + dbus_g_object_register_marshaller ( + g_cclosure_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_monitor_connman_state_changed_cb), + connectivity_monitor, NULL); + + connectivity_monitor_connman_check_state (connectivity_monitor); + } + 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_monitor_finalize (GObject *object) +{ +#ifdef HAVE_NM + McdConnectivityMonitor *connectivity_monitor = MCD_CONNECTIVITY_MONITOR (object); + McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv; + + 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 + McdConnectivityMonitor *connectivity_monitor = MCD_CONNECTIVITY_MONITOR (object); + McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv; + + if (priv->proxy != NULL) + { + dbus_g_proxy_disconnect_signal (priv->proxy, "StateChanged", + G_CALLBACK (connectivity_monitor_connman_state_changed_cb), connectivity_monitor); + + g_object_unref (priv->proxy); + priv->proxy = NULL; + } +#endif + + G_OBJECT_CLASS (mcd_connectivity_monitor_parent_class)->finalize (object); +} + +static void +connectivity_monitor_dispose (GObject *object) +{ + G_OBJECT_CLASS (mcd_connectivity_monitor_parent_class)->dispose (object); +} + +static GObject * +connectivity_monitor_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *retval; + + if (!connectivity_monitor_singleton) + { + retval = G_OBJECT_CLASS (mcd_connectivity_monitor_parent_class)->constructor + (type, n_construct_params, construct_params); + + connectivity_monitor_singleton = MCD_CONNECTIVITY_MONITOR (retval); + g_object_add_weak_pointer (retval, (gpointer) &connectivity_monitor_singleton); + } + else + { + retval = g_object_ref (connectivity_monitor_singleton); + } + + return retval; +} + +static void +connectivity_monitor_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + McdConnectivityMonitor *connectivity_monitor = MCD_CONNECTIVITY_MONITOR (object); + + switch (param_id) + { + case PROP_USE_CONN: + g_value_set_boolean (value, mcd_connectivity_monitor_get_use_conn ( + connectivity_monitor)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +connectivity_monitor_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + McdConnectivityMonitor *connectivity_monitor = MCD_CONNECTIVITY_MONITOR (object); + + switch (param_id) + { + case PROP_USE_CONN: + mcd_connectivity_monitor_set_use_conn (connectivity_monitor, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + }; +} + +static void +mcd_connectivity_monitor_class_init (McdConnectivityMonitorClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + + oclass->finalize = connectivity_monitor_finalize; + oclass->dispose = connectivity_monitor_dispose; + oclass->constructor = connectivity_monitor_constructor; + oclass->get_property = connectivity_monitor_get_property; + oclass->set_property = connectivity_monitor_set_property; + + signals[STATE_CHANGE] = + g_signal_new ("state-change", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 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 (McdConnectivityMonitorPrivate)); +} + +/* public methods */ + +McdConnectivityMonitor * +mcd_connectivity_monitor_new (void) +{ + return g_object_new (MCD_TYPE_CONNECTIVITY_MONITOR, NULL); +} + +gboolean +mcd_connectivity_monitor_is_online (McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv; + + return priv->connected; +} + +gboolean +mcd_connectivity_monitor_get_use_conn (McdConnectivityMonitor *connectivity_monitor) +{ + McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv; + + return priv->use_conn; +} + +void +mcd_connectivity_monitor_set_use_conn (McdConnectivityMonitor *connectivity_monitor, + gboolean use_conn) +{ + McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv; + + if (use_conn == priv->use_conn) + return; + + DEBUG ("use_conn GSetting 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_monitor_nm_state_change_cb (priv->nm_client, NULL, connectivity_monitor); +#elif defined(HAVE_CONNMAN) + connectivity_monitor_connman_check_state (connectivity_monitor); +#endif + } + else +#endif + { + connectivity_monitor_change_state (connectivity_monitor, TRUE); + } + + g_object_notify (G_OBJECT (connectivity_monitor), "use-conn"); +} diff --git a/src/connectivity-monitor.h b/src/connectivity-monitor.h new file mode 100644 index 00000000..ce4b59e7 --- /dev/null +++ b/src/connectivity-monitor.h @@ -0,0 +1,74 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* + * Copyright © 2009–2011 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Jonny Lamb + * Will Thompson + */ + +#ifndef MCD_CONNECTIVITY_MONITOR_H +#define MCD_CONNECTIVITY_MONITOR_H + +#include + +G_BEGIN_DECLS + +#define MCD_TYPE_CONNECTIVITY_MONITOR (mcd_connectivity_monitor_get_type ()) +#define MCD_CONNECTIVITY_MONITOR(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), MCD_TYPE_CONNECTIVITY_MONITOR, \ + McdConnectivityMonitor)) +#define MCD_CONNECTIVITY_MONITOR_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST ((k), MCD_TYPE_CONNECTIVITY_MONITOR, \ + McdConnectivityMonitorClass)) +#define MCD_IS_CONNECTIVITY_MONITOR(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), MCD_TYPE_CONNECTIVITY_MONITOR)) +#define MCD_IS_CONNECTIVITY_MONITOR_CLASS(k) \ + (G_TYPE_CHECK_CLASS_TYPE ((k), MCD_TYPE_CONNECTIVITY_MONITOR)) +#define MCD_CONNECTIVITY_MONITOR_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), MCD_TYPE_CONNECTIVITY_MONITOR, \ + McdConnectivityMonitorClass)) + +typedef struct _McdConnectivityMonitor McdConnectivityMonitor; +typedef struct _McdConnectivityMonitorClass McdConnectivityMonitorClass; +typedef struct _McdConnectivityMonitorPrivate McdConnectivityMonitorPrivate; + +struct _McdConnectivityMonitor { + GObject parent; + McdConnectivityMonitorPrivate *priv; +}; + +struct _McdConnectivityMonitorClass { + GObjectClass parent_class; +}; + +GType mcd_connectivity_monitor_get_type (void); + +/* public methods */ + +McdConnectivityMonitor *mcd_connectivity_monitor_new (void); + +gboolean mcd_connectivity_monitor_is_online (McdConnectivityMonitor *connectivity); + +gboolean mcd_connectivity_monitor_get_use_conn (McdConnectivityMonitor *connectivity); +void mcd_connectivity_monitor_set_use_conn (McdConnectivityMonitor *connectivity, + gboolean use_conn); + +G_END_DECLS + +#endif /* MCD_CONNECTIVITY_MONITOR_H */ + -- cgit v1.2.1