cpw.malu.ft_thumbnails: bf054a03: Allow PRPLs to specify the image formats...

malu at pidgin.im malu at pidgin.im
Mon Mar 15 17:50:39 EDT 2010


-----------------------------------------------------------------
Revision: bf054a034768bfc7ccbb15069ff35119ad966c54
Ancestor: 6d0b700da492704070282de79a182df628f383de
Author: malu at pidgin.im
Date: 2010-03-15T21:49:02
Branch: im.pidgin.cpw.malu.ft_thumbnails
URL: http://d.pidgin.im/viewmtn/revision/info/bf054a034768bfc7ccbb15069ff35119ad966c54

Modified 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

ChangeLog: 

Allow PRPLs to specify the image formats acceptable for thumbnails (in
preferred order).

-------------- next part --------------
============================================================
--- libpurple/ft.c	5933e377f88b1978fdb4cab0bb44af071d44f07b
+++ libpurple/ft.c	90d872b2df114f026ae8025a9bfa006eb1da30a8
@@ -179,6 +179,7 @@ purple_xfer_destroy(PurpleXfer *xfer)
 
 	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 @@ purple_xfer_get_thumbnail_size(const Pur
 	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);
 	}
 }
 
============================================================
--- libpurple/ft.h	2d73f7b5b9662fbe483d2fd48d1d5bb14b001422
+++ libpurple/ft.h	0c611773b01e5d2a465f6993857e6ab5b5fc0105
@@ -189,6 +189,7 @@ struct _PurpleXfer
 
 	gpointer thumbnail_data;		/**< thumbnail image */
 	gsize thumbnail_size;
+	gchar *thumbnail_mimetype;
 };
 
 #ifdef __cplusplus
@@ -711,16 +712,25 @@ gsize purple_xfer_get_thumbnail_size(con
  */
 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)
============================================================
--- libpurple/protocols/jabber/libxmpp.c	eb3c713d4904a50323e1e11e5474a3c5af410cef
+++ libpurple/protocols/jabber/libxmpp.c	b51b4468b6f840bbba4ec145211789786bc548a6
@@ -127,7 +127,8 @@ static PurplePluginProtocolInfo prpl_inf
 	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)
============================================================
--- libpurple/protocols/jabber/si.c	a9a33032eeac3ca9eacd21f88f13cde362708980
+++ libpurple/protocols/jabber/si.c	000854e8663e3814adddf346bf4e1f518cf7fe9a
@@ -1267,15 +1267,16 @@ static void jabber_si_xfer_send_request(
 
 	/* 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 @@ jabber_si_thumbnail_cb(JabberStream *js,
 
 		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) {
============================================================
--- libpurple/protocols/msn/msn.c	5a8106a51928918380677fbe201ed78c92bc4735
+++ libpurple/protocols/msn/msn.c	f5987ad55632c2518575b7dc185696515995c709
@@ -2733,7 +2733,8 @@ static PurplePluginProtocolInfo prpl_inf
 	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 =
============================================================
--- libpurple/protocols/msn/slp.c	8ff6f316d306aba37246e203e7fd3e1dc83a7093
+++ libpurple/protocols/msn/slp.c	7bf6d92724e3a1e24706432385a193d6627ce8f3
@@ -424,7 +424,8 @@ got_sessionreq(MsnSlpCall *slpcall, cons
 
 			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);
============================================================
--- libpurple/prpl.h	a776b8844260e205c5edf8094fb78c8f899f8531
+++ libpurple/prpl.h	ade31d168fd6e6fcafdb59ba3adc7935098f6d2a
@@ -52,6 +52,13 @@ typedef struct _PurpleBuddyIconSpec Purp
 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 @@ struct _PurpleBuddyIconSpec {
 	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 @@ struct _PurplePluginProtocolInfo
 	 * "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) \
============================================================
--- pidgin/gtkft.c	60ccf0932b8aa56181481b01acf74fc0bf6d4fad
+++ pidgin/gtkft.c	dedca28500ef823175c034694522a9eb83baf2e7
@@ -1163,29 +1163,75 @@ pidgin_xfer_add_thumbnail(PurpleXfer *xf
 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);
 		}
 	}
 }


More information about the Commits mailing list