changeset 20570:5913725cbcd6

Use an independant status type for 'current media' stuff, instead of using status attributes. This includes changes in both xmpp and msn. Also, in MSN, CurrentMedia is sent with PSM if you turn on the status and set the attributes on the account.
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Thu, 20 Sep 2007 16:30:17 +0000
parents 7393ee28c819
children c97e3ab9ef11 1933f2084eb3
files libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/message.c libpurple/protocols/jabber/presence.c libpurple/protocols/jabber/usertune.c libpurple/protocols/msn/msn.c libpurple/protocols/msn/notification.c libpurple/protocols/msn/state.c libpurple/protocols/msn/state.h libpurple/protocols/msn/user.c libpurple/protocols/msn/user.h libpurple/status.c libpurple/status.h pidgin/gtkblist.c
diffstat 13 files changed, 174 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Thu Sep 20 16:30:17 2007 +0000
@@ -1532,15 +1532,6 @@
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
@@ -1555,15 +1546,6 @@
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
@@ -1578,15 +1560,6 @@
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
@@ -1601,15 +1574,6 @@
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
@@ -1624,15 +1588,6 @@
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			"mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
 			"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
-			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
-			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
@@ -1650,6 +1605,20 @@
 			NULL);
 	types = g_list_append(types, type);
 
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
+			"tune", NULL, FALSE, FALSE, TRUE,
+			PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_GENRE, _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_COMMENT, _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_TRACK, _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_TIME, _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
+			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
+			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
+			NULL);
+	types = g_list_append(types, type);
+
 	return types;
 }
 
--- a/libpurple/protocols/jabber/message.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/jabber/message.c	Thu Sep 20 16:30:17 2007 +0000
@@ -104,6 +104,7 @@
 
 					g_snprintf(buf, sizeof(buf),
 					           _("%s has left the conversation."), escaped);
+					g_free(escaped);
 
 					/* At some point when we restructure PurpleConversation,
 					 * this should be able to be implemented by removing the
--- a/libpurple/protocols/jabber/presence.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Thu Sep 20 16:30:17 2007 +0000
@@ -104,9 +104,10 @@
 	char *stripped = NULL;
 	JabberBuddyState state;
 	int priority;
-	const char *artist, *title, *source, *uri, *track;
-	int length;
+	const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL;
+	int length = -1;
 	gboolean allowBuzz;
+	PurpleStatus *tune;
 
 	if(NULL == status) {
 		PurplePresence *gpresence = purple_account_get_presence(account);
@@ -172,12 +173,16 @@
 	}
 					  	
 	/* next, check if there are any changes to the tune values */
-	artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-	title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-	source = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-	uri = purple_status_get_attr_string(status, PURPLE_TUNE_URL);
-	track = purple_status_get_attr_string(status, PURPLE_TUNE_TRACK);
-	length = (!purple_status_get_attr_value(status, PURPLE_TUNE_TIME))?-1:purple_status_get_attr_int(status, PURPLE_TUNE_TIME);
+	tune = purple_presence_get_status(purple_status_get_presence(status), "tune");
+	if (tune && purple_status_is_active(tune)) {
+		artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
+		title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
+		source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
+		uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL);
+		track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK);
+		length = (!purple_status_get_attr_value(tune, PURPLE_TUNE_TIME)) ? -1 :
+				purple_status_get_attr_int(tune, PURPLE_TUNE_TIME);
+	}
 	
 	if(CHANGED(artist, js->old_artist) || CHANGED(title, js->old_title) || CHANGED(source, js->old_source) ||
 	   CHANGED(uri, js->old_uri) || CHANGED(track, js->old_track) || (length != js->old_length)) {
--- a/libpurple/protocols/jabber/usertune.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Thu Sep 20 16:30:17 2007 +0000
@@ -35,7 +35,6 @@
 	xmlnode *tuneinfo, *tune;
 	PurpleJabberTuneInfo tuneinfodata;
 	JabberBuddyResource *resource;
-	const char *status_id;
 	
 	/* ignore the tune of people not on our buddy list */
 	if (!buddy || !item)
@@ -81,9 +80,8 @@
 			}
 		}
 	}
