diff options
author | Xavier Claessens <xavier.claessens@collabora.co.uk> | 2012-05-08 15:27:39 +0200 |
---|---|---|
committer | Xavier Claessens <xavier.claessens@collabora.co.uk> | 2012-05-09 14:59:35 +0200 |
commit | ac3538ae8029988458947efda467bc035cf3d3c8 (patch) | |
tree | 1303349872335e3af30eede548f061a2c574e5ab /telepathy-glib/contact.c | |
parent | 89ee88d7a534502f6dc73653f4407098eb835d3f (diff) | |
download | telepathy-glib-ac3538ae8029988458947efda467bc035cf3d3c8.tar.gz |
Add tp_connection_upgrade_contacts_async/finish
This replaces tp_connection_upgrade_contacts() but with a proper async API.
Diffstat (limited to 'telepathy-glib/contact.c')
-rw-r--r-- | telepathy-glib/contact.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c index 56ec9f4d5..dc7bca045 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) |