[Telepathy-commits] [telepathy-salut/master] ContactManager: implement TpChannelManager

Will Thompson will.thompson at collabora.co.uk
Thu Oct 23 07:30:40 PDT 2008


---
 src/salut-contact-manager.c |  196 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 191 insertions(+), 5 deletions(-)

diff --git a/src/salut-contact-manager.c b/src/salut-contact-manager.c
index e0521ae..99854bf 100644
--- a/src/salut-contact-manager.c
+++ b/src/salut-contact-manager.c
@@ -30,6 +30,7 @@
 #include "salut-contact.h"
 #include "salut-presence-enumtypes.h"
 
+#include <telepathy-glib/dbus.h>
 #include <telepathy-glib/channel-factory-iface.h>
 #include <telepathy-glib/interfaces.h>
 
@@ -38,15 +39,20 @@
 
 static void salut_contact_manager_factory_iface_init (gpointer g_iface,
     gpointer iface_data);
+static void salut_contact_manager_manager_iface_init (gpointer g_iface,
+    gpointer iface_data);
 
 static SalutContactChannel *salut_contact_manager_get_channel
-    (SalutContactManager *mgr, TpHandle handle, gboolean *created);
+    (SalutContactManager *mgr, TpHandle handle, gpointer request_token,
+    gboolean *created);
 
 static void
 _contact_finalized_cb (gpointer data, GObject *old_object);
 
 G_DEFINE_TYPE_WITH_CODE(SalutContactManager, salut_contact_manager,
     G_TYPE_OBJECT,
+    G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER,
+      salut_contact_manager_manager_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_FACTORY_IFACE,
       salut_contact_manager_factory_iface_init));
 