-	status_id = jabber_buddy_state_get_status_id(resource->state);
 
-	purple_prpl_got_user_status(js->gc->account, from, status_id,
+	purple_prpl_got_user_status(js->gc->account, from, "tune",
 			PURPLE_TUNE_ARTIST, tuneinfodata.artist,
 			PURPLE_TUNE_TITLE, tuneinfodata.title,
 			PURPLE_TUNE_ALBUM, tuneinfodata.album,
--- a/libpurple/protocols/msn/msn.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Thu Sep 20 16:30:17 2007 +0000
@@ -539,25 +539,36 @@
 
 /*
  * Set the User status text
- * Add the PSM String Using "Name - PSM String" format
  */
 static char *
 msn_status_text(PurpleBuddy *buddy)
 {
 	PurplePresence *presence;
 	PurpleStatus *status;
-	const char *msg, *cmedia;
+	const char *msg;
 
 	presence = purple_buddy_get_presence(buddy);
 	status = purple_presence_get_active_status(presence);
 
+	/* I think status message should take precedence over media */
 	msg = purple_status_get_attr_string(status, "message");
-	cmedia = purple_status_get_attr_string(status, "currentmedia");
-
-	if (cmedia)
-		return g_markup_escape_text(cmedia, -1);
-	else if (msg)
+	if (msg && *msg)
 		return g_markup_escape_text(msg, -1);
+
+	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+		const char *title, *artist;
+		char *media, *esc;
+		status = purple_presence_get_status(presence, "tune");
+		title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+		artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+
+		media = g_strdup_printf("%s%s%s", title, artist ? " - " : "",
+				artist ? artist : "");
+		esc = g_markup_escape_text(media, -1);
+		g_free(media);
+		return esc;
+	}
+
 	return NULL;
 }
 
@@ -570,14 +581,21 @@
 
 	user = buddy->proto_data;
 
-
 	if (purple_presence_is_online(presence))
 	{
-		const char *psm, *currentmedia, *name;
+		const char *psm, *name;
+		char *currentmedia = NULL;
 		char *tmp;
 
 		psm = purple_status_get_attr_string(status, "message");
-		currentmedia = purple_status_get_attr_string(status, "currentmedia");
+		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+			PurpleStatus *tune = purple_presence_get_status(presence, "tune");
+			const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
+			const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
+			currentmedia = g_strdup_printf("%s%s%s", title, artist ? " - " : "",
+					artist ? artist : "");
+			/* We could probably just use user->media.title etc. here */
+		}
 
 		if (!purple_presence_is_available(presence)) {
 			name = purple_status_get_name(status);
@@ -609,6 +627,7 @@
 			tmp = g_markup_escape_text(currentmedia, -1);
 			purple_notify_user_info_add_pair(user_info, _("Current media"), tmp);
 			g_free(tmp);
+			g_free(currentmedia);
 		}
 	}
 
