changeset 29822:25a53c299713

Allow PRPLs to specify the image formats acceptable for thumbnails (in preferred order).
author Marcus Lundblad <ml@update.uu.se>
date Mon, 15 Mar 2010 21:49:02 +0000
parents bf0cbb79d629
children 79bb2804a19e
files libpurple/ft.c libpurple/ft.h libpurple/protocols/jabber/libxmpp.c libpurple/protocols/jabber/si.c libpurple/protocols/msn/msn.c libpurple/protocols/msn/slp.c libpurple/prpl.h pidgin/gtkft.c
diffstat 8 files changed, 103 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/ft.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/ft.c	Mon Mar 15 21:49:02 2010 +0000
@@ -179,6 +179,7 @@
 
 	g_hash_table_remove(xfers_data, xfer);
 	g_free(xfer->thumbnail_data);
+	g_free(xfer->thumbnail_mimetype);
 
 	PURPLE_DBUS_UNREGISTER_POINTER(xfer);
 	xfers = g_list_remove(xfers, xfer);
@@ -1630,13 +1631,20 @@
 	return xfer->thumbnail_size;
 }
 
+const gchar *
+purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer)
+{
+	return xfer->thumbnail_mimetype;
+}
+
 void
 purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
-	gsize size)
+	gsize size, const gchar *mimetype)
 {
 	if (thumbnail && size > 0) {
 		xfer->thumbnail_data = g_memdup(thumbnail, size);
 		xfer->thumbnail_size = size;
+		xfer->thumbnail_mimetype = g_strdup(mimetype);
 	}
 }
 
--- a/libpurple/ft.h	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/ft.h	Mon Mar 15 21:49:02 2010 +0000
@@ -189,6 +189,7 @@
 
 	gpointer thumbnail_data;		/**< thumbnail image */
 	gsize thumbnail_size;
+	gchar *thumbnail_mimetype;
 };
 
 #ifdef __cplusplus
@@ -711,16 +712,25 @@
  */
 gsize purple_xfer_get_thumbnail_size(const PurpleXfer *xfer);
 
-
+/**
+ * Gets the mimetype of the thumbnail preview for a transfer
+ *
+ * @param xfer The file transfer to get the mimetype for
+ * @return The mimetype of the thumbnail, or @c NULL if not thumbnail is set
+ */
+const gchar *purple_xfer_get_thumbnail_mimetype(const PurpleXfer *xfer);
+	
+	
 /**
  * Sets the thumbnail data for a transfer
  *
  * @param xfer The file transfer to set the data for
  * @param thumbnail A pointer to the thumbnail data, this will be copied
  * @param size The size in bytes of the passed in thumbnail data
+ * @param mimetype The mimetype of the generated thumbnail
  */
 void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
-	gsize size);
+	gsize size, const gchar *mimetype);
 
 /**
  * Prepare a thumbnail for a transfer (if the UI supports it)
--- a/libpurple/protocols/jabber/libxmpp.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Mar 15 21:49:02 2010 +0000
@@ -127,7 +127,8 @@
 	NULL, /* get_account_text_table */
 	jabber_initiate_media,          /* initiate_media */
 	jabber_get_media_caps,                  /* get_media_caps */
-	jabber_get_moods  							/* get_moods */
+	jabber_get_moods,  							/* get_moods */
+	{"jpeg,png"}					/* file transfer thumbnail spec */
 };
 
 static gboolean load_plugin(PurplePlugin *plugin)
--- a/libpurple/protocols/jabber/si.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/protocols/jabber/si.c	Mon Mar 15 21:49:02 2010 +0000
@@ -1267,15 +1267,16 @@
 
 	/* add thumbnail, if appropriate */
 	if (purple_xfer_get_thumbnail_data(xfer)) {
-		JabberData *thumbnail_data = 
+		const gchar *mimetype = purple_xfer_get_thumbnail_mimetype(xfer);
+		JabberData *thumbnail_data =
 			jabber_data_create_from_data(purple_xfer_get_thumbnail_data(xfer),
-				purple_xfer_get_thumbnail_size(xfer), "image/png", TRUE,
+				purple_xfer_get_thumbnail_size(xfer), mimetype, TRUE,
 				jsx->js);
 		xmlnode *thumbnail = xmlnode_new_child(file, "thumbnail");
 		xmlnode_set_namespace(thumbnail, NS_THUMBS);
 		xmlnode_set_attrib(thumbnail, "cid", 
 			jabber_data_get_cid(thumbnail_data));
-		xmlnode_set_attrib(thumbnail, "mime-type", "image/png");
+		xmlnode_set_attrib(thumbnail, "mime-type", mimetype);
 		/* cache data */
 		jabber_data_associate_local(thumbnail_data, NULL);
 	}
@@ -1671,7 +1672,7 @@
 
 		if (data) {
 			purple_xfer_set_thumbnail(xfer, jabber_data_get_data(data),
-				jabber_data_get_size(data));
+				jabber_data_get_size(data), jabber_data_get_type(data));
 			jabber_data_destroy(data);
 		}
 	} else if (item_not_found) {
--- a/libpurple/protocols/msn/msn.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Mar 15 21:49:02 2010 +0000
@@ -2733,7 +2733,8 @@
 	msn_get_account_text_table,             /* get_account_text_table */
 	NULL,                                   /* initiate_media */
 	NULL,                                   /* get_media_caps */
-	NULL                                    /* get_moods */
+	NULL,                                    /* get_moods */
+	{"png"}					/* file transfer thumbnail spec */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/msn/slp.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/protocols/msn/slp.c	Mon Mar 15 21:49:02 2010 +0000
@@ -424,7 +424,8 @@
 
 			if (header->type == 0 && bin_len >= sizeof(MsnFileContext)) {
 				purple_xfer_set_thumbnail(xfer, &header->preview,
-				                          bin_len - sizeof(MsnFileContext));
+				                          bin_len - sizeof(MsnFileContext),
+				    					  "image/png");
 			}
 
 			purple_xfer_request(xfer);
