soc.2008.vv: bf98d5aa: Preliminary video embedded in the conver...

maiku at soc.pidgin.im maiku at soc.pidgin.im
Tue Jun 10 01:25:50 EDT 2008


-----------------------------------------------------------------
Revision: bf98d5aa636e703a012f08daaa1fd2a7cfff716c
Ancestor: abb70b8005b3219cf51fa57178e0510beef74f97
Author: maiku at soc.pidgin.im
Date: 2008-06-10T05:18:29
Branch: im.pidgin.soc.2008.vv
URL: http://d.pidgin.im/viewmtn/revision/info/bf98d5aa636e703a012f08daaa1fd2a7cfff716c

Modified files:
        libpurple/media.c pidgin/gtkconv.c pidgin/gtkconv.h
        pidgin/gtkmedia.c pidgin/gtkmedia.h

ChangeLog: 

Preliminary video embedded in the conversation window. It's still kind of buggy.

-------------- next part --------------
============================================================
--- libpurple/media.c	69c3ed1d6909e7a7c47ad19ff878941fa39631c4
+++ libpurple/media.c	1a7c1d7a9854f561ed97f2a5287d5c7852cfa4f4
@@ -676,7 +676,7 @@ purple_media_video_init_src(GstElement *
 void
 purple_media_video_init_src(GstElement **sendbin)
 {
-	GstElement *src;
+	GstElement *src, *tee, *queue, *local_sink;
 	GstPad *pad;
 	GstPad *ghost;
 	const gchar *video_plugin = purple_prefs_get_string("/purple/media/video/plugin");
@@ -685,17 +685,34 @@ purple_media_video_init_src(GstElement *
 	purple_debug_info("media", "purple_media_video_init_src\n");
 
 	*sendbin = gst_bin_new("purplesendvideobin");
-	src = gst_element_factory_make(video_plugin, "videosrc");
+	src = gst_element_factory_make(video_plugin, "purplevideosource");
 	gst_bin_add(GST_BIN(*sendbin), src);
 
+	tee = gst_element_factory_make("tee", NULL);
+	gst_bin_add(GST_BIN(*sendbin), tee);
+	gst_element_link(src, tee);
+
+	queue = gst_element_factory_make("queue", NULL);
+	gst_bin_add(GST_BIN(*sendbin), queue);
+	gst_element_link(tee, queue);
+
 	if (!strcmp(video_plugin, "videotestsrc")) {
 		/* unless is-live is set to true it doesn't throttle videotestsrc */
 		g_object_set (G_OBJECT(src), "is-live", TRUE, NULL);
 	}
-	pad = gst_element_get_pad(src, "src");
+
+	pad = gst_element_get_pad(queue, "src");
 	ghost = gst_ghost_pad_new("ghostsrc", pad);
 	gst_element_add_pad(*sendbin, ghost);
 
+	queue = gst_element_factory_make("queue", NULL);
+	gst_bin_add(GST_BIN(*sendbin), queue);
+	gst_element_link(tee, queue);
+
+	local_sink = gst_element_factory_make("autovideosink", "purplelocalvideosink");
+	gst_bin_add(GST_BIN(*sendbin), local_sink);
+	gst_element_link(queue, local_sink);
+
 	/* set current video device on "src"... */
 	if (video_device) {
 		GList *devices = purple_media_get_devices(src);
============================================================
--- pidgin/gtkconv.c	7b2cf562f5f111869f46ca1d4c056003a414f003
+++ pidgin/gtkconv.c	78a31883798a3fbf2829ddce2013027b923f3a28
@@ -4743,7 +4743,7 @@ setup_common_pane(PidginConversation *gt
 static GtkWidget *
 setup_common_pane(PidginConversation *gtkconv)
 {
-	GtkWidget *vbox, *frame, *imhtml_sw, *event_box;
+	GtkWidget *vbox, *hpaned, *frame, *imhtml_sw, *event_box;
 	GtkCellRenderer *rend;
 	GtkTreePath *path;
 	PurpleConversation *conv = gtkconv->active_conv;
@@ -4823,23 +4823,21 @@ setup_common_pane(PidginConversation *gt
 	/* Setup the gtkimhtml widget */
 	frame = pidgin_create_imhtml(FALSE, &gtkconv->imhtml, NULL, &imhtml_sw);
 	gtk_widget_set_size_request(gtkconv->imhtml, -1, 0);
-	if (chat) {
-		GtkWidget *hpaned;
 
+	/* Add the gtkimhtml frame */
+	gtkconv->middle_hpaned = hpaned = gtk_hpaned_new();
+	gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
+	gtk_widget_show(hpaned);
+	gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
+
+	if (chat) {
 		/* Add the topic */
 		setup_chat_topic(gtkconv, vbox);
 
-		/* Add the gtkimhtml frame */
-		hpaned = gtk_hpaned_new();
-		gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0);
-		gtk_widget_show(hpaned);
-		gtk_paned_pack1(GTK_PANED(hpaned), frame, TRUE, TRUE);
-
 		/* Now add the userlist */
 		setup_chat_userlist(gtkconv, hpaned);
-	} else {
-		gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 0);
 	}
+
 	gtk_widget_show(frame);
 
 	gtk_widget_set_name(gtkconv->imhtml, "pidgin_conv_imhtml");
@@ -7727,6 +7725,9 @@ pidgin_conv_new_media_cb(PurpleMediaMana
 
 	gtkconv->gtkmedia = gtkmedia;
 	g_signal_connect(G_OBJECT(gtkmedia), "destroy", G_CALLBACK(gtk_widget_destroyed), &(gtkconv->gtkmedia));
+
+	gtk_paned_pack2(GTK_PANED(gtkconv->middle_hpaned),
+			pidgin_media_get_display_widget(gtkmedia), FALSE, TRUE);
 }
 
 #endif
============================================================
--- pidgin/gtkconv.h	5036f2250c314d599e0b25d73854487b0a05cd74
+++ pidgin/gtkconv.h	cfe6730a8323fa2464f55cc035da708adcf2dbe4
@@ -150,6 +150,7 @@ struct _PidginConversation
 	gpointer depr1;
 #endif
 
+	GtkWidget *middle_hpaned;
 	GtkWidget *lower_hbox;
 
 	GtkWidget *toolbar;
============================================================
--- pidgin/gtkmedia.c	952215222430cccf9855ddacfe5f76e3f95a6e32
+++ pidgin/gtkmedia.c	875b88881a1f72f3da9d05294922696d56fdc06a
@@ -28,11 +28,14 @@
 #include "internal.h"
 #include "connection.h"
 #include "media.h"
+#include "pidgin.h"
 
 #include "gtkmedia.h"
 
 #ifdef USE_VV
 
+#include <gst/interfaces/xoverlay.h>
+
 typedef enum
 {
 	/* Waiting for response */
@@ -60,6 +63,10 @@ struct _PidginMediaPrivate
 	GtkWidget *recv_progress;
 
 	PidginMediaState state;
+
+	GtkWidget *display;
+	GtkWidget *local_video;
+	GtkWidget *remote_video;
 };
 
 #define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate))
@@ -178,6 +185,8 @@ pidgin_media_init (PidginMedia *media)
 
 	gtk_widget_show_all(media->priv->accept);
 	gtk_widget_show_all(media->priv->reject);
+
+	media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 }
 
 static gboolean
@@ -246,6 +255,8 @@ pidgin_media_finalize (GObject *media)
 		gst_object_unref(gtkmedia->priv->send_level);
 	if (gtkmedia->priv->recv_level)
 		gst_object_unref(gtkmedia->priv->recv_level);
+	if (gtkmedia->priv->display)
+		gtk_widget_destroy(gtkmedia->priv->display);
 }
 
 static void
@@ -254,6 +265,12 @@ pidgin_media_emit_message(PidginMedia *g
 	g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg);
 }
 
+GtkWidget *
+pidgin_media_get_display_widget(GtkWidget *gtkmedia)
+{
+	return PIDGIN_MEDIA_GET_PRIVATE(gtkmedia)->display;
+}
+
 static gboolean
 media_bus_call(GstBus *bus, GstMessage *msg, gpointer gtkmedia)
 {
@@ -284,30 +301,57 @@ media_bus_call(GstBus *bus, GstMessage *
 	return TRUE;
 }
 
+static gboolean
+create_window (GstBus *bus, GstMessage *message, PidginMedia *gtkmedia)
+{
+	char *name;
+
+	if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
+		return TRUE;
+
+	if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
+		return TRUE;
+
+	name = gst_object_get_name(GST_MESSAGE_SRC (message));
+	purple_debug_info("gtkmedia", "prepare-xwindow-id object name: %s\n", name);
+
+	/* The XOverlay's name is the sink's name with a suffix */
+	if (!strncmp(name, "purplevideosink", strlen("purplevideosink")))
+		gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)),
+					     GDK_WINDOW_XWINDOW(gtkmedia->priv->remote_video->window));
+	else if (!strncmp(name, "purplelocalvideosink", strlen("purplelocalvideosink")))
+		gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)),
+					     GDK_WINDOW_XWINDOW(gtkmedia->priv->local_video->window));
+	g_free(name);
+	return TRUE;
+}
+
 static void
 pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia)
 {
 	GstElement *element = purple_media_get_pipeline(media);
 
-	GstElement *audiosendbin, *audiosendlevel;
-	GstElement *audiorecvbin, *audiorecvlevel;
-	GstElement *videosendbin;
-	GstElement *videorecvbin;
+	GstElement *audiosendbin = NULL, *audiosendlevel = NULL;
+	GstElement *audiorecvbin = NULL, *audiorecvlevel = NULL;
+	GstElement *videosendbin = NULL;
+	GstElement *videorecvbin = NULL;
 
 	GList *sessions = purple_media_get_session_names(media);
 	GstBus *bus;
 
-	purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
-	purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
-
-	purple_media_video_init_src(&videosendbin);
-	purple_media_video_init_recv(&videorecvbin);
-
 	for (; sessions; sessions = sessions->next) {
 		if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_AUDIO) {
+			if (!audiosendbin)
+				purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
+			if (!audiorecvbin)
+				purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
 			purple_media_set_src(media, sessions->data, audiosendbin);
 			purple_media_set_sink(media, sessions->data, audiorecvbin);
 		} else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) {
+			if (!videosendbin)
+				purple_media_video_init_src(&videosendbin);
+			if (!videorecvbin)
+				purple_media_video_init_recv(&videorecvbin);
 			purple_media_set_src(media, sessions->data, videosendbin);
 			purple_media_set_sink(media, sessions->data, videorecvbin);
 		}