@@ -632,40 +651,34 @@
 	status = purple_status_type_new_with_attrs(
 				PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
 				"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-				"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 				NULL);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_with_attrs(
 			PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_with_attrs(
 			PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, status);
 
 	status = purple_status_type_new_with_attrs(
 			PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, status);
 	status = purple_status_type_new_with_attrs(
 			PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, status);
 	status = purple_status_type_new_with_attrs(
 			PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-			"currentmedia", _("Current media"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
 	types = g_list_append(types, status);
 
@@ -681,6 +694,14 @@
 			"mobile", NULL, FALSE, FALSE, TRUE);
 	types = g_list_append(types, status);
 
+	status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
+			"tune", NULL, FALSE, FALSE, TRUE,
+			PURPLE_TUNE_ARTIST, _("Artist"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_ALBUM, _("Album"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_TUNE_TITLE, _("Title"), purple_value_new(PURPLE_TYPE_STRING),
+			NULL);
+	types = g_list_append(types, status);
+
 	return types;
 }
 
--- a/libpurple/protocols/msn/notification.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Thu Sep 20 16:30:17 2007 +0000
@@ -1625,10 +1625,8 @@
 	PurpleConnection *gc;
 	MsnUser *user;
 	const char *passport;
-	char *psm_str, *currentmedia_str, *str;
-
-	/*get the payload content*/
-//	purple_debug_info("MSNP14","UBX {%s} payload{%s}\n",cmd->params[0], cmd->payload);
+	char *psm_str, *str;
+	CurrentMedia media = {NULL, NULL, NULL};
 
 	session = cmdproc->session;
 	account = session->account;
@@ -1638,16 +1636,17 @@
 	user = msn_userlist_find_user(session->userlist, passport);
 	
 	psm_str = msn_get_psm(cmd->payload,len);
-	currentmedia_str = msn_parse_currentmedia(
-	                                 str = msn_get_currentmedia(cmd->payload, len));
+	msn_user_set_statusline(user, psm_str);
+	g_free(psm_str);
+
+	str = msn_get_currentmedia(cmd->payload, len);
+	if (msn_parse_currentmedia(str, &media))
+		msn_user_set_currentmedia(user, &media);
+	else
+		msn_user_set_currentmedia(user, NULL);
 	g_free(str);
 
-	msn_user_set_statusline(user, psm_str);
-	msn_user_set_currentmedia(user, currentmedia_str);
 	msn_user_update(user);
-
-	g_free(psm_str);
-	g_free(currentmedia_str);
 }
 
 static void
--- a/libpurple/protocols/msn/state.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/state.c	Thu Sep 20 16:30:17 2007 +0000
@@ -83,16 +83,15 @@
 }
 
 /* parse CurrentMedia string */
-char *
-msn_parse_currentmedia(const char *cmedia)
+gboolean
+msn_parse_currentmedia(const char *cmedia, CurrentMedia *media)
 {
 	char **cmedia_array;
-	GString *buffer = NULL;
 	int strings;
 
 	if ((cmedia == NULL) || (*cmedia == '\0')) {
 		purple_debug_info("msn", "No currentmedia string\n");
-		return NULL;
+		return FALSE;
 	}
 
 	purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
@@ -104,6 +103,30 @@
 	 * the cmedia string starting with \0 -- see the examples below. */
 	while (cmedia_array[++strings] != NULL);
 
+	if (strings < 4)
+		return FALSE;
+	if (strcmp(cmedia_array[2], "1"))
+		return FALSE;
+
+	if (strings == 4) {
+		media->title = g_strdup(cmedia_array[3]);
+	} else {
+		media->title = g_strdup(cmedia_array[4]);
+	}
+
+	if (strings > 5)
+		media->artist = g_strdup(cmedia_array[5]);
+	else
+		media->artist = NULL;
+
+	if (strings > 6)
+		media->album = g_strdup(cmedia_array[6]);
+	else
+		media->album = NULL;
+
+	return TRUE;
+
+#if 0
 	/* The cmedia_array[2] field contains a 1 if enabled. */
 	if ((strings > 3) && (!strcmp(cmedia_array[2], "1"))) {
 		char *inptr = cmedia_array[3];
@@ -137,6 +160,7 @@
 
 	g_strfreev(cmedia_array);
 	return buffer ? g_string_free(buffer, FALSE) : NULL;
+#endif
 }
 
 /* get the CurrentMedia info from the XML string */
@@ -191,6 +215,27 @@
 	return psm;
 }
 