@@ -220,7 +226,7 @@ change_all_groups (SalutContactManager *mgr, TpIntSet *add, TpIntSet *rem)
 
   for (i = LIST_HANDLE_FIRST; i <= LIST_HANDLE_LAST; i++)
     {
-      c = salut_contact_manager_get_channel (mgr, i, NULL);
+      c = salut_contact_manager_get_channel (mgr, i, NULL, NULL);
       tp_group_mixin_change_members (G_OBJECT(c),
                                      "", add, rem,
                                      empty, empty, 0, 0);
@@ -418,7 +424,7 @@ salut_contact_manager_factory_iface_request (TpChannelFactoryIface *iface,
     return TP_CHANNEL_FACTORY_REQUEST_STATUS_INVALID_HANDLE;
   }
 
-  chan = salut_contact_manager_get_channel (mgr, handle, &created);
+  chan = salut_contact_manager_get_channel (mgr, handle, NULL, &created);
   *ret = TP_CHANNEL_IFACE (chan);
   return created ? TP_CHANNEL_FACTORY_REQUEST_STATUS_CREATED
                  : TP_CHANNEL_FACTORY_REQUEST_STATUS_EXISTING;
@@ -437,9 +443,179 @@ static void salut_contact_manager_factory_iface_init (gpointer g_iface,
   klass->request = salut_contact_manager_factory_iface_request;
 }
 
+
+struct foreach_channel_data {
+  TpExportableChannelFunc func;
+  gpointer data;
+};
+
+static void
+salut_contact_manager_foreach_one (gpointer key,
+    gpointer value,
+    gpointer data)
+{
+  TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
+  struct foreach_channel_data *f = data;
+
+  f->func (chan, f->data);
+}
+
+static void
+salut_contact_manager_foreach_channel (TpChannelManager *iface,
+    TpExportableChannelFunc func,
+    gpointer data)
+{
+  SalutContactManager *mgr = SALUT_CONTACT_MANAGER (iface);
+  SalutContactManagerPrivate *priv = SALUT_CONTACT_MANAGER_GET_PRIVATE (mgr);
+  struct foreach_channel_data f;
+  f.func = func;
+  f.data = data;
+
+  g_hash_table_foreach (priv->channels,
+                        salut_contact_manager_foreach_one, &f);
+}
+
+static const gchar * const list_channel_fixed_properties[] = {
+    TP_IFACE_CHANNEL ".ChannelType",
+    TP_IFACE_CHANNEL ".TargetHandleType",
+    NULL
+};
+
+static const gchar * const list_channel_allowed_properties[] = {
+    TP_IFACE_CHANNEL ".TargetHandle",
+    NULL
+};
+
+static void
+salut_contact_manager_foreach_channel_class (TpChannelManager *manager,
+    TpChannelManagerChannelClassFunc 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_CONTACT_LIST);
+  g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value);
+
+  handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+  g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_LIST);
+  g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
+      handle_type_value);
+
+  func (manager, table, list_channel_allowed_properties, user_data);
+
+  g_hash_table_destroy (table);
+}
+
+static gboolean
+salut_contact_manager_request (SalutContactManager *self,
+    gpointer request_token,
+    GHashTable *request_properties,
+    gboolean require_new)
+{
+  TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (
+      TP_BASE_CONNECTION (self->connection), TP_HANDLE_TYPE_LIST);
+  TpHandleType handle_type;
+  TpHandle handle;
+  SalutContactChannel *channel;
+  gboolean created;
+
+  if (tp_strdiff (tp_asv_get_string (request_properties,
+          TP_IFACE_CHANNEL ".ChannelType"),
+        TP_IFACE_CHANNEL_TYPE_CONTACT_LIST))
+    return FALSE;
+
+  handle_type = tp_asv_get_uint32 (request_properties,
+      TP_IFACE_CHANNEL ".TargetHandleType", NULL);
+
+  if (handle_type != TP_HANDLE_TYPE_LIST)
+    return FALSE;
+
+  handle = tp_asv_get_uint32 (request_properties,
+      TP_IFACE_CHANNEL ".TargetHandle", NULL);
+  g_assert (tp_handle_is_valid (handle_repo, handle, NULL));
+
+  channel = salut_contact_manager_get_channel (self, handle, request_token,
+      &created);
+
+  if (created)
+    {
+      /* Do nothing; salut_contact_manager_new_channel emits the new-channel
+       * signal
+       */
+    }
+  else
+    {
+      if (require_new)
+        {
+          GError *error = NULL;
+          g_set_error (&error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+            "Contact list channel #%u already exists", handle);
+          tp_channel_manager_emit_request_failed (self, request_token,
+              error->domain, error->code, error->message);
+          g_error_free (error);
+        }
+      else
+        {
+          tp_channel_manager_emit_request_already_satisfied (self, request_token,
+              TP_EXPORTABLE_CHANNEL (channel));
+        }
+    }
+  return TRUE;
+}
+
+static gboolean
+salut_contact_manager_request_channel (TpChannelManager *manager,
+    gpointer request_token,
+    GHashTable *request_properties)
+{
+  SalutContactManager *self = SALUT_CONTACT_MANAGER (manager);
+
+  return salut_contact_manager_request (self, request_token,
+      request_properties, FALSE);
+}
+
+static gboolean
+salut_contact_manager_create_channel (TpChannelManager *manager,
+    gpointer request_token,
+    GHashTable *request_properties)
+{
+  SalutContactManager *self = SALUT_CONTACT_MANAGER (manager);
+
+  return salut_contact_manager_request (self, request_token,
+      request_properties, TRUE);
+}
+
+static gboolean
+salut_contact_manager_ensure_channel (TpChannelManager *manager,
+    gpointer request_token,
+    GHashTable *request_properties)
+{
+  SalutContactManager *self = SALUT_CONTACT_MANAGER (manager);
+
+  return salut_contact_manager_request (self, request_token,
+      request_properties, FALSE);
+}
+
+static void
+salut_contact_manager_manager_iface_init (gpointer g_iface,
+    gpointer iface_data)
+{
+  TpChannelManagerIface *iface = g_iface;
+
+  iface->foreach_channel = salut_contact_manager_foreach_channel;
+  iface->foreach_channel_class = salut_contact_manager_foreach_channel_class;
+  iface->request_channel = salut_contact_manager_request_channel;
+  iface->create_channel = salut_contact_manager_create_channel;
+  iface->ensure_channel = salut_contact_manager_ensure_channel;
+}
+
 /* private functions */
 static SalutContactChannel *
 salut_contact_manager_new_channel (SalutContactManager *mgr,
+    gpointer request_token,
     TpHandle handle)
 {
   SalutContactManagerPrivate *priv = SALUT_CONTACT_MANAGER_GET_PRIVATE (mgr);
@@ -449,6 +625,7 @@ salut_contact_manager_new_channel (SalutContactManager *mgr,
   SalutContactChannel *chan;
   const gchar *name;
   gchar *path;
+  GSList *requests = NULL;
 
   g_assert (g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle))
              == NULL);
@@ -461,18 +638,27 @@ salut_contact_manager_new_channel (SalutContactManager *mgr,
       "connection", mgr->connection,
       "object-path", path,
       "handle", handle,
+      "requested", (request_token != NULL),
       NULL);
   g_free (path);
   g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan);
   tp_channel_factory_iface_emit_new_channel (mgr, TP_CHANNEL_IFACE (chan),
       NULL);
 
+  if (request_token != NULL)
+    requests = g_slist_prepend (requests, request_token);
+
+  tp_channel_manager_emit_new_channel (mgr, TP_EXPORTABLE_CHANNEL (chan),
+      requests);
+
+  g_slist_free (requests);
+
   return chan;
 }
 
 static SalutContactChannel *
 salut_contact_manager_get_channel (SalutContactManager *mgr,
-    TpHandle handle, gboolean *created)
+    TpHandle handle, gpointer request_token, gboolean *created)
 {
   SalutContactManagerPrivate *priv = SALUT_CONTACT_MANAGER_GET_PRIVATE (mgr);
   SalutContactChannel *chan;
@@ -484,7 +670,7 @@ salut_contact_manager_get_channel (SalutContactManager *mgr,
     }
   if (chan == NULL)
     {
-      chan = salut_contact_manager_new_channel (mgr, handle);
+      chan = salut_contact_manager_new_channel (mgr, request_token, handle);
     }
 
   return chan;
-- 
1.5.6.5




More information about the Telepathy-commits mailing list