telepathy-glib: Add tp_connection_dup_contact_by_id_async/finish
Xavier Claessens
xclaesse at kemper.freedesktop.org
Wed May 9 05:59:54 PDT 2012
Module: telepathy-glib
Branch: master
Commit: 89ee88d7a534502f6dc73653f4407098eb835d3f
URL: http://cgit.freedesktop.org/telepathy/telepathy-glib/commit/?id=89ee88d7a534502f6dc73653f4407098eb835d3f
Author: Xavier Claessens <xavier.claessens at collabora.co.uk>
Date: Tue May 8 14:30:06 2012 +0200
Add tp_connection_dup_contact_by_id_async/finish
This replaces tp_connection_get_contacts_by_id() but for single id
and with a proper async API.
merge by_id
---
docs/reference/telepathy-glib-sections.txt | 5 +
telepathy-glib/contact.c | 205 ++++++++++++++++++++++++++++
telepathy-glib/contact.h | 12 ++
3 files changed, 222 insertions(+), 0 deletions(-)
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index b5d0909..c83c4a5 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -4975,6 +4975,11 @@ tp_contact_get_contact_groups
tp_contact_set_contact_groups_async
tp_contact_set_contact_groups_finish
tp_contact_has_feature
+
+<SUBSECTION>
+tp_connection_dup_contact_by_id_async
+tp_connection_dup_contact_by_id_finish
+
<SUBSECTION operations>
tp_contact_request_subscription_async
tp_contact_request_subscription_finish
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 70912f6..56ec9f4 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -4561,6 +4561,211 @@ tp_connection_get_contacts_by_id (TpConnection *self,
weak_object);
}
+typedef struct
+{
+ GSimpleAsyncResult *result;
+ ContactFeatureFlags features;
+
+ /* Used for fallback in tp_connection_dup_contact_by_id_async */
+ gchar *id;
+ GArray *features_array;
+} ContactsAsyncData;
+
+static ContactsAsyncData *
+contacts_async_data_new (GSimpleAsyncResult *result,
+ ContactFeatureFlags features)
+{
+ ContactsAsyncData *data;
+
+ data = g_slice_new0 (ContactsAsyncData);
+ data->result = g_object_ref (result);
+ data->features = features;
+
+ return data;
+}
+
+static void
+contacts_async_data_free (ContactsAsyncData *data)
+{
+ g_object_unref (data->result);
+ g_free (data->id);
+ tp_clear_pointer (&data->features_array, g_array_unref);
+ g_slice_free (ContactsAsyncData, data);
+}
+
+static void
+got_contact_by_id_fallback_cb (TpConnection *self,
+ guint n_contacts,
+ TpContact * const *contacts,
+ const gchar * const *requested_ids,
+ GHashTable *failed_id_errors,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsAsyncData *data = user_data;
+ GError *e = NULL;
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (data->result, error);
+ g_simple_async_result_complete_in_idle (data->result);
+ return;
+ }
+ if (g_hash_table_size (failed_id_errors) > 0)
+ {
+ e = g_hash_table_lookup (failed_id_errors, data->id);
+
+ if (e == NULL)
+ {
+ g_set_error (&e, TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+ "We requested 1 id, and got an error for another id - Broken CM");
+ g_simple_async_result_take_error (data->result, e);
+ }
+ else
+ {
+ g_simple_async_result_set_from_error (data->result, e);
+ }
+
+ g_simple_async_result_complete_in_idle (data->result);
+ return;
+ }
+ if (n_contacts != 1 || contacts[0] == NULL)
+ {
+ g_set_error (&e, TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+ "We requested 1 id, but no contacts and no error - Broken CM");
+ g_simple_async_result_take_error (data->result, e);
+ g_simple_async_result_complete_in_idle (data->result);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gpointer (data->result,
+ g_object_ref (contacts[0]), g_object_unref);
+ g_simple_async_result_complete (data->result);
+}
+
+static void
+got_contact_by_id_cb (TpConnection *self,
+ TpHandle handle,
+ GHashTable *attributes,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsAsyncData *data = user_data;
+ TpContact *contact;
+ GError *e = NULL;
+
+ if (error != NULL)
+ {
+ /* Retry the old way, for old CMs does that not exist in the real world */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tp_connection_get_contacts_by_id (self, 1,
+ (const gchar * const *) &data->id,
+ data->features_array->len,
+ (TpContactFeature *) data->features_array->data,
+ got_contact_by_id_fallback_cb,
+ data, (GDestroyNotify) contacts_async_data_free, NULL);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+ return;
+ }
+
+ /* set up the contact with its attributes */
+ contact = tp_contact_ensure (self, handle);
+ g_simple_async_result_set_op_res_gpointer (data->result,
+ contact, g_object_unref);
+
+ if (!tp_contact_set_attributes (contact, attributes, data->features, &e))
+ g_simple_async_result_take_error (data->result, e);
+
+ g_simple_async_result_complete (data->result);
+ contacts_async_data_free (data);
+}
+
+/**
+ * tp_connection_dup_contact_by_id_async:
+ * @self: A connection, which must have the %TP_CONNECTION_FEATURE_CONNECTED
+ * feature prepared
+ * @id: A strings representing the desired contact by its
+ * identifier in the IM protocol (an XMPP JID, SIP URI, MSN Passport,
+ * AOL screen-name etc.)
+ * @n_features: The number of features in @features (may be 0)
+ * @features: (array length=n_features) (allow-none): An array of features
+ * that must be ready for use (if supported)
+ * before the callback is called (may be %NULL if @n_features is 0)
+ * @callback: A user callback to call when the contact is ready
+ * @user_data: Data to pass to the callback
+ *
+ * Create a #TpContact object and make any asynchronous method calls necessary
+ * to 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_dup_contact_by_id_async (TpConnection *self,
+ const gchar *id,
+ guint n_features,
+ const TpContactFeature *features,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ContactsAsyncData *data;
+ GSimpleAsyncResult *result;
+ ContactFeatureFlags feature_flags = 0;
+ const gchar **supported_interfaces;
+
+ g_return_if_fail (tp_proxy_is_prepared (self,
+ TP_CONNECTION_FEATURE_CONNECTED));
+ g_return_if_fail (id != NULL);
+ g_return_if_fail (n_features == 0 || features != NULL);
+
+ if (!get_feature_flags (n_features, features, &feature_flags))
+ return;
+
+ supported_interfaces = contacts_bind_to_signals (self, feature_flags);
+
+ result = g_simple_async_result_new ((GObject *) self, callback, user_data,
+ tp_connection_dup_contact_by_id_async);
+
+ data = contacts_async_data_new (result, feature_flags);
+ data->id = g_strdup (id);
+ data->features_array = g_array_sized_new (FALSE, FALSE,
+ sizeof (TpContactFeature), n_features);
+ g_array_append_vals (data->features_array, features, n_features);
+ tp_cli_connection_interface_contacts_call_get_contact_by_id (self, -1,
+ id, supported_interfaces, got_contact_by_id_cb,
+ data, NULL, NULL);
+
+ g_free (supported_interfaces);
+ g_object_unref (result);
+}
+
+/**
+ * tp_connection_dup_contact_by_id_finish:
+ * @self: a #TpConnection
+ * @result: a #GAsyncResult
+ * @error: a #GError to fill
+ *
+ * Finishes tp_connection_get_contact_by_id_async().
+ *
+ * Returns: (transfer full): a #TpContact or %NULL on error.
+ * Since: 0.UNRELEASED
+ */
+TpContact *
+tp_connection_dup_contact_by_id_finish (TpConnection *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ _tp_implement_finish_return_copy_pointer (self,
+ tp_connection_dup_contact_by_id_async, g_object_ref);
+}
+
void
_tp_contact_set_is_blocked (TpContact *self,
gboolean is_blocked)
diff --git a/telepathy-glib/contact.h b/telepathy-glib/contact.h
index 412e569..6a7b389 100644
--- a/telepathy-glib/contact.h
+++ b/telepathy-glib/contact.h
@@ -169,6 +169,18 @@ void tp_connection_get_contacts_by_id (TpConnection *self,
TpContact *tp_connection_dup_contact_if_possible (TpConnection *connection,
TpHandle handle, const gchar *identifier);
+_TP_AVAILABLE_IN_UNRELEASED
+void tp_connection_dup_contact_by_id_async (TpConnection *self,
+ const gchar *id,
+ guint n_features,
+ const TpContactFeature *features,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+_TP_AVAILABLE_IN_UNRELEASED
+TpContact *tp_connection_dup_contact_by_id_finish (TpConnection *self,
+ GAsyncResult *result,
+ GError **error);
+
/* TP_CONTACT_FEATURE_CONTACT_BLOCKING */
_TP_AVAILABLE_IN_0_18
More information about the telepathy-commits
mailing list