Thu, 25 Jun 2015 20:48:26 -0400
facebook: queue icon downloads to prevent lag
--- a/libpurple/protocols/facebook/data.c Wed Jun 24 18:13:18 2015 -0400 +++ b/libpurple/protocols/facebook/data.c Thu Jun 25 20:48:26 2015 -0400 @@ -30,6 +30,8 @@ PurpleConnection *gc; PurpleRoomlist *roomlist; gint chatid; + GHashTable *icons; + GHashTable *icona; }; static const gchar *fb_props_strs[] = { @@ -39,6 +41,9 @@ "token" }; +static void +fb_data_icon_free(FbDataIcon *icon); + G_DEFINE_TYPE(FbData, fb_data, G_TYPE_OBJECT); static void @@ -53,6 +58,9 @@ if (priv->roomlist != NULL) { g_object_unref(priv->roomlist); } + + g_hash_table_destroy(priv->icons); + g_hash_table_destroy(priv->icona); } static void @@ -71,6 +79,13 @@ priv = G_TYPE_INSTANCE_GET_PRIVATE(fata, FB_TYPE_DATA, FbDataPrivate); fata->priv = priv; + + priv->icons = g_hash_table_new_full(g_direct_hash, g_direct_equal, + (GDestroyNotify) fb_data_icon_free, + NULL); + priv->icona = g_hash_table_new_full(g_direct_hash, g_direct_equal, + (GDestroyNotify) fb_data_icon_free, + NULL); } FbData * @@ -243,3 +258,103 @@ priv->roomlist = list; } + +FbDataIcon * +fb_data_icon_add(FbData *fata, PurpleBuddy *buddy, const gchar *url, + PurpleHttpCallback func) +{ + FbDataIcon *icon; + FbDataPrivate *priv; + + g_return_val_if_fail(FB_IS_DATA(fata), NULL); + g_return_val_if_fail(PURPLE_IS_BUDDY(buddy), NULL); + g_return_val_if_fail(url != NULL, NULL); + priv = fata->priv; + + icon = g_new(FbDataIcon, 1); + icon->fata = fata; + icon->buddy = buddy; + icon->url = g_strdup(url); + icon->func = func; + + g_hash_table_replace(priv->icons, icon, icon); + return icon; +} + +static void +fb_data_icon_free(FbDataIcon *icon) +{ + g_return_if_fail(icon != NULL); + + g_free(icon->url); + g_free(icon); +} + +void +fb_data_icon_destroy(FbDataIcon *icon) +{ + FbDataPrivate *priv; + + g_return_if_fail(icon != NULL); + g_return_if_fail(FB_IS_DATA(icon->fata)); + priv = icon->fata->priv; + + if (!g_hash_table_remove(priv->icons, icon) && + !g_hash_table_remove(priv->icona, icon)) + { + fb_data_icon_free(icon); + } +} + +static void +fb_data_icon_cb(PurpleHttpConnection *con, PurpleHttpResponse *res, + gpointer data) +{ + FbDataIcon *icon = data; + FbData *fata = icon->fata; + + if (icon->func != NULL) { + icon->func(con, res, icon); + } + + fb_data_icon_destroy(icon); + fb_data_icon_queue(fata); +} + +void +fb_data_icon_queue(FbData *fata) +{ + FbDataIcon *icon; + FbDataPrivate *priv; + GHashTableIter iter; + guint size; + PurpleAccount *acct; + PurpleConnection *gc; + + g_return_if_fail(FB_IS_DATA(fata)); + priv = fata->priv; + size = g_hash_table_size(priv->icona); + + if (size >= FB_DATA_ICON_MAX) { + return; + } + + g_hash_table_iter_init(&iter, priv->icons); + + while (g_hash_table_iter_next(&iter, (gpointer*) &icon, NULL)) { + acct = purple_buddy_get_account(icon->buddy); + gc = purple_account_get_connection(acct); + + if (g_hash_table_lookup_extended(priv->icona, icon, NULL, NULL)) { + continue; + } + + g_hash_table_iter_steal(&iter); + g_hash_table_replace(priv->icona, icon, icon); + purple_http_get(gc, fb_data_icon_cb, icon, icon->url); + + if (++size >= FB_DATA_ICON_MAX) { + break; + } + } +}
--- a/libpurple/protocols/facebook/data.h Wed Jun 24 18:13:18 2015 -0400 +++ b/libpurple/protocols/facebook/data.h Thu Jun 25 20:48:26 2015 -0400 @@ -25,6 +25,8 @@ #include "connection.h" #include "glibcompat.h" +#define FB_DATA_ICON_MAX 4 + #define FB_TYPE_DATA (fb_data_get_type()) #define FB_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FB_TYPE_DATA, FbData)) #define FB_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FB_TYPE_DATA, FbData)) @@ -36,6 +38,7 @@ typedef struct _FbData FbData; typedef struct _FbDataClass FbDataClass; typedef struct _FbDataPrivate FbDataPrivate; +typedef struct _FbDataIcon FbDataIcon; struct _FbData { @@ -48,6 +51,15 @@ GObjectClass parent_class; }; +struct _FbDataIcon +{ + FbData *fata; + PurpleBuddy *buddy; + gchar *url; + gchar *csum; + PurpleHttpCallback func; +}; + GType fb_data_get_type(void); @@ -76,4 +88,14 @@ void fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list); +FbDataIcon * +fb_data_icon_add(FbData *fata, PurpleBuddy *buddy, const gchar *url, + PurpleHttpCallback func); + +void +fb_data_icon_destroy(FbDataIcon *icon); + +void +fb_data_icon_queue(FbData *fata); + #endif /* _FACEBOOK_DATA_H_ */
--- a/libpurple/protocols/facebook/facebook.c Wed Jun 24 18:13:18 2015 -0400 +++ b/libpurple/protocols/facebook/facebook.c Thu Jun 25 20:48:26 2015 -0400 @@ -64,30 +64,26 @@ } static void -fb_cb_icon_fetch(PurpleHttpConnection *con, PurpleHttpResponse *res, - gpointer data) +fb_cb_data_icon(PurpleHttpConnection *con, PurpleHttpResponse *res, + gpointer data) { const gchar *csum; const gchar *name; const gchar *str; FbApi *api; - FbData *fata; + FbDataIcon *icon = data; FbHttpParams *params; GError *err = NULL; gsize size; guchar *idata; PurpleAccount *acct; - PurpleBuddy *bdy = data; - PurpleConnection *gc; PurpleHttpRequest *req; - acct = purple_buddy_get_account(bdy); - gc = purple_account_get_connection(acct); - fata = purple_connection_get_protocol_data(gc); - api = fb_data_get_api(fata); + acct = purple_buddy_get_account(icon->buddy); + api = fb_data_get_api(icon->fata); if (!fb_http_error_chk(res, &err)) { - fb_cb_api_error(api, err, fata); + fb_cb_api_error(api, err, icon->fata); g_error_free(err); return; } @@ -97,7 +93,7 @@ params = fb_http_params_new_parse(str, TRUE); csum = fb_http_params_get_str(params, "oh", &err); - name = purple_buddy_get_name(bdy); + name = purple_buddy_get_name(icon->buddy); str = purple_http_response_get_data(res, &size); idata = g_memdup(str, size); @@ -149,17 +145,20 @@ if (bdy == NULL) { bdy = purple_buddy_new(acct, uid, user->name); purple_blist_add_buddy(bdy, NULL, grp, NULL); - purple_http_get(gc, fb_cb_icon_fetch, bdy, user->icon); + fb_data_icon_add(fata, bdy, user->icon, + fb_cb_data_icon); continue; } csum = purple_buddy_icons_get_checksum_for_user(bdy); if (!purple_strequal(csum, user->csum)) { - purple_http_get(gc, fb_cb_icon_fetch, bdy, user->icon); + fb_data_icon_add(fata, bdy, user->icon, + fb_cb_data_icon); } } + fb_data_icon_queue(fata); purple_connection_update_progress(gc, _("Connecting"), 3, 4); fb_api_connect(api); }