telepathy-haze: capabilities: implement ContactCapabilities

Jonny Lamb jonny at kemper.freedesktop.org
Wed May 2 06:32:01 PDT 2012


Module: telepathy-haze
Branch: master
Commit: 04909550618339a33f6a5b40ac5e6176ca280972
URL:    http://cgit.freedesktop.org/telepathy/telepathy-haze/commit/?id=04909550618339a33f6a5b40ac5e6176ca280972

Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
Date:   Tue May  1 11:06:42 2012 +0100

capabilities: implement ContactCapabilities

Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>

---

 src/connection-capabilities.c |  150 +++++++++++++++++++++++++++++++++++++++++
 src/connection-capabilities.h |    2 +
 src/connection.c              |    3 +
 3 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/src/connection-capabilities.c b/src/connection-capabilities.c
index 951dc02..f082d53 100644
--- a/src/connection-capabilities.c
+++ b/src/connection-capabilities.c
@@ -267,6 +267,61 @@ haze_connection_get_handle_capabilities (HazeConnection *self,
     }
 }
 
+static GPtrArray *
+haze_connection_get_handle_contact_capabilities (HazeConnection *self,
+                                                 TpHandle handle)
+{
+  GPtrArray *arr = g_ptr_array_new ();
+  GValue monster = {0, };
+  GHashTable *fixed_properties;
+  GValue *channel_type_value;
+  GValue *target_handle_type_value;
+  gchar *text_allowed_properties[] =
+      {
+        TP_IFACE_CHANNEL ".TargetHandle",
+        NULL
+      };
+
+  if (0 == handle)
+    {
+      /* obsolete request for the connection's capabilities, do nothing */
+      return arr;
+    }
+
+  /* TODO: Check for presence */
+
+  /* TODO: do media */
+
+  g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS);
+  g_value_take_boxed (&monster,
+      dbus_g_type_specialized_construct (
+        TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS));
+
+  fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+      (GDestroyNotify) tp_g_value_slice_free);
+
+  channel_type_value = tp_g_value_slice_new (G_TYPE_STRING);
+  g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TEXT);
+  g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType",
+      channel_type_value);
+
+  target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT);
+  g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT);
+  g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".TargetHandleType",
+      target_handle_type_value);
+
+  dbus_g_type_struct_set (&monster,
+      0, fixed_properties,
+      1, text_allowed_properties,
+      G_MAXUINT);
+
+  g_hash_table_unref (fixed_properties);
+
+  g_ptr_array_add (arr, g_value_get_boxed (&monster));
+
+  return arr;
+}
+
 /**
  * haze_connection_get_capabilities
  *
@@ -351,6 +406,37 @@ conn_capabilities_fill_contact_attributes (GObject *obj,
       g_ptr_array_free (array, TRUE);
 }
 
+static void
+conn_capabilities_fill_contact_attributes_contact_caps (
+    GObject *obj,
+    const GArray *contacts,
+    GHashTable *attributes_hash)
+{
+  HazeConnection *self = HAZE_CONNECTION (obj);
+  guint i;
+
+  for (i = 0; i < contacts->len; i++)
+    {
+      TpHandle handle = g_array_index (contacts, TpHandle, i);
+      GPtrArray *array;
+
+      array = haze_connection_get_handle_contact_capabilities (self, handle);
+
+      if (array->len > 0)
+        {
+          GValue *val = tp_g_value_slice_new (
+              TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST);
+
+          g_value_take_boxed (val, array);
+          tp_contacts_mixin_set_contact_attribute (attributes_hash,
+              handle, TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES "/capabilities",
+              val);
+        }
+      else
+        g_ptr_array_free (array, TRUE);
+    }
+}
+
 void
 haze_connection_capabilities_iface_init (gpointer g_iface,
                                          gpointer iface_data)
@@ -365,6 +451,67 @@ haze_connection_capabilities_iface_init (gpointer g_iface,
 #undef IMPLEMENT
 }
 
+static void
+free_rcc_list (GPtrArray *rccs)
+{
+  g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, rccs);
+}
+
+static void
+haze_connection_get_contact_capabilities (
+    TpSvcConnectionInterfaceContactCapabilities *svc,
+    const GArray *handles,
+    DBusGMethodInvocation *context)
+{
+  HazeConnection *self = HAZE_CONNECTION (svc);
+  TpBaseConnection *base = (TpBaseConnection *) self;
+  TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
+      TP_HANDLE_TYPE_CONTACT);
+  guint i;
+  GHashTable *ret;
+  GError *error = NULL;
+
+  TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
+
+  if (!tp_handles_are_valid (contact_handles, handles, FALSE, &error))
+    {
+      dbus_g_method_return_error (context, error);
+      g_error_free (error);
+      return;
+    }
+
+  ret = g_hash_table_new_full (NULL, NULL, NULL,
+      (GDestroyNotify) free_rcc_list);
+
+  for (i = 0; i < handles->len; i++)
+    {
+      TpHandle handle = g_array_index (handles, TpHandle, i);
+      GPtrArray *arr;
+
+      arr = haze_connection_get_handle_contact_capabilities (self, handle);
+      g_hash_table_insert (ret, GUINT_TO_POINTER (handle), arr);
+    }
+
+  tp_svc_connection_interface_contact_capabilities_return_from_get_contact_capabilities
+      (context, ret);
+
+  g_hash_table_unref (ret);
+}
+
+void
+haze_connection_contact_capabilities_iface_init (gpointer g_iface,
+                                                 gpointer iface_data)
+{
+  TpSvcConnectionInterfaceContactCapabilitiesClass *klass = g_iface;
+
+#define IMPLEMENT(x) \
+    tp_svc_connection_interface_contact_capabilities_implement_##x (\
+    klass, haze_connection_##x)
+  /*IMPLEMENT(update_capabilities);*/
+  IMPLEMENT(get_contact_capabilities);
+#undef IMPLEMENT
+}
+
 #ifdef ENABLE_MEDIA
 static void
 caps_changed_cb (PurpleBuddy *buddy,
@@ -400,4 +547,7 @@ haze_connection_capabilities_init (GObject *object)
   tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (object),
       TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
       conn_capabilities_fill_contact_attributes);