--- a/libpurple/prpl.h	Sun Mar 14 21:20:14 2010 +0000
+++ b/libpurple/prpl.h	Mon Mar 15 21:49:02 2010 +0000
@@ -52,6 +52,13 @@
 typedef struct _PurpleBuddyIconSpec PurpleBuddyIconSpec;
 
 /**
+ * A description of a file transfer thumbnail specification.
+ * This tells the UI if and what image formats the prpl support for file
+ * transfer thumbnails.
+ */
+typedef struct _PurpleThumbnailSpec PurpleThumbnailSpec;
+
+/**
  * This \#define exists just to make it easier to fill out the buddy icon
  * field in the prpl info struct for protocols that couldn't care less.
  */
@@ -91,6 +98,14 @@
 	PurpleIconScaleRules scale_rules;  /**< How to stretch this icon */
 };
 
+/** @copydoc PurpleThumbnailSpec */
+struct _PurpleThumbnailSpec {
+	/** This is a comma-delimited list of image formats or @c NULL if the
+	 *  prpl does not support file transfer thumbnails
+	 */
+	char *format;
+};
+	
 /** Represents an entry containing information that must be supplied by the
  *  user when joining a chat.
  */
@@ -575,6 +590,11 @@
 	 * "mood" set to @c NULL.
 	 */
 	PurpleMood *(*get_moods)(PurpleAccount *account);
+
+	/**
+	 * File transfer thumbnail spec
+	 */
+	PurpleThumbnailSpec thumbnail_spec;
 };
 
 #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
--- a/pidgin/gtkft.c	Sun Mar 14 21:20:14 2010 +0000
+++ b/pidgin/gtkft.c	Mon Mar 15 21:49:02 2010 +0000
@@ -1163,29 +1163,75 @@
 static void
 pidgin_xfer_add_thumbnail(PurpleXfer *xfer)
 {
+	PurpleAccount *account = purple_xfer_get_account(xfer);
+	PurpleConnection *gc = purple_account_get_connection(account);
+	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	const char *thumbnail_format = prpl_info->thumbnail_spec.format;
+	
 	purple_debug_info("pidgin", "creating thumbnail for transfer\n");
 
-	if (purple_xfer_get_size(xfer) <= PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL) {
+	if (thumbnail_format != NULL &&
+	    purple_xfer_get_size(xfer) <= PIDGIN_XFER_MAX_SIZE_IMAGE_THUMBNAIL) {
 		GdkPixbuf *thumbnail = 
 			gdk_pixbuf_new_from_file_at_size(
 				purple_xfer_get_local_filename(xfer), 128, 128, NULL);
 
 		if (thumbnail) {
+			gchar **formats = g_strsplit(thumbnail_format, ",", 0);
 			gchar *buffer = NULL;
 			gsize size;
-			char *option_keys[2] = {"compression", NULL};
-			char *option_values[2] = {"9", NULL};
-			gdk_pixbuf_save_to_bufferv(thumbnail, &buffer, &size, "png", 
+			char *option_keys[2] = {NULL, NULL};
+			char *option_values[2] = {NULL, NULL};
+			gboolean supports_jpeg = FALSE;
+			gboolean supports_png = FALSE;
+			int i;
+			gchar *format = NULL;
+			
+			for (i = 0 ; formats[i] ; i++) {
+				if (purple_strequal(formats[i], "jpeg")) {
+					supports_jpeg = TRUE;
+				} else if (purple_strequal(formats[i], "png")) {
+					supports_png = TRUE;
+				}
+			}
+
+			/* prefer JPEG, then PNG, otherwise try the first format given
+			 by the PRPL without options */
+			if (supports_jpeg) {
+				purple_debug_info("pidgin", "creating JPEG thumbnail\n");
+				option_keys[0] = "quality";
+				option_keys[1] = NULL;
+				option_values[0] = "90";
+				option_values[1] = NULL;
+				format = "jpeg";
+			} else if (supports_png) {
+				purple_debug_info("pidgin", "creating PNG thumbnail\n");
+				option_keys[0] = "compression";
+				option_keys[1] = NULL;
+				option_values[0] = "9";
+				option_values[1] = NULL;
+				format = "png";
+			} else {
+				purple_debug_info("pidgin",
+				    "creating thumbnail of format %s as demanded by PRPL\n",
+				    formats[0]);
+				format = formats[0];
+			}
+
+			gdk_pixbuf_save_to_bufferv(thumbnail, &buffer, &size, format, 
 				option_keys, option_values, NULL);
 
 			if (buffer) {
+				const gchar *mimetype = g_strdup_printf("image/%s", format);
 				purple_debug_info("pidgin",
 				                  "created thumbnail of %" G_GSIZE_FORMAT " bytes\n",
 					size);
-				purple_xfer_set_thumbnail(xfer, buffer, size);
+				purple_xfer_set_thumbnail(xfer, buffer, size, mimetype);
 				g_free(buffer);
+				g_free(mimetype);
 			}
 			g_object_unref(thumbnail);
+			g_strfreev(formats);
 		}
 	}
 }