Index: gst/gstbin.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstbin.c,v
retrieving revision 1.336
diff -u -p -r1.336 gstbin.c
--- gst/gstbin.c	7 Jul 2006 15:42:08 -0000	1.336
+++ gst/gstbin.c	8 Jul 2006 17:13:55 -0000
@@ -1762,6 +1762,83 @@ done:
   return ret;
 }
 
+/* gst_iterator_fold functions for pads_activate */
+
+static gboolean
+activate_pads (GstPad * pad, GValue * ret, gboolean * active)
+{
+  if (!gst_pad_set_active (pad, *active))
+    g_value_set_boolean (ret, FALSE);
+  else if (!*active)
+    gst_pad_set_caps (pad, NULL);
+
+  gst_object_unref (pad);
+  return TRUE;
+}
+
+/* returns false on error or early cutout of the fold, true otherwise */
+static gboolean
+iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
+    GValue * ret, gpointer user_data)
+{
+  GstIteratorResult ires;
+  gboolean res = TRUE;
+
+  while (1) {
+    ires = gst_iterator_fold (iter, func, ret, user_data);
+
+    switch (ires) {
+      case GST_ITERATOR_RESYNC:
+        gst_iterator_resync (iter);
+        break;
+      case GST_ITERATOR_DONE:
+        res = TRUE;
+        goto done;
+      default:
+        res = FALSE;
+        goto done;
+    }
+  }
+
+done:
+  return res;
+}
+
+/* is called with STATE_LOCK
+ */
+static gboolean
+gst_bin_src_pads_activate (GstBin * bin, gboolean active)
+{
+  GValue ret = { 0, };
+  GstIterator *iter;
+  gboolean fold_ok;
+
+  GST_DEBUG_OBJECT (bin, "src_pads_activate with active %d", active);
+
+  /* no need to unset this later, it's just a boolean */
+  g_value_init (&ret, G_TYPE_BOOLEAN);
+  g_value_set_boolean (&ret, TRUE);
+
+  iter = gst_element_iterate_src_pads ((GstElement*) bin);
+
+  fold_ok = iterator_fold_with_resync
+      (iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
+  gst_iterator_free (iter);
+  if (G_UNLIKELY (!fold_ok || !g_value_get_boolean (&ret)))
+    goto failed;
+
+
+  GST_DEBUG_OBJECT (bin, "pads_activate successful");
+
+  return TRUE;
+
+  /* ERRORS */
+failed:
+  {
+    GST_DEBUG_OBJECT (bin, "source pads_activate failed");
+    return FALSE;
+  }
+}
 static GstStateChangeReturn
 gst_bin_change_state_func (GstElement * element, GstStateChange transition)
 {
@@ -1791,6 +1868,9 @@ gst_bin_change_state_func (GstElement * 
       GST_DEBUG_OBJECT (element, "clearing EOS elements");
       bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
       GST_OBJECT_UNLOCK (bin);
+      if (current == GST_STATE_READY)
+	if (!(gst_bin_src_pads_activate (bin, TRUE)))
+	  goto activate_failure;
       break;
     case GST_STATE_READY:
       /* Clear message list on next READY */
@@ -1798,7 +1878,15 @@ gst_bin_change_state_func (GstElement * 
       GST_DEBUG_OBJECT (element, "clearing all cached messages");
       bin_remove_messages (bin, NULL, GST_MESSAGE_ANY);
       GST_OBJECT_UNLOCK (bin);
-      break;
+      if (current == GST_STATE_PAUSED)
+	if (!(gst_bin_src_pads_activate (bin, FALSE)))
+	  goto activate_failure;
+      break;
+  case GST_STATE_NULL:
+    if (current == GST_STATE_READY)
+      if (!(gst_bin_src_pads_activate (bin, FALSE)))
+	goto activate_failure;
+    break;
     default:
       break;
   }
@@ -1897,6 +1985,11 @@ done:
       gst_element_state_get_name (GST_STATE (element)), ret);
 
   return ret;
+
+ activate_failure:
+  GST_CAT_WARNING_OBJECT (GST_CAT_STATES, element,
+			  "failure (de)activating src pads");
+  return GST_STATE_CHANGE_FAILURE;
 }
 
 /*
Index: gst/gstghostpad.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstghostpad.c,v
retrieving revision 1.36
diff -u -p -r1.36 gstghostpad.c
--- gst/gstghostpad.c	5 May 2006 12:53:33 -0000	1.36
+++ gst/gstghostpad.c	8 Jul 2006 17:13:55 -0000
@@ -84,6 +84,7 @@ struct _GstProxyPadClass
 G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
 
 static GstPad *gst_proxy_pad_get_target (GstPad * pad);
+static GstPad *gst_proxy_pad_get_neighbour (GstPad * pad);
 
 static void gst_proxy_pad_dispose (GObject * object);
 static void gst_proxy_pad_finalize (GObject * object);
@@ -129,13 +130,18 @@ gst_proxy_pad_do_query_type (GstPad * pa
 static gboolean
 gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
 {
-  gboolean res;
-  GstPad *target = gst_proxy_pad_get_target (pad);
+  gboolean res = FALSE;
+  GstPad *neighbour = gst_proxy_pad_get_neighbour (pad);
 
-  g_return_val_if_fail (target != NULL, FALSE);
+  g_return_val_if_fail (neighbour != NULL, FALSE);
 
-  res = gst_pad_send_event (target, event);
-  gst_object_unref (target);
+  GST_DEBUG_OBJECT (pad, "direction:%d , neighbour is %s:%s : direction:%d",
+      GST_PAD_DIRECTION (pad),
+      GST_DEBUG_PAD_NAME (neighbour), GST_PAD_DIRECTION (neighbour));
+
+  res = gst_pad_push_event (neighbour, event);
+
+  gst_object_unref (neighbour);
 
   return res;
 }
@@ -173,23 +179,13 @@ gst_proxy_pad_do_bufferalloc (GstPad * p
     GstCaps * caps, GstBuffer ** buf)
 {
   GstFlowReturn result;
-  GstPad *target = gst_proxy_pad_get_target (pad);
-  GstPad *peer;
-
-  g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
-
-  peer = gst_pad_get_peer (target);
-  if (peer) {
-    GST_DEBUG ("buffer alloc on %s:%s", GST_DEBUG_PAD_NAME (target));
+  GstPad *neighbour = gst_proxy_pad_get_neighbour (pad);
 
-    result = gst_pad_alloc_buffer (peer, offset, size, caps, buf);
+  g_return_val_if_fail (neighbour != NULL, GST_FLOW_NOT_LINKED);
 
-    gst_object_unref (peer);
-  } else {
-    result = GST_FLOW_NOT_LINKED;
-  }
+  result = gst_pad_alloc_buffer (neighbour, offset, size, caps, buf);
 
-  gst_object_unref (target);
+  gst_object_unref (neighbour);
 
   return result;
 }
@@ -197,13 +193,14 @@ gst_proxy_pad_do_bufferalloc (GstPad * p
 static GstFlowReturn
 gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
 {
-  GstPad *target = gst_proxy_pad_get_target (pad);
+  GstPad *neighbour = gst_proxy_pad_get_neighbour (pad);
   GstFlowReturn res;
 
-  g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
+  g_return_val_if_fail (neighbour != NULL, GST_FLOW_NOT_LINKED);
 
-  res = gst_pad_chain (target, buffer);
-  gst_object_unref (target);
+  res = gst_pad_push (neighbour, buffer);
+
+  gst_object_unref (neighbour);
 
   return res;
 }
@@ -212,13 +209,13 @@ static GstFlowReturn
 gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
     GstBuffer ** buffer)
 {
-  GstPad *target = gst_proxy_pad_get_target (pad);
+  GstPad *neighbour = gst_proxy_pad_get_neighbour (pad);
   GstFlowReturn res;
 
-  g_return_val_if_fail (target != NULL, GST_FLOW_NOT_LINKED);
+  g_return_val_if_fail (neighbour != NULL, GST_FLOW_NOT_LINKED);
 
-  res = gst_pad_get_range (target, offset, size, buffer);
-  gst_object_unref (target);
+  res = gst_pad_pull_range (neighbour, offset, size, buffer);
+  gst_object_unref (neighbour);
 
   return res;
 }
@@ -227,19 +224,13 @@ static gboolean
 gst_proxy_pad_do_checkgetrange (GstPad * pad)
 {
   gboolean result;
-  GstPad *target = gst_proxy_pad_get_target (pad);
-  GstPad *peer;
+  GstPad *neighbour = gst_proxy_pad_get_neighbour (pad);
 
-  g_return_val_if_fail (target != NULL, FALSE);
+  g_return_val_if_fail (neighbour != NULL, FALSE);
 
-  peer = gst_pad_get_peer (target);
-  if (peer) {
-    result = gst_pad_check_pull_range (peer);
-    gst_object_unref (peer);
-  } else {
-    result = FALSE;
-  }
-  gst_object_unref (target);
+  result = gst_pad_check_pull_range (neighbour);
+
+  gst_object_unref (neighbour);
 
   return result;
 }
@@ -250,11 +241,15 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
   GstPad *target = gst_proxy_pad_get_target (pad);
   GstCaps *res;
 
-  g_return_val_if_fail (target != NULL, NULL);
-
-  res = gst_pad_get_caps (target);
-  gst_object_unref (target);
-
+  if (target) {
+    GST_LOG_OBJECT (pad, "Returning caps of %s:%s",
+		    GST_DEBUG_PAD_NAME (target));
+    res = gst_pad_get_caps (target);
+    gst_object_unref (target);
+  } else {
+    GST_LOG_OBJECT (pad, "NO TARGET !! Returning ANY");
+    res = gst_caps_new_any ();
+  }
   return res;
 }
 
@@ -302,8 +297,14 @@ gst_proxy_pad_set_target_unlocked (GstPa
 {
   GstPad *oldtarget;
 
-  GST_DEBUG ("set target %s:%s on %s:%s",
-      GST_DEBUG_PAD_NAME (target), GST_DEBUG_PAD_NAME (pad));
+  if (target) {
+    GST_DEBUG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
+    if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target))) {
+      GST_ERROR_OBJECT (pad, "target pad doesn't have the same direction as ourself");
+      return FALSE;
+    }
+  } else
+    GST_DEBUG_OBJECT (pad, "clearing target");
 
   /* clear old target */
   if ((oldtarget = GST_PROXY_PAD_TARGET (pad))) {
@@ -314,35 +315,6 @@ gst_proxy_pad_set_target_unlocked (GstPa
   if (target) {
     /* set and ref new target if any */
     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
-
-    gst_pad_set_query_type_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
-    gst_pad_set_event_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
-    gst_pad_set_query_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
-    gst_pad_set_internal_link_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
-    gst_pad_set_getcaps_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
-    gst_pad_set_acceptcaps_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
-    gst_pad_set_fixatecaps_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
-    gst_pad_set_setcaps_function (pad,
-        GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
-
-    if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
-      gst_pad_set_bufferalloc_function (pad,
-          GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
-      gst_pad_set_chain_function (pad,
-          GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));
-    } else {
-      gst_pad_set_getrange_function (pad,
-          GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
-      gst_pad_set_checkgetrange_function (pad,
-          GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
-    }
   }
   return TRUE;
 }
@@ -374,12 +346,6 @@ gst_proxy_pad_get_target (GstPad * pad)
 }
 
 static void
-gst_proxy_pad_init (GstProxyPad * pad)
-{
-  pad->proxy_lock = g_mutex_new ();
-}
-
-static void
 gst_proxy_pad_dispose (GObject * object)
 {
   GstPad *pad = GST_PAD (object);
@@ -404,6 +370,30 @@ gst_proxy_pad_finalize (GObject * object
   G_OBJECT_CLASS (gst_proxy_pad_parent_class)->finalize (object);
 }
 
+static void
+gst_proxy_pad_init (GstProxyPad * ppad)
+{
+  GstPad *pad = (GstPad *) ppad;
+
+  ppad->proxy_lock = g_mutex_new ();
+
+  gst_pad_set_query_type_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query_type));
+  gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_event));
+  gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_proxy_pad_do_query));
+  gst_pad_set_internal_link_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_internal_link));
+  gst_pad_set_getcaps_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getcaps));
+  gst_pad_set_acceptcaps_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_acceptcaps));
+  gst_pad_set_fixatecaps_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_fixatecaps));
+  gst_pad_set_setcaps_function (pad,
+      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_setcaps));
+
+}
+
 #ifndef GST_DISABLE_LOADSAVE
 /**
  * gst_proxy_pad_save_thyself:
@@ -467,6 +457,29 @@ static gboolean gst_ghost_pad_set_intern
 
 static void gst_ghost_pad_dispose (GObject * object);
 
+/*
+   Returns the proxypad's neighbour (they're associated in pairs).
+   FIXME : This is slightly hackish. Since proxypad/ghostpad are associated
+   in pairs, this should be in both elements.  
+ */
+
+static GstPad *
+gst_proxy_pad_get_neighbour (GstPad * pad)
+{
+  GstPad *neighbour = NULL;
+
+  GST_PROXY_LOCK (pad);
+  if (GST_IS_GHOST_PAD (pad))
+    neighbour = ((GstGhostPad *) pad)->internal;
+  else
+    neighbour = (GstPad *) GST_OBJECT_PARENT (pad);
+  if (neighbour)
+    gst_object_ref (neighbour);
+  GST_PROXY_UNLOCK (pad);
+
+  return neighbour;
+}
+
 /* Work around g_logv's use of G_GNUC_PRINTF because gcc chokes on %P, which we
  * use for GST_PTR_FORMAT. */
 static void
