telepathy-glib: Add tp_connection_upgrade_contacts_async/finish

Xavier Claessens xclaesse at kemper.freedesktop.org
Wed May 9 05:59:55 PDT 2012


Module: telepathy-glib
Branch: master
Commit: ac3538ae8029988458947efda467bc035cf3d3c8
URL:    http://cgit.freedesktop.org/telepathy/telepathy-glib/commit/?id=ac3538ae8029988458947efda467bc035cf3d3c8

Author: Xavier Claessens <xavier.claessens at collabora.co.uk>
Date:   Tue May  8 15:27:39 2012 +0200

Add tp_connection_upgrade_contacts_async/finish

This replaces tp_connection_upgrade_contacts() but with a proper async API.

---

 docs/reference/telepathy-glib-sections.txt |    2 +
 telepathy-glib/contact.c                   |  157 ++++++++++++++++++++++++++++
 telepathy-glib/contact.h                   |   14 +++
 3 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index c83c4a5..112782b 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -4979,6 +4979,8 @@ tp_contact_has_feature
 <SUBSECTION>
 tp_connection_dup_contact_by_id_async
 tp_connection_dup_contact_by_id_finish
+tp_connection_upgrade_contacts_async
+tp_connection_upgrade_contacts_finish
 
 <SUBSECTION operations>
 tp_contact_request_subscription_async
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 56ec9f4..dc7bca0 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -4766,6 +4766,163 @@ tp_connection_dup_contact_by_id_finish (TpConnection *self,
       tp_connection_dup_contact_by_id_async, g_object_ref);
 }
 
