/dev/tomkiewicz/new-smileys: e4a656378516: Remote smileys: parti...

Tomasz Wasilczyk twasilczyk at pidgin.im
Fri Apr 4 08:04:55 EDT 2014


Changeset: e4a656378516673d849fa98e3a4bf4c445b8ca14
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-04 14:04 +0200
Branch:	 default
URL: https://hg.pidgin.im/dev/tomkiewicz/new-smileys/rev/e4a656378516

Description:

Remote smileys: partial implementation with XMPP

diffstat:

 libpurple/conversation.c             |  25 ++++++++-
 libpurple/protocols/jabber/message.c |  96 +++++++++++++++++++++--------------
 libpurple/smiley-list.c              |  10 +++-
 libpurple/smiley-remote.c            |  80 +++++++++++++++++++++++++++--
 libpurple/smiley-remote.h            |   8 +++
 5 files changed, 171 insertions(+), 48 deletions(-)

diffs (truncated from 377 to 300 lines):

diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -948,6 +948,7 @@ purple_conversation_add_remote_smiley(Pu
 {
 	PurpleConversationPrivate *priv = PURPLE_CONVERSATION_GET_PRIVATE(conv);
 	PurpleSmiley *smiley;
+	PurpleRemoteSmiley *rsmiley;
 
 	g_return_val_if_fail(priv != NULL, NULL);
 	g_return_val_if_fail(shortcut != NULL, NULL);
@@ -958,13 +959,33 @@ purple_conversation_add_remote_smiley(Pu
 
 	smiley = purple_smiley_list_get_by_shortcut(
 		priv->remote_smileys, shortcut);
-	if (!PURPLE_IS_REMOTE_SMILEY(smiley)) {
+	if (smiley && !PURPLE_IS_REMOTE_SMILEY(smiley)) {
 		purple_debug_warning("conversation", "Invalid type of smiley "
 			"stored in remote smileys list");
 		return NULL;
 	}
 
-	return PURPLE_REMOTE_SMILEY(smiley);
+	/* smiley was already added */
+	if (smiley)
+		return NULL;
+
+	rsmiley = g_object_new(PURPLE_TYPE_REMOTE_SMILEY,
+		"shortcut", shortcut,
+		"is-ready", FALSE,
+		NULL);
+
+	if (!purple_smiley_list_add(priv->remote_smileys,
+		PURPLE_SMILEY(rsmiley)))
+	{
+		purple_debug_error("conversation", "failed adding remote "
+			"smiley to the list");
+		g_object_unref(rsmiley);
+		return NULL;
+	}
+
+	/* priv->remote_smileys holds the only one ref */
+	g_object_unref(rsmiley);
+	return rsmiley;
 }
 
 PurpleSmileyList *
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
--- a/libpurple/protocols/jabber/message.c
+++ b/libpurple/protocols/jabber/message.c
@@ -482,23 +482,63 @@ jabber_message_add_remote_smileys(Jabber
 	}
 }
 
-#if 0
 static void
-jabber_message_request_data_cb(JabberData *data, gchar *alt,
-    gpointer userdata)
+jabber_message_remote_smiley_got(JabberData *data, gchar *alt, gpointer _smiley)
 {
-	PurpleConversation *conv = PURPLE_CONVERSATION(userdata);
+	PurpleRemoteSmiley *smiley = _smiley;
+
+	g_free(alt); /* we really don't need it */
 
 	if (data) {
-		purple_conversation_custom_smiley_write(conv, alt,
-										jabber_data_get_data(data),
-										jabber_data_get_size(data));
-		purple_conversation_custom_smiley_close(conv, alt);
+		purple_debug_info("jabber",
+			"smiley data retrieved successfully");
+		purple_remote_smiley_write(smiley, jabber_data_get_data(data),
+			jabber_data_get_size(data));
+		purple_remote_smiley_close(smiley);
+	} else {
+		purple_debug_error("jabber", "failed retrieving smiley data");
+		purple_remote_smiley_failed(smiley);
 	}
 
-	g_free(alt);
+	g_object_unref(smiley);
 }
-#endif
+
+static void
+jabber_message_remote_smiley_add(JabberStream *js, PurpleConversation *conv,
+	const gchar *from, const gchar *shortcut, const gchar *cid)
+{
+	PurpleRemoteSmiley *smiley;
+	const JabberData *jdata;
+
+	purple_debug_misc("jabber", "about to add remote smiley %s to the conv",
+		shortcut);
+
+	smiley = purple_conversation_add_remote_smiley(conv, shortcut);
+	if (!smiley) {
+		purple_debug_misc("jabber", "smiley was already present");
+		return;
+	}
+
+	/* TODO: cache lookup by "cid" */
+
+	jdata = jabber_data_find_remote_by_cid(js, from, cid);
+	if (jdata) {
+		purple_debug_info("jabber", "smiley data is already known");
+
+		purple_remote_smiley_write(smiley, jabber_data_get_data(jdata),
+			jabber_data_get_size(jdata));
+		purple_remote_smiley_close(smiley);
+	} else {
+		gchar *alt = g_strdup(shortcut); /* it it really necessary? */
+
+		purple_debug_info("jabber", "smiley data is unknown, "
+			"need to request it");
+
+		g_object_ref(smiley);
+		jabber_data_request(js, cid, from, alt, FALSE,
+			jabber_message_remote_smiley_got, smiley);
+	}
+}
 
 void jabber_message_parse(JabberStream *js, PurpleXmlNode *packet)
 {
@@ -602,7 +642,7 @@ void jabber_message_parse(JabberStream *
 				const PurpleConnection *gc = js->gc;
 				PurpleAccount *account = purple_connection_get_account(gc);
 				PurpleConversation *conv = NULL;
-				GList *smiley_refs = NULL;
+				GList *smiley_refs = NULL, *it;
 				gchar *reformatted_xhtml;
 
 				if (purple_account_get_bool(account, "custom_smileys", TRUE)) {
@@ -654,39 +694,19 @@ void jabber_message_parse(JabberStream *
 				/* note: if there were no smileys in the incoming message, or
 				  	if receiving custom smileys is turned off, smiley_refs will
 					be NULL */
-				for (; conv && smiley_refs ; smiley_refs = g_list_delete_link(smiley_refs, smiley_refs)) {
-					JabberSmileyRef *ref = (JabberSmileyRef *) smiley_refs->data;
-					const gchar *cid = ref->cid;
-					gchar *alt = g_strdup(ref->alt);
+				for (it = smiley_refs; it; it = g_list_next(it)) {
+					JabberSmileyRef *ref = it->data;
 
-					purple_debug_info("jabber",
-						"about to add custom smiley %s to the conv\n", alt);
-#if 0
-					if (purple_conversation_custom_smiley_add(conv, alt, "cid", cid,
-						    TRUE)) {
-						const JabberData *data =
-								jabber_data_find_remote_by_cid(js, from, cid);
-						/* if data is already known, we write it immediatly */
-						if (data) {
-							purple_debug_info("jabber",
-								"data is already known\n");
-							purple_conversation_custom_smiley_write(conv, alt,
-								jabber_data_get_data(data),
-								jabber_data_get_size(data));
-							purple_conversation_custom_smiley_close(conv, alt);
-						} else {
-							/* we need to request the smiley (data) */
-							purple_debug_info("jabber",
-								"data is unknown, need to request it\n");
-							jabber_data_request(js, cid, from, alt, FALSE,
-							    jabber_message_request_data_cb, conv);
-						}
+					if (conv) {
+						jabber_message_remote_smiley_add(js,
+							conv, from, ref->alt, ref->cid);
 					}
-#endif
+
 					g_free(ref->cid);
 					g_free(ref->alt);
 					g_free(ref);
 				}
+				g_list_free(smiley_refs);
 
 			    /* Convert all newlines to whitespace. Technically, even regular, non-XML HTML is supposed to ignore newlines, but Pidgin has, as convention
 				 * treated \n as a newline for compatibility with other protocols
diff --git a/libpurple/smiley-list.c b/libpurple/smiley-list.c
--- a/libpurple/smiley-list.c
+++ b/libpurple/smiley-list.c
@@ -128,6 +128,11 @@ purple_smiley_list_add(PurpleSmileyList 
 		priv->smileys_end);
 
 	smiley_path = purple_smiley_get_path(smiley);
+
+	/* TODO: add to the table, when smiley sets the path */
+	if (!smiley_path)
+		return TRUE;
+
 	if (g_hash_table_lookup(priv->path_map, smiley_path) == NULL) {
 		g_hash_table_insert(priv->path_map,
 			g_strdup(smiley_path), smiley);
@@ -160,7 +165,8 @@ purple_smiley_list_remove(PurpleSmileyLi
 	path = purple_smiley_get_path(smiley);
 
 	g_hash_table_remove(priv->shortcut_map, shortcut);
-	g_hash_table_remove(priv->path_map, path);
+	if (path)
+		g_hash_table_remove(priv->path_map, path);
 
 	if (purple_smiley_parse_escape())
 		shortcut = tmp = g_markup_escape_text(shortcut, -1);
@@ -171,7 +177,7 @@ purple_smiley_list_remove(PurpleSmileyLi
 	_list_remove_link2(&priv->smileys, &priv->smileys_end, list_elem);
 
 	/* re-add entry to path_map if smiley was not unique */
-	for (it = priv->smileys; it; it = g_list_next(it)) {
+	for (it = priv->smileys; it && path; it = g_list_next(it)) {
 		PurpleSmiley *smiley = it->data;
 
 		if (g_strcmp0(purple_smiley_get_path(smiley), path) == 0) {
diff --git a/libpurple/smiley-remote.c b/libpurple/smiley-remote.c
--- a/libpurple/smiley-remote.c
+++ b/libpurple/smiley-remote.c
@@ -22,6 +22,7 @@
 #include "internal.h"
 #include "glibcompat.h"
 
+#include "debug.h"
 #include "smiley.h"
 #include "smiley-remote.h"
 
@@ -29,6 +30,9 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_REMOTE_SMILEY, PurpleRemoteSmileyPrivate))
 
 typedef struct {
+	GString *contents;
+
+	gboolean failed;
 } PurpleRemoteSmileyPrivate;
 
 #if 0
@@ -56,24 +60,87 @@ static GParamSpec *properties[PROP_LAST]
  * API implementation
  ******************************************************************************/
 
+void
+purple_remote_smiley_write(PurpleRemoteSmiley *smiley, const guchar *data,
+	gsize size)
+{
+	PurpleRemoteSmileyPrivate *priv =
+		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);
+
+	g_return_if_fail(priv != NULL);
+	g_return_if_fail(!priv->failed);
+	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));
+	g_return_if_fail(data != NULL || size == 0);
+
+	if (size == 0)
+		return;
+
+	g_string_append_len(priv->contents, (const gchar*)data, size);
+}
+
+void
+purple_remote_smiley_close(PurpleRemoteSmiley *smiley)
+{
+	PurpleRemoteSmileyPrivate *priv =
+		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);
+
+	g_return_if_fail(priv != NULL);
+	g_return_if_fail(!priv->failed);
+	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));
+
+	if (priv->contents->len == 0) {
+		purple_debug_error("smiley-remote", "Smiley is empty");
+		purple_remote_smiley_failed(smiley);
+		return;
+	}
+
+	g_object_set(smiley, "is-ready", TRUE, NULL);
+	/* TODO: call ready signal */
+}
+
+void
+purple_remote_smiley_failed(PurpleRemoteSmiley *smiley)
+{
+	PurpleRemoteSmileyPrivate *priv =
+		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);
+
+	g_return_if_fail(priv != NULL);
+	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));
+
+	if (priv->failed)
+		return;
+
+	g_object_set(smiley, "failed", TRUE, NULL);
+	/* TODO: call failed signal */
+}
+
 /******************************************************************************
  * Object stuff
  ******************************************************************************/
 
-#if 0
 static void
 purple_remote_smiley_init(GTypeInstance *instance, gpointer klass)



More information about the Commits mailing list