+  tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (object),
+      TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+      conn_capabilities_fill_contact_attributes_contact_caps);
 }
diff --git a/src/connection-capabilities.h b/src/connection-capabilities.h
index b8bb4fd..2d2e866 100644
--- a/src/connection-capabilities.h
+++ b/src/connection-capabilities.h
@@ -25,6 +25,8 @@
 
 void haze_connection_capabilities_iface_init (gpointer g_iface,
                                               gpointer iface_data);
+void haze_connection_contact_capabilities_iface_init (gpointer g_iface,
+                                                      gpointer iface_data);
 void haze_connection_capabilities_class_init (GObjectClass *object_class);
 void haze_connection_capabilities_init (GObject *object);
 
diff --git a/src/connection.c b/src/connection.c
index 3ec4c8e..c903249 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -75,6 +75,8 @@ G_DEFINE_TYPE_WITH_CODE(HazeConnection,
         haze_connection_aliasing_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS,
         haze_connection_avatars_iface_init);
+    G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
+        haze_connection_contact_capabilities_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CAPABILITIES,
         haze_connection_capabilities_iface_init);
     G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS,
@@ -105,6 +107,7 @@ static const gchar * implemented_interfaces[] = {
     TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
     TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE,
     TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
+    TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES,
     TP_IFACE_CONNECTION_INTERFACE_CONTACTS,
     /* TODO: This is a lie.  Not all protocols supported by libpurple
      *       actually have the concept of a user-settable alias, but



More information about the telepathy-commits mailing list