Use new ghostpad API; now they actually work in Totem, also.
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 3 Aug 2005 17:18:31 +0000 (17:18 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 3 Aug 2005 17:18:31 +0000 (17:18 +0000)
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.

ChangeLog
ext/gconf/gstgconfaudiosink.c
ext/gconf/gstgconfaudiosink.h
ext/gconf/gstgconfvideosink.c
ext/gconf/gstgconfvideosink.h
gst/autodetect/gstautoaudiosink.c
gst/autodetect/gstautoaudiosink.h
gst/autodetect/gstautovideosink.c
gst/autodetect/gstautovideosink.h

index 2ab458e..75c5df2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 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.
 
index edca50a..256f569 100644 (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);
+  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
@@ -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,
index 28f6d82..3029aec 100644 (file)
@@ -45,7 +45,6 @@ typedef struct _GstGConfAudioSink {
   GConfClient *client;
   GstElement *kid;
   GstPad *pad;
-  gboolean init;
 } GstGConfAudioSink;
 
 typedef struct _GstGConfAudioSinkClass {
index f8f6838..88b7644 100644 (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);
+  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
@@ -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,
index 2aa4675..9bd0bfb 100644 (file)
@@ -45,7 +45,6 @@ typedef struct _GstGConfVideoSink {
   GConfClient *client;
   GstElement *kid;
   GstPad *pad;
-  gboolean init;
 } GstGConfVideoSink;
 
 typedef struct _GstGConfVideoSinkClass {
index a77a541..9d62c7d 100644 (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;
-
-  /* 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
@@ -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);
 }
index 3df3b94..50b6b47 100644 (file)
@@ -43,7 +43,6 @@ typedef struct _GstAutoAudioSink {
   /* explicit pointers to stuff used */
   GstPad *pad;
   GstElement *kid;
-  gboolean init;
 } GstAutoAudioSink;
 
 typedef struct _GstAutoAudioSinkClass {
index 0a472eb..ba22a21 100644 (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;
-
-  /* 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
@@ -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);
index 42885c5..06995ad 100644 (file)
@@ -43,7 +43,6 @@ typedef struct _GstAutoVideoSink {
   /* explicit pointers to stuff used */
   GstPad *pad;
   GstElement *kid;
-  gboolean init;
 } GstAutoVideoSink;
 
 typedef struct _GstAutoVideoSinkClass {