[Telepathy-commits] [telepathy-sofiasip/master] Reimplemented TpsipTextFactory as an implementation of TpChannelManager
Mikhail Zabaluev
mikhail.zabaluev at nokia.com
Fri Nov 7 07:36:31 PST 2008
Implemented ExportableChannel on text channel.
---
src/sip-text-channel.c | 27 +++-
src/text-factory.c | 307 +++++++++++++++++++++++++++++++++++-------------
src/text-factory.h | 4 +-
3 files changed, 245 insertions(+), 93 deletions(-)
diff --git a/src/sip-text-channel.c b/src/sip-text-channel.c
index 734b5cc..9099aa7 100644
--- a/src/sip-text-channel.c
+++ b/src/sip-text-channel.c
@@ -64,6 +64,7 @@ G_DEFINE_TYPE_WITH_CODE (TpsipTextChannel, tpsip_text_channel, G_TYPE_OBJECT,
tp_dbus_properties_mixin_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, text_iface_init);
+ G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
static const char *tpsip_text_channel_interfaces[] = {
@@ -85,6 +86,7 @@ enum
PROP_REQUESTED,
PROP_INTERFACES,
PROP_CHANNEL_DESTROYED,
+ PROP_CHANNEL_PROPERTIES,
LAST_PROPERTY
};
@@ -259,6 +261,11 @@ tpsip_text_channel_class_init(TpsipTextChannelClass *klass)
g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
"channel-type");
+ g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
+ "channel-destroyed");
+ g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
+ "channel-properties");
+
param_spec = g_param_spec_object("connection", "TpsipConnection object",
"SIP connection object that owns this SIP media channel object.",
TPSIP_TYPE_CONNECTION,
@@ -296,13 +303,6 @@ tpsip_text_channel_class_init(TpsipTextChannelClass *klass)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
- param_spec = g_param_spec_boolean ("channel-destroyed", "Destroyed?",
- "If true, the channel has *really* closed, rather than just "
- "appearing to do so",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CHANNEL_DESTROYED, param_spec);
-
klass->dbus_props_class.interfaces =
prop_interfaces;
tp_dbus_properties_mixin_class_init (object_class,
@@ -373,6 +373,19 @@ tpsip_text_channel_get_property(GObject *object,
g_value_set_boolean (value, priv->closed);
break;
+ case PROP_CHANNEL_PROPERTIES:
+ g_value_take_boxed (value,
+ tp_dbus_properties_mixin_make_properties_hash (object,
+ TP_IFACE_CHANNEL, "ChannelType",
+ TP_IFACE_CHANNEL, "TargetHandleType",
+ TP_IFACE_CHANNEL, "TargetHandle",
+ TP_IFACE_CHANNEL, "TargetID",
+ TP_IFACE_CHANNEL, "InitiatorHandle",
+ TP_IFACE_CHANNEL, "InitiatorID",
+ TP_IFACE_CHANNEL, "Requested",
+ NULL));
+ break;
+
case PROP_INTERFACES:
g_value_set_static_boxed (value, tpsip_text_channel_interfaces);
break;
diff --git a/src/text-factory.c b/src/text-factory.c
index 2ff0cb4..afdd312 100644
--- a/src/text-factory.c
+++ b/src/text-factory.c
@@ -1,6 +1,6 @@
/*
* text-factory.c - Text channel factory for SIP connection manager
- * Copyright (C) 2007 Collabora Ltd.
+ * Copyright (C) 2007-2008 Collabora Ltd.
* Copyright (C) 2007-2008 Nokia Corporation
*
* This work is free software; you can redistribute it and/or
@@ -22,9 +22,11 @@
#include <string.h>
-#include <telepathy-glib/svc-connection.h>
+#include <telepathy-glib/channel-manager.h>
+#include <telepathy-glib/dbus.h>
#include <telepathy-glib/interfaces.h>
+#include "sip-text-channel.h"
#include "sip-connection.h"
#include "sip-connection-helpers.h"
@@ -36,12 +38,15 @@
#include "debug.h"
-static void factory_iface_init (gpointer, gpointer);
+static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data);
+static void connection_status_changed_cb (TpsipConnection *conn,
+ guint status, guint reason, TpsipTextFactory *self);
+static void tpsip_text_factory_close_all (TpsipTextFactory *self);
G_DEFINE_TYPE_WITH_CODE (TpsipTextFactory, tpsip_text_factory,
G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
- factory_iface_init))
+ G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+ channel_manager_iface_init))
enum
{
@@ -56,6 +61,9 @@ struct _TpsipTextFactoryPrivate
/* guint handle => TpsipTextChannel *channel */
GHashTable *channels;
+ gulong status_changed_id;
+ gulong message_received_id;
+
gboolean dispose_has_run;
};
@@ -74,6 +82,21 @@ tpsip_text_factory_init (TpsipTextFactory *fac)
}
static void
+tpsip_text_factory_constructed (GObject *object)
+{
+ TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (object);
+ TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ GObjectClass *parent_object_class =
+ G_OBJECT_CLASS (tpsip_text_factory_parent_class);
+
+ if (parent_object_class->constructed != NULL)
+ parent_object_class->constructed (object);
+
+ priv->status_changed_id = g_signal_connect (priv->conn,
+ "status-changed", (GCallback) connection_status_changed_cb, object);
+}
+
+static void
tpsip_text_factory_dispose (GObject *object)
{
TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (object);
@@ -84,8 +107,7 @@ tpsip_text_factory_dispose (GObject *object)
priv->dispose_has_run = TRUE;
- tp_channel_factory_iface_close_all (TP_CHANNEL_FACTORY_IFACE (object));
-
+ tpsip_text_factory_close_all (fac);
g_assert (priv->channels == NULL);
if (G_OBJECT_CLASS (tpsip_text_factory_parent_class)->dispose)
@@ -138,6 +160,7 @@ tpsip_text_factory_class_init (TpsipTextFactoryClass *klass)
g_type_class_add_private (klass, sizeof (TpsipTextFactoryPrivate));
+ object_class->constructed = tpsip_text_factory_constructed;
object_class->get_property = tpsip_text_factory_get_property;
object_class->set_property = tpsip_text_factory_set_property;
object_class->dispose = tpsip_text_factory_dispose;
@@ -150,12 +173,18 @@ tpsip_text_factory_class_init (TpsipTextFactoryClass *klass)
}
static void
-tpsip_text_factory_close_all (TpChannelFactoryIface *iface)
+tpsip_text_factory_close_all (TpsipTextFactory *fac)
{
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (iface);
TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
GHashTable *channels;
+ if (priv->status_changed_id != 0)
+ {
+ g_signal_handler_disconnect (priv->conn,
+ priv->status_changed_id);
+ priv->status_changed_id = 0;
+ }
+
if (!priv->channels)
return;
@@ -167,7 +196,7 @@ tpsip_text_factory_close_all (TpChannelFactoryIface *iface)
struct _ForeachData
{
- TpChannelFunc foreach;
+ TpExportableChannelFunc func;
gpointer user_data;
};
@@ -175,19 +204,22 @@ static void
_foreach_slave (gpointer key, gpointer value, gpointer user_data)
{
struct _ForeachData *data = (struct _ForeachData *)user_data;
- TpChannelIface *chan = TP_CHANNEL_IFACE (value);
+ TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
- data->foreach (chan, data->user_data);
+ data->func (chan, data->user_data);
}
static void
-tpsip_text_factory_foreach (TpChannelFactoryIface *iface,
- TpChannelFunc foreach,
- gpointer user_data)
+tpsip_text_factory_foreach_channel (TpChannelManager *manager,
+ TpExportableChannelFunc func,
+ gpointer user_data)
{
- struct _ForeachData data = { foreach, user_data };
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (iface);
+ TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (manager);
TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ struct _ForeachData data;
+
+ data.func = func;
+ data.user_data = user_data;
g_hash_table_foreach (priv->channels, _foreach_slave, &data);
}
@@ -201,11 +233,14 @@ tpsip_text_factory_foreach (TpChannelFactoryIface *iface,
static void
channel_closed (TpsipTextChannel *chan, gpointer user_data)
{
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (user_data);
- TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ TpsipTextFactory *self = TPSIP_TEXT_FACTORY (user_data);
+ TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (self);
TpHandle contact_handle;
gboolean really_destroyed = TRUE;
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ (TpExportableChannel *) chan);
+
if (priv->channels == NULL)
return;
@@ -223,8 +258,8 @@ channel_closed (TpsipTextChannel *chan, gpointer user_data)
{
DEBUG ("reopening channel with handle %u due to pending messages",
contact_handle);
- tp_channel_factory_iface_emit_new_channel (
- (TpChannelFactoryIface *) fac, (TpChannelIface *)chan, NULL);
+ tp_channel_manager_emit_new_channel (self,
+ (TpExportableChannel *) chan, NULL);
}
}
@@ -237,12 +272,13 @@ static TpsipTextChannel *
tpsip_text_factory_new_channel (TpsipTextFactory *fac,
TpHandle handle,
TpHandle initiator,
- gpointer request)
+ gpointer request_token)
{
TpsipTextFactoryPrivate *priv;
TpsipTextChannel *chan;
gchar *object_path;
TpBaseConnection *conn;
+ GSList *request_tokens;
priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
conn = (TpBaseConnection *)(priv->conn);
@@ -265,59 +301,159 @@ tpsip_text_factory_new_channel (TpsipTextFactory *fac,
g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);
- tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *)chan,
- request);
+ if (request_token != NULL)
+ request_tokens = g_slist_prepend (NULL, request_token);
+ else
+ request_tokens = NULL;
+
+ tp_channel_manager_emit_new_channel (fac,
+ (TpExportableChannel *) chan, request_tokens);
+
+ g_slist_free (request_tokens);
return chan;
}
-static inline TpsipTextChannel *
-tpsip_text_factory_lookup_channel (TpsipTextFactory *fac,
- TpHandle handle)
+
+static const gchar * const text_channel_fixed_properties[] = {
+ TP_IFACE_CHANNEL ".ChannelType",
+ TP_IFACE_CHANNEL ".TargetHandleType",
+ NULL
+};
+
+static const gchar * const text_channel_allowed_properties[] = {
+ TP_IFACE_CHANNEL ".TargetHandle",
+ TP_IFACE_CHANNEL ".TargetID",
+ NULL
+};
+
+static void
+tpsip_text_factory_foreach_channel_class (TpChannelManager *manager,
+ TpChannelManagerChannelClassFunc func,
+ gpointer user_data)
{
- TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) tp_g_value_slice_free);
+ GValue *value;
- return (TpsipTextChannel *)g_hash_table_lookup (priv->channels,
- GUINT_TO_POINTER(handle));
+ value = tp_g_value_slice_new (G_TYPE_STRING);
+ g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT);
+ g_hash_table_insert (table, (gchar *) text_channel_fixed_properties[0],
+ value);
+
+ value = tp_g_value_slice_new (G_TYPE_UINT);
+ g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
+ g_hash_table_insert (table, (gchar *) text_channel_fixed_properties[1],
+ value);
+
+ func (manager, table, text_channel_allowed_properties, user_data);
+
+ g_hash_table_destroy (table);
}
-static TpChannelFactoryRequestStatus
-tpsip_text_factory_request (TpChannelFactoryIface *iface,
- const gchar *chan_type,
- TpHandleType handle_type,
- guint handle,
- gpointer request,
- TpChannelIface **ret,
- GError **error)
+
+static gboolean
+tpsip_text_factory_requestotron (TpsipTextFactory *self,
+ gpointer request_token,
+ GHashTable *request_properties,
+ gboolean require_new)
{
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (iface);
- TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
- TpChannelIface *chan;
- TpChannelFactoryRequestStatus status;
+ TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (self);
+ TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
+ TpHandle handle;
+ GError *error = NULL;
+ TpExportableChannel *channel;
+
+ if (tp_strdiff (tp_asv_get_string (request_properties,
+ TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT))
+ return FALSE;
- if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_TEXT))
+ if (tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
+ return FALSE;
+
+ /* validity already checked by TpBaseConnection */
+ handle = tp_asv_get_uint32 (request_properties,
+ TP_IFACE_CHANNEL ".TargetHandle", NULL);
+ g_assert (handle != 0);
+
+ if (tp_channel_manager_asv_has_unknown_properties (request_properties,
+ text_channel_fixed_properties, text_channel_allowed_properties,
+ &error))
+ goto error;
+
+ channel = g_hash_table_lookup (priv->channels,
+ GUINT_TO_POINTER (handle));
+
+ if (channel == NULL)
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
+ tpsip_text_factory_new_channel (self,
+ handle, base_conn->self_handle, request_token);
+ return TRUE;
}
- if (handle_type != TP_HANDLE_TYPE_CONTACT)
+ if (require_new)
{
- return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_AVAILABLE;
+ g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Already chatting with contact #%u in another channel", handle);
+ goto error;
}
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
- chan = g_hash_table_lookup (priv->channels, GINT_TO_POINTER (handle));
- if (!chan)
- {
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
+ tp_channel_manager_emit_request_already_satisfied (self, request_token,
+ channel);
+ return TRUE;
+
+error:
+ tp_channel_manager_emit_request_failed (self, request_token,
+ error->domain, error->code, error->message);
+ g_error_free (error);
+ return TRUE;
+}
- chan = (TpChannelIface *)tpsip_text_factory_new_channel (fac,
- handle, base_conn->self_handle, request);
- status = TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
- }
- *ret = chan;
- return status;
+static gboolean
+tpsip_text_factory_create_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ TpsipTextFactory *self = TPSIP_TEXT_FACTORY (manager);
+
+ return tpsip_text_factory_requestotron (self, request_token,
+ request_properties, TRUE);
+}
+
+
+static gboolean
+tpsip_text_factory_request_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ TpsipTextFactory *self = TPSIP_TEXT_FACTORY (manager);
+
+ return tpsip_text_factory_requestotron (self, request_token,
+ request_properties, FALSE);
+}
+
+
+static gboolean
+tpsip_text_factory_ensure_channel (TpChannelManager *manager,
+ gpointer request_token,
+ GHashTable *request_properties)
+{
+ TpsipTextFactory *self = TPSIP_TEXT_FACTORY (manager);
+
+ return tpsip_text_factory_requestotron (self, request_token,
+ request_properties, FALSE);
+}
+
+static inline TpsipTextChannel *
+tpsip_text_factory_lookup_channel (TpsipTextFactory *fac,
+ TpHandle handle)
+{
+ TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+
+ return (TpsipTextChannel *)g_hash_table_lookup (priv->channels,
+ GUINT_TO_POINTER(handle));
}
static gboolean
@@ -462,38 +598,43 @@ end:
}
static void
-tpsip_text_factory_connected (TpChannelFactoryIface *iface)
+connection_status_changed_cb (TpsipConnection *conn,
+ guint status,
+ guint reason,
+ TpsipTextFactory *self)
{
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (iface);
- TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (self);
- g_signal_connect (priv->conn,
- "nua-event::nua_i_message",
- G_CALLBACK (tpsip_nua_i_message_cb),
- fac);
-}
+ switch (status)
+ {
+ case TP_CONNECTION_STATUS_CONNECTING:
-static void
-tpsip_text_factory_disconnected (TpChannelFactoryIface *iface)
-{
- TpsipTextFactory *fac = TPSIP_TEXT_FACTORY (iface);
- TpsipTextFactoryPrivate *priv = TPSIP_TEXT_FACTORY_GET_PRIVATE (fac);
+ priv->message_received_id = g_signal_connect (priv->conn,
+ "nua-event::nua_i_message",
+ G_CALLBACK (tpsip_nua_i_message_cb),
+ self);
+
+ break;
+ case TP_CONNECTION_STATUS_DISCONNECTED:
+ tpsip_text_factory_close_all (self);
+
+ g_signal_handler_disconnect (conn, priv->message_received_id);
+ priv->message_received_id = 0;
- g_signal_handlers_disconnect_by_func (priv->conn,
- G_CALLBACK (tpsip_nua_i_message_cb),
- fac);
+ break;
+ default:
+ break;
+ }
}
static void
-factory_iface_init (gpointer g_iface, gpointer iface_data)
+channel_manager_iface_init (gpointer g_iface, gpointer iface_data)
{
- TpChannelFactoryIfaceClass *klass = (TpChannelFactoryIfaceClass *) g_iface;
-
-#define IMPLEMENT(x) klass->x = tpsip_text_factory_##x
- IMPLEMENT(close_all);
- IMPLEMENT(foreach);
- IMPLEMENT(request);
- IMPLEMENT(connected);
- IMPLEMENT(disconnected);
-#undef IMPLEMENT
+ TpChannelManagerIface *iface = g_iface;
+
+ iface->foreach_channel = tpsip_text_factory_foreach_channel;
+ iface->foreach_channel_class = tpsip_text_factory_foreach_channel_class;
+ iface->create_channel = tpsip_text_factory_create_channel;
+ iface->request_channel = tpsip_text_factory_request_channel;
+ iface->ensure_channel = tpsip_text_factory_ensure_channel;
}
diff --git a/src/text-factory.h b/src/text-factory.h
index ea0c013..8a998d7 100644
--- a/src/text-factory.h
+++ b/src/text-factory.h
@@ -21,9 +21,7 @@
#ifndef __TPSIP_TEXT_FACTORY_H__
#define __TPSIP_TEXT_FACTORY_H__
-#include <telepathy-glib/channel-factory-iface.h>
-
-#include "sip-text-channel.h"
+#include <glib-object.h>
G_BEGIN_DECLS
--
1.5.6.5
More information about the Telepathy-commits
mailing list