Use new ghostpad API; now they actually work in Totem, also.

Original commit message from CVS:
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_reset),
(gst_gconf_audio_sink_init), (do_toggle_element),
(cb_toggle_element), (gst_gconf_audio_sink_change_state):
* ext/gconf/gstgconfaudiosink.h:
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_reset),
(gst_gconf_video_sink_init), (do_toggle_element),
(cb_toggle_element), (gst_gconf_video_sink_change_state):
* ext/gconf/gstgconfvideosink.h:
* gst/autodetect/gstautoaudiosink.c: (gst_auto_audio_sink_reset),
(gst_auto_audio_sink_init), (gst_auto_audio_sink_detect),
(gst_auto_audio_sink_change_state):
* gst/autodetect/gstautoaudiosink.h:
* gst/autodetect/gstautovideosink.c: (gst_auto_video_sink_reset),
(gst_auto_video_sink_init), (gst_auto_video_sink_detect),
(gst_auto_video_sink_change_state):
* gst/autodetect/gstautovideosink.h:
Use new ghostpad API; now they actually work in Totem, also.
This commit is contained in:
Ronald S. Bultje 2005-08-03 17:18:31 +00:00
parent 1b23cf61a8
commit 7e8df65cc2
9 changed files with 225 additions and 170 deletions

View file

@ -1,3 +1,23 @@
2005-08-03 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_reset),
(gst_gconf_audio_sink_init), (do_toggle_element),
(cb_toggle_element), (gst_gconf_audio_sink_change_state):
* ext/gconf/gstgconfaudiosink.h:
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_reset),
(gst_gconf_video_sink_init), (do_toggle_element),
(cb_toggle_element), (gst_gconf_video_sink_change_state):
* ext/gconf/gstgconfvideosink.h:
* gst/autodetect/gstautoaudiosink.c: (gst_auto_audio_sink_reset),
(gst_auto_audio_sink_init), (gst_auto_audio_sink_detect),
(gst_auto_audio_sink_change_state):
* gst/autodetect/gstautoaudiosink.h:
* gst/autodetect/gstautovideosink.c: (gst_auto_video_sink_reset),
(gst_auto_video_sink_init), (gst_auto_video_sink_detect),
(gst_auto_video_sink_change_state):
* gst/autodetect/gstautovideosink.h:
Use new ghostpad API; now they actually work in Totem, also.
2005-08-03 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/libpng/Makefile.am:

View file

