X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy%2Fempathy-tp-contact-list.c;h=95ec3bea2109631ee34d9ef2d22b599996792b68;hp=b936416493cdba79db52ab667f1c4d3b54f45f6d;hb=940d0e9778828657a6ffbcadd35a8a84d706ac70;hpb=357abe46ebdc57f29037d12350c06d7fd14581b3 diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index b9364164..95ec3bea 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -43,7 +43,6 @@ typedef struct { EmpathyTpContactFactory *factory; TpConnection *connection; - const gchar *protocol_group; TpChannel *publish; TpChannel *subscribe; @@ -54,6 +53,8 @@ typedef struct { GHashTable *add_to_group; /* group name -> GArray of handles */ EmpathyContactListFlags flags; + + TpProxySignalConnection *new_channels_sig; } EmpathyTpContactListPriv; typedef enum { @@ -697,45 +698,113 @@ tp_contact_list_finalize (GObject *object) G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object); } +static gboolean +received_all_list_channels (EmpathyTpContactList *self) +{ + EmpathyTpContactListPriv *priv = GET_PRIV (self); + + return (priv->stored != NULL && priv->publish != NULL && + priv->subscribe != NULL); +} + static void -list_ensure_channel_cb (TpConnection *conn, - gboolean yours, - const gchar *path, - GHashTable *properties, - const GError *error, - gpointer user_data, - GObject *weak_object) +got_list_channel (EmpathyTpContactList *list, + TpChannel *channel) { - EmpathyTpContactList *list = user_data; EmpathyTpContactListPriv *priv = GET_PRIV (list); const gchar *id; - TpChannel *channel; - - if (error != NULL) { - DEBUG ("failed: %s\n", error->message); - return; - } /* We requested that channel by providing TargetID property, so it's * guaranteed that tp_channel_get_identifier will return it. */ - channel = tp_channel_new_from_properties (conn, path, properties, NULL); id = tp_channel_get_identifier (channel); /* TpChannel emits initial set of members just before being ready */ if (!tp_strdiff (id, "stored")) { - priv->stored = channel; + if (priv->stored != NULL) + return; + priv->stored = g_object_ref (channel); } else if (!tp_strdiff (id, "publish")) { - priv->publish = channel; + if (priv->publish != NULL) + return; + priv->publish = g_object_ref (channel); g_signal_connect (priv->publish, "group-members-changed", G_CALLBACK (tp_contact_list_publish_group_members_changed_cb), list); } else if (!tp_strdiff (id, "subscribe")) { - priv->subscribe = channel; + if (priv->subscribe != NULL) + return; + priv->subscribe = g_object_ref (channel); g_signal_connect (priv->subscribe, "group-members-changed", G_CALLBACK (tp_contact_list_subscribe_group_members_changed_cb), list); - } else { - g_warn_if_reached (); + } + + if (received_all_list_channels (list) && priv->new_channels_sig != NULL) { + /* We don't need to watch NewChannels anymore */ + tp_proxy_signal_connection_disconnect (priv->new_channels_sig); + priv->new_channels_sig = NULL; + } +} + +static void +list_ensure_channel_cb (TpConnection *conn, + gboolean yours, + const gchar *path, + GHashTable *properties, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyTpContactList *list = user_data; + TpChannel *channel; + + if (error != NULL) { + DEBUG ("failed: %s\n", error->message); + return; + } + + channel = tp_channel_new_from_properties (conn, path, properties, NULL); + got_list_channel (list, channel); + g_object_unref (channel); +} + +static void +new_channels_cb (TpConnection *conn, + const GPtrArray *channels, + gpointer user_data, + GObject *weak_object) +{ + EmpathyTpContactList *list = EMPATHY_TP_CONTACT_LIST (weak_object); + guint i; + + for (i = 0; i < channels->len ; i++) { + GValueArray *arr = g_ptr_array_index (channels, i); + const gchar *path; + GHashTable *properties; + const gchar *id; + TpChannel *channel; + + path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); + properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); + + if (tp_strdiff (tp_asv_get_string (properties, + TP_IFACE_CHANNEL ".ChannelType"), + TP_IFACE_CHANNEL_TYPE_CONTACT_LIST)) + return; + + if (tp_asv_get_uint32 (properties, + TP_IFACE_CHANNEL ".TargetHandleType", NULL) + != TP_HANDLE_TYPE_LIST) + return; + + id = tp_asv_get_string (properties, + TP_IFACE_CHANNEL ".TargetID"); + if (id == NULL) + return; + + channel = tp_channel_new_from_properties (conn, path, + properties, NULL); + got_list_channel (list, channel); g_object_unref (channel); } } @@ -759,6 +828,13 @@ conn_ready_cb (TpConnection *connection, TP_IFACE_CHANNEL ".TargetHandleType", G_TYPE_UINT, TP_HANDLE_TYPE_LIST, NULL); + /* Watch the NewChannels signal so if ensuring list channels fails (for + * example because the server is slow and the D-Bus call timeouts before CM + * fetches the roster), we have a chance to get them later. */ + priv->new_channels_sig = + tp_cli_connection_interface_requests_connect_to_new_channels ( + priv->connection, new_channels_cb, NULL, NULL, G_OBJECT (list), NULL); + /* Request the 'stored' list. */ tp_asv_set_static_string (request, TP_IFACE_CHANNEL ".TargetID", "stored"); tp_cli_connection_interface_requests_call_ensure_channel (priv->connection, @@ -783,7 +859,6 @@ static void tp_contact_list_constructed (GObject *list) { EmpathyTpContactListPriv *priv = GET_PRIV (list); - gchar *protocol_name = NULL; priv->factory = empathy_tp_contact_factory_dup_singleton (priv->connection); @@ -825,15 +900,6 @@ tp_contact_list_constructed (GObject *list) tp_contact_list_new_channel_cb, NULL, NULL, list, NULL); - - /* Check for protocols that does not support contact groups. We can - * put all contacts into a special group in that case. - * FIXME: Default group should be an information in the profile */ - tp_connection_parse_object_path (priv->connection, &protocol_name, NULL); - if (!tp_strdiff (protocol_name, "local-xmpp")) { - priv->protocol_group = _("People nearby"); - } - g_free (protocol_name); } static void @@ -990,8 +1056,6 @@ tp_contact_list_remove (EmpathyContactList *list, if (priv->stored != NULL) { tp_cli_channel_interface_group_call_remove_members (priv->stored, -1, &handles, message, NULL, NULL, NULL, NULL); - /* Contact will be removed from 'publish' and 'subscribe' too */ - return; } if (priv->subscribe) { @@ -1037,10 +1101,6 @@ tp_contact_list_get_all_groups (EmpathyContactList *list) l->data = g_strdup (l->data); } - if (priv->protocol_group) { - ret = g_list_prepend (ret, g_strdup (priv->protocol_group)); - } - return ret; } @@ -1066,10 +1126,6 @@ tp_contact_list_get_groups (EmpathyContactList *list, } } - if (priv->protocol_group) { - ret = g_list_prepend (ret, g_strdup (priv->protocol_group)); - } - return ret; }