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:
Fix uninstalled build.
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
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) {
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);
+ GST_DEBUG_OBJECT (sink, "done changing gconf audio sink");
- if (peer) {
- GST_DEBUG_OBJECT (sink, "Linking...");
- gst_pad_link (peer, sink->pad);
- }
+ return TRUE;
+}
- GST_DEBUG_OBJECT (sink, "done changing gconf audio sink");
- sink->init = 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
{
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,
GConfClient *client;
GstElement *kid;
GstPad *pad;
- gboolean init;
} GstGConfAudioSink;
typedef struct _GstGConfAudioSinkClass {
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
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) {
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);
+ GST_DEBUG_OBJECT (sink, "done changing gconf video sink");
- if (peer) {
- GST_DEBUG_OBJECT (sink, "Linking...");
- gst_pad_link (peer, sink->pad);
- }
+ return TRUE;
+}
- GST_DEBUG_OBJECT (sink, "done changing gconf video sink");
- sink->init = 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
{
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,
GConfClient *client;
GstElement *kid;
GstPad *pad;
- gboolean init;
} GstGConfVideoSink;
typedef struct _GstGConfVideoSinkClass {
#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);
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
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;
-
- /* 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;
- }
+ GstPad *targetpad;
- /* 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
{
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);
}
/* explicit pointers to stuff used */
GstPad *pad;
GstElement *kid;
- gboolean init;
} GstAutoAudioSink;
typedef struct _GstAutoAudioSinkClass {
#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);
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
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;
-
- /* 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;
- }
+ GstPad *targetpad;
- /* 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
{
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);
/* explicit pointers to stuff used */
GstPad *pad;
GstElement *kid;
- gboolean init;
} GstAutoVideoSink;
typedef struct _GstAutoVideoSinkClass {