@ -62,20 +62,40 @@ gst_gconf_audio_sink_class_init (GstGConfAudioSinkClass * klass)
eklass->change_state = gst_gconf_audio_sink_change_state;
}
/*
* Hack to make negotiation work.
*/
static void
gst_gconf_audio_sink_reset (GstGConfAudioSink * sink)
{
GstPad *targetpad;
/* fakesink */
if (sink->kid) {
gst_bin_remove (GST_BIN (sink), sink->kid);
}
sink->kid = gst_element_factory_make ("fakesink", "testsink");
gst_bin_add (GST_BIN (sink), sink->kid);
targetpad = gst_element_get_pad (sink->kid, "sink");
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
}
static void
gst_gconf_audio_sink_init (GstGConfAudioSink * sink)
{
sink->pad = NULL;
sink->kid = NULL;
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
gst_gconf_audio_sink_reset (sink);
sink->client = gconf_client_get_default ();
gconf_client_add_dir (sink->client, GST_GCONF_DIR,
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
gconf_client_notify_add (sink->client, GST_GCONF_DIR "/default/audiosink",
cb_toggle_element, sink, NULL, NULL);
cb_toggle_element (sink->client, 0, NULL, sink);
sink->init = FALSE;
}
static void
@ -91,23 +111,10 @@ gst_gconf_audio_sink_dispose (GObject * object)
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
static void
cb_toggle_element (GConfClient * client,
guint connection_id, GConfEntry * entry, gpointer data)
static gboolean
do_toggle_element (GstGConfAudioSink * sink)
{
GstGConfAudioSink *sink = GST_GCONF_AUDIO_SINK (data);
GstPad *peer = NULL, *targetpad;
/* save ghostpad */
if (sink->pad) {
peer = GST_PAD_PEER (sink->pad);
if (peer) {
gst_pad_unlink (peer, sink->pad);
GST_DEBUG_OBJECT (sink, "Caching peer %p", peer);
}
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
sink->pad = NULL;
}
GstPad *targetpad;
/* kill old element */
if (sink->kid) {
@ -116,31 +123,30 @@ cb_toggle_element (GConfClient * client,
sink->kid = NULL;
}
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)",
entry ? "audio" : "fake");
sink->kid = entry ? gst_gconf_get_default_audio_sink () :
gst_element_factory_make ("fakesink", "temporary-element");
if (!sink->kid) {
GST_DEBUG_OBJECT (sink, "Creating new kid");
if (!(sink->kid = gst_gconf_get_default_audio_sink ())) {
GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
("Failed to render audio sink from GConf"));
return;
return FALSE;
}
gst_element_set_state (sink->kid, GST_STATE (sink));
gst_bin_add (GST_BIN (sink), sink->kid);
/* re-attach ghostpad */
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
targetpad = gst_element_get_pad (sink->kid, "sink");
sink->pad = gst_ghost_pad_new ("sink", targetpad);
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
if (peer) {
GST_DEBUG_OBJECT (sink, "Linking...");
gst_pad_link (peer, sink->pad);
}
GST_DEBUG_OBJECT (sink, "done changing gconf audio sink");
sink->init = TRUE;
return TRUE;
}
static void
cb_toggle_element (GConfClient * client,
guint connection_id, GConfEntry * entry, gpointer data)
{
do_toggle_element (GST_GCONF_AUDIO_SINK (data));
}
static GstElementStateReturn
@ -148,12 +154,16 @@ gst_gconf_audio_sink_change_state (GstElement * element)
{
GstGConfAudioSink *sink = GST_GCONF_AUDIO_SINK (element);
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
cb_toggle_element (sink->client, 0,
gconf_client_get_entry (sink->client,
GST_GCONF_DIR "/default/audiosink", NULL, TRUE, NULL), sink);
if (!sink->init)
return GST_STATE_FAILURE;
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
if (!do_toggle_element (sink))
return GST_STATE_FAILURE;
break;
case GST_STATE_READY_TO_NULL:
gst_gconf_audio_sink_reset (sink);
break;
default:
break;
}
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,

View file