+static char *
+create_media_string(PurplePresence *presence)
+{
+	const char *artist, *title, *album;
+	char *ret;
+	PurpleStatus *status = purple_presence_get_status(presence, "tune");
+	if (!status || !purple_status_is_active(status))
+		return g_strdup_printf("WMP\\0Music\\00\\0{0} - {1}\\0\\0\\0\\0\\0");
+
+	artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+	title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+	album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
+
+	ret = g_strdup_printf("WMP\\0Music\\0%c\\0{0} - {1}\\0%s\\0%s\\0%s\\0\\0",
+			(title && *title) ? '1' : '0',
+			title ? title : "",
+			artist ? artist : "",
+			album ? album : "");
+	return ret;
+}
+
 /* set the MSN's PSM info,Currently Read from the status Line 
  * Thanks for Cris Code
  */
@@ -204,7 +249,7 @@
 	MsnTransaction *trans;
 	char *payload;
 	const char *statusline;
-	gchar *unescapedstatusline;
+	gchar *unescapedstatusline, *media = NULL;
 
 	g_return_if_fail(session != NULL);
 	g_return_if_fail(session->notification != NULL);
@@ -219,8 +264,10 @@
 	status = purple_presence_get_active_status(presence);
 	statusline = purple_status_get_attr_string(status, "message");
 	unescapedstatusline = purple_unescape_html(statusline);
-	session->psm = msn_build_psm(unescapedstatusline, NULL, NULL);
+	media = create_media_string(presence);
+	session->psm = msn_build_psm(unescapedstatusline, media, NULL);
 	g_free(unescapedstatusline);
+	g_free(media);
 	payload = session->psm;
 
 	purple_debug_misc("MSNP14","Sending UUX command with payload: %s\n",payload);
--- a/libpurple/protocols/msn/state.h	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/state.h	Thu Sep 20 16:30:17 2007 +0000
@@ -62,7 +62,7 @@
 void msn_set_psm(MsnSession *session);
 
 /* Parse CurrentMedia string */
-char * msn_parse_currentmedia(const char *cmedia);
+gboolean msn_parse_currentmedia(const char *cmedia, CurrentMedia *media);
 
 /* Get the CurrentMedia info from the XML string */
 char * msn_get_currentmedia(char *xml_str,gsize len);
--- a/libpurple/protocols/msn/user.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/user.c	Thu Sep 20 16:30:17 2007 +0000
@@ -80,6 +80,9 @@
 	g_free(user->phone.home);
 	g_free(user->phone.work);
 	g_free(user->phone.mobile);
+	g_free(user->media.artist);
+	g_free(user->media.title);
+	g_free(user->media.album);
 
 	g_free(user);
 }
@@ -91,23 +94,24 @@
 
 	account = user->userlist->session->account;
 
-	if (user->statusline != NULL && user->currentmedia != NULL) {
+	if (user->status != NULL) {
+		gboolean offline = (strcmp(user->status, "offline") == 0);
 		purple_prpl_got_user_status(account, user->passport, user->status,
-		                          "message", user->statusline,
-		                          "currentmedia", user->currentmedia, NULL);
-	} else if (user->currentmedia != NULL) {
-		purple_prpl_got_user_status(account, user->passport, user->status, "currentmedia",
-		                          user->currentmedia, NULL);
-	} else if (user->statusline != NULL) {
-		//char *status = g_strdup_printf("%s - %s", user->status, user->statusline);
-		purple_prpl_got_user_status(account, user->passport, user->status,
-		                          "message", user->statusline, NULL);
-	} else if (user->status != NULL) {
-		if (!strcmp(user->status, "offline") && user->mobile) {
-			purple_prpl_got_user_status(account, user->passport, "offline", NULL);
+				"message", user->statusline, NULL);
+
+		if (!offline && user->media.title) {
+			purple_prpl_got_user_status(account, user->passport, "tune",
+					PURPLE_TUNE_ARTIST, user->media.artist,
+					PURPLE_TUNE_ALBUM, user->media.album,
+					PURPLE_TUNE_TITLE, user->media.title,
+					NULL);
+		} else {
+			purple_prpl_got_user_status_deactive(account, user->passport, "tune");
+		}
+
+		if (!offline && user->mobile) {
 			purple_prpl_got_user_status(account, user->passport, "mobile", NULL);
 		} else {
-			purple_prpl_got_user_status(account, user->passport, user->status, NULL);
 			purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
 		}
 	}
@@ -172,12 +176,17 @@
 }
 
 void
