/soc/2015/jgeboski/facebook: 853fadf2e250: facebook: queue icon ...
James Geboski
jgeboski at gmail.com
Thu Jun 25 20:48:35 EDT 2015
Changeset: 853fadf2e250e048daf9b1de370b875df11dd68e
Author: James Geboski <jgeboski at gmail.com>
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);
}
More information about the Commits
mailing list