@ -45,7 +45,6 @@ typedef struct _GstGConfAudioSink {
GConfClient *client;
GstElement *kid;
GstPad *pad;
gboolean init;
} GstGConfAudioSink;
typedef struct _GstGConfAudioSinkClass {

View file

@ -62,20 +62,40 @@ gst_gconf_video_sink_class_init (GstGConfVideoSinkClass * klass)
eklass->change_state = gst_gconf_video_sink_change_state;
}
/*
* Hack to make negotiation work.
*/
static void
gst_gconf_video_sink_reset (GstGConfVideoSink * sink)
{
GstPad *targetpad;
/* fakesink */
if (sink->kid) {
gst_bin_remove (GST_BIN (sink), sink->kid);
}
sink->kid = gst_element_factory_make ("fakesink", "testsink");
gst_bin_add (GST_BIN (sink), sink->kid);
targetpad = gst_element_get_pad (sink->kid, "sink");
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
}
static void
gst_gconf_video_sink_init (GstGConfVideoSink * sink)
{
sink->pad = NULL;
sink->kid = NULL;
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
gst_gconf_video_sink_reset (sink);
sink->client = gconf_client_get_default ();
gconf_client_add_dir (sink->client, GST_GCONF_DIR,
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
gconf_client_notify_add (sink->client, GST_GCONF_DIR "/default/videosink",
cb_toggle_element, sink, NULL, NULL);
cb_toggle_element (sink->client, 0, NULL, sink);
sink->init = FALSE;
}
static void
@ -91,23 +111,10 @@ gst_gconf_video_sink_dispose (GObject * object)
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
static void
cb_toggle_element (GConfClient * client,
guint connection_id, GConfEntry * entry, gpointer data)
static gboolean
do_toggle_element (GstGConfVideoSink * sink)
{
GstGConfVideoSink *sink = GST_GCONF_VIDEO_SINK (data);
GstPad *peer = NULL, *targetpad;
/* save ghostpad */
if (sink->pad) {
peer = GST_PAD_PEER (sink->pad);
if (peer) {
gst_pad_unlink (peer, sink->pad);
GST_DEBUG_OBJECT (sink, "Caching peer %p", peer);
}
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
sink->pad = NULL;
}
GstPad *targetpad;
/* kill old element */
if (sink->kid) {
@ -116,31 +123,30 @@ cb_toggle_element (GConfClient * client,
sink->kid = NULL;
}
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)",
entry ? "video" : "fake");
sink->kid = entry ? gst_gconf_get_default_video_sink () :
gst_element_factory_make ("fakesink", "temporary-element");
if (!sink->kid) {
GST_DEBUG_OBJECT (sink, "Creating new kid");
if (!(sink->kid = gst_gconf_get_default_video_sink ())) {
GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
("Failed to render video sink from GConf"));
return;
return FALSE;
}
gst_element_set_state (sink->kid, GST_STATE (sink));
gst_bin_add (GST_BIN (sink), sink->kid);
/* re-attach ghostpad */
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
targetpad = gst_element_get_pad (sink->kid, "sink");
sink->pad = gst_ghost_pad_new ("sink", targetpad);
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
if (peer) {
GST_DEBUG_OBJECT (sink, "Linking...");
gst_pad_link (peer, sink->pad);
}
GST_DEBUG_OBJECT (sink, "done changing gconf video sink");
sink->init = TRUE;
return TRUE;
}
static void
cb_toggle_element (GConfClient * client,
guint connection_id, GConfEntry * entry, gpointer data)
{
do_toggle_element (GST_GCONF_VIDEO_SINK (data));
}
static GstElementStateReturn
@ -148,12 +154,16 @@ gst_gconf_video_sink_change_state (GstElement * element)
{
GstGConfVideoSink *sink = GST_GCONF_VIDEO_SINK (element);
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
cb_toggle_element (sink->client, 0,
gconf_client_get_entry (sink->client,
GST_GCONF_DIR "/default/videosink", NULL, TRUE, NULL), sink);
if (!sink->init)
return GST_STATE_FAILURE;
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
if (!do_toggle_element (sink))
return GST_STATE_FAILURE;
break;
case GST_STATE_READY_TO_NULL:
gst_gconf_video_sink_reset (sink);
break;
default:
break;
}
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,

View file