@@ -320,9 +364,42 @@ pidgin_media_ready_cb(PurpleMedia *media
 				       NULL);
 	}
 
+	if (videorecvbin || videosendbin) {
+		GtkWidget *aspect;
+		GtkWidget *remote_video;
+		GtkWidget *local_video;
+
+		gtk_widget_show(gtkmedia->priv->display);
+
+		aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
+		gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
+		gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0);
+
+		remote_video = gtk_drawing_area_new();
+		gtk_container_add(GTK_CONTAINER(aspect), remote_video);
+		gtk_widget_set_size_request (GTK_WIDGET(remote_video), 100, -1);
+		gtk_widget_show(remote_video);
+		gtk_widget_show(aspect);
+
+		aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
+		gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
+		gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0);
+
+		local_video = gtk_drawing_area_new();
+		gtk_container_add(GTK_CONTAINER(aspect), local_video);
+		gtk_widget_show(local_video);
+		gtk_widget_show(aspect);
+
+		gtkmedia->priv->local_video = local_video;
+		gtkmedia->priv->remote_video = remote_video;
+	}
+
 	bus = gst_pipeline_get_bus(GST_PIPELINE(element));
 	gst_bus_add_signal_watch(GST_BUS(bus));
-	g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), "message", G_CALLBACK(level_message_cb), gtkmedia);
+	g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))),
+			 "message", G_CALLBACK(level_message_cb), gtkmedia);
+	if (videorecvbin || videosendbin)
+		gst_bus_set_sync_handler(bus, (GstBusSyncHandler)create_window, gtkmedia);
 	gst_bus_add_watch(bus, media_bus_call, gtkmedia);
 	gst_object_unref(bus);
 }
============================================================
--- pidgin/gtkmedia.h	be5ac6f0e1d7ce0e844b111c3c28431761e24b83
+++ pidgin/gtkmedia.h	c1e4ba66efda8001b5f97304072a6f51f5765adb
@@ -60,6 +60,7 @@ GtkWidget *pidgin_media_new(PurpleMedia 
 GType pidgin_media_get_type(void);
 
 GtkWidget *pidgin_media_new(PurpleMedia *media);
+GtkWidget *pidgin_media_get_display_widget(GtkWidget *gtkmedia);
 
 G_END_DECLS
 


More information about the Commits mailing list