[Telepathy-commits] [telepathy-gabble/master] GabbleMediaFactory: add basic GabbleChannelManager implementation (CreateChannel does nothing)

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Aug 21 08:54:19 PDT 2008


20080801174826-53eee-7e7ffbefc1a515699174d6e4cbadd6f27ae7e59c.gz
---
 src/media-factory.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 188 insertions(+), 12 deletions(-)

diff --git a/src/media-factory.c b/src/media-factory.c
index 62372c4..ac6208c 100644
--- a/src/media-factory.c
+++ b/src/media-factory.c
@@ -28,11 +28,13 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 #include <loudmouth/loudmouth.h>
-#include <telepathy-glib/interfaces.h>
 #include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/dbus.h>
+#include <telepathy-glib/interfaces.h>
 
 #define DEBUG_FLAG GABBLE_DEBUG_MEDIA
 
+#include "channel-manager.h"
 #include "connection.h"
 #include "debug.h"
 #include "media-channel.h"
@@ -40,6 +42,7 @@
 #include "text-mixin.h"
 #include "util.h"
 
+static void channel_manager_iface_init (gpointer, gpointer);
 static void gabble_media_factory_iface_init (gpointer g_iface,
     gpointer iface_data);
 static LmHandlerResult media_factory_jingle_cb (LmMessageHandler *,
@@ -47,6 +50,8 @@ static LmHandlerResult media_factory_jingle_cb (LmMessageHandler *,
 
 G_DEFINE_TYPE_WITH_CODE (GabbleMediaFactory, gabble_media_factory,
     G_TYPE_OBJECT,
+    G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CHANNEL_MANAGER,
+      channel_manager_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
       gabble_media_factory_iface_init));
 
@@ -340,8 +345,12 @@ media_factory_jingle_cb (LmMessageHandler *handler,
         sid, message, session_node, action, &error))
     {
       if (chan_is_new)
-        tp_channel_factory_iface_emit_new_channel (fac,
-            (TpChannelIface *) chan, NULL);
+        {
+          tp_channel_factory_iface_emit_new_channel (fac,
+              (TpChannelIface *) chan, NULL);
+          gabble_channel_manager_emit_new_channel (fac,
+              GABBLE_EXPORTABLE_CHANNEL (chan), NULL);
+        }
     }
   else
     {
@@ -457,7 +466,10 @@ media_channel_closed_cb (GabbleMediaChannel *chan, gpointer user_data)
   GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data);
   GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
 
-  if (priv->channels)
+  gabble_channel_manager_emit_channel_closed_for_object (fac,
+      GABBLE_EXPORTABLE_CHANNEL (chan));
+
+  if (priv->channels != NULL)
     {
       DEBUG ("removing media channel %p with ref count %d",
           chan, G_OBJECT (chan)->ref_count);
@@ -466,7 +478,7 @@ media_channel_closed_cb (GabbleMediaChannel *chan, gpointer user_data)
       g_object_unref (chan);
     }
 