@ -45,7 +45,6 @@ typedef struct _GstGConfVideoSink {
GConfClient *client;
GstElement *kid;
GstPad *pad;
gboolean init;
} GstGConfVideoSink;
typedef struct _GstGConfVideoSinkClass {

View file

@ -26,7 +26,6 @@
#include "gstautoaudiosink.h"
#include "gstautodetect.h"
static void gst_auto_audio_sink_detect (GstAutoAudioSink * sink, gboolean fake);
static GstElementStateReturn
gst_auto_audio_sink_change_state (GstElement * element);
@ -60,13 +59,36 @@ gst_auto_audio_sink_class_init (GstAutoAudioSinkClass * klass)
eklass->change_state = gst_auto_audio_sink_change_state;
}
/*
* Hack to make initial linking work; ideally, this'd work even when
* no target has been assigned to the ghostpad yet.
*/
static void
gst_auto_audio_sink_reset (GstAutoAudioSink * sink)
{
GstPad *targetpad;
/* fakesink placeholder */
if (sink->kid) {
gst_bin_remove (GST_BIN (sink), sink->kid);
}
sink->kid = gst_element_factory_make ("fakesink", "tempsink");
gst_bin_add (GST_BIN (sink), sink->kid);
/* pad */
targetpad = gst_element_get_pad (sink->kid, "sink");
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
}
static void
gst_auto_audio_sink_init (GstAutoAudioSink * sink)
{
sink->pad = NULL;
sink->kid = NULL;
gst_auto_audio_sink_detect (sink, TRUE);
sink->init = FALSE;
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
gst_auto_audio_sink_reset (sink);
}
static gboolean
@ -171,56 +193,35 @@ done:
return choice;
}
static void
gst_auto_audio_sink_detect (GstAutoAudioSink * sink, gboolean fake)
static gboolean
gst_auto_audio_sink_detect (GstAutoAudioSink * sink)
{
GstElement *esink;
GstPad *targetpad, *peer = NULL;
GstPad *targetpad;
/* save ghostpad */
if (sink->pad) {
peer = GST_PAD_PEER (sink->pad);
if (peer) {
gst_pad_unlink (peer, sink->pad);
GST_DEBUG_OBJECT (sink, "Element was linked, caching peer %p", peer);
}
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
sink->pad = NULL;
}
/* kill old element */
if (sink->kid) {
GST_DEBUG_OBJECT (sink, "Removing old kid");
gst_bin_remove (GST_BIN (sink), sink->kid);
sink->kid = NULL;
}
/* find element */
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)", fake ? "fake" : "audio");
if (fake) {
esink = gst_element_factory_make ("fakesink", "temporary-sink");
} else if (!(esink = gst_auto_audio_sink_find_best (sink))) {
GST_DEBUG_OBJECT (sink, "Creating new kid");
if (!(esink = gst_auto_audio_sink_find_best (sink))) {
GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
("Failed to find a supported audio sink"));
return;
return FALSE;
}
sink->kid = esink;
gst_bin_add (GST_BIN (sink), esink);
/* attach ghost pad */
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
targetpad = gst_element_get_pad (sink->kid, "sink");
sink->pad = gst_ghost_pad_new ("sink", targetpad);
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
if (peer) {
GST_DEBUG_OBJECT (sink, "Linking...");
gst_pad_link (peer, sink->pad);
}
GST_DEBUG_OBJECT (sink, "done changing auto audio sink");
sink->init = TRUE;
return TRUE;
}
static GstElementStateReturn
@ -228,12 +229,20 @@ gst_auto_audio_sink_change_state (GstElement * element)
{
GstAutoAudioSink *sink = GST_AUTO_AUDIO_SINK (element);
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
gst_auto_audio_sink_detect (sink, FALSE);
if (!sink->init)
return GST_STATE_FAILURE;
GST_DEBUG_OBJECT (element, "Change state 0x%x",
GST_STATE_TRANSITION (element));
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
if (!gst_auto_audio_sink_detect (sink))
return GST_STATE_FAILURE;
break;
case GST_STATE_READY_TO_NULL:
gst_auto_audio_sink_reset (sink);
break;
default:
break;
}
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
(element), GST_STATE_SUCCESS);
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
}

View file

