pidgin: e247c79e: Allow adding or removing media sessions ...

rekkanoryo at pidgin.im rekkanoryo at pidgin.im
Thu Mar 24 20:12:10 EDT 2011


----------------------------------------------------------------------
Revision: e247c79e5d292103eaa86a95c85fe11aa2a9ab18
Parent:   4ac2c53a02a28d532c23623c06465b14c0ff667b
Author:   jakub.adam at ktknet.cz
Date:     03/24/11 19:02:12
Branch:   im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/e247c79e5d292103eaa86a95c85fe11aa2a9ab18

Changelog: 

Allow adding or removing media sessions (voice or video) on-the-fly.  This
allows, for example, starting a call with only audio and adding video later,
followed by removing the audio component of the call.

Changes against parent 4ac2c53a02a28d532c23623c06465b14c0ff667b

  patched  libpurple/media/backend-fs2.c

-------------- next part --------------
============================================================
--- libpurple/media/backend-fs2.c	91b00b19579d6d6f26f50a86d6686ad9d76819c2
+++ libpurple/media/backend-fs2.c	9035de5df989f8cf4851bbf1680a753991621408
@@ -86,6 +86,9 @@ static gboolean purple_media_backend_fs2
 		PurpleMediaBackend *self, const gchar *sess_id,
 		PurpleMediaCodec *codec);
 
+static void free_stream(PurpleMediaBackendFs2Stream *stream);
+static void free_session(PurpleMediaBackendFs2Session *session);
+
 struct _PurpleMediaBackendFs2Class
 {
 	GObjectClass parent_class;
@@ -110,6 +113,8 @@ struct _PurpleMediaBackendFs2Stream
 	GstElement *tee;
 	GstElement *volume;
 	GstElement *level;
+	GstElement *fakesink;
+	GstElement *queue;
 
 	GList *local_candidates;
 	GList *remote_candidates;
@@ -300,20 +305,7 @@ purple_media_backend_fs2_finalize(GObjec
 	for (; priv->streams; priv->streams =
 			g_list_delete_link(priv->streams, priv->streams)) {
 		PurpleMediaBackendFs2Stream *stream = priv->streams->data;
-
-		/* Remove the connected_cb timeout */
-		if (stream->connected_cb_id != 0)
-			purple_timeout_remove(stream->connected_cb_id);
-
-		g_free(stream->participant);
-
-		if (stream->local_candidates)
-			fs_candidate_list_destroy(stream->local_candidates);
-
-		if (stream->remote_candidates)
-			fs_candidate_list_destroy(stream->remote_candidates);
-
-		g_free(stream);
+		free_stream(stream);
 	}
 
 	if (priv->sessions) {
@@ -323,8 +315,7 @@ purple_media_backend_fs2_finalize(GObjec
 				g_list_delete_link(sessions, sessions)) {
 			PurpleMediaBackendFs2Session *session =
 					sessions->data;
-			g_free(session->id);
-			g_free(session);
+			free_session(session);
 		}
 
 		g_hash_table_destroy(priv->sessions);
@@ -1138,9 +1129,62 @@ static void
 }
 
 static void
+remove_element(GstElement *element)
+{
+	if (element) {
+		gst_element_set_locked_state(element, TRUE);
+		gst_element_set_state(element, GST_STATE_NULL);
+		gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(element)), element);
+	}
+}
+
+static void
 state_changed_cb(PurpleMedia *media, PurpleMediaState state,
 		gchar *sid, gchar *name, PurpleMediaBackendFs2 *self)
 {
+	if (state == PURPLE_MEDIA_STATE_END) {
+		PurpleMediaBackendFs2Private *priv =
+				PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
+
+		if (sid && name) {
+			PurpleMediaBackendFs2Stream *stream = get_stream(self, sid, name);
+			gst_object_unref(stream->stream);
+
+			priv->streams = g_list_remove(priv->streams, stream);
+
+			remove_element(stream->src);
+			remove_element(stream->tee);
+			remove_element(stream->volume);
+			remove_element(stream->level);
+			remove_element(stream->fakesink);
+			remove_element(stream->queue);
+
+			free_stream(stream);
+		} else if (sid && !name) {
+			PurpleMediaBackendFs2Session *session = get_session(self, sid);
+			GstPad *pad;
+
+			g_object_get(session->session, "sink-pad", &pad, NULL);
+			gst_pad_unlink(GST_PAD_PEER(pad), pad);
+			gst_object_unref(pad);
+
+			gst_object_unref(session->session);
+			g_hash_table_remove(priv->sessions, session->id);
+
+			pad = gst_pad_get_peer(session->srcpad);
+			gst_element_remove_pad(GST_ELEMENT_PARENT(pad), pad);
+			gst_object_unref(pad);
+			gst_object_unref(session->srcpad);
+
+			remove_element(session->srcvalve);
+			remove_element(session->tee);
+
+			free_session(session);
+		}
+
+		purple_media_manager_remove_output_windows(
+				purple_media_get_manager(media), media, sid, name);
+	}
 }
 
 static void