+static void
+got_contact_attributes_cb (TpConnection *self,
+    GHashTable *attributes,
+    const GError *error,
+    gpointer user_data,
+    GObject *weak_object)
+{
+  ContactsAsyncData *data = user_data;
+  GHashTableIter iter;
+  gpointer key, value;
+
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (data->result, error);
+      g_simple_async_result_complete_in_idle (data->result);
+      return;
+    }
+
+  g_hash_table_iter_init (&iter, attributes);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      TpHandle handle = GPOINTER_TO_UINT (key);
+      GHashTable *asv = value;
+      TpContact *contact;
+
+      /* set up the contact with its attributes */
+      contact = tp_contact_ensure (self, handle);
+      tp_contact_set_attributes (contact, asv, data->features, NULL);
+      g_object_unref (contact);
+    }
+
+  g_simple_async_result_complete (data->result);
+}
+
+/**
+ * tp_connection_upgrade_contacts_async:
+ * @self: A connection, which must have the %TP_CONNECTION_FEATURE_CONNECTED
+ *  feature prepared
+ * @n_contacts: The number of contacts in @contacts (must be at least 1)
+ * @contacts: (array length=n_contacts): An array of #TpContact objects
+ *  associated with @self
+ * @n_features: The number of features in @features (must be at least 1)
+ * @features: (array length=n_features): An array of features that must be
+ *  ready for use (if supported) before the callback is called
+ * @callback: A user callback to call when the contacts are ready
+ * @user_data: Data to pass to the callback
+ *
+ * Given several #TpContact objects, make asynchronous method calls
+ * ensure that all the features specified in @features are ready for use
+ * (if they are supported at all).
+ *
+ * It is not an error to put features in @features even if the connection
+ * manager doesn't support them - users of this method should have a static
+ * list of features they would like to use if possible, and use it for all
+ * connection managers.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_connection_upgrade_contacts_async (TpConnection *self,
+    guint n_contacts,
+    TpContact * const *contacts,
+    guint n_features,
+    const TpContactFeature *features,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  ContactsAsyncData *data;
+  GSimpleAsyncResult *result;
+  ContactFeatureFlags feature_flags = 0;
+  guint minimal_feature_flags = G_MAXUINT;
+  const gchar **supported_interfaces;
+  GPtrArray *contacts_array;
+  GArray *handles;
+  guint i;
+
+  g_return_if_fail (tp_proxy_is_prepared (self,
+        TP_CONNECTION_FEATURE_CONNECTED));
+  g_return_if_fail (n_contacts >= 1);
+  g_return_if_fail (contacts != NULL);
+  g_return_if_fail (n_features == 0 || features != NULL);
+
+  for (i = 0; i < n_contacts; i++)
+    {
+      g_return_if_fail (contacts[i]->priv->connection == self);
+      g_return_if_fail (contacts[i]->priv->identifier != NULL);
+    }
+
+  if (!get_feature_flags (n_features, features, &feature_flags))
+    return;
+
+  handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), n_contacts);
+  contacts_array = g_ptr_array_new_full (n_contacts, g_object_unref);
+  for (i = 0; i < n_contacts; i++)
+    {
+      /* feature flags that all contacts have */
+      minimal_feature_flags &= contacts[i]->priv->has_features;
+
+      /* Keep handles of contacts that does not already have all features */
+      if ((feature_flags & (~contacts[i]->priv->has_features)) != 0)
+        g_array_append_val (handles, contacts[i]->priv->handle);
+
+      /* Keep a ref on all contacts to ensure they do not disappear
+       * while upgrading them */
+      g_ptr_array_add (contacts_array, g_object_ref (contacts[i]));
+    }
+
+  /* Remove features that all contacts have */
+  feature_flags &= (~minimal_feature_flags);
+
+  supported_interfaces = contacts_bind_to_signals (self, feature_flags);
+
+  result = g_simple_async_result_new ((GObject *) self, callback, user_data,
+      tp_connection_upgrade_contacts_async);
+  g_simple_async_result_set_op_res_gpointer (result, contacts_array,
+      (GDestroyNotify) g_ptr_array_unref);
+
+  if (handles->len > 0 && supported_interfaces[0] != NULL)
+    {
+      data = contacts_async_data_new (result, feature_flags);
+      tp_cli_connection_interface_contacts_call_get_contact_attributes (self,
+          -1, handles, supported_interfaces, TRUE, got_contact_attributes_cb,
+          data, (GDestroyNotify) contacts_async_data_free, NULL);
+    }
+  else
+    {
+      g_simple_async_result_complete_in_idle (result);
+    }
+
+  g_free (supported_interfaces);
+  g_object_unref (result);
+  g_array_unref (handles);
+}
+
+/**
+ * tp_connection_upgrade_contacts_finish:
+ * @self: a #TpConnection
+ * @result: a #GAsyncResult
+ * @contacts: (element-type TelepathyGLib.Contact) (transfer container) (out) (allow-none):
+ *  a location to set a #GPtrArray of upgraded #TpContact, or %NULL.
+ * @error: a #GError to fill
+ *
+ * Finishes tp_connection_upgrade_contacts_async().
+ *
+ * Returns: %TRUE on success, %FALSE otherwise.
+ * Since: 0.UNRELEASED
+ */
+gboolean
+tp_connection_upgrade_contacts_finish (TpConnection *self,
+    GAsyncResult *result,
+    GPtrArray **contacts,
+    GError **error)
+{
+  _tp_implement_finish_copy_pointer (self,
+      tp_connection_upgrade_contacts_async, g_ptr_array_ref, contacts);
+}
+
 void
 _tp_contact_set_is_blocked (TpContact *self,
     gboolean is_blocked)
diff --git a/telepathy-glib/contact.h b/telepathy-glib/contact.h
index 6a7b389..bce6747 100644
--- a/telepathy-glib/contact.h
+++ b/telepathy-glib/contact.h
@@ -181,6 +181,20 @@ TpContact *tp_connection_dup_contact_by_id_finish (TpConnection *self,
     GAsyncResult *result,
     GError **error);
 
+_TP_AVAILABLE_IN_UNRELEASED
+void tp_connection_upgrade_contacts_async (TpConnection *self,
+    guint n_contacts,
+    TpContact * const *contacts,
+    guint n_features,
+    const TpContactFeature *features,
+    GAsyncReadyCallback callback,
+    gpointer user_data);
+_TP_AVAILABLE_IN_UNRELEASED
+gboolean tp_connection_upgrade_contacts_finish (TpConnection *self,
+    GAsyncResult *result,
+    GPtrArray **contacts,
+    GError **error);
+
 /* TP_CONTACT_FEATURE_CONTACT_BLOCKING */
 
 _TP_AVAILABLE_IN_0_18



More information about the telepathy-commits mailing list