@ -43,7 +43,6 @@ typedef struct _GstAutoAudioSink {
/* explicit pointers to stuff used */
GstPad *pad;
GstElement *kid;
gboolean init;
} GstAutoAudioSink;
typedef struct _GstAutoAudioSinkClass {

View file

@ -26,7 +26,6 @@
#include "gstautovideosink.h"
#include "gstautodetect.h"
static void gst_auto_video_sink_detect (GstAutoVideoSink * sink, gboolean fake);
static GstElementStateReturn
gst_auto_video_sink_change_state (GstElement * element);
@ -60,13 +59,36 @@ gst_auto_video_sink_class_init (GstAutoVideoSinkClass * klass)
eklass->change_state = gst_auto_video_sink_change_state;
}
/*
* Hack to make initial linking work; ideally, this'd work even when
* no target has been assigned to the ghostpad yet.
*/
static void
gst_auto_video_sink_reset (GstAutoVideoSink * sink)
{
GstPad *targetpad;
/* fakesink placeholder */
if (sink->kid) {
gst_bin_remove (GST_BIN (sink), sink->kid);
}
sink->kid = gst_element_factory_make ("fakesink", "tempsink");
gst_bin_add (GST_BIN (sink), sink->kid);
/* pad */
targetpad = gst_element_get_pad (sink->kid, "sink");
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
}
static void
gst_auto_video_sink_init (GstAutoVideoSink * sink)
{
sink->pad = NULL;
sink->kid = NULL;
gst_auto_video_sink_detect (sink, TRUE);
sink->init = FALSE;
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
gst_auto_video_sink_reset (sink);
}
static gboolean
@ -132,56 +154,35 @@ gst_auto_video_sink_find_best (GstAutoVideoSink * sink)
return NULL;
}
static void
gst_auto_video_sink_detect (GstAutoVideoSink * sink, gboolean fake)
static gboolean
gst_auto_video_sink_detect (GstAutoVideoSink * sink)
{
GstElement *esink;
GstPad *targetpad, *peer = NULL;
GstPad *targetpad;
/* save ghostpad */
if (sink->pad) {
peer = GST_PAD_PEER (sink->pad);
if (peer) {
gst_pad_unlink (peer, sink->pad);
GST_DEBUG_OBJECT (sink, "Element was linked, caching peer %p", peer);
}
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
sink->pad = NULL;
}
/* kill old element */
if (sink->kid) {
GST_DEBUG_OBJECT (sink, "Removing old kid");
gst_bin_remove (GST_BIN (sink), sink->kid);
sink->kid = NULL;
}
/* find element */
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)", fake ? "fake" : "video");
if (fake) {
esink = gst_element_factory_make ("fakesink", "temporary-sink");
} else if (!(esink = gst_auto_video_sink_find_best (sink))) {
GST_DEBUG_OBJECT (sink, "Creating new kid");
if (!(esink = gst_auto_video_sink_find_best (sink))) {
GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
("Failed to find a supported video sink"));
return;
return FALSE;
}
sink->kid = esink;
gst_bin_add (GST_BIN (sink), esink);
/* attach ghost pad */
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
targetpad = gst_element_get_pad (sink->kid, "sink");
sink->pad = gst_ghost_pad_new ("sink", targetpad);
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
gst_object_unref (targetpad);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
if (peer) {
GST_DEBUG_OBJECT (sink, "Linking...");
gst_pad_link (peer, sink->pad);
}
GST_DEBUG_OBJECT (sink, "done changing auto video sink");
sink->init = TRUE;
return TRUE;
}
static GstElementStateReturn
@ -189,10 +190,19 @@ gst_auto_video_sink_change_state (GstElement * element)
{
GstAutoVideoSink *sink = GST_AUTO_VIDEO_SINK (element);
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
gst_auto_video_sink_detect (sink, FALSE);
if (!sink->init)
return GST_STATE_FAILURE;
GST_DEBUG_OBJECT (element, "Change state 0x%x",
GST_STATE_TRANSITION (element));
switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_NULL_TO_READY:
if (!gst_auto_video_sink_detect (sink))
return GST_STATE_FAILURE;
break;
case GST_STATE_READY_TO_NULL:
gst_auto_video_sink_reset (sink);
break;
default:
break;
}
return GST_ELEMENT_CLASS (parent_class)->change_state (element);

View file

@ -43,7 +43,6 @@ typedef struct _GstAutoVideoSink {
/* explicit pointers to stuff used */
GstPad *pad;
GstElement *kid;
gboolean init;
} GstAutoVideoSink;
typedef struct _GstAutoVideoSinkClass {