Mercurial > pidgin
changeset 26381:6bcf5ad967ea
Make sharing sources between media sessions work.
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Mon, 30 Mar 2009 22:00:35 +0000 |
parents | b0a9c48b5f69 |
children | f42892982e30 |
files | libpurple/media.c libpurple/mediamanager.c |
diffstat | 2 files changed, 93 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/media.c Mon Mar 30 04:15:53 2009 +0000 +++ b/libpurple/media.c Mon Mar 30 22:00:35 2009 +0000 @@ -1151,12 +1151,21 @@ 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 @@ 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
--- a/libpurple/mediamanager.c Mon Mar 30 04:15:53 2009 +0000 +++ b/libpurple/mediamanager.c Mon Mar 30 22:00:35 2009 +0000 @@ -328,28 +328,94 @@ #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 (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 (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 (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");