-msn_user_set_currentmedia(MsnUser *user, const char *currentmedia)
+msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *media)
 {
 	g_return_if_fail(user != NULL);
 
-	g_free(user->currentmedia);
-	user->currentmedia = g_strdup(currentmedia);
+	g_free(user->media.title);
+	g_free(user->media.album);
+	g_free(user->media.artist);
+
+	user->media.title  = media ? g_strdup(media->title) : NULL;
+	user->media.artist = media ? g_strdup(media->artist) : NULL;
+	user->media.album  = media ? g_strdup(media->album) : NULL;
 }
 
 void
--- a/libpurple/protocols/msn/user.h	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/protocols/msn/user.h	Thu Sep 20 16:30:17 2007 +0000
@@ -43,6 +43,16 @@
 } MsnUserType;
 
 /**
+ * Current media.
+ */
+typedef struct _CurrentMedia
+{
+	char *artist;   /**< Artist. */
+	char *album;    /**< Album.  */
+	char *title;    /**< Title.  */
+} CurrentMedia;
+
+/**
  * A user.
  */
 struct _MsnUser
@@ -60,7 +70,7 @@
 
 	const char *status;     /**< The state of the user.         */
 	char *statusline;       /**< The state of the user.         */	
-	char *currentmedia;     /**< The current media of the user. */
+	CurrentMedia media;     /**< Current media of the user.     */
 
 	gboolean idle;          /**< The idle state of the user.    */
 
@@ -134,10 +144,10 @@
  /**
   *  Sets the current media of user.
   * 
-  *  @param user The user.
-  *  @param state The statusline string.
+  *  @param user   The user.
+  *  @param cmedia Current media.
   */
-void msn_user_set_currentmedia(MsnUser *user, const char *currentmedia);
+void msn_user_set_currentmedia(MsnUser *user, const CurrentMedia *cmedia);
 
 /**
  * Sets the new state of user.
--- a/libpurple/status.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/status.c	Thu Sep 20 16:30:17 2007 +0000
@@ -903,6 +903,8 @@
 	}
 	g_return_if_fail(purple_value_get_type(attr_value) == PURPLE_TYPE_STRING);
 
+	/* XXX: Check if the value has actually changed. If it has, and the status
+	 * is active, should this trigger 'status_has_changed'? */
 	purple_value_set_string(attr_value, value);
 }
 
--- a/libpurple/status.h	Thu Sep 20 06:29:21 2007 +0000
+++ b/libpurple/status.h	Thu Sep 20 16:30:17 2007 +0000
@@ -104,6 +104,7 @@
 	PURPLE_STATUS_AWAY,
 	PURPLE_STATUS_EXTENDED_AWAY,
 	PURPLE_STATUS_MOBILE,
+	PURPLE_STATUS_TUNE,
 	PURPLE_STATUS_NUM_PRIMITIVES
 
 } PurpleStatusPrimitive;
--- a/pidgin/gtkblist.c	Thu Sep 20 06:29:21 2007 +0000
+++ b/pidgin/gtkblist.c	Thu Sep 20 16:30:17 2007 +0000
@@ -3384,7 +3384,7 @@
 		return ret;
 	}
 
-	if (purple_status_get_attr_string(purple_presence_get_active_status(p), PURPLE_TUNE_TITLE)) {
+	if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) {
 		path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL);
 		ret = gdk_pixbuf_new_from_file(path, NULL);
 		g_free(path);