diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-01-10 00:13:45 +0800 |
---|---|---|
committer | Xavier Claessens <xclaesse@src.gnome.org> | 2009-01-10 00:13:45 +0800 |
commit | 0d1f7a91769775a85a3d201fade513978f23557a (patch) | |
tree | a997ed93110285f13857e1a9881d1f047e74e098 /src/empathy-tube-dispatch.c | |
parent | d971d3e84d6c6f5791b3de7557a5708f4d110044 (diff) | |
download | gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar.gz gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar.bz2 gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar.lz gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar.xz gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.tar.zst gsoc2013-empathy-0d1f7a91769775a85a3d201fade513978f23557a.zip |
Add EmpathyTubeDispatcher as a helper for dispatching tubes
Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
svn path=/trunk/; revision=2157
Diffstat (limited to 'src/empathy-tube-dispatch.c')
-rw-r--r-- | src/empathy-tube-dispatch.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/empathy-tube-dispatch.c b/src/empathy-tube-dispatch.c new file mode 100644 index 000000000..5c162bb27 --- /dev/null +++ b/src/empathy-tube-dispatch.c @@ -0,0 +1,377 @@ +/* + * empathy-tube-dispatch.c - Source for EmpathyTubeDispatch + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + * 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 + */ + + +#include <stdio.h> +#include <stdlib.h> + +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/proxy-subclass.h> + +#include <libempathy/empathy-tube-handler.h> +#include <extensions/extensions.h> + +#include "empathy-tube-dispatch.h" +#include "empathy-tube-dispatch-enumtypes.h" + + +G_DEFINE_TYPE(EmpathyTubeDispatch, empathy_tube_dispatch, G_TYPE_OBJECT) + +static void empathy_tube_dispatch_set_ability ( + EmpathyTubeDispatch *tube_dispatch, + EmpathyTubeDispatchAbility dispatchability); + +/* private structure */ +typedef struct _EmpathyTubeDispatchPriv EmpathyTubeDispatchPriv; + +/* properties */ +enum { + PROP_OPERATION = 1, + PROP_DISPATCHABILITY +}; + + +struct _EmpathyTubeDispatchPriv +{ + gboolean dispose_has_run; + EmpathyDispatchOperation *operation; + EmpathyTubeDispatchAbility dispatchability; + gchar *bus_name; + gchar *object_path; + TpDBusDaemon *dbus; +}; + +#define GET_PRIV(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + EMPATHY_TYPE_TUBE_DISPATCH, EmpathyTubeDispatchPriv)) + +static void +empathy_tube_dispatch_init (EmpathyTubeDispatch *obj) +{ + EmpathyTubeDispatchPriv *priv = GET_PRIV (obj); + + priv->dispatchability = EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN; +} + +static void empathy_tube_dispatch_dispose (GObject *object); +static void empathy_tube_dispatch_finalize (GObject *object); + +static void +empathy_tube_dispatch_list_activatable_names_cb (TpDBusDaemon *proxy, + const gchar **names, const GError *error, gpointer user_data, + GObject *object) +{ + EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + gchar **name; + + for (name = (gchar **) names; *name != NULL; name++) + { + if (!tp_strdiff (*name, priv->bus_name)) + { + empathy_tube_dispatch_set_ability (self, + EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE); + return; + } + } + + empathy_tube_dispatch_set_ability (self, + EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE); +} + +static void +empathy_tube_dispatch_name_has_owner_cb (TpDBusDaemon *proxy, + gboolean has_owner, const GError *error, gpointer user_data, + GObject *object) +{ + EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + + if (error != NULL) + { + empathy_tube_dispatch_set_ability (self, + EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE); + return; + } + + if (has_owner) + { + empathy_tube_dispatch_set_ability (self, + EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE); + } + else + { + tp_cli_dbus_daemon_call_list_activatable_names (priv->dbus, -1, + empathy_tube_dispatch_list_activatable_names_cb, NULL, NULL, + G_OBJECT (self)); + } +} + +static void +empathy_tube_dispatch_constructed (GObject *object) +{ + EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + TpChannel *channel; + GHashTable *properties; + const gchar *service; + + priv->dbus = tp_dbus_daemon_new (tp_get_bus()); + + channel = empathy_dispatch_operation_get_channel (priv->operation); + properties = tp_channel_borrow_immutable_properties (channel); + + service = tp_asv_get_string (properties, + EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service"); + + + if (service == NULL) + goto failed; + + priv->bus_name = empathy_tube_handler_build_bus_name ( + TP_TUBE_TYPE_STREAM, service); + priv->object_path = + empathy_tube_handler_build_object_path (TP_TUBE_TYPE_STREAM, service); + + tp_cli_dbus_daemon_call_name_has_owner (priv->dbus, -1, priv->bus_name, + empathy_tube_dispatch_name_has_owner_cb, NULL, NULL, G_OBJECT (self)); + + + g_object_unref (channel); + return; + +failed: + empathy_tube_dispatch_set_ability (self, + EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE); +} + +static void +empathy_tube_dispatch_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch); + + switch (property_id) + { + case PROP_OPERATION: + priv->operation = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +empathy_tube_dispatch_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch); + + switch (property_id) + { + case PROP_OPERATION: + g_value_set_object (value, priv->operation); + break; + case PROP_DISPATCHABILITY: + g_value_set_enum (value, priv->dispatchability); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +empathy_tube_dispatch_class_init ( + EmpathyTubeDispatchClass *empathy_tube_dispatch_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_tube_dispatch_class); + GParamSpec *param_spec; + + g_type_class_add_private (empathy_tube_dispatch_class, + sizeof (EmpathyTubeDispatchPriv)); + + object_class->set_property = empathy_tube_dispatch_set_property; + object_class->get_property = empathy_tube_dispatch_get_property; + + object_class->constructed = empathy_tube_dispatch_constructed; + object_class->dispose = empathy_tube_dispatch_dispose; + object_class->finalize = empathy_tube_dispatch_finalize; + + param_spec = g_param_spec_object ("operation", + "operation", "The telepathy connection", + EMPATHY_TYPE_DISPATCH_OPERATION, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_OPERATION, param_spec); + + param_spec = g_param_spec_enum ("dispatchability", + "dispatchability", + "Whether or not there is a handler to dispatch the operation to", + EMPATHY_TYPE_TUBE_DISPATCH_ABILITY, EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DISPATCHABILITY, + param_spec); + +} + +void +empathy_tube_dispatch_dispose (GObject *object) +{ + EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + /* release any references held by the object here */ + if (priv->operation != NULL) + g_object_unref (priv->operation); + + priv->operation = NULL; + + if (priv->dbus != NULL) + g_object_unref (priv->dbus); + + priv->dbus = NULL; + + + if (G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose) + G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose (object); +} + +void +empathy_tube_dispatch_finalize (GObject *object) +{ + EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object); + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + + g_free (priv->bus_name); + g_free (priv->object_path); + + /* free any data held directly by the object here */ + + G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->finalize (object); +} + +EmpathyTubeDispatch * +empathy_tube_dispatch_new (EmpathyDispatchOperation *operation) +{ + return EMPATHY_TUBE_DISPATCH (g_object_new (EMPATHY_TYPE_TUBE_DISPATCH, + "operation", operation, NULL)); +} + +EmpathyTubeDispatchAbility +empathy_tube_dispatch_is_dispatchable (EmpathyTubeDispatch *tube_dispatch) +{ + EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch); + + return priv->dispatchability; +} + +static void +empathy_tube_dispatch_set_ability (EmpathyTubeDispatch *tube_dispatch, + EmpathyTubeDispatchAbility dispatchability) +{ + EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch); + + if (priv->dispatchability == dispatchability) + return; + + priv->dispatchability = dispatchability; + g_object_notify (G_OBJECT (tube_dispatch), "dispatchability"); +} + +static void +empathy_tube_do_dispatch (EmpathyTubeDispatch *self) +{ + EmpathyTubeDispatchPriv *priv = GET_PRIV (self); + TpChannel *channel; + TpProxy *connection; + TpProxy *thandler; + gchar *object_path; + guint handle_type; + guint handle; + + channel = empathy_dispatch_operation_get_channel (priv->operation); + + + /* Create the proxy for the tube handler */ + thandler = g_object_new (TP_TYPE_PROXY, + "dbus-connection", tp_get_bus (), + "bus-name", priv->bus_name, + "object-path", priv->object_path, + NULL); + + tp_proxy_add_interface_by_id (thandler, EMP_IFACE_QUARK_TUBE_HANDLER); + + /* Give the tube to the handler */ + g_object_get (channel, + "connection", &connection, + "object-path", &object_path, + "handle_type", &handle_type, + "handle", &handle, + NULL); + + emp_cli_tube_handler_call_handle_tube (thandler, -1, + connection->bus_name, connection->object_path, + object_path, handle_type, handle, NULL, NULL, NULL, NULL); + + g_object_unref (channel); + g_object_unref (thandler); + g_object_unref (connection); + g_free (object_path); +} + +void +empathy_tube_dispatch_handle (EmpathyTubeDispatch *tube_dispatch) +{ + EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch); + + /* Keep ourselves alive untill the dispatching is finished */ + g_object_ref (tube_dispatch); + + /* If we can't claim it, don't do anything */ + if (!empathy_dispatch_operation_claim (priv->operation)) + goto done; + + if (priv->dispatchability != EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE) + { + TpChannel *channel = empathy_dispatch_operation_get_channel ( + priv->operation); + + tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL); + + g_object_unref (channel); + goto done; + } + + empathy_tube_do_dispatch (tube_dispatch); + + return; +done: + g_object_unref (tube_dispatch); +} + |