diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 46 | ||||
-rw-r--r-- | src/empathy-tube-dispatch.c | 377 | ||||
-rw-r--r-- | src/empathy-tube-dispatch.h | 75 |
3 files changed, 498 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index d9c2b2aa4..faf9cd474 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,13 @@ bin_PROGRAMS = \ empathy \ empathy-logs +BUILT_SOURCES= \ + empathy-marshal.h \ + empathy-marshal.c \ + empathy-marshal.list \ + empathy-tube-dispatch-enumtypes.h \ + empathy-tube-dispatch-enumtypes.c + empathy_SOURCES = \ bacon-message-connection.c bacon-message-connection.h \ empathy.c \ @@ -29,8 +36,11 @@ empathy_SOURCES = \ empathy-new-chatroom-dialog.c empathy-new-chatroom-dialog.h \ empathy-preferences.c empathy-preferences.h \ empathy-status-icon.c empathy-status-icon.h \ + empathy-tube-dispatch.c empathy-tube-dispatch.h \ ephy-spinner.c ephy-spinner.h +nodist_empathy_SOURCES = $(BUILT_SOURCES) + empathy_logs_SOURCES = empathy-logs.c gladedir = $(datadir)/empathy @@ -49,6 +59,42 @@ glade_DATA = \ dist_man_MANS = \ empathy.1 +empathy-marshal.list: $(empathy_SOURCES) Makefile.am + ( cd $(srcdir) && \ + sed -n -e 's/.*empathy_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ + $(empathy_SOURCES) ) \ + | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp + if cmp -s $@.tmp $@; then \ + rm $@.tmp; \ + else \ + mv $@.tmp $@; \ + fi + +%-marshal.h: %-marshal.list Makefile + $(GLIB_GENMARSHAL) --header --prefix=_$(subst -,_,$*)_marshal $< > $*-marshal.h + +%-marshal.c: %-marshal.list Makefile + echo "#include \"empathy-marshal.h\"" > $@ && \ + $(GLIB_GENMARSHAL) --body --prefix=_$(subst -,_,$*)_marshal $< >> $*-marshal.c + +# rules for making the glib enum objects +%-enumtypes.h: %.h Makefile.in + glib-mkenums \ + --fhead "#ifndef __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__\n#define __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define $(shell echo $* | tr [:lower:]- [:upper:]_ | sed 's/_.*//')_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __$(shell echo $* | tr [:lower:]- [:upper:]_)_ENUM_TYPES_H__ */" \ + $< > $@ + +%-enumtypes.c: %.h Makefile.in + glib-mkenums \ + --fhead "#include <$*.h>\n#include <$*-enumtypes.h>" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@VALUENAME@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + $< > $@ + EXTRA_DIST = \ $(autostart_DATA) \ $(glade_DATA) 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); +} + diff --git a/src/empathy-tube-dispatch.h b/src/empathy-tube-dispatch.h new file mode 100644 index 000000000..f1328bb68 --- /dev/null +++ b/src/empathy-tube-dispatch.h @@ -0,0 +1,75 @@ +/* + * empathy-tube-dispatch.h - Header 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 + */ + +#ifndef __EMPATHY_TUBE_DISPATCH_H__ +#define __EMPATHY_TUBE_DISPATCH_H__ + +#include <glib-object.h> + +#include <libempathy/empathy-dispatch-operation.h> + +G_BEGIN_DECLS + +typedef enum { + EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN, + EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE, + EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE, +} EmpathyTubeDispatchAbility; + +typedef struct _EmpathyTubeDispatch EmpathyTubeDispatch; +typedef struct _EmpathyTubeDispatchClass EmpathyTubeDispatchClass; + +struct _EmpathyTubeDispatchClass { + GObjectClass parent_class; +}; + +struct _EmpathyTubeDispatch { + GObject parent; +}; + +GType empathy_tube_dispatch_get_type(void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_TUBE_DISPATCH \ + (empathy_tube_dispatch_get_type()) +#define EMPATHY_TUBE_DISPATCH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_TUBE_DISPATCH, \ + EmpathyTubeDispatch)) +#define EMPATHY_TUBE_DISPATCH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_TUBE_DISPATCH, \ + EmpathyTubeDispatchClass)) +#define EMPATHY_IS_TUBE_DISPATCH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_TUBE_DISPATCH)) +#define EMPATHY_IS_TUBE_DISPATCH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_TUBE_DISPATCH)) +#define EMPATHY_TUBE_DISPATCH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_TUBE_DISPATCH, \ + EmpathyTubeDispatchClass)) + +EmpathyTubeDispatch * empathy_tube_dispatch_new ( + EmpathyDispatchOperation *operation); + +EmpathyTubeDispatchAbility empathy_tube_dispatch_is_dispatchable ( + EmpathyTubeDispatch *tube_dispatch); +void empathy_tube_dispatch_handle (EmpathyTubeDispatch *tube_dispatch); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_TUBE_DISPATCH_H__*/ |