pidgin.vv: 8d9e0cb3: Make sharing sources between media sessi...

maiku at soc.pidgin.im maiku at soc.pidgin.im
Mon Mar 30 18:07:15 EDT 2009


-----------------------------------------------------------------
Revision: 8d9e0cb37a09a393a8d0a05be8c2df7a38568961
Ancestor: c95a65b7b24deeab5f3c217a7f4ed0f8b422c3d3
Author: maiku at soc.pidgin.im
Date: 2009-03-30T22:00:35
Branch: im.pidgin.pidgin.vv
URL: http://d.pidgin.im/viewmtn/revision/info/8d9e0cb37a09a393a8d0a05be8c2df7a38568961

Modified files:
        libpurple/media.c libpurple/mediamanager.c

ChangeLog: 

Make sharing sources between media sessions work.

-------------- next part --------------
============================================================
--- libpurple/media.c	e2991907b994729191cd32076089086cb50afecc
+++ libpurple/media.c	b586b86e33379d00cc842076ec7ad27ba3ddda4c
@@ -1151,12 +1151,21 @@ purple_media_set_src(PurpleMedia *media,
 		gst_object_unref(session->src);
 	session->src = src;
 	gst_element_set_locked_state(session->src, TRUE);
-	gst_bin_add(GST_BIN(session->media->priv->confbin),
-		    session->src);
 
 	session->tee = gst_element_factory_make("tee", NULL);
 	gst_bin_add(GST_BIN(session->media->priv->confbin), session->tee);
-	gst_element_link(session->src, session->tee);
+
+	/* This supposedly isn't necessary, but it silences some warnings */
+	if (GST_ELEMENT_PARENT(session->media->priv->confbin)
+			== GST_ELEMENT_PARENT(session->src)) {
+		GstPad *pad = gst_element_get_static_pad(session->tee, "sink");
+		GstPad *ghost = gst_ghost_pad_new(NULL, pad);
+		gst_object_unref(pad);
+		gst_pad_set_active(ghost, TRUE);
+		gst_element_add_pad(session->media->priv->confbin, ghost);
+	}
+
+	gst_element_link(session->src, session->media->priv->confbin);
 	gst_element_set_state(session->tee, GST_STATE_PLAYING);
 
 	g_object_get(session->session, "sink-pad", &sinkpad, NULL);
@@ -1165,6 +1174,7 @@ purple_media_set_src(PurpleMedia *media,
 			  gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK
 			  ? "success" : "failure");
 	gst_element_set_locked_state(session->src, FALSE);
+	gst_object_unref(session->src);
 }
 #endif
 
============================================================
--- libpurple/mediamanager.c	09bdedc4750b6440f17c0accabf67ba26c7efc4a
+++ libpurple/mediamanager.c	d41dccf3403ce64d5b40dc0263e83be2e605ef2f
@@ -328,29 +328,95 @@ purple_media_manager_remove_media(Purple
 #endif
 }
 
+#ifdef USE_VV
+static void
+request_pad_unlinked_cb(GstPad *pad, GstPad *peer, gpointer user_data)
+{
+	GstElement *parent = GST_ELEMENT_PARENT(pad);
+	GstIterator *iter;
+	GstPad *remaining_pad;
+
+	gst_element_release_request_pad(GST_ELEMENT_PARENT(pad), pad);
+	iter = gst_element_iterate_pads(parent);
+
+	if (gst_iterator_next(iter, (gpointer)&remaining_pad)
+			== GST_ITERATOR_DONE) {
+		gst_element_set_locked_state(parent, TRUE);
+		gst_element_set_state(parent, GST_STATE_NULL);
+		gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(parent)), parent);
+	}
+
+	gst_iterator_free(iter);
+}
+#endif
+
 GstElement *
 purple_media_manager_get_element(PurpleMediaManager *manager,
 		PurpleMediaSessionType type)
 {
 #ifdef USE_VV
 	GstElement *ret = NULL;
+	PurpleMediaElementInfo *info = NULL;
 
-	/* TODO: If src, retrieve current src */
-	/* TODO: Send a signal here to allow for overriding the source/sink */
+	if (type & PURPLE_MEDIA_SEND_AUDIO)
+		info = manager->priv->audio_src;
+	else if (type & PURPLE_MEDIA_RECV_AUDIO)
+		info = manager->priv->audio_sink;
+	else if (type & PURPLE_MEDIA_SEND_VIDEO)
+		info = manager->priv->video_src;
+	else if (type & PURPLE_MEDIA_RECV_VIDEO)
+		info = manager->priv->video_sink;
 
-	if (type & PURPLE_MEDIA_SEND_AUDIO
-			&& manager->priv->audio_src != NULL)
-		ret = manager->priv->audio_src->create();
-	else if (type & PURPLE_MEDIA_RECV_AUDIO
-			&& manager->priv->audio_sink != NULL)
-		ret = manager->priv->audio_sink->create();
-	else if (type & PURPLE_MEDIA_SEND_VIDEO
-			&& manager->priv->video_src != NULL)
-		ret = manager->priv->video_src->create();
-	else if (type & PURPLE_MEDIA_RECV_VIDEO
-			&& manager->priv->video_sink != NULL)
-		ret = manager->priv->video_sink->create();
+	if (info == NULL)
+		return NULL;
 
+	if (info->type & PURPLE_MEDIA_ELEMENT_UNIQUE &&
+			info->type & PURPLE_MEDIA_ELEMENT_SRC) {
+		GstElement *tee;
+		GstPad *pad;
+		GstPad *ghost;
+
+		ret = gst_bin_get_by_name(GST_BIN(
+				purple_media_manager_get_pipeline(
+				manager)), info->id);
+
+		if (ret == NULL) {
+			GstElement *bin, *fakesink;
+			ret = info->create();
+			bin = gst_bin_new(info->id);
+			tee = gst_element_factory_make("tee", "tee");
+			gst_bin_add_many(GST_BIN(bin), ret, tee, NULL);
+			gst_element_link(ret, tee);
+
+			/*
+			 * This shouldn't be necessary, but it stops it from
+			 * giving a not-linked error upon destruction
+			 */
+			fakesink = gst_element_factory_make("fakesink", NULL);
+			g_object_set(fakesink, "sync", FALSE, NULL);
+			gst_bin_add(GST_BIN(bin), fakesink);
+			gst_element_link(tee, fakesink);
+
+			ret = bin;
+			gst_element_set_locked_state(ret, TRUE);
+			gst_object_ref(ret);
+			gst_bin_add(GST_BIN(purple_media_manager_get_pipeline(
+					manager)), ret);
+		}
+
+		tee = gst_bin_get_by_name(GST_BIN(ret), "tee");
+		pad = gst_element_get_request_pad(tee, "src%d");
+		gst_object_unref(tee);
+		ghost = gst_ghost_pad_new(NULL, pad);
+		gst_object_unref(pad);
+		g_signal_connect(GST_PAD(ghost), "unlinked",
+				G_CALLBACK(request_pad_unlinked_cb), NULL);
+		gst_pad_set_active(ghost, TRUE);
+		gst_element_add_pad(ret, ghost);
+	} else {
+		ret = info->create();
+	}
+
 	if (ret == NULL)
 		purple_debug_error("media", "Error creating source or sink\n");
 


More information about the Commits mailing list