@@ -494,11 +507,32 @@ gst_ghost_pad_get_internal (GstPad * pad
 }
 
 static void
+gst_ghost_pad_parent_set (GstObject * object, GstObject * parent)
+{
+  GstGhostPad * gpad = (GstGhostPad *) object;
+  GstPad * target = ((GstProxyPad*)gpad)->target;
+
+  if (target && !(gst_pad_is_linked(gpad->internal))) {
+    GST_DEBUG_OBJECT (gpad, "linking internal pad with target");
+    if (GST_PAD_IS_SRC (gpad->internal))
+      gst_pad_link (gpad->internal, target);
+    else
+      gst_pad_link (target, gpad->internal);
+  }
+
+  if (GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set)
+    GST_OBJECT_CLASS (gst_ghost_pad_parent_class)->parent_set (object, parent);
+
+}
+
+static void
 gst_ghost_pad_class_init (GstGhostPadClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstObjectClass *gstobject_class = (GstObjectClass *) klass;
 
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
+  gstobject_class->parent_set = GST_DEBUG_FUNCPTR (gst_ghost_pad_parent_set);
 }
 
 /* see gstghostpad design docs */
@@ -507,6 +541,8 @@ gst_ghost_pad_internal_do_activate_push 
 {
   gboolean ret;
 
+  GST_DEBUG_OBJECT (pad, "active:%d", active);
+
   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
     GstPad *parent = GST_PAD (gst_object_get_parent (GST_OBJECT (pad)));
 
@@ -538,6 +574,8 @@ gst_ghost_pad_internal_do_activate_pull 
 {
   gboolean ret;
 
+  GST_DEBUG_OBJECT (pad, "active:%d", active);
+
   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
     GstPad *peer = gst_pad_get_peer (pad);
 
@@ -569,6 +607,8 @@ gst_ghost_pad_do_activate_push (GstPad *
 {
   gboolean ret;
 
+  GST_DEBUG_OBJECT (pad, "active:%d", active);
+
   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
     GstPad *internal = gst_ghost_pad_get_internal (pad);
 
@@ -590,6 +630,8 @@ gst_ghost_pad_do_activate_pull (GstPad *
 {
   gboolean ret;
 
+  GST_DEBUG_OBJECT (pad, "active:%d", active);
+
   if (GST_PAD_DIRECTION (pad) == GST_PAD_SINK) {
     GstPad *peer = gst_pad_get_peer (pad);
 
@@ -617,25 +659,15 @@ static GstPadLinkReturn
 gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
 {
   GstPad *internal, *target;
-  GstPadLinkReturn ret;
+  GstPadLinkReturn ret = GST_FLOW_OK;
 
   target = gst_proxy_pad_get_target (pad);
 
   g_return_val_if_fail (target != NULL, GST_PAD_LINK_NOSCHED);
-
-  /* proxy the peer into the bin */
-  internal = g_object_new (GST_TYPE_PROXY_PAD,
-      "name", NULL,
-      "direction", GST_PAD_DIRECTION (peer),
-      "template", GST_PAD_PAD_TEMPLATE (peer), NULL);
+  internal = ((GstGhostPad*) pad)->internal;
 
   gst_proxy_pad_set_target (internal, peer);
-  gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), internal);
-
-  if (GST_PAD_IS_SRC (internal))
-    ret = gst_pad_link (internal, target);
-  else
-    ret = gst_pad_link (target, internal);
+  GST_PAD_PAD_TEMPLATE (internal) = GST_PAD_PAD_TEMPLATE (peer);
 
   /* if we are a source pad, we should call the peer link function
    * if the peer has one */
@@ -658,16 +690,18 @@ static void
 gst_ghost_pad_do_unlink (GstPad * pad)
 {
   GstPad *target = gst_proxy_pad_get_target (pad);
+  GstPad *internal = ((GstGhostPad*)pad)->internal;
 
   g_return_if_fail (target != NULL);
 
   GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
 
+  gst_proxy_pad_set_target (internal, NULL);
+  GST_PAD_PAD_TEMPLATE (internal) = NULL;
+
   if (target->unlinkfunc)
     target->unlinkfunc (target);
 
-  gst_ghost_pad_set_internal (GST_GHOST_PAD (pad), NULL);
-
   gst_object_unref (target);
 }
 
@@ -690,6 +724,10 @@ on_int_notify (GstPad * internal, GParam
 static gboolean
 gst_ghost_pad_set_internal (GstGhostPad * pad, GstPad * internal)
 {
+
+  GST_LOG_OBJECT (pad, "Setting internal to %s:%s",
+		  GST_DEBUG_PAD_NAME (internal));
+
   GST_PROXY_LOCK (pad);
   /* first remove old internal pad */
   if (pad->internal) {
@@ -778,15 +816,49 @@ GstPad *
 gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
 {
   GstPad *ret;
+  GstPad *internal;
 
+  GST_LOG ("name:%s, direction:%d", name, dir);
+  
   ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, NULL);
 
-  gst_pad_set_activatepush_function (ret,
-      GST_DEBUG_FUNCPTR (gst_ghost_pad_do_activate_push));
+  /* Set directional padfunctions for ghostpad */
+  if (dir == GST_PAD_SINK) {
+    gst_pad_set_bufferalloc_function (ret,
+				      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
+    gst_pad_set_chain_function (ret,
+				GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));   
+  } else {
+    gst_pad_set_getrange_function (ret,
+				   GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
+    gst_pad_set_checkgetrange_function (ret,
+					GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
+  }
+
   gst_pad_set_link_function (ret, GST_DEBUG_FUNCPTR (gst_ghost_pad_do_link));
   gst_pad_set_unlink_function (ret,
       GST_DEBUG_FUNCPTR (gst_ghost_pad_do_unlink));
 
+  internal =
+    g_object_new (GST_TYPE_PROXY_PAD, "name", NULL,
+		  "direction", (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC,
+		  NULL);
+
+  /* Set directional padfunctions for internal pad */
+  if (dir == GST_PAD_SRC) {
+    gst_pad_set_bufferalloc_function (internal,
+				      GST_DEBUG_FUNCPTR (gst_proxy_pad_do_bufferalloc));
+    gst_pad_set_chain_function (internal,
+				GST_DEBUG_FUNCPTR (gst_proxy_pad_do_chain));   
+  } else {
+    gst_pad_set_getrange_function (internal,
+				   GST_DEBUG_FUNCPTR (gst_proxy_pad_do_getrange));
+    gst_pad_set_checkgetrange_function (internal,
+					GST_DEBUG_FUNCPTR (gst_proxy_pad_do_checkgetrange));
+  }
+
+  gst_ghost_pad_set_internal ((GstGhostPad*) ret, internal);
+
   return ret;
 }
 
@@ -807,12 +879,12 @@ gst_ghost_pad_new (const gchar * name, G
 {
   GstPad *ret;
 
+  GST_LOG ("name:%s, target:%s:%s", name, GST_DEBUG_PAD_NAME (target));
+
   g_return_val_if_fail (GST_IS_PAD (target), NULL);
   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
 
   if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target)))) {
-    g_object_set (G_OBJECT (ret),
-        "template", GST_PAD_PAD_TEMPLATE (target), NULL);
     gst_ghost_pad_set_target (GST_GHOST_PAD (ret), target);
   }
   return ret;
@@ -857,8 +929,8 @@ gst_ghost_pad_set_target (GstGhostPad * 
   GST_PROXY_LOCK (gpad);
   internal = gpad->internal;
 
-  GST_DEBUG ("set target %s:%s on %s:%s",
-      GST_DEBUG_PAD_NAME (newtarget), GST_DEBUG_PAD_NAME (gpad));
+  GST_DEBUG_OBJECT (gpad, "set target %s:%s",
+		    GST_DEBUG_PAD_NAME (newtarget));
 
   /* clear old target */
   if ((oldtarget = GST_PROXY_PAD_TARGET (gpad))) {
@@ -874,12 +946,17 @@ gst_ghost_pad_set_target (GstGhostPad * 
   result = gst_proxy_pad_set_target_unlocked (GST_PAD_CAST (gpad), newtarget);
 
   if (result && newtarget) {
-    /* and link to internal pad if we have one */
-    if (internal) {
+    g_object_set (G_OBJECT (gpad), "template",
+		  GST_PAD_PAD_TEMPLATE (newtarget), NULL);
+    /* and link to internal pad if we are not floating */
+    if (!GST_OBJECT_IS_FLOATING(gpad)) {
       if (GST_PAD_IS_SRC (internal))
         result = gst_pad_link (internal, newtarget);
       else
         result = gst_pad_link (newtarget, internal);
+    } else {
+      GST_DEBUG_OBJECT (gpad, "GhostPad is still floating, will connect internal pad later");
+      /* we need to connect the internal pad once we have a parent */
     }
   }
   GST_PROXY_UNLOCK (gpad);
Index: gst/gstpad.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstpad.c,v
retrieving revision 1.517
diff -u -p -r1.517 gstpad.c
--- gst/gstpad.c	6 Jul 2006 15:21:46 -0000	1.517
+++ gst/gstpad.c	8 Jul 2006 17:13:56 -0000
@@ -63,7 +63,6 @@
 #include "gst_private.h"
 
 #include "gstpad.h"
-#include "gstghostpad.h"
 #include "gstpadtemplate.h"
 #include "gstenumtypes.h"
 #include "gstmarshal.h"
@@ -883,18 +882,10 @@ gboolean
 gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
     GstPadBlockCallback callback, gpointer user_data)
 {
-  gboolean was_blocked, was_ghost = FALSE;
+  gboolean was_blocked = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return FALSE;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
 
   was_blocked = GST_PAD_IS_BLOCKED (pad);
@@ -934,10 +925,6 @@ gst_pad_set_blocked_async (GstPad * pad,
   }
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
-
   return TRUE;
 
 had_right_state:
@@ -947,9 +934,6 @@ had_right_state:
         was_blocked);
     GST_OBJECT_UNLOCK (pad);
 
-    if (was_ghost) {
-      gst_object_unref (pad);
-    }
     return FALSE;
   }
 }
Index: gst/gstutils.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstutils.c,v
retrieving revision 1.142
diff -u -p -r1.142 gstutils.c
--- gst/gstutils.c	19 May 2006 10:29:07 -0000	1.142
+++ gst/gstutils.c	8 Jul 2006 17:13:56 -0000
@@ -2783,19 +2783,10 @@ gulong
 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
 {
   gulong sigid;
-  gboolean was_ghost = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return 0;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   sigid = g_signal_connect (pad, "have-data", handler, data);
   GST_PAD_DO_EVENT_SIGNALS (pad)++;
@@ -2805,10 +2796,6 @@ gst_pad_add_data_probe (GstPad * pad, GC
       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
-
   return sigid;
 }
 
@@ -2827,19 +2814,10 @@ gulong
 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
 {
   gulong sigid;
-  gboolean was_ghost = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return 0;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   sigid = g_signal_connect (pad, "have-data::event", handler, data);
   GST_PAD_DO_EVENT_SIGNALS (pad)++;
@@ -2847,10 +2825,6 @@ gst_pad_add_event_probe (GstPad * pad, G
       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
-
   return sigid;
 }
 
@@ -2869,19 +2843,10 @@ gulong
 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
 {
   gulong sigid;
-  gboolean was_ghost = FALSE;
 
   g_return_val_if_fail (GST_IS_PAD (pad), 0);
   g_return_val_if_fail (handler != NULL, 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return 0;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
@@ -2889,10 +2854,6 @@ gst_pad_add_buffer_probe (GstPad * pad, 
       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
-
   return sigid;
 }
 
@@ -2906,19 +2867,9 @@ gst_pad_add_buffer_probe (GstPad * pad, 
 void
 gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
 {
-  gboolean was_ghost = FALSE;
-
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (handler_id > 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
@@ -2929,9 +2880,6 @@ gst_pad_remove_data_probe (GstPad * pad,
       GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
 }
 
 /**
@@ -2944,29 +2892,15 @@ gst_pad_remove_data_probe (GstPad * pad,
 void
 gst_pad_remove_event_probe (GstPad * pad, guint handler_id)
 {
-  gboolean was_ghost = FALSE;
-
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (handler_id > 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_EVENT_SIGNALS (pad)--;
   GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
-
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
 }
 
 /**
@@ -2979,19 +2913,9 @@ gst_pad_remove_event_probe (GstPad * pad
 void
 gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id)
 {
-  gboolean was_ghost = FALSE;
-
   g_return_if_fail (GST_IS_PAD (pad));
   g_return_if_fail (handler_id > 0);
 
-  if (GST_IS_GHOST_PAD (pad)) {
-    pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
-    if (!pad) {
-      return;
-    }
-    was_ghost = TRUE;
-  }
-
   GST_OBJECT_LOCK (pad);
   g_signal_handler_disconnect (pad, handler_id);
   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
@@ -2999,9 +2923,6 @@ gst_pad_remove_buffer_probe (GstPad * pa
       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
   GST_OBJECT_UNLOCK (pad);
 
-  if (was_ghost) {
-    gst_object_unref (pad);
-  }
 }
 
 /**