-  if (priv->session_chans)
+  if (priv->session_chans != NULL)
     {
       g_hash_table_foreach_remove (priv->session_chans, _remove_sid_mapping,
           chan);
@@ -809,18 +821,22 @@ gabble_media_factory_constructed (GObject *object)
 
 
 static void
-gabble_media_factory_iface_foreach (TpChannelFactoryIface *iface,
-                                    TpChannelFunc foreach,
-                                    gpointer user_data)
+gabble_media_factory_foreach_channel (GabbleChannelManager *manager,
+                                      GabbleExportableChannelFunc foreach,
+                                      gpointer user_data)
 {
-  GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (iface);
+  GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (manager);
   GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
   guint i;
 
   for (i = 0; i < priv->channels->len; i++)
     {
-      foreach (TP_CHANNEL_IFACE (g_ptr_array_index (priv->channels, i)),
-          user_data);
+      GabbleExportableChannel *channel = GABBLE_EXPORTABLE_CHANNEL (
+          g_ptr_array_index (priv->channels, i));
+
+      g_assert (TP_IS_CHANNEL_IFACE (channel));
+
+      foreach (channel, user_data);
     }
 }
 
@@ -837,6 +853,7 @@ gabble_media_factory_iface_request (TpChannelFactoryIface *iface,
   GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (fac);
   TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
   GabbleMediaChannel *chan = NULL;
+  GSList *request_tokens = NULL;
 
   if (strcmp (chan_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
     return TP_CHANNEL_FACTORY_REQUEST_STATUS_NOT_IMPLEMENTED;
@@ -864,9 +881,15 @@ gabble_media_factory_iface_request (TpChannelFactoryIface *iface,
     }
 
   g_assert (chan != NULL);
+
   tp_channel_factory_iface_emit_new_channel (fac, (TpChannelIface *) chan,
       request);
 
+  request_tokens = g_slist_prepend (NULL, request);
+  gabble_channel_manager_emit_new_channel (fac,
+      GABBLE_EXPORTABLE_CHANNEL (chan), request_tokens);
+  g_slist_free (request_tokens);
+
   *ret = TP_CHANNEL_IFACE (chan);
   return TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED;
 }
@@ -879,7 +902,160 @@ gabble_media_factory_iface_init (gpointer g_iface,
 
   klass->close_all =
       (TpChannelFactoryIfaceProc) gabble_media_factory_close_all;
-  klass->foreach = gabble_media_factory_iface_foreach;
+  klass->foreach =
+      (TpChannelFactoryIfaceForeachImpl) gabble_media_factory_foreach_channel;
   klass->request = gabble_media_factory_iface_request;
 }
 
+
+static const gchar * const no_properties[] = {
+    NULL
+};
+
+static const gchar * const named_channel_required_properties[] = {
+    TP_IFACE_CHANNEL ".TargetHandle",
+    NULL
+};
+
+static const gchar * const anon_channel_optional_properties[] = {
+    TP_IFACE_CHANNEL ".TargetHandle",   /* must be 0 if given */
+    NULL
+};
+
+
+static void
+gabble_media_factory_foreach_channel_class (GabbleChannelManager *manager,
+    GabbleChannelManagerChannelClassFunc func,
+    gpointer user_data)
+{
+  GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal,
+      NULL, (GDestroyNotify) tp_g_value_slice_free);
+  GValue *value, *handle_type_value;
+
+  value = tp_g_value_slice_new (G_TYPE_STRING);
+  g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
+  g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value);
+
+  handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+  /* no uint value yet - we'll change it for each channel class */
+  g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+      handle_type_value);
+
+  g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_NONE);
+  func (manager, table, no_properties,
+      anon_channel_optional_properties, user_data);
+
+  g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_CONTACT);
+  func (manager, table, named_channel_required_properties,
+      no_properties, user_data);
+
+  g_hash_table_destroy (table);
+}
+
+
+static gboolean
+gabble_media_factory_request_channel (GabbleChannelManager *manager,
+                                      gpointer request_token,
+                                      GHashTable *request_properties)
+{
+  GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (manager);
+  GabbleMediaFactoryPrivate *priv = GABBLE_MEDIA_FACTORY_GET_PRIVATE (self);
+  TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
+  TpHandleType handle_type;
+  TpHandle handle;
+  GabbleMediaChannel *channel = NULL;
+  GError *error = NULL;
+  GSList *request_tokens;
+
+  if (tp_strdiff (tp_asv_get_string (request_properties,
+          TP_IFACE_CHANNEL ".ChannelType"),
+        TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA))
+    return FALSE;
+
+  handle_type = tp_asv_get_uint32 (request_properties,
+      TP_IFACE_CHANNEL ".TargetHandleType", NULL);
+
+  handle = tp_asv_get_uint32 (request_properties,
+      TP_IFACE_CHANNEL ".TargetHandle", NULL);
+
+  /* FIXME: which of these modes should we support for CreateChannel too?
+   *
+   * Options are:
+   * - (NONE, 0) [*]
+   * - (CONTACT, non-0), InitialStreams is mandatory
+   * - (CONTACT, non-0), InitialStreams is optional [*]
+   *
+   * Options [*] must be supported for RequestChannel, but need not be
+   * supported for CreateChannel since there is no backwards compatibility.
+   */
+
+  switch (handle_type)
+    {
+    case TP_HANDLE_TYPE_NONE:
+      if (handle != 0)
+        {
+          g_set_error (&error, TP_ERRORS, TP_ERROR_INVALID_ARGUMENT,
+              "TargetHandle must be zero or omitted if TargetHandleType is "
+              "NONE");
+          goto error;
+        }
+
+      channel = new_media_channel (self, conn->self_handle);
+      break;
+
+    case TP_HANDLE_TYPE_CONTACT:
+      if (!tp_handle_is_valid (
+            tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT),
+            handle, &error))
+        goto error;
+
+      channel = new_media_channel (self, conn->self_handle);
+
+      if (!_gabble_media_channel_add_member ((GObject *) channel, handle,
+            "", &error))
+        {
+          gabble_media_channel_close (channel);
+          goto error;
+        }
+
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  g_assert (channel != NULL);
+
+  tp_channel_factory_iface_emit_new_channel (self, (TpChannelIface *) channel,
+      request_token);
+
+  request_tokens = g_slist_prepend (NULL, request_token);
+  gabble_channel_manager_emit_new_channel (self,
+      GABBLE_EXPORTABLE_CHANNEL (channel), request_tokens);
+  g_slist_free (request_tokens);
+
+  return TRUE;
+
+error:
+  gabble_channel_manager_emit_request_failed (self, request_token,
+      error->domain, error->code, error->message);
+  g_error_free (error);
+  return TRUE;
+}
+
+
+static void
+channel_manager_iface_init (gpointer g_iface,
+                            gpointer iface_data)
+{
+  GabbleChannelManagerIface *iface = g_iface;
+
+  iface->foreach_channel = gabble_media_factory_foreach_channel;
+  iface->foreach_channel_class = gabble_media_factory_foreach_channel_class;
+  iface->request_channel = gabble_media_factory_request_channel;
+
+  /* FIXME: for the moment, CreateChannel is unsupported. We should
+   * decide on the preferred requestotron API for media channels -
+   * see _request_channel for possibilities */
+  iface->create_channel = NULL;
+}
-- 
1.5.6.3




More information about the Telepathy-commits mailing list