diff options
-rw-r--r-- | libempathy/empathy-tp-contact-factory.c | 239 |
1 files changed, 141 insertions, 98 deletions
diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c index ac486897d..8773207e0 100644 --- a/libempathy/empathy-tp-contact-factory.c +++ b/libempathy/empathy-tp-contact-factory.c @@ -43,7 +43,7 @@ struct _EmpathyTpContactFactoryPriv { gboolean ready; GList *contacts; - guint self_handle; + EmpathyContact *user; }; static void empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass); @@ -155,6 +155,27 @@ tp_contact_factory_get_presence_cb (TpConnection *connection, if (error) { empathy_debug (DEBUG_DOMAIN, "Error getting presence: %s", error->message); + if (error->domain == TP_DBUS_ERRORS && + error->code == TP_DBUS_ERROR_NO_INTERFACE) { + guint *handles = user_data; + + /* We have no presence iface, set default presence + * to available */ + while (*handles != 0) { + EmpathyContact *contact; + + contact = tp_contact_factory_find_by_handle ( + (EmpathyTpContactFactory*) tp_factory, + *handles); + if (contact) { + empathy_contact_set_presence (contact, + MC_PRESENCE_AVAILABLE); + } + + handles++; + } + } + return; } @@ -564,11 +585,17 @@ tp_contact_factory_request_everything (EmpathyTpContactFactory *tp_factory, EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory); guint *dup_handles; + if (!priv->ready) { + return; + } + + dup_handles = g_malloc0 ((handles->len + 1) * sizeof (guint)); + g_memmove (dup_handles, handles->data, handles->len * sizeof (guint)); tp_cli_connection_interface_presence_call_get_presence (priv->connection, -1, handles, tp_contact_factory_get_presence_cb, - NULL, NULL, + dup_handles, g_free, G_OBJECT (tp_factory)); dup_handles = g_memdup (handles->data, handles->len * sizeof (guint)); @@ -610,10 +637,9 @@ tp_contact_factory_request_handles_cb (TpConnection *connection, gpointer user_data, GObject *tp_factory) { - EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory); - GList *contacts = user_data; - GList *l; - guint i = 0; + GList *contacts = user_data; + GList *l; + guint i = 0; if (error) { empathy_debug (DEBUG_DOMAIN, "Failed to request handles: %s", @@ -626,9 +652,6 @@ tp_contact_factory_request_handles_cb (TpConnection *connection, handle = g_array_index (handles, guint, i); empathy_contact_set_handle (l->data, handle); - if (handle == priv->self_handle) { - empathy_contact_set_is_user (l->data, TRUE); - } i++; } @@ -638,6 +661,30 @@ tp_contact_factory_request_handles_cb (TpConnection *connection, } static void +tp_contact_factory_inspect_handles_cb (TpConnection *connection, + const gchar **ids, + const GError *error, + gpointer user_data, + GObject *tp_factory) +{ + const gchar **id; + GList *contacts = user_data; + GList *l; + + if (error) { + empathy_debug (DEBUG_DOMAIN, "Failed to inspect handles: %s", + error->message); + return; + } + + id = ids; + for (l = contacts; l; l = l->next) { + empathy_contact_set_id (l->data, *id); + id++; + } +} + +static void tp_contact_factory_disconnect_contact_foreach (gpointer data, gpointer user_data) { @@ -657,7 +704,6 @@ tp_contact_factory_connection_invalidated_cb (EmpathyTpContactFactory *tp_factor g_object_unref (priv->connection); priv->connection = NULL; priv->ready = FALSE; - priv->self_handle = 0; g_list_foreach (priv->contacts, tp_contact_factory_disconnect_contact_foreach, @@ -673,9 +719,11 @@ tp_contact_factory_got_self_handle_cb (TpConnection *proxy, GObject *tp_factory) { EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory); - const gchar **contact_ids; - guint i; GList *l; + GArray *handle_needed; + GArray *id_needed; + GList *handle_needed_contacts = NULL; + GList *id_needed_contacts = NULL; if (error) { empathy_debug (DEBUG_DOMAIN, "Failed to get self handles: %s", @@ -683,7 +731,7 @@ tp_contact_factory_got_self_handle_cb (TpConnection *proxy, return; } - priv->self_handle = handle; + empathy_contact_set_handle (priv->user, handle); priv->ready = TRUE; /* Connect signals */ @@ -713,30 +761,52 @@ tp_contact_factory_got_self_handle_cb (TpConnection *proxy, G_OBJECT (tp_factory), NULL); - /* Request new handles for all contacts */ - if (priv->contacts) { - GList *contacts; - - contacts = g_list_copy (priv->contacts); - g_list_foreach (contacts, (GFunc) g_object_ref, NULL); + /* Request needed info for all existing contacts */ + handle_needed = g_array_new (TRUE, FALSE, sizeof (gchar*)); + id_needed = g_array_new (FALSE, FALSE, sizeof (guint)); + for (l = priv->contacts; l; l = l->next) { + EmpathyContact *contact; + guint handle; + const gchar *id; - i = g_list_length (contacts); - contact_ids = g_new0 (const gchar*, i + 1); - i = 0; - for (l = contacts; l; l = l->next) { - contact_ids[i] = empathy_contact_get_id (l->data); - i++; + contact = l->data; + handle = empathy_contact_get_handle (contact); + id = empathy_contact_get_id (contact); + if (handle == 0) { + g_assert (!G_STR_EMPTY (id)); + g_array_append_val (handle_needed, id); + handle_needed_contacts = g_list_prepend (handle_needed_contacts, + g_object_ref (contact)); + } + if (G_STR_EMPTY (id)) { + g_array_append_val (id_needed, handle); + id_needed_contacts = g_list_prepend (id_needed_contacts, + g_object_ref (contact)); } - - tp_cli_connection_call_request_handles (priv->connection, - -1, - TP_HANDLE_TYPE_CONTACT, - contact_ids, - tp_contact_factory_request_handles_cb, - contacts, tp_contact_factory_list_free, - G_OBJECT (tp_factory)); - g_free (contact_ids); } + handle_needed_contacts = g_list_reverse (handle_needed_contacts); + id_needed_contacts = g_list_reverse (id_needed_contacts); + + tp_cli_connection_call_request_handles (priv->connection, + -1, + TP_HANDLE_TYPE_CONTACT, + (const gchar**) handle_needed->data, + tp_contact_factory_request_handles_cb, + handle_needed_contacts, tp_contact_factory_list_free, + G_OBJECT (tp_factory)); + + tp_contact_factory_request_everything ((EmpathyTpContactFactory*) tp_factory, + id_needed); + tp_cli_connection_call_inspect_handles (priv->connection, + -1, + TP_HANDLE_TYPE_CONTACT, + id_needed, + tp_contact_factory_inspect_handles_cb, + id_needed_contacts, tp_contact_factory_list_free, + G_OBJECT (tp_factory)); + + g_array_free (handle_needed, TRUE); + g_array_free (id_needed, TRUE); } static void @@ -809,47 +879,12 @@ tp_contact_factory_add_contact (EmpathyTpContactFactory *tp_factory, tp_factory); priv->contacts = g_list_prepend (priv->contacts, contact); - if (!tp_proxy_has_interface_by_id (priv->connection, - TP_IFACE_QUARK_CONNECTION_INTERFACE_PRESENCE)) { - /* We have no presence iface, set default presence - * to available */ - empathy_contact_set_presence (contact, MC_PRESENCE_AVAILABLE); - } - empathy_debug (DEBUG_DOMAIN, "Contact added: %s (%d)", empathy_contact_get_id (contact), empathy_contact_get_handle (contact)); } static void -tp_contact_factory_inspect_handles_cb (TpConnection *connection, - const gchar **ids, - const GError *error, - gpointer user_data, - GObject *tp_factory) -{ - guint *handles = user_data; - guint i; - const gchar **id; - - if (error) { - empathy_debug (DEBUG_DOMAIN, "Failed to inspect handles: %s", - error->message); - } - - i = 0; - for (id = ids; *id; id++) { - EmpathyContact *contact; - - contact = tp_contact_factory_find_by_handle (EMPATHY_TP_CONTACT_FACTORY (tp_factory), - handles[i]); - empathy_contact_set_id (contact, *id); - - i++; - } -} - -static void tp_contact_factory_hold_handles_cb (TpConnection *connection, const GError *error, gpointer userdata, @@ -868,8 +903,7 @@ empathy_tp_contact_factory_get_user (EmpathyTpContactFactory *tp_factory) g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL); - return empathy_tp_contact_factory_get_from_handle (tp_factory, - priv->self_handle); + return g_object_ref (priv->user); } EmpathyContact * @@ -895,8 +929,7 @@ empathy_tp_contact_factory_get_from_id (EmpathyTpContactFactory *tp_factory, NULL); tp_contact_factory_add_contact (tp_factory, contact); - /* If the account is connected, request contact's handle */ - if (priv->connection) { + if (priv->ready) { const gchar *contact_ids[] = {id, NULL}; GList *contacts; @@ -942,7 +975,7 @@ empathy_tp_contact_factory_get_from_handles (EmpathyTpContactFactory *tp_factory EmpathyTpContactFactoryPriv *priv = GET_PRIV (tp_factory); GList *contacts = NULL; GArray *new_handles; - guint *dup_handles; + GList *new_contacts = NULL; guint i; g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory), NULL); @@ -976,41 +1009,41 @@ empathy_tp_contact_factory_get_from_handles (EmpathyTpContactFactory *tp_factory for (i = 0; i < new_handles->len; i++) { EmpathyContact *contact; guint handle; - gboolean is_user; handle = g_array_index (new_handles, guint, i); - is_user = (handle == priv->self_handle); contact = g_object_new (EMPATHY_TYPE_CONTACT, "account", priv->account, "handle", handle, - "is-user", is_user, NULL); tp_contact_factory_add_contact (tp_factory, contact); contacts = g_list_prepend (contacts, contact); + new_contacts = g_list_prepend (new_contacts, g_object_ref (contact)); } + new_contacts = g_list_reverse (new_contacts); - tp_contact_factory_request_everything (tp_factory, new_handles); - - /* Get the IDs of all new handles */ - dup_handles = g_memdup (new_handles->data, new_handles->len * sizeof (guint)); - tp_cli_connection_call_inspect_handles (priv->connection, - -1, - TP_HANDLE_TYPE_CONTACT, - new_handles, - tp_contact_factory_inspect_handles_cb, - dup_handles, g_free, - G_OBJECT (tp_factory)); + if (priv->ready) { + /* Get the IDs of all new handles */ + tp_cli_connection_call_inspect_handles (priv->connection, + -1, + TP_HANDLE_TYPE_CONTACT, + new_handles, + tp_contact_factory_inspect_handles_cb, + new_contacts, tp_contact_factory_list_free, + G_OBJECT (tp_factory)); - /* Hold all new handles. */ - /* FIXME: Should be unholded when removed from the factory */ - tp_cli_connection_call_hold_handles (priv->connection, - -1, - TP_HANDLE_TYPE_CONTACT, - new_handles, - tp_contact_factory_hold_handles_cb, - NULL, NULL, - G_OBJECT (tp_factory)); + /* Hold all new handles. */ + /* FIXME: Should be unholded when removed from the factory */ + tp_cli_connection_call_hold_handles (priv->connection, + -1, + TP_HANDLE_TYPE_CONTACT, + new_handles, + tp_contact_factory_hold_handles_cb, + NULL, NULL, + G_OBJECT (tp_factory)); + + tp_contact_factory_request_everything (tp_factory, new_handles); + } return contacts; } @@ -1029,6 +1062,10 @@ empathy_tp_contact_factory_set_alias (EmpathyTpContactFactory *tp_factory, g_return_if_fail (empathy_account_equal (empathy_contact_get_account (contact), priv->account)); + if (!priv->ready) { + return; + } + handle = empathy_contact_get_handle (contact); empathy_debug (DEBUG_DOMAIN, "Setting alias for contact %s (%d) to %s", @@ -1064,6 +1101,10 @@ empathy_tp_contact_factory_set_avatar (EmpathyTpContactFactory *tp_factory, g_return_if_fail (EMPATHY_IS_TP_CONTACT_FACTORY (tp_factory)); + if (!priv->ready) { + return; + } + if (data && size > 0 && size < G_MAXUINT) { GArray avatar; @@ -1172,12 +1213,14 @@ tp_contact_factory_constructor (GType type, priv = GET_PRIV (tp_factory); priv->ready = FALSE; + priv->user = empathy_contact_new (priv->account); + empathy_contact_set_is_user (priv->user, TRUE); + tp_contact_factory_add_contact ((EmpathyTpContactFactory*) tp_factory, priv->user); tp_contact_factory_status_updated (EMPATHY_TP_CONTACT_FACTORY (tp_factory)); return tp_factory; } - static void empathy_tp_contact_factory_class_init (EmpathyTpContactFactoryClass *klass) { |