/soc/2015/jgeboski/facebook: 853fadf2e250: facebook: queue icon ...

James Geboski <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 853fadf2e250e048daf9b1de370b875df11dd68e
Author:	 James Geboski <[email protected]>
Date:	 2015-06-25 20:48 -0400
Branch:	 facebook
URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/853fadf2e250

Description:

facebook: queue icon downloads to prevent lag

diffstat:

 libpurple/protocols/facebook/data.c     |  115 ++++++++++++++++++++++++++++++++
 libpurple/protocols/facebook/data.h     |   22 ++++++
 libpurple/protocols/facebook/facebook.c |   25 +++---
 3 files changed, 149 insertions(+), 13 deletions(-)

diffs (273 lines):

diff --git a/libpurple/protocols/facebook/data.c b/libpurple/protocols/facebook/data.c
--- a/libpurple/protocols/facebook/data.c
+++ b/libpurple/protocols/facebook/data.c
@@ -30,6 +30,8 @@ struct _FbDataPrivate
 	PurpleConnection *gc;
 	PurpleRoomlist *roomlist;
 	gint chatid;
+	GHashTable *icons;
+	GHashTable *icona;
 };
 
 static const gchar *fb_props_strs[] = {
@@ -39,6 +41,9 @@ static const gchar *fb_props_strs[] = {
 	"token"
 };
 
+static void
+fb_data_icon_free(FbDataIcon *icon);
+
 G_DEFINE_TYPE(FbData, fb_data, G_TYPE_OBJECT);
 
 static void
@@ -53,6 +58,9 @@ fb_data_dispose(GObject *obj)
 	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 @@ fb_data_init(FbData *fata)
 
 	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 @@ fb_data_set_roomlist(FbData *fata, Purpl
 
 	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;
+		}
+	}
+}
diff --git a/libpurple/protocols/facebook/data.h b/libpurple/protocols/facebook/data.h
--- a/libpurple/protocols/facebook/data.h
+++ b/libpurple/protocols/facebook/data.h
@@ -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 @@ struct _FbDataClass
 	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 @@ fb_data_get_roomlist(FbData *fata);
 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_ */
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
--- a/libpurple/protocols/facebook/facebook.c
+++ b/libpurple/protocols/facebook/facebook.c
@@ -64,30 +64,26 @@ fb_cb_api_connect(FbApi *api, gpointer d
 }
 
 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 @@ fb_cb_icon_fetch(PurpleHttpConnection *c
 	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 @@ fb_cb_api_contacts(FbApi *api, GSList *u
 		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);
 }

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.