@@ -1420,6 +1464,7 @@ create_src(PurpleMediaBackendFs2 *self, 
 			  ? "success" : "failure");
 	gst_element_set_locked_state(session->src, FALSE);
 	gst_object_unref(session->src);
+	gst_object_unref(sinkpad);
 
 	gst_element_set_state(session->src, GST_STATE_PLAYING);
 
@@ -1536,6 +1581,13 @@ create_session(PurpleMediaBackendFs2 *se
 	return TRUE;
 }
 
+static void
+free_session(PurpleMediaBackendFs2Session *session)
+{
+	g_free(session->id);
+	g_free(session);
+}
+
 static gboolean
 create_participant(PurpleMediaBackendFs2 *self, const gchar *name)
 {
@@ -1603,7 +1655,6 @@ src_pad_added_cb(FsStream *fsstream, Gst
 		GstElement *sink = NULL;
 
 		if (codec->media_type == FS_MEDIA_TYPE_AUDIO) {
-			GstElement *queue = NULL;
 			double output_volume = purple_prefs_get_int(
 					"/purple/media/audio/volume/output")/10.0;
 			/*
@@ -1611,7 +1662,7 @@ src_pad_added_cb(FsStream *fsstream, Gst
 			 *  audioconvert ! audioresample ! liveadder !
 			 *   audioresample ! audioconvert ! realsink
 			 */
-			queue = gst_element_factory_make("queue", NULL);
+			stream->queue = gst_element_factory_make("queue", NULL);
 			stream->volume = gst_element_factory_make(
 					"volume", NULL);
 			g_object_set(stream->volume, "volume",
@@ -1625,18 +1676,18 @@ src_pad_added_cb(FsStream *fsstream, Gst
 					PURPLE_MEDIA_RECV_AUDIO, priv->media,
 					stream->session->id,
 					stream->participant);
-			gst_bin_add(GST_BIN(priv->confbin), queue);
+			gst_bin_add(GST_BIN(priv->confbin), stream->queue);
 			gst_bin_add(GST_BIN(priv->confbin), stream->volume);
 			gst_bin_add(GST_BIN(priv->confbin), stream->level);
 			gst_bin_add(GST_BIN(priv->confbin), sink);
 			gst_element_set_state(sink, GST_STATE_PLAYING);
 			gst_element_set_state(stream->level, GST_STATE_PLAYING);
 			gst_element_set_state(stream->volume, GST_STATE_PLAYING);
-			gst_element_set_state(queue, GST_STATE_PLAYING);
+			gst_element_set_state(stream->queue, GST_STATE_PLAYING);
 			gst_element_link(stream->level, sink);
 			gst_element_link(stream->volume, stream->level);
-			gst_element_link(queue, stream->volume);
-			sink = queue;
+			gst_element_link(stream->queue, stream->volume);
+			sink = stream->queue;
 		} else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) {
 			stream->src = gst_element_factory_make(
 					"fsfunnel", NULL);
@@ -1645,6 +1696,7 @@ src_pad_added_cb(FsStream *fsstream, Gst
 			g_object_set(G_OBJECT(sink), "async", FALSE, NULL);
 			gst_bin_add(GST_BIN(priv->confbin), sink);
 			gst_element_set_state(sink, GST_STATE_PLAYING);
+			stream->fakesink = sink;
 		}
 		stream->tee = gst_element_factory_make("tee", NULL);
 		gst_bin_add_many(GST_BIN(priv->confbin),
@@ -1814,6 +1866,24 @@ create_stream(PurpleMediaBackendFs2 *sel
 	return TRUE;
 }
 
+static void
+free_stream(PurpleMediaBackendFs2Stream *stream)
+{
+	/* Remove the connected_cb timeout */
+	if (stream->connected_cb_id != 0)
+		purple_timeout_remove(stream->connected_cb_id);
+
+	g_free(stream->participant);
+
+	if (stream->local_candidates)
+		fs_candidate_list_destroy(stream->local_candidates);
+
+	if (stream->remote_candidates)
+		fs_candidate_list_destroy(stream->remote_candidates);
+
+	g_free(stream);
+}
+
 static gboolean
 purple_media_backend_fs2_add_stream(PurpleMediaBackend *self,
 		const gchar *sess_id, const gchar *who,


More information about the Commits mailing list