changeset 27512:ff18653ef9f4

Add support in Pidgin for playing back audio:// links. Also include a "Save File" menu item to save a permanent copy. Playback uses purple_sound_play_file, which uses a playbin. This will not correctly play back the Siren codec until Bug 588218 is fixed, but that looks like it will be soon. Also, if anyone has a better idea for GtkIMHtml->PidginConversation than g_object_[gs]_data, feel free to fix it. References #393.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 11 Jul 2009 07:01:00 +0000
parents a7d2bc001b6b
children 2dff07ddcc83
files ChangeLog pidgin/gtkconv.c pidgin/gtkutils.c
diffstat 3 files changed, 83 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Jul 11 06:49:43 2009 +0000
+++ b/ChangeLog	Sat Jul 11 07:01:00 2009 +0000
@@ -29,6 +29,7 @@
 	* Add support for receiving handwritten (ink) messages on MSN.
 	* Don't do IPv6 address lookups if the computer does not have an IPv6
 	  address configured.
+	* Add support for receiving audio clips on MSN.
 
 	AIM and ICQ:
 	* Preliminary support for a new authentication scheme called
--- a/pidgin/gtkconv.c	Sat Jul 11 06:49:43 2009 +0000
+++ b/pidgin/gtkconv.c	Sat Jul 11 07:01:00 2009 +0000
@@ -4939,6 +4939,7 @@
 
 	gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
 	gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),TRUE);
+	g_object_set_data(gtkconv->imhtml, "gtkconv", gtkconv);
 
 	gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(imhtml_sw),
 	                               &imhtml_sw_hscroll, NULL);
--- a/pidgin/gtkutils.c	Sat Jul 11 06:49:43 2009 +0000
+++ b/pidgin/gtkutils.c	Sat Jul 11 07:01:00 2009 +0000
@@ -54,6 +54,7 @@
 #include "prpl.h"
 #include "request.h"
 #include "signals.h"
+#include "sound.h"
 #include "util.h"
 
 #include "gtkaccount.h"
@@ -3707,6 +3708,83 @@
 	return TRUE;
 }
 
+#define AUDIOLINKSIZE  (sizeof("audio://") - 1)
+static gboolean
+audio_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
+{
+	const char *uri;
+	PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
+	if (!conv) /* no playback in debug window */
+		return TRUE;
+	uri = gtk_imhtml_link_get_url(link) + AUDIOLINKSIZE;
+	purple_sound_play_file(uri, NULL);
+	return TRUE;
+}
+
+static void
+savefile_write_cb(gpointer user_data, char *file)
+{
+	char *temp_file = user_data;
+	gchar *contents;
+	gsize length;
+	GError *error;
+
+	if (!g_file_get_contents(temp_file, &contents, &length, &error)) {
+		purple_debug_error("gtkutils", "Unable to read contents of %s: %s\n",
+		                   temp_file, error->message);
+		g_error_free(error);
+		return;
+	}
+
+	if (!g_file_set_contents(file, contents, length, &error)) {
+		purple_debug_error("gtkutils", "Unable to write contents to %s: %s\n",
+		                   file, error->message);
+		g_error_free(error);
+	}
+}
+
+static gboolean
+save_file_cb(GtkWidget *item, const char *url)
+{
+	PidginConversation *conv = g_object_get_data(G_OBJECT(item), "gtkconv");
+	if (!conv)
+		return TRUE;
+	purple_request_file(conv->active_conv, _("Save File"), NULL, TRUE,
+	                    G_CALLBACK(savefile_write_cb), NULL,
+	                    conv->active_conv->account, NULL, conv->active_conv,
+	                    (void *)url);
+	return TRUE;
+}
+
+static gboolean
+audio_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu)
+{
+	GtkWidget *img, *item;
+	const char *url;
+	PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
+	if (!conv) /* No menu in debug window */
+		return TRUE;
+
+	url = gtk_imhtml_link_get_url(link);
+
+	/* Play Sound */
+	img = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("_Play Sound"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	/* Save File */
+	img = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("_Save File"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(save_file_cb), (gpointer)(url+AUDIOLINKSIZE));
+	g_object_set_data(G_OBJECT(item), "gtkconv", conv);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	return TRUE;
+}
+
 /* XXX: The following two functions are for demonstration purposes only! */
 static gboolean
 open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
@@ -3814,6 +3892,7 @@
 	gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address);
 
 	gtk_imhtml_class_register_protocol("file://", file_clicked_cb, file_context_menu);
+	gtk_imhtml_class_register_protocol("audio://", audio_clicked_cb, audio_context_menu);
 
 	/* Example custom URL handler. */
 	gtk_imhtml_class_register_protocol("open://", open_dialog, dummy);
@@ -3840,6 +3919,8 @@
 		gnome_url_handlers = NULL;
 		return;
 	}
+
+	gtk_imhtml_class_register_protocol("audio://", NULL, NULL);
 	gtk_imhtml_class_register_protocol("file://", NULL, NULL);
 
 	gtk_imhtml_class_register_protocol("http://", NULL, NULL);