Remove old query functions. Ported old code.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 9 May 2005 10:53:13 +0000 (10:53 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 9 May 2005 10:53:13 +0000 (10:53 +0000)
Original commit message from CVS:
Remove old query functions. Ported old code.
Added position/convert helper functions to gstutils.
Reordered gstpad.c code, grouping relevant things.
Remove gst_message_new(), always need to speficy a specific
message.

24 files changed:
ChangeLog
docs/design/draft-push-pull.txt
gst/base/gstbasesrc.c
gst/elements/gstfilesink.c
gst/elements/gsttypefindelement.c
gst/gstelement.c
gst/gstelement.h
gst/gstmessage.c
gst/gstmessage.h
gst/gstpad.c
gst/gstpad.h
gst/gstquery.c
gst/gstquery.h
gst/gstqueryutils.c
gst/gstqueryutils.h
gst/gstqueue.c
gst/gstutils.c
gst/gstutils.h
libs/gst/base/gstbasesrc.c
plugins/elements/gstfilesink.c
plugins/elements/gstqueue.c
plugins/elements/gsttypefindelement.c
tools/gst-inspect.c
tools/gst-xmlinspect.c

index f661d61..aa23ce1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,60 @@
+2005-05-09  Wim Taymans  <wim@fluendo.com>
+
+       * docs/design/draft-push-pull.txt:
+       * gst/base/gstbasesrc.c: (gst_basesrc_init), (gst_basesrc_query):
+       * gst/elements/gstfilesink.c: (gst_filesink_init),
+       (gst_filesink_query):
+       * gst/elements/gsttypefindelement.c: (gst_type_find_element_init),
+       (gst_type_find_handle_src_query), (find_element_get_length):
+       * gst/gstelement.c: (gst_element_seek), (gst_element_query):
+       * gst/gstelement.h:
+       * gst/gstmessage.c:
+       * gst/gstmessage.h:
+       * gst/gstpad.c: (gst_real_pad_init), (gst_pad_get_query_types),
+       (gst_real_pad_get_caps_unlocked),
+       (gst_pad_get_internal_links_default), (gst_pad_get_internal_links),
+       (gst_pad_event_default_dispatch), (gst_pad_event_default),
+       (gst_pad_dispatcher), (gst_pad_query), (gst_pad_query_default),
+       (gst_real_pad_dispose), (gst_real_pad_finalize),
+       (gst_pad_load_and_link), (gst_pad_save_thyself),
+       (gst_ghost_pad_save_thyself), (handle_pad_block), (gst_pad_push),
+       (gst_pad_check_pull_range), (gst_pad_pull_range),
+       (gst_pad_template_get_type), (gst_pad_template_class_init),
+       (gst_pad_template_init), (gst_pad_template_dispose),
+       (name_is_valid), (gst_static_pad_template_get),
+       (gst_pad_template_new), (gst_static_pad_template_get_caps),
+       (gst_pad_template_get_caps), (gst_pad_set_element_private),
+       (gst_pad_get_element_private), (gst_pad_start_task),
+       (gst_pad_pause_task), (gst_pad_stop_task),
+       (gst_ghost_pad_get_type), (gst_ghost_pad_class_init),
+       (gst_ghost_pad_init), (gst_ghost_pad_dispose),
+       (gst_ghost_pad_set_property), (gst_ghost_pad_get_property),
+       (gst_ghost_pad_new):
+       * gst/gstpad.h:
+       * gst/gstquery.c: (_gst_query_initialize), (gst_query_new),
+       (gst_query_new_position), (gst_query_set_position),
+       (gst_query_parse_position), (gst_query_new_convert),
+       (gst_query_set_convert), (gst_query_parse_convert):
+       * gst/gstquery.h:
+       * gst/gstqueryutils.c:
+       * gst/gstqueryutils.h:
+       * gst/gstqueue.c: (gst_queue_init), (gst_queue_getcaps),
+       (gst_queue_bufferalloc), (gst_queue_handle_sink_event),
+       (gst_queue_handle_src_query):
+       * gst/gstutils.c: (gst_element_get_compatible_pad_template),
+       (gst_element_query_position), (gst_element_query_convert),
+       (intersect_caps_func), (gst_pad_query_position),
+       (gst_pad_query_convert):
+       * gst/gstutils.h:
+       * tools/gst-inspect.c: (print_pad_info):
+       * tools/gst-xmlinspect.c: (print_element_info):
+       Remove old query functions. Ported old code.
+       Added position/convert helper functions to gstutils.
+       Reordered gstpad.c code, grouping relevant things.
+       Remove gst_message_new(), always need to speficy a specific
+       message.
+
+
 2005-05-09  Andy Wingo  <wingo@pobox.com>
 
        * gst/gstiterator.h: Add some includes.
index fbcbee7..e56ce5f 100644 (file)
@@ -80,9 +80,31 @@ Proposition:
     decision.
 
 
-
-
+Things to query:
+
+  - pad can do real random access (downstream peer can ask for offset != -1)
+     - min offset
+     - suggest sequential access
+     - max offset
+     - align: all offsets should be aligned with this value.
+  - pad can give ranges from A to B length (peer can ask for A <= length <= B)
+     - min length
+     - suggested length
+     - max length
+
+Use cases:
+
+  - An audio source can provide random access to the samples queued in its
+    DMA buffer, it however suggests sequential access method.
+    An audio source can provide a random number of samples but prefers 
+    reading from the hardware using a fixed segment size.
+
+  - A caching network source would suggest sequential access but is seekable
+    in the cached region. Applications can query for the already downloaded
+    portion and update the GUI, a seek can be done in that area.
     
+  - a live video source can only provide buffers sequentialy. It exposes
+    offsets as -1. lengths are also -1. 
 
   
 
index 5031568..2d7b966 100644 (file)
@@ -89,9 +89,11 @@ static void gst_basesrc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event);
 
-static gboolean gst_basesrc_query2 (GstPad * pad, GstQuery * query);
+static gboolean gst_basesrc_query (GstPad * pad, GstQuery * query);
 
+#if 0
 static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad);
+#endif
 
 static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc);
 static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size);
@@ -158,9 +160,7 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class)
 
   gst_pad_set_activate_function (pad, gst_basesrc_activate);
   gst_pad_set_event_function (pad, gst_basesrc_event_handler);
-  gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask);
-
-  gst_pad_set_query2_function (pad, gst_basesrc_query2);
+  gst_pad_set_query_function (pad, gst_basesrc_query);
 
   gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range);
 
@@ -193,7 +193,7 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this)
 }
 
 static gboolean
-gst_basesrc_query2 (GstPad * pad, GstQuery * query)
+gst_basesrc_query (GstPad * pad, GstQuery * query)
 {
   gboolean b;
   guint64 ui64;
@@ -207,7 +207,7 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query)
     {
       GstFormat format;
 
-      gst_query_parse_position_query (query, &format);
+      gst_query_parse_position (query, &format, NULL, NULL);
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
@@ -243,10 +243,11 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query)
     case GST_QUERY_RATE:
     case GST_QUERY_CONVERT:
     default:
-      return gst_pad_query2_default (pad, query);
+      return gst_pad_query_default (pad, query);
   }
 }
 
+#if 0
 static const GstEventMask *
 gst_basesrc_get_event_mask (GstPad * pad)
 {
@@ -260,6 +261,7 @@ gst_basesrc_get_event_mask (GstPad * pad)
   };
   return masks;
 }
+#endif
 
 static gboolean
 gst_basesrc_do_seek (GstBaseSrc * src, GstEvent * event)
index c0da0e3..cc44e97 100644 (file)
@@ -80,7 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event);
 static GstFlowReturn gst_filesink_render (GstBaseSink * sink,
     GstBuffer * buffer);
 
-static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query);
+static gboolean gst_filesink_query (GstPad * pad, GstQuery * query);
 
 static void gst_filesink_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
@@ -144,7 +144,7 @@ gst_filesink_init (GstFileSink * filesink)
 
   pad = GST_BASESINK_PAD (filesink);
 
-  gst_pad_set_query2_function (pad, gst_filesink_query2);
+  gst_pad_set_query_function (pad, gst_filesink_query);
 
   filesink->filename = NULL;
   filesink->file = NULL;
@@ -255,7 +255,7 @@ gst_filesink_close_file (GstFileSink * sink)
 }
 
 static gboolean
-gst_filesink_query2 (GstPad * pad, GstQuery * query)
+gst_filesink_query (GstPad * pad, GstQuery * query)
 {
   GstFileSink *self;
   GstFormat format;
@@ -264,7 +264,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
-      gst_query_parse_position_query (query, &format);
+      gst_query_parse_position (query, &format, NULL, NULL);
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
@@ -280,7 +280,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query)
       return TRUE;
 
     default:
-      return gst_pad_query2_default (pad, query);
+      return gst_pad_query_default (pad, query);
   }
 }
 
index 994e04f..5aeece8 100644 (file)
@@ -115,11 +115,13 @@ static void gst_type_find_element_set_property (GObject * object,
 static void gst_type_find_element_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
+#if 0
 static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
+#endif
+
 static gboolean gst_type_find_element_src_event (GstPad * pad,
     GstEvent * event);
-static gboolean gst_type_find_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value);
+static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
 static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind);
 
 static gboolean gst_type_find_element_handle_event (GstPad * pad,
@@ -219,8 +221,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
       gst_type_find_element_checkgetrange);
   gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange);
   gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
-  gst_pad_set_event_mask_function (typefind->src,
-      gst_type_find_element_src_event_mask);
   gst_pad_set_query_function (typefind->src,
       GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
   gst_pad_use_fixed_caps (typefind->src);
@@ -295,32 +295,48 @@ gst_type_find_element_get_property (GObject * object, guint prop_id,
 }
 
 static gboolean
-gst_type_find_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value)
+gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
 {
-  GstTypeFindElement *typefind =
-      GST_TYPE_FIND_ELEMENT (gst_pad_get_parent (pad));
+  GstTypeFindElement *typefind;
   gboolean res;
 
-  res = gst_pad_query (GST_PAD_PEER (typefind->sink), type, fmt, value);
+  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
+
+  res = gst_pad_query (GST_PAD_PEER (typefind->sink), query);
   if (!res)
     return FALSE;
 
-  if (type == GST_QUERY_POSITION && typefind->store != NULL) {
-    /* FIXME: this code assumes that there's no discont in the queue */
-    switch (*fmt) {
-      case GST_FORMAT_BYTES:
-        *value -= gst_buffer_store_get_size (typefind->store, 0);
-        break;
-      default:
-        /* FIXME */
-        break;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+    {
+      gint64 peer_pos, peer_total;
+      GstFormat format;
+
+      if (typefind->store == NULL)
+        return TRUE;
+
+      gst_query_parse_position (query, &format, &peer_pos, &peer_total);
+
+      /* FIXME: this code assumes that there's no discont in the queue */
+      switch (format) {
+        case GST_FORMAT_BYTES:
+          peer_pos -= gst_buffer_store_get_size (typefind->store, 0);
+          break;
+        default:
+          /* FIXME */
+          break;
+      }
+      gst_query_set_position (query, format, peer_pos, peer_total);
+      break;
     }
+    default:
+      break;
   }
 
   return TRUE;
 }
 
+#if 0
 static const GstEventMask *
 gst_type_find_element_src_event_mask (GstPad * pad)
 {
@@ -334,6 +350,7 @@ gst_type_find_element_src_event_mask (GstPad * pad)
 
   return mask;
 }
+#endif
 
 static gboolean
 gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
@@ -462,24 +479,29 @@ find_element_get_length (gpointer data)
     return 0;
   }
   if (entry->self->stream_length == 0) {
-    typefind->stream_length_available =
-        gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL,
-        &format, (gint64 *) & entry->self->stream_length);
-    if (format != GST_FORMAT_BYTES)
+    if (!gst_pad_query_position (GST_PAD_PEER (entry->self->sink), &format,
+            NULL, (gint64 *) & entry->self->stream_length))
+      goto no_length;
+
+    if (format != GST_FORMAT_BYTES) {
       typefind->stream_length_available = FALSE;
-    if (!typefind->stream_length_available) {
-      GST_DEBUG_OBJECT (entry->self,
-          "'%s' called get_length () but it's not available",
-          GST_PLUGIN_FEATURE_NAME (entry->factory));
-      return 0;
+      entry->self->stream_length = 0;
     } else {
       GST_DEBUG_OBJECT (entry->self,
           "'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes",
           GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
     }
   }
-
   return entry->self->stream_length;
+
+no_length:
+  {
+    typefind->stream_length_available = FALSE;
+    GST_DEBUG_OBJECT (entry->self,
+        "'%s' called get_length () but it's not available",
+        GST_PLUGIN_FEATURE_NAME (entry->factory));
+    return 0;
+  }
 }
 
 static gboolean
index 28ffe83..0523f4f 100644 (file)
@@ -1050,48 +1050,6 @@ wrong_direction:
 }
 
 /**
- * gst_element_get_event_masks:
- * @element: a #GstElement to query
- *
- * Get an array of event masks from the element.
- * If the element doesn't implement an event masks function,
- * the query will be forwarded to a random linked sink pad.
- *
- * Returns: An array of #GstEventMask elements. The array 
- * cannot be modified or freed.
- *
- * MT safe.
- */
-const GstEventMask *
-gst_element_get_event_masks (GstElement * element)
-{
-  GstElementClass *oclass;
-  const GstEventMask *result = NULL;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
-  oclass = GST_ELEMENT_GET_CLASS (element);
-
-  if (oclass->get_event_masks) {
-    result = oclass->get_event_masks (element);
-  } else {
-    GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
-
-    if (pad) {
-      GstPad *peer = gst_pad_get_peer (pad);
-
-      if (peer) {
-        result = gst_pad_get_event_masks (peer);
-        gst_object_unref (GST_OBJECT (peer));
-      }
-      gst_object_unref (GST_OBJECT (pad));
-    }
-  }
-
-  return result;
-}
-
-/**
  * gst_element_send_event:
  * @element: a #GstElement to send the event to.
  * @event: the #GstEvent to send to the element.
@@ -1156,9 +1114,12 @@ gst_element_send_event (GstElement * element, GstEvent * event)
 gboolean
 gst_element_seek (GstElement * element, GstSeekType seek_type, guint64 offset)
 {
-  GstEvent *event = gst_event_new_seek (seek_type, offset);
+  GstEvent *event;
   gboolean result;
 
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+
+  event = gst_event_new_seek (seek_type, offset);
   result = gst_element_send_event (element, event);
 
   return result;
@@ -1224,25 +1185,23 @@ gst_element_get_query_types (GstElement * element)
  * MT safe.
  */
 gboolean
-gst_element_query (GstElement * element, GstQueryType type,
-    GstFormat * format, gint64 * value)
+gst_element_query (GstElement * element, GstQuery * query)
 {
   GstElementClass *oclass;
   gboolean result = FALSE;
 
   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
+  g_return_val_if_fail (query != NULL, FALSE);
 
   oclass = GST_ELEMENT_GET_CLASS (element);
 
   if (oclass->query) {
-    result = oclass->query (element, type, format, value);
+    result = oclass->query (element, query);
   } else {
     GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SRC);
 
     if (pad) {
-      result = gst_pad_query (pad, type, format, value);
+      result = gst_pad_query (pad, query);
 
       gst_object_unref (GST_OBJECT (pad));
     } else {
@@ -1251,7 +1210,7 @@ gst_element_query (GstElement * element, GstQueryType type,
         GstPad *peer = gst_pad_get_peer (pad);
 
         if (peer) {
-          result = gst_pad_query (peer, type, format, value);
+          result = gst_pad_query (peer, query);
 
           gst_object_unref (GST_OBJECT (peer));
         }
@@ -1263,104 +1222,6 @@ gst_element_query (GstElement * element, GstQueryType type,
 }
 
 /**
- * gst_element_get_formats:
- * @element: a #GstElement to query
- *
- * Get an array of formats from the element.
- * If the element doesn't implement a formats function,
- * the query will be forwarded to a random sink pad.
- *
- * Returns: An array of #GstFormat elements.
- *
- * MT safe.
- */
-const GstFormat *
-gst_element_get_formats (GstElement * element)
-{
-  GstElementClass *oclass;
-  const GstFormat *result = NULL;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
-  oclass = GST_ELEMENT_GET_CLASS (element);
-
-  if (oclass->get_formats) {
-    result = oclass->get_formats (element);
-  } else {
-    GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
-
-    if (pad) {
-      GstPad *peer = gst_pad_get_peer (pad);
-
-      if (peer) {
-        result = gst_pad_get_formats (peer);
-
-        gst_object_unref (GST_OBJECT (peer));
-      }
-      gst_object_unref (GST_OBJECT (pad));
-    }
-  }
-
-  return result;
-}
-
-/**
- * gst_element_convert:
- * @element: a #GstElement to invoke the converter on.
- * @src_format: the source #GstFormat.
- * @src_value: the source value.
- * @dest_format: a pointer to the destination #GstFormat.
- * @dest_value: a pointer to the destination value.
- *
- * Invokes a conversion on the element.
- * If the element doesn't implement a convert function,
- * the query will be forwarded to a random sink pad.
- *
- * Returns: TRUE if the conversion could be performed.
- *
- * MT safe.
- */
-gboolean
-gst_element_convert (GstElement * element,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  GstElementClass *oclass;
-  gboolean result = FALSE;
-
-  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
-  g_return_val_if_fail (dest_value != NULL, FALSE);
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  oclass = GST_ELEMENT_GET_CLASS (element);
-
-  if (oclass->convert) {
-    result = oclass->convert (element,
-        src_format, src_value, dest_format, dest_value);
-  } else {
-    GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
-
-    if (pad) {
-      GstPad *peer = gst_pad_get_peer (pad);
-
-      if (peer) {
-        result = gst_pad_convert (peer,
-            src_format, src_value, dest_format, dest_value);
-
-        gst_object_unref (GST_OBJECT (peer));
-      }
-      gst_object_unref (GST_OBJECT (pad));
-    }
-  }
-  return result;
-}
-
-/**
  * gst_element_post_message:
  * @element: a #GstElement posting the message
  * @message: a #GstMessage to post
index 6e3c137..be4e9f0 100644 (file)
@@ -249,13 +249,13 @@ struct _GstElementClass
   void                 (*release_pad)          (GstElement *element, GstPad *pad);
 
   /* state changes */
-  GstElementStateReturn (*get_state)   (GstElement * element, GstElementState * state,
-                                        GstElementState * pending, GTimeVal * timeout);
+  GstElementStateReturn (*get_state)           (GstElement * element, GstElementState * state,
+                                                GstElementState * pending, GTimeVal * timeout);
   GstElementStateReturn (*change_state)                (GstElement *element);
 
   /* manager */
-  void (*set_manager)      (GstElement * element, GstPipeline * pipeline);
-  void (*set_bus)          (GstElement * element, GstBus * bus);
+  void                         (*set_manager)          (GstElement * element, GstPipeline * pipeline);
+  void                         (*set_bus)              (GstElement * element, GstBus * bus);
   void                 (*set_scheduler)        (GstElement *element, GstScheduler *scheduler);
 
   /* set/get clocks */
@@ -266,16 +266,11 @@ struct _GstElementClass
   GstIndex*            (*get_index)            (GstElement *element);
   void                 (*set_index)            (GstElement *element, GstIndex *index);
 
-  /* query/convert/events functions */
-  const GstEventMask*   (*get_event_masks)             (GstElement *element);
+  /* query functions */
   gboolean             (*send_event)           (GstElement *element, GstEvent *event);
-  const GstFormat*      (*get_formats)         (GstElement *element);
-  gboolean              (*convert)             (GstElement *element,
-                                                GstFormat  src_format,  gint64  src_value,
-                                                GstFormat *dest_format, gint64 *dest_value);
+
   const GstQueryType*  (*get_query_types)      (GstElement *element);
-  gboolean             (*query)                (GstElement *element, GstQueryType type,
-                                                GstFormat *format, gint64 *value);
+  gboolean             (*query)                (GstElement *element, GstQuery *query);
 
   /*< private >*/
   gpointer _gst_reserved[GST_PADDING];
@@ -309,10 +304,10 @@ void                      gst_element_set_index           (GstElement *element, GstIndex *index);
 GstIndex*              gst_element_get_index           (GstElement *element);
 
 /* manager and tasks */
-void gst_element_set_manager (GstElement * element, GstPipeline * pipeline);
-GstPipeline *gst_element_get_manager (GstElement * element);
-void gst_element_set_bus (GstElement * element, GstBus * bus);
-GstBus *gst_element_get_bus (GstElement * element);
+void                   gst_element_set_manager         (GstElement * element, GstPipeline * pipeline);
+GstPipeline *          gst_element_get_manager         (GstElement * element);
+void                   gst_element_set_bus             (GstElement * element, GstBus * bus);
+GstBus *               gst_element_get_bus             (GstElement * element);
 void                   gst_element_set_scheduler       (GstElement *element, GstScheduler *sched);
 GstScheduler*          gst_element_get_scheduler       (GstElement *element);
 
@@ -330,44 +325,37 @@ void                      gst_element_release_request_pad (GstElement *element, GstPad *pad);
 GstIterator *          gst_element_iterate_pads        (GstElement * element);
 
 /* event/query/format stuff */
-G_CONST_RETURN GstEventMask*
-                       gst_element_get_event_masks     (GstElement *element);
 gboolean               gst_element_send_event          (GstElement *element, GstEvent *event);
 gboolean               gst_element_seek                (GstElement *element, GstSeekType seek_type,
                                                         guint64 offset);
 G_CONST_RETURN GstQueryType*
                        gst_element_get_query_types     (GstElement *element);
-gboolean               gst_element_query               (GstElement *element, GstQueryType type,
-                                                        GstFormat *format, gint64 *value);
-G_CONST_RETURN GstFormat*
-                       gst_element_get_formats         (GstElement *element);
-gboolean               gst_element_convert             (GstElement *element, 
-                                                        GstFormat  src_format,  gint64  src_value,
-                                                        GstFormat *dest_format, gint64 *dest_value);
+gboolean               gst_element_query               (GstElement *element, GstQuery *query);
 
 /* messages */
-gboolean gst_element_post_message (GstElement * element, GstMessage * message);
+gboolean               gst_element_post_message        (GstElement * element, GstMessage * message);
 
 /* error handling */
 gchar *                        _gst_element_error_printf       (const gchar *format, ...);
-void gst_element_message_full (GstElement * element, GstMessageType type,
-    GQuark domain, gint code, gchar * text, gchar * debug, const gchar * file,
-    const gchar * function, gint line);
+void                   gst_element_message_full        (GstElement * element, GstMessageType type,
+                                                        GQuark domain, gint code, gchar * text, 
+                                                        gchar * debug, const gchar * file,
+                                                        const gchar * function, gint line);
 
 /* state management */
 gboolean               gst_element_is_locked_state     (GstElement *element);
 gboolean               gst_element_set_locked_state    (GstElement *element, gboolean locked_state);
 gboolean               gst_element_sync_state_with_parent (GstElement *element);
 
-GstElementStateReturn  gst_element_get_state                   (GstElement * element, 
-                                                                GstElementState * state,
-                                                                GstElementState * pending, 
-                                                                GTimeVal * timeout);
+GstElementStateReturn  gst_element_get_state           (GstElement * element, 
+                                                        GstElementState * state,
+                                                        GstElementState * pending, 
+                                                        GTimeVal * timeout);
 GstElementStateReturn  gst_element_set_state           (GstElement *element, GstElementState state);
 
-void                   gst_element_abort_state                 (GstElement * element);
-void                   gst_element_commit_state                (GstElement * element);
-void                   gst_element_lost_state                  (GstElement * element);
+void                   gst_element_abort_state         (GstElement * element);
+void                   gst_element_commit_state        (GstElement * element);
+void                   gst_element_lost_state          (GstElement * element);
 
 /* factory management */
 GstElementFactory*     gst_element_get_factory         (GstElement *element);
index bc459eb..ab887a8 100644 (file)
@@ -128,7 +128,7 @@ gst_message_get_type (void)
  *
  * MT safe.
  */
-GstMessage *
+static GstMessage *
 gst_message_new (GstMessageType type, GstObject * src)
 {
   GstMessage *message;
index 286682a..91a5743 100644 (file)
@@ -111,7 +111,6 @@ struct _GstMessage
 void           _gst_message_initialize         (void);
 
 GType          gst_message_get_type            (void);
-GstMessage *   gst_message_new                 (GstMessageType type, GstObject * src);
 
 /* refcounting */
 #define         gst_message_ref(msg)           GST_MESSAGE (gst_data_ref (GST_DATA (msg)))
index cc63fca..8981c38 100644 (file)
@@ -247,16 +247,10 @@ gst_real_pad_init (GstRealPad * pad)
   pad->getcapsfunc = NULL;
 
   pad->eventfunc = gst_pad_event_default;
-  pad->convertfunc = gst_pad_convert_default;
+  pad->querytypefunc = gst_pad_get_query_types_default;
   pad->queryfunc = gst_pad_query_default;
   pad->intlinkfunc = gst_pad_get_internal_links_default;
 
-  pad->query2func = gst_pad_query2_default;
-
-  pad->eventmaskfunc = gst_pad_get_event_masks_default;
-  pad->formatsfunc = gst_pad_get_formats_default;
-  pad->querytypefunc = gst_pad_get_query_types_default;
-
   GST_FLAG_UNSET (pad, GST_PAD_ACTIVE);
 
   pad->preroll_lock = g_mutex_new ();
@@ -879,99 +873,6 @@ gst_pad_set_event_function (GstPad * pad, GstPadEventFunction event)
 }
 
 /**
- * gst_pad_set_event_mask_function:
- * @pad: a real #GstPad of either direction.
- * @mask_func: the #GstPadEventMaskFunction to set.
- *
- * Sets the given event mask function for the pad.
- */
-void
-gst_pad_set_event_mask_function (GstPad * pad,
-    GstPadEventMaskFunction mask_func)
-{
-  g_return_if_fail (GST_IS_REAL_PAD (pad));
-
-  GST_RPAD_EVENTMASKFUNC (pad) = mask_func;
-
-  GST_CAT_DEBUG (GST_CAT_PADS, "eventmaskfunc for %s:%s  set to %s",
-      GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (mask_func));
-}
-
-/**
- * gst_pad_get_event_masks:
- * @pad: a #GstPad.
- *
- * Gets the array of eventmasks from the given pad.
- *
- * Returns: a zero-terminated array of #GstEventMask, or NULL if the pad does
- * not have an event mask function.
- */
-const GstEventMask *
-gst_pad_get_event_masks (GstPad * pad)
-{
-  GstRealPad *rpad;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  rpad = GST_PAD_REALIZE (pad);
-
-  g_return_val_if_fail (rpad, NULL);
-
-  if (GST_RPAD_EVENTMASKFUNC (rpad))
-    return GST_RPAD_EVENTMASKFUNC (rpad) (GST_PAD (pad));
-
-  return NULL;
-}
-
-static gboolean
-gst_pad_get_event_masks_dispatcher (GstPad * pad, const GstEventMask ** data)
-{
-  *data = gst_pad_get_event_masks (pad);
-
-  return TRUE;
-}
-
-/**
- * gst_pad_get_event_masks_default:
- * @pad: a #GstPad.
- *
- * Invokes the default event masks dispatcher on the pad.
- *
- * Returns: a zero-terminated array of #GstEventMask, or NULL if none of the
- * internally-linked pads have an event mask function.
- */
-const GstEventMask *
-gst_pad_get_event_masks_default (GstPad * pad)
-{
-  GstEventMask *result = NULL;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
-      gst_pad_get_event_masks_dispatcher, &result);
-
-  return result;
-}
-
-/**
- * gst_pad_set_convert_function:
- * @pad: a real #GstPad of either direction.
- * @convert: the #GstPadConvertFunction to set.
- *
- * Sets the given convert function for the pad.
- */
-void
-gst_pad_set_convert_function (GstPad * pad, GstPadConvertFunction convert)
-{
-  g_return_if_fail (GST_IS_REAL_PAD (pad));
-
-  GST_RPAD_CONVERTFUNC (pad) = convert;
-
-  GST_CAT_DEBUG (GST_CAT_PADS, "convertfunc for %s:%s  set to %s",
-      GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (convert));
-}
-
-/**
  * gst_pad_set_query_function:
  * @pad: a real #GstPad of either direction.
  * @query: the #GstPadQueryFunction to set.
@@ -990,24 +891,6 @@ gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query)
 }
 
 /**
- * gst_pad_set_query2_function:
- * @pad: a real #GstPad of either direction.
- * @query: the #GstPadQueryFunction to set.
- *
- * Set the given query function for the pad.
- */
-void
-gst_pad_set_query2_function (GstPad * pad, GstPadQuery2Function query)
-{
-  g_return_if_fail (GST_IS_REAL_PAD (pad));
-
-  GST_RPAD_QUERY2FUNC (pad) = query;
-
-  GST_CAT_DEBUG (GST_CAT_PADS, "query2func for %s:%s  set to %s",
-      GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (query));
-}
-
-/**
  * gst_pad_set_query_type_function:
  * @pad: a real #GstPad of either direction.
  * @type_func: the #GstPadQueryTypeFunction to set.
@@ -1039,6 +922,7 @@ const GstQueryType *
 gst_pad_get_query_types (GstPad * pad)
 {
   GstRealPad *rpad;
+  GstPadQueryTypeFunction func;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
@@ -1046,10 +930,15 @@ gst_pad_get_query_types (GstPad * pad)
 
   g_return_val_if_fail (rpad, NULL);
 
-  if (GST_RPAD_QUERYTYPEFUNC (rpad))
-    return GST_RPAD_QUERYTYPEFUNC (rpad) (GST_PAD (pad));
+  if (G_UNLIKELY ((func = GST_RPAD_QUERYTYPEFUNC (rpad)) == NULL))
+    goto no_func;
+
+  return func (GST_PAD (rpad));
 
-  return NULL;
+no_func:
+  {
+    return NULL;
+  }
 }
 
 static gboolean
@@ -1101,23 +990,6 @@ gst_pad_set_internal_link_function (GstPad * pad, GstPadIntLinkFunction intlink)
 }
 
 /**
- * gst_pad_set_formats_function:
- * @pad: a real #GstPad of either direction.
- * @formats: the #GstPadFormatsFunction to set.
- *
- * Sets the given formats function for the pad.
- */
-void
-gst_pad_set_formats_function (GstPad * pad, GstPadFormatsFunction formats)
-{
-  g_return_if_fail (GST_IS_REAL_PAD (pad));
-
-  GST_RPAD_FORMATSFUNC (pad) = formats;
-  GST_CAT_DEBUG (GST_CAT_PADS, "formats function for %s:%s  set to %s",
-      GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (formats));
-}
-
-/**
  * gst_pad_set_link_function:
  * @pad: a real #GstPad.
  * @link: the #GstPadLinkFunction to set.
@@ -1622,6 +1494,8 @@ gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ)
  *
  * Returns: the #GstPadTemplate from which this pad was instantiated, or %NULL
  * if this pad has no template.
+ *
+ * FIXME: currently returns an unrefcounted padtemplate.
  */
 GstPadTemplate *
 gst_pad_get_pad_template (GstPad * pad)
@@ -1641,7 +1515,7 @@ gst_pad_get_pad_template (GstPad * pad)
  * returned, as opposed to #gst_pad_get_parent().
  * Unref the object after use.
  *
- * Returns: the parent #GstElement.
+ * Returns: the parent #GstElement. unref after usage.
  *
  * MT safe.
  */
@@ -1717,7 +1591,7 @@ gst_real_pad_get_caps_unlocked (GstRealPad * realpad)
     GST_FLAG_UNSET (realpad, GST_PAD_IN_GETCAPS);
 
     if (result == NULL) {
-      g_critical ("pad %s:%s returned NULL caps from getcaps function\n",
+      g_critical ("pad %s:%s returned NULL caps from getcaps function",
           GST_DEBUG_PAD_NAME (realpad));
     } else {
 #ifndef G_DISABLE_ASSERT
@@ -2408,1140 +2282,801 @@ not_negotiated:
   }
 }
 
-static void
-gst_real_pad_dispose (GObject * object)
+/**
+ * gst_pad_get_internal_links_default:
+ * @pad: the #GstPad to get the internal links of.
+ *
+ * Gets a list of pads to which the given pad is linked to
+ * inside of the parent element.
+ * This is the default handler, and thus returns a list of all of the
+ * pads inside the parent element with opposite direction.
+ * The caller must free this list after use.
+ *
+ * Returns: a newly allocated #GList of pads.
+ *
+ * Not MT safe.
+ */
+GList *
+gst_pad_get_internal_links_default (GstPad * pad)
 {
-  GstPad *pad;
+  GList *res = NULL;
+  GstElement *parent;
+  GList *parent_pads;
+  GstPadDirection direction;
   GstRealPad *rpad;
 
-  pad = GST_PAD (object);
-  rpad = GST_REAL_PAD (object);
-
-  /* No linked pad can ever be disposed.
-   * It has to have a parent to be linked 
-   * and a parent would hold a reference */
-  /* FIXME: what about if g_object_dispose is explicitly called on the pad? Is
-     that legal? otherwise we could assert GST_OBJECT_PARENT (pad) == NULL as
-     well... */
-  g_assert (GST_PAD_PEER (pad) == NULL);
-
-  GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s",
-      GST_DEBUG_PAD_NAME (pad));
-
-  /* we destroy the ghostpads, because they are nothing without the real pad */
-  if (rpad->ghostpads) {
-    GList *orig, *ghostpads;
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-    orig = ghostpads = g_list_copy (rpad->ghostpads);
+  rpad = GST_PAD_REALIZE (pad);
+  direction = rpad->direction;
 
-    while (ghostpads) {
-      GstPad *ghostpad = GST_PAD (ghostpads->data);
+  parent = GST_PAD_PARENT (rpad);
+  parent_pads = parent->pads;
 
-      if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) {
-        GstElement *parent = GST_ELEMENT (GST_OBJECT_PARENT (ghostpad));
+  while (parent_pads) {
+    GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data);
 
-        GST_CAT_DEBUG (GST_CAT_REFCOUNTING,
-            "removing ghost pad from element '%s'", GST_OBJECT_NAME (parent));
-        gst_element_remove_pad (parent, ghostpad);
-      } else {
-        /* handle the case where we have some floating ghost pad that was never
-           added to an element */
-        g_object_set (ghostpad, "real-pad", NULL, NULL);
-      }
-      ghostpads = g_list_next (ghostpads);
+    if (parent_pad->direction != direction) {
+      res = g_list_prepend (res, parent_pad);
     }
-    g_list_free (orig);
-    /* as the ghost pads are removed, they remove themselves from ->ghostpads.
-       So it should be empty now. Let's assert that. */
-    g_assert (rpad->ghostpads == NULL);
-  }
 
-  /* clear the caps */
-  gst_caps_replace (&GST_RPAD_CAPS (pad), NULL);
-
-  if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
-    GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'",
-        GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
-
-    gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
+    parent_pads = g_list_next (parent_pads);
   }
 
-  G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
+  return res;
 }
 
-static void
-gst_real_pad_finalize (GObject * object)
+/**
+ * gst_pad_get_internal_links:
+ * @pad: the #GstPad to get the internal links of.
+ *
+ * Gets a list of pads to which the given pad is linked to
+ * inside of the parent element.
+ * The caller must free this list after use.
+ *
+ * Returns: a newly allocated #GList of pads.
+ *
+ * Not MT safe.
+ */
+GList *
+gst_pad_get_internal_links (GstPad * pad)
 {
+  GList *res = NULL;
   GstRealPad *rpad;
 
-  rpad = GST_REAL_PAD (object);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  if (rpad->stream_rec_lock) {
-    g_static_rec_mutex_free (rpad->stream_rec_lock);
-    rpad->stream_rec_lock = NULL;
-  }
-  if (rpad->preroll_lock) {
-    g_mutex_free (rpad->preroll_lock);
-    g_cond_free (rpad->preroll_cond);
-    rpad->preroll_lock = NULL;
-    rpad->preroll_cond = NULL;
-  }
-  if (rpad->block_cond) {
-    g_cond_free (rpad->block_cond);
-    rpad->block_cond = NULL;
-  }
+  rpad = GST_PAD_REALIZE (pad);
 
-  G_OBJECT_CLASS (real_pad_parent_class)->finalize (object);
+  if (GST_RPAD_INTLINKFUNC (rpad))
+    res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD_CAST (rpad));
+
+  return res;
 }
 
 
-#ifndef GST_DISABLE_LOADSAVE
-/* FIXME: why isn't this on a GstElement ? */
-/**
- * gst_pad_load_and_link:
- * @self: an #xmlNodePtr to read the description from.
- * @parent: the #GstObject element that owns the pad.
- *
- * Reads the pad definition from the XML node and links the given pad
- * in the element to a pad of an element up in the hierarchy.
- */
-void
-gst_pad_load_and_link (xmlNodePtr self, GstObject * parent)
+static gboolean
+gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
 {
-  xmlNodePtr field = self->xmlChildrenNode;
-  GstPad *pad = NULL, *targetpad;
-  gchar *peer = NULL;
-  gchar **split;
-  GstElement *target;
-  GstObject *grandparent;
-  gchar *name = NULL;
-
-  while (field) {
-    if (!strcmp ((char *) field->name, "name")) {
-      name = (gchar *) xmlNodeGetContent (field);
-      pad = gst_element_get_pad (GST_ELEMENT (parent), name);
-      g_free (name);
-    } else if (!strcmp ((char *) field->name, "peer")) {
-      peer = (gchar *) xmlNodeGetContent (field);
-    }
-    field = field->next;
-  }
-  g_return_if_fail (pad != NULL);
+  GList *orig, *pads;
+  gboolean result;
 
-  if (peer == NULL)
-    return;
+  GST_INFO_OBJECT (pad, "Sending event %p to all internally linked pads",
+      event);
 
-  split = g_strsplit (peer, ".", 2);
+  result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
 
-  if (split[0] == NULL || split[1] == NULL) {
-    GST_CAT_DEBUG (GST_CAT_XML,
-        "Could not parse peer '%s' for pad %s:%s, leaving unlinked",
-        peer, GST_DEBUG_PAD_NAME (pad));
+  orig = pads = gst_pad_get_internal_links (pad);
 
-    g_free (peer);
-    return;
-  }
-  g_free (peer);
-
-  g_return_if_fail (split[0] != NULL);
-  g_return_if_fail (split[1] != NULL);
-
-  grandparent = gst_object_get_parent (parent);
-
-  if (grandparent && GST_IS_BIN (grandparent)) {
-    target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
-  } else
-    goto cleanup;
-
-  if (target == NULL)
-    goto cleanup;
+  while (pads) {
+    GstPad *eventpad = GST_PAD (pads->data);
 
-  targetpad = gst_element_get_pad (target, split[1]);
+    pads = g_list_next (pads);
 
-  if (targetpad == NULL)
-    goto cleanup;
+    /* for all of the internally-linked pads that are actually linked */
+    if (GST_PAD_IS_LINKED (eventpad)) {
+      if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
+        /* for each pad we send to, we should ref the event; it's up
+         * to downstream to unref again when handled. */
+        GST_LOG_OBJECT (pad, "Reffing and sending event %p to %s:%s", event,
+            GST_DEBUG_PAD_NAME (eventpad));
+        gst_event_ref (event);
+        gst_pad_push_event (eventpad, event);
+      } else {
+        /* we only send the event on one pad, multi-sinkpad elements
+         * should implement a handler */
+        GST_LOG_OBJECT (pad, "sending event %p to one sink pad %s:%s", event,
+            GST_DEBUG_PAD_NAME (eventpad));
+        result = gst_pad_push_event (eventpad, event);
+        goto done;
+      }
+    }
+  }
+  /* we handled the incoming event so we unref once */
+  GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
+  gst_event_unref (event);
 
-  gst_pad_link (pad, targetpad);
+done:
+  g_list_free (orig);
 
-cleanup:
-  g_strfreev (split);
+  return result;
 }
 
 /**
- * gst_pad_save_thyself:
- * @pad: a #GstPad to save.
- * @parent: the parent #xmlNodePtr to save the description in.
+ * gst_pad_event_default:
+ * @pad: a #GstPad to call the default event handler on.
+ * @event: the #GstEvent to handle.
  *
- * Saves the pad into an xml representation.
+ * Invokes the default event handler for the given pad. End-of-stream and
+ * discontinuity events are handled specially, and then the event is sent to all
+ * pads internally linked to @pad. Note that if there are many possible sink
+ * pads that are internally linked to @pad, only one will be sent an event.
+ * Multi-sinkpad elements should implement custom event handlers.
  *
- * Returns: the #xmlNodePtr representation of the pad.
+ * Returns: TRUE if the event was sent succesfully.
  */
-static xmlNodePtr
-gst_pad_save_thyself (GstObject * object, xmlNodePtr parent)
+gboolean
+gst_pad_event_default (GstPad * pad, GstEvent * event)
 {
-  GstRealPad *realpad;
-  GstPad *peer;
-
-  g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL);
-
-  realpad = GST_REAL_PAD (object);
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
 
-  xmlNewChild (parent, NULL, (xmlChar *) "name",
-      (xmlChar *) GST_PAD_NAME (realpad));
-  if (GST_RPAD_PEER (realpad) != NULL) {
-    gchar *content;
+  switch (GST_EVENT_TYPE (event)) {
+    case GST_EVENT_EOS:
+    {
+      GstRealPad *rpad = GST_PAD_REALIZE (pad);
 
-    peer = GST_PAD (GST_RPAD_PEER (realpad));
-    /* first check to see if the peer's parent's parent is the same */
-    /* we just save it off */
-    content = g_strdup_printf ("%s.%s",
-        GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));
-    xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content);
-    g_free (content);
-  } else
-    xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL);
+      if (GST_RPAD_TASK (rpad)) {
+        GST_DEBUG_OBJECT (rpad, "pausing task because of eos");
+        gst_task_pause (GST_RPAD_TASK (rpad));
+      }
+    }
+    default:
+      break;
+  }
 
-  return parent;
+  return gst_pad_event_default_dispatch (pad, event);
 }
 
 /**
- * gst_ghost_pad_save_thyself:
- * @pad: a ghost #GstPad to save.
- * @parent: the parent #xmlNodePtr to save the description in.
+ * gst_pad_dispatcher:
+ * @pad: a #GstPad to dispatch.
+ * @dispatch: the #GstDispatcherFunction to call.
+ * @data: gpointer user data passed to the dispatcher function.
  *
- * Saves the ghost pad into an xml representation.
+ * Invokes the given dispatcher function on all pads that are 
+ * internally linked to the given pad. 
+ * The GstPadDispatcherFunction should return TRUE when no further pads 
+ * need to be processed.
  *
- * Returns: the #xmlNodePtr representation of the pad.
+ * Returns: TRUE if one of the dispatcher functions returned TRUE.
  */
-xmlNodePtr
-gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent)
+gboolean
+gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch,
+    gpointer data)
 {
-  xmlNodePtr self;
-
-  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
-
-  self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
-  xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad));
-  xmlNewChild (self, NULL, (xmlChar *) "parent",
-      (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
-
-  /* FIXME FIXME FIXME! */
-
-  return self;
-}
-#endif /* GST_DISABLE_LOADSAVE */
+  gboolean res = FALSE;
+  GList *int_pads, *orig;
 
-/* 
- * should be called with pad lock held 
- *
- * MT safe.
- */
-static void
-handle_pad_block (GstRealPad * pad)
-{
-  GstPadBlockCallback callback;
-  gpointer user_data;
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (dispatch != NULL, FALSE);
 
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "signal block taken on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+  orig = int_pads = gst_pad_get_internal_links (pad);
 
-  /* need to grab extra ref for the callbacks */
-  gst_object_ref (GST_OBJECT (pad));
+  while (int_pads) {
+    GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data);
+    GstRealPad *int_peer = GST_RPAD_PEER (int_rpad);
 
-  callback = pad->block_callback;
-  if (callback) {
-    user_data = pad->block_data;
-    GST_UNLOCK (pad);
-    callback (GST_PAD_CAST (pad), TRUE, user_data);
-    GST_LOCK (pad);
-  } else {
-    GST_PAD_BLOCK_SIGNAL (pad);
+    if (int_peer) {
+      res = dispatch (GST_PAD (int_peer), data);
+      if (res)
+        break;
+    }
+    int_pads = g_list_next (int_pads);
   }
 
-  while (GST_RPAD_IS_BLOCKED (pad))
-    GST_PAD_BLOCK_WAIT (pad);
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
-
-  callback = pad->block_callback;
-  if (callback) {
-    user_data = pad->block_data;
-    GST_UNLOCK (pad);
-    callback (GST_PAD_CAST (pad), FALSE, user_data);
-    GST_LOCK (pad);
-  } else {
-    GST_PAD_BLOCK_SIGNAL (pad);
-  }
+  g_list_free (orig);
 
-  gst_object_unref (GST_OBJECT (pad));
+  return res;
 }
 
 /**
- * gst_pad_push:
- * @pad: a source #GstPad.
- * @buffer: the #GstBuffer to push.
+ * gst_pad_query:
+ * @pad: a #GstPad to invoke the default query on.
+ * @query: the #GstQuery to perform.
  *
- * Pushes a buffer to the peer of @pad. @pad must be linked.
+ * Dispatches a query to a pad. The query should have been allocated by the
+ * caller via one of the type-specific allocation functions in gstquery.h. The
+ * element is responsible for filling the query with an appropriate response,
+ * which should then be parsed with a type-specific query parsing function.
  *
- * Returns: a #GstFlowReturn from the peer pad.
+ * Again, the caller is responsible for both the allocation and deallocation of
+ * the query structure.
  *
- * MT safe.
+ * Returns: TRUE if the query could be performed.
  */
-GstFlowReturn
-gst_pad_push (GstPad * pad, GstBuffer * buffer)
+gboolean
+gst_pad_query (GstPad * pad, GstQuery * query)
 {
-  GstRealPad *peer;
-  GstFlowReturn ret;
-  GstPadChainFunction chainfunc;
-  GstCaps *caps;
-  gboolean caps_changed;
-
-  g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC,
-      GST_FLOW_ERROR);
-  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
+  GstRealPad *rpad;
+  GstPadQueryFunction func;
 
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
 
-  GST_LOCK (pad);
-  while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
-    handle_pad_block (GST_REAL_PAD_CAST (pad));
+  rpad = GST_PAD_REALIZE (pad);
 
-  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
-    goto not_linked;
+  g_return_val_if_fail (rpad, FALSE);
 
-  if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer)))
-    goto not_active;
+  GST_DEBUG ("sending query %p to pad %s:%s", query, GST_DEBUG_PAD_NAME (pad));
 
-  if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer)))
-    goto flushing;
+  if ((func = GST_RPAD_QUERYFUNC (rpad)) == NULL)
+    goto no_func;
 
-  gst_object_ref (GST_OBJECT_CAST (peer));
-  GST_UNLOCK (pad);
+  return func (GST_PAD_CAST (rpad), query);
 
-  /* FIXME, move capnego this into a base class? */
-  caps = GST_BUFFER_CAPS (buffer);
-  caps_changed = caps && caps != GST_RPAD_CAPS (peer);
-  GST_DEBUG ("caps changed %d %" GST_PTR_FORMAT "\n", caps_changed, caps);
-  /* we got a new datatype on the peer pad, see if it can handle it */
-  if (G_UNLIKELY (caps_changed)) {
-    if (G_UNLIKELY (!gst_pad_configure_sink (GST_PAD_CAST (peer), caps)))
-      goto not_negotiated;
+no_func:
+  {
+    GST_DEBUG ("pad had no query function");
+    return FALSE;
   }
+}
 
-  /* NOTE: we read the peer chainfunc unlocked. 
-   * we cannot hold the lock for the peer so we might send
-   * the data to the wrong function. This is not really a
-   * problem since functions are assigned at creation time
-   * and don't change that often... */
-  if (G_UNLIKELY ((chainfunc = peer->chainfunc) == NULL))
-    goto no_function;
-
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "calling chainfunction &%s of peer pad %s:%s",
-      GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (peer));
-
-  ret = chainfunc (GST_PAD_CAST (peer), buffer);
-
-  gst_object_unref (GST_OBJECT_CAST (peer));
-
-  return ret;
-
-  /* ERROR recovery here */
-not_linked:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but it was not linked");
-    GST_UNLOCK (pad);
-    return GST_FLOW_NOT_CONNECTED;
-  }
-not_active:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but it was inactive");
-    GST_UNLOCK (pad);
-    return GST_FLOW_WRONG_STATE;
-  }
-flushing:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but pad was flushing");
-    GST_UNLOCK (pad);
-    return GST_FLOW_UNEXPECTED;
-  }
-not_negotiated:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing buffer but peer did not accept");
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-no_function:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pushing, but not chainhandler");
-    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
-        ("push on pad %s:%s but the peer pad %s:%s has no chainfunction",
-            GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
-    gst_object_unref (GST_OBJECT (peer));
-    return GST_FLOW_ERROR;
-  }
-}
-
-/**
- * gst_pad_check_pull_range:
- * @pad: a sink #GstRealPad.
- *
- * Checks if a #gst_pad_pull_range() can be performed on the peer
- * source pad. This function is used by plugins that want to check
- * if they can use random access on the peer source pad. 
- *
- * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction
- * if it needs to perform some logic to determine if pull_range is
- * possible.
- *
- * Returns: a gboolean with the result.
- *
- * MT safe.
- */
 gboolean
-gst_pad_check_pull_range (GstPad * pad)
+gst_pad_query_default (GstPad * pad, GstQuery * query)
 {
-  GstRealPad *peer;
-  gboolean ret;
-  GstPadCheckGetRangeFunction checkgetrangefunc;
-
-  g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
-
-  GST_LOCK (pad);
-  if (GST_RPAD_DIRECTION (pad) != GST_PAD_SINK)
-    goto wrong_direction;
-
-  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
-    goto not_connected;
-
-  gst_object_ref (GST_OBJECT_CAST (peer));
-  GST_UNLOCK (pad);
-
-  /* see note in above function */
-  if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) {
-    ret = GST_RPAD_GETRANGEFUNC (peer) != NULL;
-  } else {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "calling checkgetrangefunc %s of peer pad %s:%s",
-        GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer));
-
-    ret = checkgetrangefunc (GST_PAD_CAST (peer));
-  }
-
-  gst_object_unref (GST_OBJECT_CAST (peer));
-
-  return ret;
-
-  /* ERROR recovery here */
-wrong_direction:
-  {
-    GST_UNLOCK (pad);
-    return FALSE;
-  }
-not_connected:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "checking pull range, but it was not linked");
-    GST_UNLOCK (pad);
-    return FALSE;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+    case GST_QUERY_SEEKING:
+    case GST_QUERY_FORMATS:
+    case GST_QUERY_LATENCY:
+    case GST_QUERY_JITTER:
+    case GST_QUERY_RATE:
+    case GST_QUERY_CONVERT:
+    default:
+      return gst_pad_dispatcher
+          (pad, (GstPadDispatcherFunction) gst_pad_query, query);
   }
 }
 
-/**
- * gst_pad_pull_range:
- * @pad: a sink #GstPad.
- * @buffer: a pointer to hold the #GstBuffer.
- * @offset: The start offset of the buffer
- * @length: The length of the buffer
- *
- * Pulls a buffer from the peer pad. @pad must be linked.
- *
- * Returns: a #GstFlowReturn from the peer pad.
- *
- * MT safe.
- */
-GstFlowReturn
-gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
-    GstBuffer ** buffer)
+static void
+gst_real_pad_dispose (GObject * object)
 {
-  GstRealPad *peer;
-  GstFlowReturn ret;
-  GstPadGetRangeFunction getrangefunc;
-
-  g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK,
-      GST_FLOW_ERROR);
-  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
-
-  GST_LOCK (pad);
-
-  while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
-    handle_pad_block (GST_REAL_PAD_CAST (pad));
-
-  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
-    goto not_connected;
-
-  if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer)))
-    goto not_active;
+  GstPad *pad;
+  GstRealPad *rpad;
 
-  if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer)))
-    goto flushing;
+  pad = GST_PAD (object);
+  rpad = GST_REAL_PAD (object);
 
-  gst_object_ref (GST_OBJECT_CAST (peer));
-  GST_UNLOCK (pad);
+  /* No linked pad can ever be disposed.
+   * It has to have a parent to be linked 
+   * and a parent would hold a reference */
+  /* FIXME: what about if g_object_dispose is explicitly called on the pad? Is
+     that legal? otherwise we could assert GST_OBJECT_PARENT (pad) == NULL as
+     well... */
+  g_assert (GST_PAD_PEER (pad) == NULL);
 
-  /* see note in above function */
-  if (G_UNLIKELY ((getrangefunc = peer->getrangefunc) == NULL))
-    goto no_function;
+  GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "dispose %s:%s",
+      GST_DEBUG_PAD_NAME (pad));
 
-  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-      "calling getrangefunc %s of peer pad %s:%s, offset %"
-      G_GUINT64_FORMAT ", size %u",
-      GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer),
-      offset, size);
+  /* we destroy the ghostpads, because they are nothing without the real pad */
+  if (rpad->ghostpads) {
+    GList *orig, *ghostpads;
 
-  ret = getrangefunc (GST_PAD_CAST (peer), offset, size, buffer);
+    orig = ghostpads = g_list_copy (rpad->ghostpads);
 
-  gst_object_unref (GST_OBJECT_CAST (peer));
+    while (ghostpads) {
+      GstPad *ghostpad = GST_PAD (ghostpads->data);
 
-  return ret;
+      if (GST_IS_ELEMENT (GST_OBJECT_PARENT (ghostpad))) {
+        GstElement *parent = GST_ELEMENT (GST_OBJECT_PARENT (ghostpad));
 
-  /* ERROR recovery here */
-not_connected:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pulling range, but it was not linked");
-    GST_UNLOCK (pad);
-    return GST_FLOW_NOT_CONNECTED;
-  }
-not_active:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pulling range, but it was inactive");
-    GST_UNLOCK (pad);
-    return GST_FLOW_WRONG_STATE;
-  }
-flushing:
-  {
-    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
-        "pulling range, but pad was flushing");
-    GST_UNLOCK (pad);
-    return GST_FLOW_UNEXPECTED;
-  }
-no_function:
-  {
-    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
-        ("pullrange on pad %s:%s but the peer pad %s:%s has no getrangefunction",
-            GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
-    gst_object_unref (GST_OBJECT (peer));
-    return GST_FLOW_ERROR;
+        GST_CAT_DEBUG (GST_CAT_REFCOUNTING,
+            "removing ghost pad from element '%s'", GST_OBJECT_NAME (parent));
+        gst_element_remove_pad (parent, ghostpad);
+      } else {
+        /* handle the case where we have some floating ghost pad that was never
+           added to an element */
+        g_object_set (ghostpad, "real-pad", NULL, NULL);
+      }
+      ghostpads = g_list_next (ghostpads);
+    }
+    g_list_free (orig);
+    /* as the ghost pads are removed, they remove themselves from ->ghostpads.
+       So it should be empty now. Let's assert that. */
+    g_assert (rpad->ghostpads == NULL);
   }
-}
-
-/************************************************************************
- *
- * templates
- *
- */
-static void gst_pad_template_class_init (GstPadTemplateClass * klass);
-static void gst_pad_template_init (GstPadTemplate * templ);
-static void gst_pad_template_dispose (GObject * object);
 
-GType
-gst_pad_template_get_type (void)
-{
-  static GType padtemplate_type = 0;
+  /* clear the caps */
+  gst_caps_replace (&GST_RPAD_CAPS (pad), NULL);
 
-  if (!padtemplate_type) {
-    static const GTypeInfo padtemplate_info = {
-      sizeof (GstPadTemplateClass), NULL, NULL,
-      (GClassInitFunc) gst_pad_template_class_init, NULL, NULL,
-      sizeof (GstPadTemplate),
-      0,
-      (GInstanceInitFunc) gst_pad_template_init, NULL
-    };
+  if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
+    GST_CAT_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'",
+        GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
 
-    padtemplate_type =
-        g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate",
-        &padtemplate_info, 0);
+    gst_element_remove_pad (GST_ELEMENT (GST_OBJECT_PARENT (pad)), pad);
   }
-  return padtemplate_type;
-}
 
-static void
-gst_pad_template_class_init (GstPadTemplateClass * klass)
-{
-  GObjectClass *gobject_class;
-  GstObjectClass *gstobject_class;
-
-  gobject_class = (GObjectClass *) klass;
-  gstobject_class = (GstObjectClass *) klass;
-
-  padtemplate_parent_class = g_type_class_ref (GST_TYPE_OBJECT);
-
-  gst_pad_template_signals[TEMPL_PAD_CREATED] =
-      g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
-      G_STRUCT_OFFSET (GstPadTemplateClass, pad_created),
-      NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
-
-  gobject_class->dispose = gst_pad_template_dispose;
-
-  gstobject_class->path_string_separator = "*";
+  G_OBJECT_CLASS (real_pad_parent_class)->dispose (object);
 }
 
 static void
-gst_pad_template_init (GstPadTemplate * templ)
+gst_real_pad_finalize (GObject * object)
 {
-}
+  GstRealPad *rpad;
 
-static void
-gst_pad_template_dispose (GObject * object)
-{
-  GstPadTemplate *templ = GST_PAD_TEMPLATE (object);
+  rpad = GST_REAL_PAD (object);
 
-  g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
-  if (GST_PAD_TEMPLATE_CAPS (templ)) {
-    gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
+  if (rpad->stream_rec_lock) {
+    g_static_rec_mutex_free (rpad->stream_rec_lock);
+    rpad->stream_rec_lock = NULL;
   }
-
-  G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object);
-}
-
-/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make
- * sense.
- * SOMETIMES padtemplates can do whatever they want, they are provided by the
- * element.
- * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the
- * 'sink%d' template is automatically selected), so we need to restrict their
- * naming.
- */
-static gboolean
-name_is_valid (const gchar * name, GstPadPresence presence)
-{
-  const gchar *str;
-
-  if (presence == GST_PAD_ALWAYS) {
-    if (strchr (name, '%')) {
-      g_warning ("invalid name template %s: conversion specifications are not"
-          " allowed for GST_PAD_ALWAYS padtemplates", name);
-      return FALSE;
-    }
-  } else if (presence == GST_PAD_REQUEST) {
-    if ((str = strchr (name, '%')) && strchr (str + 1, '%')) {
-      g_warning ("invalid name template %s: only one conversion specification"
-          " allowed in GST_PAD_REQUEST padtemplate", name);
-      return FALSE;
-    }
-    if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) {
-      g_warning ("invalid name template %s: conversion specification must be of"
-          " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name);
-      return FALSE;
-    }
-    if (str && (*(str + 2) != '\0')) {
-      g_warning ("invalid name template %s: conversion specification must"
-          " appear at the end of the GST_PAD_REQUEST padtemplate name", name);
-      return FALSE;
-    }
+  if (rpad->preroll_lock) {
+    g_mutex_free (rpad->preroll_lock);
+    g_cond_free (rpad->preroll_cond);
+    rpad->preroll_lock = NULL;
+    rpad->preroll_cond = NULL;
+  }
+  if (rpad->block_cond) {
+    g_cond_free (rpad->block_cond);
+    rpad->block_cond = NULL;
   }
 
-  return TRUE;
+  G_OBJECT_CLASS (real_pad_parent_class)->finalize (object);
 }
 
+
+#ifndef GST_DISABLE_LOADSAVE
+/* FIXME: why isn't this on a GstElement ? */
 /**
- * gst_static_pad_template_get:
- * @pad_template: the static pad template
- *
- * Converts a #GstStaticPadTemplate into a #GstPadTemplate.
+ * gst_pad_load_and_link:
+ * @self: an #xmlNodePtr to read the description from.
+ * @parent: the #GstObject element that owns the pad.
  *
- * Returns: a new #GstPadTemplate.
+ * Reads the pad definition from the XML node and links the given pad
+ * in the element to a pad of an element up in the hierarchy.
  */
-GstPadTemplate *
-gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
+void
+gst_pad_load_and_link (xmlNodePtr self, GstObject * parent)
 {
-  GstPadTemplate *new;
-
-  if (!name_is_valid (pad_template->name_template, pad_template->presence))
-    return NULL;
-
-  new = g_object_new (gst_pad_template_get_type (),
-      "name", pad_template->name_template, NULL);
-
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence;
+  xmlNodePtr field = self->xmlChildrenNode;
+  GstPad *pad = NULL, *targetpad;
+  gchar *peer = NULL;
+  gchar **split;
+  GstElement *target;
+  GstObject *grandparent;
+  gchar *name = NULL;
 
-  GST_PAD_TEMPLATE_CAPS (new) =
-      gst_caps_copy (gst_static_caps_get (&pad_template->static_caps));
+  while (field) {
+    if (!strcmp ((char *) field->name, "name")) {
+      name = (gchar *) xmlNodeGetContent (field);
+      pad = gst_element_get_pad (GST_ELEMENT (parent), name);
+      g_free (name);
+    } else if (!strcmp ((char *) field->name, "peer")) {
+      peer = (gchar *) xmlNodeGetContent (field);
+    }
+    field = field->next;
+  }
+  g_return_if_fail (pad != NULL);
 
-  return new;
-}
+  if (peer == NULL)
+    return;
 
-/**
- * gst_pad_template_new:
- * @name_template: the name template.
- * @direction: the #GstPadDirection of the template.
- * @presence: the #GstPadPresence of the pad.
- * @caps: a #GstCaps set for the template. The caps are taken ownership of.
- *
- * Creates a new pad template with a name according to the given template
- * and with the given arguments. This functions takes ownership of the provided
- * caps, so be sure to not use them afterwards.
- *
- * Returns: a new #GstPadTemplate.
- */
-GstPadTemplate *
-gst_pad_template_new (const gchar * name_template,
-    GstPadDirection direction, GstPadPresence presence, GstCaps * caps)
-{
-  GstPadTemplate *new;
+  split = g_strsplit (peer, ".", 2);
 
-  g_return_val_if_fail (name_template != NULL, NULL);
-  g_return_val_if_fail (caps != NULL, NULL);
-  g_return_val_if_fail (direction == GST_PAD_SRC
-      || direction == GST_PAD_SINK, NULL);
-  g_return_val_if_fail (presence == GST_PAD_ALWAYS
-      || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL);
+  if (split[0] == NULL || split[1] == NULL) {
+    GST_CAT_DEBUG (GST_CAT_XML,
+        "Could not parse peer '%s' for pad %s:%s, leaving unlinked",
+        peer, GST_DEBUG_PAD_NAME (pad));
 
-  if (!name_is_valid (name_template, presence))
-    return NULL;
+    g_free (peer);
+    return;
+  }
+  g_free (peer);
 
-  new = g_object_new (gst_pad_template_get_type (),
-      "name", name_template, NULL);
+  g_return_if_fail (split[0] != NULL);
+  g_return_if_fail (split[1] != NULL);
 
-  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template);
-  GST_PAD_TEMPLATE_DIRECTION (new) = direction;
-  GST_PAD_TEMPLATE_PRESENCE (new) = presence;
-  GST_PAD_TEMPLATE_CAPS (new) = caps;
+  grandparent = gst_object_get_parent (parent);
 
-  return new;
-}
+  if (grandparent && GST_IS_BIN (grandparent)) {
+    target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
+  } else
+    goto cleanup;
 
-/**
- * gst_static_pad_template_get_caps:
- * @templ: a #GstStaticPadTemplate to get capabilities of.
- *
- * Gets the capabilities of the static pad template.
- *
- * Returns: the #GstCaps of the static pad template. If you need to keep a 
- * reference to the caps, take a ref (see gst_caps_ref ()).
- */
-GstCaps *
-gst_static_pad_template_get_caps (GstStaticPadTemplate * templ)
-{
-  g_return_val_if_fail (templ, NULL);
+  if (target == NULL)
+    goto cleanup;
 
-  return (GstCaps *) gst_static_caps_get (&templ->static_caps);
-}
+  targetpad = gst_element_get_pad (target, split[1]);
 
-/**
- * gst_pad_template_get_caps:
- * @templ: a #GstPadTemplate to get capabilities of.
- *
- * Gets the capabilities of the pad template.
- *
- * Returns: the #GstCaps of the pad template. If you need to keep a reference to
- * the caps, take a ref (see gst_caps_ref ()).
- */
-GstCaps *
-gst_pad_template_get_caps (GstPadTemplate * templ)
-{
-  g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
+  if (targetpad == NULL)
+    goto cleanup;
 
-  return GST_PAD_TEMPLATE_CAPS (templ);
-}
+  gst_pad_link (pad, targetpad);
 
-/**
- * gst_pad_set_element_private:
- * @pad: the #GstPad to set the private data of.
- * @priv: The private data to attach to the pad.
- *
- * Set the given private data gpointer on the pad. 
- * This function can only be used by the element that owns the pad.
- */
-void
-gst_pad_set_element_private (GstPad * pad, gpointer priv)
-{
-  pad->element_private = priv;
+cleanup:
+  g_strfreev (split);
 }
 
 /**
- * gst_pad_get_element_private:
- * @pad: the #GstPad to get the private data of.
+ * gst_pad_save_thyself:
+ * @pad: a #GstPad to save.
+ * @parent: the parent #xmlNodePtr to save the description in.
  *
- * Gets the private data of a pad.
+ * Saves the pad into an xml representation.
  *
- * Returns: a #gpointer to the private data.
+ * Returns: the #xmlNodePtr representation of the pad.
  */
-gpointer
-gst_pad_get_element_private (GstPad * pad)
-{
-  return pad->element_private;
-}
-
-gboolean
-gst_pad_start_task (GstPad * pad)
-{
-  g_warning ("implement gst_pad_start_task()");
-  return FALSE;
-}
-
-gboolean
-gst_pad_pause_task (GstPad * pad)
-{
-  g_warning ("implement gst_pad_pause_task()");
-  return FALSE;
-}
-
-gboolean
-gst_pad_stop_task (GstPad * pad)
+static xmlNodePtr
+gst_pad_save_thyself (GstObject * object, xmlNodePtr parent)
 {
-  g_warning ("implement gst_pad_stop_task()");
-  return FALSE;
-}
-
-
-/***** ghost pads *****/
-GType _gst_ghost_pad_type = 0;
+  GstRealPad *realpad;
+  GstPad *peer;
 
-static void gst_ghost_pad_class_init (GstGhostPadClass * klass);
-static void gst_ghost_pad_init (GstGhostPad * pad);
-static void gst_ghost_pad_dispose (GObject * object);
-static void gst_ghost_pad_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec);
-static void gst_ghost_pad_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
+  g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL);
 
-static GstPad *ghost_pad_parent_class = NULL;
+  realpad = GST_REAL_PAD (object);
 
-/* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */
-enum
-{
-  GPAD_ARG_0,
-  GPAD_ARG_REAL_PAD
-      /* fill me */
-};
+  xmlNewChild (parent, NULL, (xmlChar *) "name",
+      (xmlChar *) GST_PAD_NAME (realpad));
+  if (GST_RPAD_PEER (realpad) != NULL) {
+    gchar *content;
 
-GType
-gst_ghost_pad_get_type (void)
-{
-  if (!_gst_ghost_pad_type) {
-    static const GTypeInfo pad_info = {
-      sizeof (GstGhostPadClass), NULL, NULL,
-      (GClassInitFunc) gst_ghost_pad_class_init, NULL, NULL,
-      sizeof (GstGhostPad),
-      0,
-      (GInstanceInitFunc) gst_ghost_pad_init,
-      NULL
-    };
+    peer = GST_PAD (GST_RPAD_PEER (realpad));
+    /* first check to see if the peer's parent's parent is the same */
+    /* we just save it off */
+    content = g_strdup_printf ("%s.%s",
+        GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer));
+    xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content);
+    g_free (content);
+  } else
+    xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL);
 
-    _gst_ghost_pad_type = g_type_register_static (GST_TYPE_PAD, "GstGhostPad",
-        &pad_info, 0);
-  }
-  return _gst_ghost_pad_type;
+  return parent;
 }
 
-static void
-gst_ghost_pad_class_init (GstGhostPadClass * klass)
+/**
+ * gst_ghost_pad_save_thyself:
+ * @pad: a ghost #GstPad to save.
+ * @parent: the parent #xmlNodePtr to save the description in.
+ *
+ * Saves the ghost pad into an xml representation.
+ *
+ * Returns: the #xmlNodePtr representation of the pad.
+ */
+xmlNodePtr
+gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent)
 {
-  GObjectClass *gobject_class;
-
-  gobject_class = (GObjectClass *) klass;
+  xmlNodePtr self;
 
-  ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
+  g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
 
-  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
-  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_set_property);
-  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_get_property);
+  self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL);
+  xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad));
+  xmlNewChild (self, NULL, (xmlChar *) "parent",
+      (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
 
-  g_object_class_install_property (gobject_class, GPAD_ARG_REAL_PAD,
-      g_param_spec_object ("real-pad", "Real pad",
-          "The real pad for the ghost pad", GST_TYPE_PAD, G_PARAM_READWRITE));
-}
+  /* FIXME FIXME FIXME! */
 
-static void
-gst_ghost_pad_init (GstGhostPad * pad)
-{
-  /* zeroed by glib */
+  return self;
 }
+#endif /* GST_DISABLE_LOADSAVE */
 
+/* 
+ * should be called with pad lock held 
+ *
+ * MT safe.
+ */
 static void
-gst_ghost_pad_dispose (GObject * object)
+handle_pad_block (GstRealPad * pad)
 {
-  g_object_set (object, "real-pad", NULL, NULL);
+  GstPadBlockCallback callback;
+  gpointer user_data;
 
-  G_OBJECT_CLASS (ghost_pad_parent_class)->dispose (object);
-}
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "signal block taken on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
 
-static void
-gst_ghost_pad_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec)
-{
-  GstPad *ghostpad = (GstPad *) object;
-  GstPad *oldrealpad = (GstPad *) GST_GPAD_REALPAD (ghostpad);
-  GstPad *realpad = NULL;
+  /* need to grab extra ref for the callbacks */
+  gst_object_ref (GST_OBJECT (pad));
 
-  switch (prop_id) {
-    case GPAD_ARG_REAL_PAD:
-      realpad = g_value_get_object (value);
+  callback = pad->block_callback;
+  if (callback) {
+    user_data = pad->block_data;
+    GST_UNLOCK (pad);
+    callback (GST_PAD_CAST (pad), TRUE, user_data);
+    GST_LOCK (pad);
+  } else {
+    GST_PAD_BLOCK_SIGNAL (pad);
+  }
 
-      if (oldrealpad) {
-        if (realpad == oldrealpad)
-          return;
-        else
-          gst_pad_remove_ghost_pad (oldrealpad, ghostpad);
-      }
+  while (GST_RPAD_IS_BLOCKED (pad))
+    GST_PAD_BLOCK_WAIT (pad);
 
-      if (realpad)
-        gst_pad_add_ghost_pad (realpad, ghostpad);
-      break;
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked");
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  callback = pad->block_callback;
+  if (callback) {
+    user_data = pad->block_data;
+    GST_UNLOCK (pad);
+    callback (GST_PAD_CAST (pad), FALSE, user_data);
+    GST_LOCK (pad);
+  } else {
+    GST_PAD_BLOCK_SIGNAL (pad);
   }
+
+  gst_object_unref (GST_OBJECT (pad));
 }
 
-static void
-gst_ghost_pad_get_property (GObject * object, guint prop_id,
-    GValue * value, GParamSpec * pspec)
-{
-  switch (prop_id) {
-    case GPAD_ARG_REAL_PAD:
-      g_value_set_object (value, GST_GPAD_REALPAD (object));
-      break;
+/**********************************************************************
+ * Data passing functions
+ */
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-}
 
 /**
- * gst_ghost_pad_new:
- * @name: the name of the new ghost pad.
- * @pad: the #GstPad to create a ghost pad for.
+ * gst_pad_push:
+ * @pad: a source #GstPad.
+ * @buffer: the #GstBuffer to push.
  *
- * Creates a new ghost pad associated with @pad, and named @name. If @name is
- * %NULL, a guaranteed unique name (across all ghost pads) will be assigned.
+ * Pushes a buffer to the peer of @pad. @pad must be linked.
  *
- * Returns: a new ghost #GstPad, or %NULL in case of an error.
+ * Returns: a #GstFlowReturn from the peer pad.
+ *
+ * MT safe.
  */
-GstPad *
-gst_ghost_pad_new (const gchar * name, GstPad * pad)
+GstFlowReturn
+gst_pad_push (GstPad * pad, GstBuffer * buffer)
 {
-  GstPad *gpad;
+  GstRealPad *peer;
+  GstFlowReturn ret;
+  GstPadChainFunction chainfunc;
+  GstCaps *caps;
+  gboolean caps_changed;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SRC,
+      GST_FLOW_ERROR);
+  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
 
-  gpad = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "real-pad", pad, NULL);
 
-  GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s",
-      GST_OBJECT_NAME (gpad), GST_DEBUG_PAD_NAME (pad));
+  GST_LOCK (pad);
+  while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
+    handle_pad_block (GST_REAL_PAD_CAST (pad));
+
+  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
+    goto not_linked;
+
+  if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer)))
+    goto not_active;
+
+  if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer)))
+    goto flushing;
 
-  return gpad;
-}
+  gst_object_ref (GST_OBJECT_CAST (peer));
+  GST_UNLOCK (pad);
 
-/**
- * gst_pad_get_internal_links_default:
- * @pad: the #GstPad to get the internal links of.
- *
- * Gets a list of pads to which the given pad is linked to
- * inside of the parent element.
- * This is the default handler, and thus returns a list of all of the
- * pads inside the parent element with opposite direction.
- * The caller must free this list after use.
- *
- * Returns: a newly allocated #GList of pads.
- *
- * Not MT safe.
- */
-GList *
-gst_pad_get_internal_links_default (GstPad * pad)
-{
-  GList *res = NULL;
-  GstElement *parent;
-  GList *parent_pads;
-  GstPadDirection direction;
-  GstRealPad *rpad;
+  /* FIXME, move capnego this into a base class? */
+  caps = GST_BUFFER_CAPS (buffer);
+  caps_changed = caps && caps != GST_RPAD_CAPS (peer);
+  GST_DEBUG ("caps changed %d %" GST_PTR_FORMAT, caps_changed, caps);
+  /* we got a new datatype on the peer pad, see if it can handle it */
+  if (G_UNLIKELY (caps_changed)) {
+    if (G_UNLIKELY (!gst_pad_configure_sink (GST_PAD_CAST (peer), caps)))
+      goto not_negotiated;
+  }
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  /* NOTE: we read the peer chainfunc unlocked. 
+   * we cannot hold the lock for the peer so we might send
+   * the data to the wrong function. This is not really a
+   * problem since functions are assigned at creation time
+   * and don't change that often... */
+  if (G_UNLIKELY ((chainfunc = peer->chainfunc) == NULL))
+    goto no_function;
 
-  rpad = GST_PAD_REALIZE (pad);
-  direction = rpad->direction;
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "calling chainfunction &%s of peer pad %s:%s",
+      GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (peer));
 
-  parent = GST_PAD_PARENT (rpad);
-  parent_pads = parent->pads;
+  ret = chainfunc (GST_PAD_CAST (peer), buffer);
 
-  while (parent_pads) {
-    GstRealPad *parent_pad = GST_PAD_REALIZE (parent_pads->data);
+  gst_object_unref (GST_OBJECT_CAST (peer));
 
-    if (parent_pad->direction != direction) {
-      res = g_list_prepend (res, parent_pad);
-    }
+  return ret;
 
-    parent_pads = g_list_next (parent_pads);
+  /* ERROR recovery here */
+not_linked:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but it was not linked");
+    GST_UNLOCK (pad);
+    return GST_FLOW_NOT_CONNECTED;
+  }
+not_active:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but it was inactive");
+    GST_UNLOCK (pad);
+    return GST_FLOW_WRONG_STATE;
+  }
+flushing:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but pad was flushing");
+    GST_UNLOCK (pad);
+    return GST_FLOW_UNEXPECTED;
+  }
+not_negotiated:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing buffer but peer did not accept");
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+no_function:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pushing, but not chainhandler");
+    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+        ("push on pad %s:%s but the peer pad %s:%s has no chainfunction",
+            GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
+    gst_object_unref (GST_OBJECT (peer));
+    return GST_FLOW_ERROR;
   }
-
-  return res;
 }
 
 /**
- * gst_pad_get_internal_links:
- * @pad: the #GstPad to get the internal links of.
+ * gst_pad_check_pull_range:
+ * @pad: a sink #GstRealPad.
  *
- * Gets a list of pads to which the given pad is linked to
- * inside of the parent element.
- * The caller must free this list after use.
+ * Checks if a #gst_pad_pull_range() can be performed on the peer
+ * source pad. This function is used by plugins that want to check
+ * if they can use random access on the peer source pad. 
  *
- * Returns: a newly allocated #GList of pads.
+ * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction
+ * if it needs to perform some logic to determine if pull_range is
+ * possible.
  *
- * Not MT safe.
+ * Returns: a gboolean with the result.
+ *
+ * MT safe.
  */
-GList *
-gst_pad_get_internal_links (GstPad * pad)
+gboolean
+gst_pad_check_pull_range (GstPad * pad)
 {
-  GList *res = NULL;
-  GstRealPad *rpad;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-  rpad = GST_PAD_REALIZE (pad);
-
-  if (GST_RPAD_INTLINKFUNC (rpad))
-    res = GST_RPAD_INTLINKFUNC (rpad) (GST_PAD_CAST (rpad));
+  GstRealPad *peer;
+  gboolean ret;
+  GstPadCheckGetRangeFunction checkgetrangefunc;
 
-  return res;
-}
+  g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE);
 
+  GST_LOCK (pad);
+  if (GST_RPAD_DIRECTION (pad) != GST_PAD_SINK)
+    goto wrong_direction;
 
-static gboolean
-gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
-{
-  GList *orig, *pads;
-  gboolean result;
+  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
+    goto not_connected;
 
-  GST_INFO_OBJECT (pad, "Sending event %p to all internally linked pads",
-      event);
+  gst_object_ref (GST_OBJECT_CAST (peer));
+  GST_UNLOCK (pad);
 
-  result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
+  /* see note in above function */
+  if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) {
+    ret = GST_RPAD_GETRANGEFUNC (peer) != NULL;
+  } else {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "calling checkgetrangefunc %s of peer pad %s:%s",
+        GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer));
 
-  orig = pads = gst_pad_get_internal_links (pad);
+    ret = checkgetrangefunc (GST_PAD_CAST (peer));
+  }
 
-  while (pads) {
-    GstPad *eventpad = GST_PAD (pads->data);
+  gst_object_unref (GST_OBJECT_CAST (peer));
 
-    pads = g_list_next (pads);
+  return ret;
 
-    /* for all of the internally-linked pads that are actually linked */
-    if (GST_PAD_IS_LINKED (eventpad)) {
-      if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
-        /* for each pad we send to, we should ref the event; it's up
-         * to downstream to unref again when handled. */
-        GST_LOG_OBJECT (pad, "Reffing and sending event %p to %s:%s", event,
-            GST_DEBUG_PAD_NAME (eventpad));
-        gst_event_ref (event);
-        gst_pad_push_event (eventpad, event);
-      } else {
-        /* we only send the event on one pad, multi-sinkpad elements
-         * should implement a handler */
-        GST_LOG_OBJECT (pad, "sending event %p to one sink pad %s:%s", event,
-            GST_DEBUG_PAD_NAME (eventpad));
-        result = gst_pad_push_event (eventpad, event);
-        goto done;
-      }
-    }
+  /* ERROR recovery here */
+wrong_direction:
+  {
+    GST_UNLOCK (pad);
+    return FALSE;
+  }
+not_connected:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "checking pull range, but it was not linked");
+    GST_UNLOCK (pad);
+    return FALSE;
   }
-  /* we handled the incoming event so we unref once */
-  GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
-  gst_event_unref (event);
-
-done:
-  g_list_free (orig);
-
-  return result;
 }
 
 /**
- * gst_pad_event_default:
- * @pad: a #GstPad to call the default event handler on.
- * @event: the #GstEvent to handle.
+ * gst_pad_pull_range:
+ * @pad: a sink #GstPad.
+ * @buffer: a pointer to hold the #GstBuffer.
+ * @offset: The start offset of the buffer
+ * @length: The length of the buffer
  *
- * Invokes the default event handler for the given pad. End-of-stream and
- * discontinuity events are handled specially, and then the event is sent to all
- * pads internally linked to @pad. Note that if there are many possible sink
- * pads that are internally linked to @pad, only one will be sent an event.
- * Multi-sinkpad elements should implement custom event handlers.
+ * Pulls a buffer from the peer pad. @pad must be linked.
  *
- * Returns: TRUE if the event was sent succesfully.
+ * Returns: a #GstFlowReturn from the peer pad.
+ *
+ * MT safe.
  */
-gboolean
-gst_pad_event_default (GstPad * pad, GstEvent * event)
+GstFlowReturn
+gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
+    GstBuffer ** buffer)
 {
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
+  GstRealPad *peer;
+  GstFlowReturn ret;
+  GstPadGetRangeFunction getrangefunc;
 
-  switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_EOS:
-    {
-      GstRealPad *rpad = GST_PAD_REALIZE (pad);
+  g_return_val_if_fail (GST_IS_REAL_PAD (pad), GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_RPAD_DIRECTION (pad) == GST_PAD_SINK,
+      GST_FLOW_ERROR);
+  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
-      if (GST_RPAD_TASK (rpad)) {
-        GST_DEBUG_OBJECT (rpad, "pausing task because of eos");
-        gst_task_pause (GST_RPAD_TASK (rpad));
-      }
-    }
-    default:
-      break;
-  }
+  GST_LOCK (pad);
+
+  while (G_UNLIKELY (GST_RPAD_IS_BLOCKED (pad)))
+    handle_pad_block (GST_REAL_PAD_CAST (pad));
 
-  return gst_pad_event_default_dispatch (pad, event);
-}
+  if (G_UNLIKELY ((peer = GST_RPAD_PEER (pad)) == NULL))
+    goto not_connected;
 
-/**
- * gst_pad_dispatcher:
- * @pad: a #GstPad to dispatch.
- * @dispatch: the #GstDispatcherFunction to call.
- * @data: gpointer user data passed to the dispatcher function.
- *
- * Invokes the given dispatcher function on all pads that are 
- * internally linked to the given pad. 
- * The GstPadDispatcherFunction should return TRUE when no further pads 
- * need to be processed.
- *
- * Returns: TRUE if one of the dispatcher functions returned TRUE.
- */
-gboolean
-gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch,
-    gpointer data)
-{
-  gboolean res = FALSE;
-  GList *int_pads, *orig;
+  if (G_UNLIKELY (!GST_RPAD_IS_ACTIVE (peer)))
+    goto not_active;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dispatch != NULL, FALSE);
+  if (G_UNLIKELY (GST_RPAD_IS_FLUSHING (peer)))
+    goto flushing;
 
-  orig = int_pads = gst_pad_get_internal_links (pad);
+  gst_object_ref (GST_OBJECT_CAST (peer));
+  GST_UNLOCK (pad);
 
-  while (int_pads) {
-    GstRealPad *int_rpad = GST_PAD_REALIZE (int_pads->data);
-    GstRealPad *int_peer = GST_RPAD_PEER (int_rpad);
+  /* see note in above function */
+  if (G_UNLIKELY ((getrangefunc = peer->getrangefunc) == NULL))
+    goto no_function;
 
-    if (int_peer) {
-      res = dispatch (GST_PAD (int_peer), data);
-      if (res)
-        break;
-    }
-    int_pads = g_list_next (int_pads);
-  }
+  GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+      "calling getrangefunc %s of peer pad %s:%s, offset %"
+      G_GUINT64_FORMAT ", size %u",
+      GST_DEBUG_FUNCPTR_NAME (getrangefunc), GST_DEBUG_PAD_NAME (peer),
+      offset, size);
 
-  g_list_free (orig);
+  ret = getrangefunc (GST_PAD_CAST (peer), offset, size, buffer);
 
-  return res;
+  gst_object_unref (GST_OBJECT_CAST (peer));
+
+  return ret;
+
+  /* ERROR recovery here */
+not_connected:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pulling range, but it was not linked");
+    GST_UNLOCK (pad);
+    return GST_FLOW_NOT_CONNECTED;
+  }
+not_active:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pulling range, but it was inactive");
+    GST_UNLOCK (pad);
+    return GST_FLOW_WRONG_STATE;
+  }
+flushing:
+  {
+    GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+        "pulling range, but pad was flushing");
+    GST_UNLOCK (pad);
+    return GST_FLOW_UNEXPECTED;
+  }
+no_function:
+  {
+    GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
+        ("pullrange on pad %s:%s but the peer pad %s:%s has no getrangefunction",
+            GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)));
+    gst_object_unref (GST_OBJECT (peer));
+    return GST_FLOW_ERROR;
+  }
 }
 
 /**
@@ -3646,304 +3181,405 @@ no_function:
   }
 }
 
-typedef struct
-{
-  GstFormat src_format;
-  gint64 src_value;
-  GstFormat *dest_format;
-  gint64 *dest_value;
-}
-GstPadConvertData;
+/************************************************************************
+ *
+ * templates
+ *
+ */
+static void gst_pad_template_class_init (GstPadTemplateClass * klass);
+static void gst_pad_template_init (GstPadTemplate * templ);
+static void gst_pad_template_dispose (GObject * object);
+
+GType
+gst_pad_template_get_type (void)
+{
+  static GType padtemplate_type = 0;
+
+  if (!padtemplate_type) {
+    static const GTypeInfo padtemplate_info = {
+      sizeof (GstPadTemplateClass), NULL, NULL,
+      (GClassInitFunc) gst_pad_template_class_init, NULL, NULL,
+      sizeof (GstPadTemplate),
+      0,
+      (GInstanceInitFunc) gst_pad_template_init, NULL
+    };
+
+    padtemplate_type =
+        g_type_register_static (GST_TYPE_OBJECT, "GstPadTemplate",
+        &padtemplate_info, 0);
+  }
+  return padtemplate_type;
+}
+
+static void
+gst_pad_template_class_init (GstPadTemplateClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstObjectClass *gstobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstobject_class = (GstObjectClass *) klass;
+
+  padtemplate_parent_class = g_type_class_ref (GST_TYPE_OBJECT);
+
+  gst_pad_template_signals[TEMPL_PAD_CREATED] =
+      g_signal_new ("pad-created", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+      G_STRUCT_OFFSET (GstPadTemplateClass, pad_created),
+      NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
+
+  gobject_class->dispose = gst_pad_template_dispose;
+
+  gstobject_class->path_string_separator = "*";
+}
+
+static void
+gst_pad_template_init (GstPadTemplate * templ)
+{
+}
+
+static void
+gst_pad_template_dispose (GObject * object)
+{
+  GstPadTemplate *templ = GST_PAD_TEMPLATE (object);
+
+  g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
+  if (GST_PAD_TEMPLATE_CAPS (templ)) {
+    gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
+  }
+
+  G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object);
+}
+
+/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make
+ * sense.
+ * SOMETIMES padtemplates can do whatever they want, they are provided by the
+ * element.
+ * REQUEST padtemplates can be reverse-parsed (the user asks for 'sink1', the
+ * 'sink%d' template is automatically selected), so we need to restrict their
+ * naming.
+ */
+static gboolean
+name_is_valid (const gchar * name, GstPadPresence presence)
+{
+  const gchar *str;
+
+  if (presence == GST_PAD_ALWAYS) {
+    if (strchr (name, '%')) {
+      g_warning ("invalid name template %s: conversion specifications are not"
+          " allowed for GST_PAD_ALWAYS padtemplates", name);
+      return FALSE;
+    }
+  } else if (presence == GST_PAD_REQUEST) {
+    if ((str = strchr (name, '%')) && strchr (str + 1, '%')) {
+      g_warning ("invalid name template %s: only one conversion specification"
+          " allowed in GST_PAD_REQUEST padtemplate", name);
+      return FALSE;
+    }
+    if (str && (*(str + 1) != 's' && *(str + 1) != 'd')) {
+      g_warning ("invalid name template %s: conversion specification must be of"
+          " type '%%d' or '%%s' for GST_PAD_REQUEST padtemplate", name);
+      return FALSE;
+    }
+    if (str && (*(str + 2) != '\0')) {
+      g_warning ("invalid name template %s: conversion specification must"
+          " appear at the end of the GST_PAD_REQUEST padtemplate name", name);
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_static_pad_template_get:
+ * @pad_template: the static pad template
+ *
+ * Converts a #GstStaticPadTemplate into a #GstPadTemplate.
+ *
+ * Returns: a new #GstPadTemplate.
+ */
+GstPadTemplate *
+gst_static_pad_template_get (GstStaticPadTemplate * pad_template)
+{
+  GstPadTemplate *new;
+
+  if (!name_is_valid (pad_template->name_template, pad_template->presence))
+    return NULL;
+
+  new = g_object_new (gst_pad_template_get_type (),
+      "name", pad_template->name_template, NULL);
+
+  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (pad_template->name_template);
+  GST_PAD_TEMPLATE_DIRECTION (new) = pad_template->direction;
+  GST_PAD_TEMPLATE_PRESENCE (new) = pad_template->presence;
+
+  GST_PAD_TEMPLATE_CAPS (new) =
+      gst_caps_copy (gst_static_caps_get (&pad_template->static_caps));
+
+  return new;
+}
+
+/**
+ * gst_pad_template_new:
+ * @name_template: the name template.
+ * @direction: the #GstPadDirection of the template.
+ * @presence: the #GstPadPresence of the pad.
+ * @caps: a #GstCaps set for the template. The caps are taken ownership of.
+ *
+ * Creates a new pad template with a name according to the given template
+ * and with the given arguments. This functions takes ownership of the provided
+ * caps, so be sure to not use them afterwards.
+ *
+ * Returns: a new #GstPadTemplate.
+ */
+GstPadTemplate *
+gst_pad_template_new (const gchar * name_template,
+    GstPadDirection direction, GstPadPresence presence, GstCaps * caps)
+{
+  GstPadTemplate *new;
+
+  g_return_val_if_fail (name_template != NULL, NULL);
+  g_return_val_if_fail (caps != NULL, NULL);
+  g_return_val_if_fail (direction == GST_PAD_SRC
+      || direction == GST_PAD_SINK, NULL);
+  g_return_val_if_fail (presence == GST_PAD_ALWAYS
+      || presence == GST_PAD_SOMETIMES || presence == GST_PAD_REQUEST, NULL);
+
+  if (!name_is_valid (name_template, presence))
+    return NULL;
+
+  new = g_object_new (gst_pad_template_get_type (),
+      "name", name_template, NULL);
+
+  GST_PAD_TEMPLATE_NAME_TEMPLATE (new) = g_strdup (name_template);
+  GST_PAD_TEMPLATE_DIRECTION (new) = direction;
+  GST_PAD_TEMPLATE_PRESENCE (new) = presence;
+  GST_PAD_TEMPLATE_CAPS (new) = caps;
 
-static gboolean
-gst_pad_convert_dispatcher (GstPad * pad, GstPadConvertData * data)
-{
-  return gst_pad_convert (pad, data->src_format, data->src_value,
-      data->dest_format, data->dest_value);
+  return new;
 }
 
 /**
- * gst_pad_convert_default:
- * @pad: a #GstPad to invoke the default converter on.
- * @src_format: the source #GstFormat.
- * @src_value: the source value.
- * @dest_format: a pointer to the destination #GstFormat.
- * @dest_value: a pointer to the destination value.
+ * gst_static_pad_template_get_caps:
+ * @templ: a #GstStaticPadTemplate to get capabilities of.
  *
- * Invokes the default converter on a pad. 
- * This will forward the call to the pad obtained 
- * using the internal link of
- * the element.
+ * Gets the capabilities of the static pad template.
  *
- * Returns: TRUE if the conversion could be performed.
+ * Returns: the #GstCaps of the static pad template. If you need to keep a 
+ * reference to the caps, take a ref (see gst_caps_ref ()).
  */
-gboolean
-gst_pad_convert_default (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
+GstCaps *
+gst_static_pad_template_get_caps (GstStaticPadTemplate * templ)
 {
-  GstPadConvertData data;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
-  g_return_val_if_fail (dest_value != NULL, FALSE);
-
-  data.src_format = src_format;
-  data.src_value = src_value;
-  data.dest_format = dest_format;
-  data.dest_value = dest_value;
+  g_return_val_if_fail (templ, NULL);
 
-  return gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
-      gst_pad_convert_dispatcher, &data);
+  return (GstCaps *) gst_static_caps_get (&templ->static_caps);
 }
 
 /**
- * gst_pad_convert:
- * @pad: a #GstPad to invoke the default converter on.
- * @src_format: the source #GstFormat.
- * @src_value: the source value.
- * @dest_format: a pointer to the destination #GstFormat.
- * @dest_value: a pointer to the destination value.
+ * gst_pad_template_get_caps:
+ * @templ: a #GstPadTemplate to get capabilities of.
  *
- * Invokes a conversion on the pad.
+ * Gets the capabilities of the pad template.
  *
- * Returns: TRUE if the conversion could be performed.
+ * Returns: the #GstCaps of the pad template. If you need to keep a reference to
+ * the caps, take a ref (see gst_caps_ref ()).
  */
-gboolean
-gst_pad_convert (GstPad * pad,
-    GstFormat src_format, gint64 src_value,
-    GstFormat * dest_format, gint64 * dest_value)
-{
-  GstRealPad *rpad;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dest_format != NULL, FALSE);
-  g_return_val_if_fail (dest_value != NULL, FALSE);
-
-  if (src_format == *dest_format) {
-    *dest_value = src_value;
-    return TRUE;
-  }
-
-  rpad = GST_PAD_REALIZE (pad);
-
-  if (GST_RPAD_CONVERTFUNC (rpad)) {
-    return GST_RPAD_CONVERTFUNC (rpad) (GST_PAD (rpad), src_format,
-        src_value, dest_format, dest_value);
-  }
-
-  return FALSE;
-}
-
-typedef struct
+GstCaps *
+gst_pad_template_get_caps (GstPadTemplate * templ)
 {
-  GstQueryType type;
-  GstFormat *format;
-  gint64 *value;
-}
-GstPadQueryData;
+  g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
 
-static gboolean
-gst_pad_query_dispatcher (GstPad * pad, GstPadQueryData * data)
-{
-  return gst_pad_query (pad, data->type, data->format, data->value);
+  return GST_PAD_TEMPLATE_CAPS (templ);
 }
 
 /**
- * gst_pad_query_default:
- * @pad: a #GstPad to invoke the default query on.
- * @type: the #GstQueryType of the query to perform.
- * @format: a pointer to the #GstFormat of the result.
- * @value: a pointer to the result.
- *
- * Invokes the default query function on a pad. 
+ * gst_pad_set_element_private:
+ * @pad: the #GstPad to set the private data of.
+ * @priv: The private data to attach to the pad.
  *
- * Returns: TRUE if the query could be performed.
+ * Set the given private data gpointer on the pad. 
+ * This function can only be used by the element that owns the pad.
  */
-gboolean
-gst_pad_query_default (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value)
+void
+gst_pad_set_element_private (GstPad * pad, gpointer priv)
 {
-  GstPadQueryData data;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
-
-  data.type = type;
-  data.format = format;
-  data.value = value;
-
-  return gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
-      gst_pad_query_dispatcher, &data);
+  pad->element_private = priv;
 }
 
 /**
- * gst_pad_query:
- * @pad: a #GstPad to invoke the default query on.
- * @type: the #GstQueryType of the query to perform.
- * @format: a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
- * @value: a pointer to the result.
+ * gst_pad_get_element_private:
+ * @pad: the #GstPad to get the private data of.
  *
- * Queries a pad for one of the available properties. The format will be
- * adjusted to the actual format used when specifying formats such as 
- * GST_FORMAT_DEFAULT.
- * FIXME: Tell if the format can be adjusted when specifying a definite format.
+ * Gets the private data of a pad.
  *
- * Returns: TRUE if the query could be performed.
+ * Returns: a #gpointer to the private data.
  */
-gboolean
-gst_pad_query (GstPad * pad, GstQueryType type,
-    GstFormat * format, gint64 * value)
+gpointer
+gst_pad_get_element_private (GstPad * pad)
 {
-  GstRealPad *rpad;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
-  g_return_val_if_fail (value != NULL, FALSE);
-
-  rpad = GST_PAD_REALIZE (pad);
-
-  g_return_val_if_fail (rpad, FALSE);
+  return pad->element_private;
+}
 
-  if (GST_RPAD_QUERYFUNC (rpad))
-    return GST_RPAD_QUERYFUNC (rpad) (GST_PAD_CAST (rpad), type, format, value);
+gboolean
+gst_pad_start_task (GstPad * pad)
+{
+  g_warning ("implement gst_pad_start_task()");
+  return FALSE;
+}
 
+gboolean
+gst_pad_pause_task (GstPad * pad)
+{
+  g_warning ("implement gst_pad_pause_task()");
   return FALSE;
 }
 
-/**
- * gst_pad_query2:
- * @pad: a #GstPad to invoke the default query on.
- * @query: the #GstQuery to perform.
- *
- * Dispatches a query to a pad. The query should have been allocated by the
- * caller via one of the type-specific allocation functions in gstquery.h. The
- * element is responsible for filling the query with an appropriate response,
- * which should then be parsed with a type-specific query parsing function.
- *
- * Again, the caller is responsible for both the allocation and deallocation of
- * the query structure.
- *
- * Returns: TRUE if the query could be performed.
- */
 gboolean
-gst_pad_query2 (GstPad * pad, GstQuery * query)
+gst_pad_stop_task (GstPad * pad)
 {
-  GstRealPad *rpad;
+  g_warning ("implement gst_pad_stop_task()");
+  return FALSE;
+}
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
 
-  rpad = GST_PAD_REALIZE (pad);
+/***** ghost pads *****/
+GType _gst_ghost_pad_type = 0;
 
-  g_return_val_if_fail (rpad, FALSE);
+static void gst_ghost_pad_class_init (GstGhostPadClass * klass);
+static void gst_ghost_pad_init (GstGhostPad * pad);
+static void gst_ghost_pad_dispose (GObject * object);
+static void gst_ghost_pad_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_ghost_pad_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
 
-  if (GST_RPAD_QUERY2FUNC (rpad))
-    return GST_RPAD_QUERY2FUNC (rpad) (GST_PAD_CAST (rpad), query);
+static GstPad *ghost_pad_parent_class = NULL;
 
-  return FALSE;
-}
+/* static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 }; */
+enum
+{
+  GPAD_ARG_0,
+  GPAD_ARG_REAL_PAD
+      /* fill me */
+};
 
-gboolean
-gst_pad_query2_default (GstPad * pad, GstQuery * query)
+GType
+gst_ghost_pad_get_type (void)
 {
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
-    case GST_QUERY_SEEKING:
-    case GST_QUERY_FORMATS:
-    case GST_QUERY_LATENCY:
-    case GST_QUERY_JITTER:
-    case GST_QUERY_RATE:
-    case GST_QUERY_CONVERT:
-    default:
-      return gst_pad_dispatcher
-          (pad, (GstPadDispatcherFunction) gst_pad_query2, query);
+  if (!_gst_ghost_pad_type) {
+    static const GTypeInfo pad_info = {
+      sizeof (GstGhostPadClass), NULL, NULL,
+      (GClassInitFunc) gst_ghost_pad_class_init, NULL, NULL,
+      sizeof (GstGhostPad),
+      0,
+      (GInstanceInitFunc) gst_ghost_pad_init,
+      NULL
+    };
+
+    _gst_ghost_pad_type = g_type_register_static (GST_TYPE_PAD, "GstGhostPad",
+        &pad_info, 0);
   }
+  return _gst_ghost_pad_type;
 }
 
-/**
- * gst_pad_query_position:
- * @pad: a #GstPad to invoke the default query on.
- * @format: a pointer to the #GstFormat asked for.
- *          On return contains the #GstFormat used.
- * @cur: A location in which to store the current position, or NULL.
- * @end: A location in which to store the end position (length), or NULL.
- *
- * Queries a pad for the stream position and length.
- *
- * Returns: TRUE if the query could be performed.
- */
-gboolean
-gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur,
-    gint64 * end)
+static void
+gst_ghost_pad_class_init (GstGhostPadClass * klass)
 {
-  GstQuery *query;
-  gboolean ret;
+  GObjectClass *gobject_class;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (format != NULL, FALSE);
+  gobject_class = (GObjectClass *) klass;
 
-  query = gst_query_new_position (*format);
-  ret = gst_pad_query2 (pad, query);
+  ghost_pad_parent_class = g_type_class_ref (GST_TYPE_PAD);
 
-  if (ret)
-    gst_query_parse_position_response (query, format, cur, end);
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_ghost_pad_dispose);
+  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_set_property);
+  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ghost_pad_get_property);
 
-  gst_query_unref (query);
+  g_object_class_install_property (gobject_class, GPAD_ARG_REAL_PAD,
+      g_param_spec_object ("real-pad", "Real pad",
+          "The real pad for the ghost pad", GST_TYPE_PAD, G_PARAM_READWRITE));
+}
 
-  return ret;
+static void
+gst_ghost_pad_init (GstGhostPad * pad)
+{
+  /* zeroed by glib */
 }
 
-static gboolean
-gst_pad_get_formats_dispatcher (GstPad * pad, const GstFormat ** data)
+static void
+gst_ghost_pad_dispose (GObject * object)
 {
-  *data = gst_pad_get_formats (pad);
+  g_object_set (object, "real-pad", NULL, NULL);
 
-  return TRUE;
+  G_OBJECT_CLASS (ghost_pad_parent_class)->dispose (object);
 }
 
-/**
- * gst_pad_get_formats_default:
- * @pad: a #GstPad to query
- *
- * Invoke the default format dispatcher for the pad.
- *
- * Returns: An array of GstFormats ended with a 0 value.
- */
-const GstFormat *
-gst_pad_get_formats_default (GstPad * pad)
+static void
+gst_ghost_pad_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
 {
-  GstFormat *result = NULL;
+  GstPad *ghostpad = (GstPad *) object;
+  GstPad *oldrealpad = (GstPad *) GST_GPAD_REALPAD (ghostpad);
+  GstPad *realpad = NULL;
 
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  switch (prop_id) {
+    case GPAD_ARG_REAL_PAD:
+      realpad = g_value_get_object (value);
 
-  gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
-      gst_pad_get_formats_dispatcher, &result);
+      if (oldrealpad) {
+        if (realpad == oldrealpad)
+          return;
+        else
+          gst_pad_remove_ghost_pad (oldrealpad, ghostpad);
+      }
 
-  return result;
+      if (realpad)
+        gst_pad_add_ghost_pad (realpad, ghostpad);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_ghost_pad_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  switch (prop_id) {
+    case GPAD_ARG_REAL_PAD:
+      g_value_set_object (value, GST_GPAD_REALPAD (object));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 /**
- * gst_pad_get_formats:
- * @pad: a #GstPad to query
+ * gst_ghost_pad_new:
+ * @name: the name of the new ghost pad.
+ * @pad: the #GstPad to create a ghost pad for.
  *
- * Gets the list of supported formats from the pad.
+ * Creates a new ghost pad associated with @pad, and named @name. If @name is
+ * %NULL, a guaranteed unique name (across all ghost pads) will be assigned.
  *
- * Returns: An array of GstFormats ended with a 0 value.
+ * Returns: a new ghost #GstPad, or %NULL in case of an error.
  */
-const GstFormat *
-gst_pad_get_formats (GstPad * pad)
+GstPad *
+gst_ghost_pad_new (const gchar * name, GstPad * pad)
 {
-  GstRealPad *rpad;
+  GstPad *gpad;
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  rpad = GST_PAD_REALIZE (pad);
+  gpad = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "real-pad", pad, NULL);
 
-  if (GST_RPAD_FORMATSFUNC (rpad))
-    return GST_RPAD_FORMATSFUNC (rpad) (GST_PAD (pad));
+  GST_CAT_DEBUG (GST_CAT_PADS, "created ghost pad \"%s\" for pad %s:%s",
+      GST_OBJECT_NAME (gpad), GST_DEBUG_PAD_NAME (pad));
 
-  return NULL;
+  return gpad;
 }
index b560b80..d8fcd9f 100644 (file)
@@ -135,26 +135,21 @@ typedef enum {
 typedef gboolean               (*GstPadActivateFunction)       (GstPad *pad, GstActivateMode mode);
 
 /* data passing */
-typedef void                   (*GstPadLoopFunction)           (GstPad *pad);
 typedef GstFlowReturn          (*GstPadChainFunction)          (GstPad *pad, GstBuffer *buffer);
 typedef GstFlowReturn          (*GstPadGetRangeFunction)       (GstPad *pad, guint64 offset, 
                                                                 guint length, GstBuffer **buffer);
-typedef gboolean               (*GstPadCheckGetRangeFunction)  (GstPad *pad); 
 typedef gboolean               (*GstPadEventFunction)          (GstPad *pad, GstEvent *event);
 
-/* old, deprecated convert/query/format functions */
-typedef gboolean               (*GstPadConvertFunction)        (GstPad *pad,
-                                                                GstFormat src_format,  gint64  src_value,
-                                                                GstFormat *dest_format, gint64 *dest_value);
-typedef gboolean               (*GstPadQueryFunction)          (GstPad *pad, GstQueryType type,
-                                                                GstFormat *format, gint64  *value);
+/* deprecate me, check range should use seeking query, loop function is internal */
+typedef gboolean               (*GstPadCheckGetRangeFunction)  (GstPad *pad); 
+typedef void                   (*GstPadLoopFunction)           (GstPad *pad);
+
+/* internal links */
 typedef GList*                 (*GstPadIntLinkFunction)        (GstPad *pad);
-typedef const GstFormat*       (*GstPadFormatsFunction)        (GstPad *pad);
-typedef const GstEventMask*    (*GstPadEventMaskFunction)      (GstPad *pad);
-typedef const GstQueryType*    (*GstPadQueryTypeFunction)      (GstPad *pad);
 
 /* generic query function */
-typedef gboolean               (*GstPadQuery2Function)         (GstPad *pad, GstQuery *query);
+typedef const GstQueryType*    (*GstPadQueryTypeFunction)      (GstPad *pad);
+typedef gboolean               (*GstPadQueryFunction)          (GstPad *pad, GstQuery *query);
 
 /* linking */
 typedef GstPadLinkReturn       (*GstPadLinkFunction)           (GstPad *pad, GstPad *peer);
@@ -247,29 +242,23 @@ struct _GstRealPad {
   GstPadGetRangeFunction        getrangefunc;
   GstPadEventFunction           eventfunc;
 
-  GstPadEventMaskFunction       eventmaskfunc;
-
   /* ghostpads */
   GList                        *ghostpads;
   guint32                       ghostpads_cookie;
 
-  /* old, deprecated query/convert/formats functions */
-  GstPadConvertFunction                 convertfunc;
-  GstPadQueryFunction           queryfunc;
-  GstPadFormatsFunction                 formatsfunc;
+  /* generic query method */
   GstPadQueryTypeFunction       querytypefunc;
+  GstPadQueryFunction           queryfunc;
+
+  /* internal links */
   GstPadIntLinkFunction                 intlinkfunc;
 
   GstPadBufferAllocFunction      bufferallocfunc;
 
   GstProbeDispatcher            probedisp;
 
-  /* generic query method */
-  GstPadQuery2Function          query2func;
-  
   /*< private >*/
-  /* fixme: bring back to gst_padding when old query functions go away */
-  gpointer _gst_reserved[GST_PADDING - 1];
+  gpointer _gst_reserved[GST_PADDING];
 };
 
 struct _GstRealPadClass {
@@ -315,13 +304,9 @@ struct _GstGhostPadClass {
 #define GST_RPAD_CHECKGETRANGEFUNC(pad)        (GST_REAL_PAD_CAST(pad)->checkgetrangefunc)
 #define GST_RPAD_GETRANGEFUNC(pad)     (GST_REAL_PAD_CAST(pad)->getrangefunc)
 #define GST_RPAD_EVENTFUNC(pad)                (GST_REAL_PAD_CAST(pad)->eventfunc)
-#define GST_RPAD_CONVERTFUNC(pad)      (GST_REAL_PAD_CAST(pad)->convertfunc)
+#define GST_RPAD_QUERYTYPEFUNC(pad)    (GST_REAL_PAD_CAST(pad)->querytypefunc)
 #define GST_RPAD_QUERYFUNC(pad)                (GST_REAL_PAD_CAST(pad)->queryfunc)
 #define GST_RPAD_INTLINKFUNC(pad)      (GST_REAL_PAD_CAST(pad)->intlinkfunc)
-#define GST_RPAD_FORMATSFUNC(pad)      (GST_REAL_PAD_CAST(pad)->formatsfunc)
-#define GST_RPAD_QUERYTYPEFUNC(pad)    (GST_REAL_PAD_CAST(pad)->querytypefunc)
-#define GST_RPAD_EVENTMASKFUNC(pad)    (GST_REAL_PAD_CAST(pad)->eventmaskfunc)
-#define GST_RPAD_QUERY2FUNC(pad)       (GST_REAL_PAD_CAST(pad)->query2func)
 
 #define GST_RPAD_PEER(pad)             (GST_REAL_PAD_CAST(pad)->peer)
 #define GST_RPAD_LINKFUNC(pad)         (GST_REAL_PAD_CAST(pad)->linkfunc)
@@ -379,11 +364,10 @@ struct _GstGhostPadClass {
 #define GST_PAD_IS_LINKED(pad)         (GST_RPAD_IS_LINKED(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_ACTIVE(pad)         (GST_RPAD_IS_ACTIVE(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_BLOCKED(pad)                (GST_RPAD_IS_BLOCKED(GST_PAD_REALIZE(pad)))
-#define GST_PAD_IS_NEGOTIATING(pad)    (GST_RPAD_IS_NEGOTIATING(GST_PAD_REALIZE(pad)))
+#define GST_PAD_IS_FLUSHING(pad)       (GST_RPAD_IS_FLUSHING(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_IN_GETCAPS(pad)     (GST_RPAD_IS_IN_GETCAPS(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_IN_SETCAPS(pad)     (GST_RPAD_IS_IN_SETCAPS(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_USABLE(pad)         (GST_RPAD_IS_USABLE(GST_PAD_REALIZE(pad)))
-#define GST_PAD_CAN_PULL(pad)          (GST_RPAD_CAN_PULL(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_SRC(pad)            (GST_RPAD_IS_SRC(GST_PAD_REALIZE(pad)))
 #define GST_PAD_IS_SINK(pad)           (GST_RPAD_IS_SINK(GST_PAD_REALIZE(pad)))
 
@@ -492,11 +476,6 @@ void                       gst_pad_set_chain_function              (GstPad *pad, GstPadChainFunction chain);
 void                   gst_pad_set_getrange_function           (GstPad *pad, GstPadGetRangeFunction get);
 void                   gst_pad_set_checkgetrange_function      (GstPad *pad, GstPadCheckGetRangeFunction check);
 void                   gst_pad_set_event_function              (GstPad *pad, GstPadEventFunction event);
-void                   gst_pad_set_event_mask_function         (GstPad *pad, GstPadEventMaskFunction mask_func);
-G_CONST_RETURN GstEventMask*
-                       gst_pad_get_event_masks                 (GstPad *pad);
-G_CONST_RETURN GstEventMask*
-                       gst_pad_get_event_masks_default         (GstPad *pad);
 
 /* pad links */
 void                   gst_pad_set_link_function               (GstPad *pad, GstPadLinkFunction link);
@@ -544,44 +523,21 @@ gboolean          gst_pad_start_task                      (GstPad *pad);
 gboolean               gst_pad_pause_task                      (GstPad *pad);
 gboolean               gst_pad_stop_task                       (GstPad *pad);
 
-/* convert/query/format functions */
-void                   gst_pad_set_formats_function            (GstPad *pad,
-                                                                GstPadFormatsFunction formats);
-G_CONST_RETURN GstFormat*
-                       gst_pad_get_formats                     (GstPad *pad);
-G_CONST_RETURN GstFormat*
-                       gst_pad_get_formats_default             (GstPad *pad);
-
-void                   gst_pad_set_convert_function            (GstPad *pad, GstPadConvertFunction convert);
-gboolean               gst_pad_convert                         (GstPad *pad,
-                                                                GstFormat src_format,  gint64  src_value,
-                                                                GstFormat *dest_format, gint64 *dest_value);
-gboolean               gst_pad_convert_default                 (GstPad *pad,
-                                                                GstFormat src_format,  gint64  src_value,
-                                                                GstFormat *dest_format, gint64 *dest_value);
+/* internal links */
+void                   gst_pad_set_internal_link_function      (GstPad *pad, GstPadIntLinkFunction intlink);
+GList*                 gst_pad_get_internal_links              (GstPad *pad);
+GList*                 gst_pad_get_internal_links_default      (GstPad *pad);
 
-void                   gst_pad_set_query_function              (GstPad *pad, GstPadQueryFunction query);
+/* generic query function */
 void                   gst_pad_set_query_type_function         (GstPad *pad, GstPadQueryTypeFunction type_func);
 G_CONST_RETURN GstQueryType*
                        gst_pad_get_query_types                 (GstPad *pad);
 G_CONST_RETURN GstQueryType*
                        gst_pad_get_query_types_default         (GstPad *pad);
-gboolean               gst_pad_query                           (GstPad *pad, GstQueryType type,
-                                                                GstFormat *format, gint64 *value);
-gboolean               gst_pad_query_default                   (GstPad *pad, GstQueryType type,
-                                                                GstFormat *format, gint64 *value);
 
-void                   gst_pad_set_internal_link_function      (GstPad *pad, GstPadIntLinkFunction intlink);
-GList*                 gst_pad_get_internal_links              (GstPad *pad);
-GList*                 gst_pad_get_internal_links_default      (GstPad *pad);
-
-gboolean               gst_pad_query2                          (GstPad *pad, GstQuery *query);
-void                   gst_pad_set_query2_function             (GstPad *pad, GstPadQuery2Function query);
-gboolean               gst_pad_query2_default                  (GstPad *pad, GstQuery *query);
-
-/* util query functions */
-gboolean               gst_pad_query_position                  (GstPad *pad, GstFormat *format,
-                                                                 gint64 *cur, gint64 *end);
+gboolean               gst_pad_query                           (GstPad *pad, GstQuery *query);
+void                   gst_pad_set_query_function              (GstPad *pad, GstPadQueryFunction query);
+gboolean               gst_pad_query_default                   (GstPad *pad, GstQuery *query);
 
 /* misc helper functions */
 gboolean               gst_pad_dispatcher                      (GstPad *pad, GstPadDispatcherFunction dispatch,
index 5f02fe4..9b57fb3 100644 (file)
 #include "gst_private.h"
 #include "gstquery.h"
 #include "gstmemchunk.h"
+#include "gstenumtypes.h"
 #include "gstdata_private.h"
 
+GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
+#define GST_CAT_DEFAULT gst_query_debug
 
 GType _gst_query_type;
 
-
 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
 static GList *_gst_queries = NULL;
 static GHashTable *_nick_to_query = NULL;
@@ -61,6 +63,8 @@ _gst_query_initialize (void)
 
   GST_CAT_INFO (GST_CAT_GST_INIT, "init queries");
 
+  GST_DEBUG_CATEGORY_INIT (gst_query_debug, "query", 0, "query system");
+
   g_static_mutex_lock (&mutex);
   if (_nick_to_query == NULL) {
     _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal);
@@ -279,12 +283,116 @@ gst_query_new (GstQueryType type, GstStructure * structure)
     query->structure = structure;
     gst_structure_set_parent_refcount (query->structure,
         &GST_DATA_REFCOUNT (query));
+  } else {
+    query->structure = NULL;
   }
 
   return query;
 }
 
 GstQuery *
+gst_query_new_position (GstFormat format)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new ("GstQueryPosition",
+      "format", GST_TYPE_FORMAT, format,
+      "cur", G_TYPE_INT64, (gint64) - 1,
+      "end", G_TYPE_INT64, (gint64) - 1, NULL);
+  query = gst_query_new (GST_QUERY_POSITION, structure);
+
+  return query;
+}
+
+void
+gst_query_set_position (GstQuery * query, GstFormat format,
+    gint64 cur, gint64 end)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_set (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "cur", G_TYPE_INT64, cur, "end", G_TYPE_INT64, end, NULL);
+}
+
+void
+gst_query_parse_position (GstQuery * query, GstFormat * format,
+    gint64 * cur, gint64 * end)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
+
+  structure = gst_query_get_structure (query);
+  if (format)
+    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
+  if (cur)
+    *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
+  if (end)
+    *end = g_value_get_int64 (gst_structure_get_value (structure, "end"));
+}
+
+GstQuery *
+gst_query_new_convert (GstFormat src_fmt, gint64 value, GstFormat dest_fmt)
+{
+  GstQuery *query;
+  GstStructure *structure;
+
+  structure = gst_structure_new ("GstQueryConvert",
+      "src_format", GST_TYPE_FORMAT, src_fmt,
+      "src_value", G_TYPE_INT64, value,
+      "dest_format", GST_TYPE_FORMAT, dest_fmt,
+      "dest_value", G_TYPE_INT64, (gint64) - 1, NULL);
+  query = gst_query_new (GST_QUERY_CONVERT, structure);
+
+  return query;
+}
+
+void
+gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
+    GstFormat dest_format, gint64 dest_value)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
+
+  structure = gst_query_get_structure (query);
+  gst_structure_set (structure,
+      "src_format", GST_TYPE_FORMAT, src_format,
+      "src_value", G_TYPE_INT64, src_value,
+      "dest_format", GST_TYPE_FORMAT, dest_format,
+      "dest_value", G_TYPE_INT64, dest_value, NULL);
+}
+
+void
+gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
+    gint64 * src_value, GstFormat * dest_format, gint64 * dest_value)
+{
+  GstStructure *structure;
+
+  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
+
+  structure = gst_query_get_structure (query);
+  if (src_format)
+    *src_format =
+        g_value_get_enum (gst_structure_get_value (structure, "src_format"));
+  if (src_value)
+    *src_value =
+        g_value_get_int64 (gst_structure_get_value (structure, "src_value"));
+  if (dest_format)
+    *dest_format =
+        g_value_get_enum (gst_structure_get_value (structure, "dest_format"));
+  if (dest_value)
+    *dest_value =
+        g_value_get_int64 (gst_structure_get_value (structure, "dest_value"));
+}
+
+
+GstQuery *
 gst_query_new_application (GstQueryType type, GstStructure * structure)
 {
   g_return_val_if_fail (gst_query_type_get_details (type) != NULL, NULL);
index 70d49e8..3501c47 100644 (file)
@@ -30,6 +30,7 @@
 #include <gst/gstiterator.h>
 #include <gst/gstdata.h>
 #include <gst/gststructure.h>
+#include <gst/gstformat.h>
 
 G_BEGIN_DECLS
 
@@ -129,9 +130,24 @@ GstIterator*    gst_query_type_iterate_definitions (void);
 #define         gst_query_copy(msg)            GST_QUERY (gst_data_copy (GST_DATA (msg)))
 #define         gst_query_copy_on_write(msg)   GST_QUERY (gst_data_copy_on_write (GST_DATA (msg)))
 
+/* position query */
+GstQuery*      gst_query_new_position          (GstFormat format);
+void           gst_query_set_position          (GstQuery *query, GstFormat format,
+                                                gint64 cur, gint64 end);
+void           gst_query_parse_position        (GstQuery *query, GstFormat *format,
+                                                gint64 *cur, gint64 *end);
+/* convert query */
+GstQuery*      gst_query_new_convert           (GstFormat src_fmt, gint64 value, GstFormat dest_fmt);
+void           gst_query_set_convert           (GstQuery *query, GstFormat src_format, gint64 src_value,
+                                                GstFormat dest_format, gint64 dest_value);
+void           gst_query_parse_convert         (GstQuery *query, GstFormat *src_format, gint64 *src_value,
+                                                GstFormat *dest_format, gint64 *dest_value);
+
+/* application specific query */
 GstQuery *     gst_query_new_application       (GstQueryType type,
                                                  GstStructure *structure);
 
+
 GstStructure *  gst_query_get_structure                (GstQuery *query);
 
 /* hmm */
index 25a39f5..b2ad663 100644 (file)
 
 /* some macros are just waiting to be defined here */
 
-
-GstQuery *
-gst_query_new_position (GstFormat format)
-{
-  GstStructure *structure = gst_structure_new ("query",
-      "format", GST_TYPE_FORMAT, format, NULL);
-
-  return gst_query_new_application (GST_QUERY_POSITION, structure);
-}
-
-void
-gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur,
-    gint64 end)
-{
-  GstStructure *structure;
-
-  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
-
-  structure = gst_query_get_structure (query);
-  gst_structure_set (structure,
-      "format", GST_TYPE_FORMAT, format,
-      "cur", G_TYPE_INT64, cur, "end", G_TYPE_INT64, end, NULL);
-}
-
-void
-gst_query_parse_position_query (GstQuery * query, GstFormat * format)
-{
-  GstStructure *structure;
-
-  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
-
-  structure = gst_query_get_structure (query);
-  if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
-}
-
-void
-gst_query_parse_position_response (GstQuery * query, GstFormat * format,
-    gint64 * cur, gint64 * end)
-{
-  GstStructure *structure;
-
-  g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
-
-  structure = gst_query_get_structure (query);
-  if (format)
-    *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
-  if (cur)
-    *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
-  if (end)
-    *end = g_value_get_int64 (gst_structure_get_value (structure, "end"));
-}
-
 void
 gst_query_parse_seeking_query (GstQuery * query, GstFormat * format)
 {
index d59a804..d72c165 100644 (file)
 #include <gst/gstquery.h>
 
 
-GstQuery* gst_query_new_position        (GstFormat format);
-void gst_query_set_position            (GstQuery *query, GstFormat format,
-                                         gint64 cur, gint64 end);
-void gst_query_parse_position_query    (GstQuery *query, GstFormat *format);
-void gst_query_parse_position_response (GstQuery *query, GstFormat *format,
-                                         gint64 *cur, gint64 *end);
 void gst_query_parse_seeking_query     (GstQuery *query, GstFormat *format);
 void gst_query_set_seeking             (GstQuery *query, GstFormat format,
                                          gboolean seekable, gint64 segment_start,
index 0596538..aa2b905 100644 (file)
@@ -133,8 +133,7 @@ static void gst_queue_loop (GstPad * pad);
 static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
 
 static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_queue_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value);
+static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query);
 
 static GstCaps *gst_queue_getcaps (GstPad * pad);
 static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
@@ -811,29 +810,42 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event)
 }
 
 static gboolean
-gst_queue_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value)
+gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
 {
   GstQueue *queue = GST_QUEUE (GST_PAD_PARENT (pad));
 
   if (!GST_PAD_PEER (queue->sinkpad))
     return FALSE;
-  if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), type, fmt, value))
+  if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), query))
     return FALSE;
 
-  if (type == GST_QUERY_POSITION) {
-    /* FIXME: this code assumes that there's no discont in the queue */
-    switch (*fmt) {
-      case GST_FORMAT_BYTES:
-        *value -= queue->cur_level.bytes;
-        break;
-      case GST_FORMAT_TIME:
-        *value -= queue->cur_level.time;
-        break;
-      default:
-        /* FIXME */
-        break;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+    {
+      gint64 peer_pos, peer_total;
+      GstFormat format;
+
+      /* get peer position */
+      gst_query_parse_position (query, &format, &peer_pos, &peer_total);
+
+      /* FIXME: this code assumes that there's no discont in the queue */
+      switch (format) {
+        case GST_FORMAT_BYTES:
+          peer_pos -= queue->cur_level.bytes;
+          break;
+        case GST_FORMAT_TIME:
+          peer_pos -= queue->cur_level.time;
+          break;
+        default:
+          /* FIXME */
+          break;
+      }
+      /* set updated positions */
+      gst_query_set_position (query, format, peer_pos, peer_total);
+      break;
     }
+    default:
+      break;
   }
 
   return TRUE;
index 0345bf4..e02ac8e 100644 (file)
@@ -1155,6 +1155,55 @@ gst_element_unlink (GstElement * src, GstElement * dest)
   }
 }
 
+gboolean
+gst_element_query_position (GstElement * element, GstFormat * format,
+    gint64 * cur, gint64 * end)
+{
+  GstQuery *query;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_PAD (element), FALSE);
+  g_return_val_if_fail (format != NULL, FALSE);
+
+  query = gst_query_new_position (*format);
+  ret = gst_element_query (element, query);
+
+  if (ret)
+    gst_query_parse_position (query, format, cur, end);
+
+  gst_query_unref (query);
+
+  return ret;
+}
+
+gboolean
+gst_element_query_convert (GstElement * element, GstFormat src_format,
+    gint64 src_val, GstFormat * dest_fmt, gint64 * dest_val)
+{
+  GstQuery *query;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
+  g_return_val_if_fail (dest_fmt != NULL, FALSE);
+  g_return_val_if_fail (dest_val != NULL, FALSE);
+
+  if (*dest_fmt == src_format) {
+    *dest_val = src_val;
+    return TRUE;
+  }
+
+  query = gst_query_new_convert (src_format, src_val, *dest_fmt);
+  ret = gst_element_query (element, query);
+
+  if (ret)
+    gst_query_parse_convert (query, NULL, NULL, dest_fmt, dest_val);
+
+  gst_query_unref (query);
+
+  return ret;
+}
+
+
 /**
  * gst_pad_can_link:
  * @srcpad: the source #GstPad to link.
@@ -1675,6 +1724,77 @@ gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps)
   return g_value_get_boolean (&ret);
 }
 
+/**
+ * gst_pad_query_position:
+ * @pad: a #GstPad to invoke the position query on.
+ * @format: a pointer to the #GstFormat asked for.
+ *          On return contains the #GstFormat used.
+ * @cur: A location in which to store the current position, or NULL.
+ * @end: A location in which to store the end position (length), or NULL.
+ *
+ * Queries a pad for the stream position and length.
+ *
+ * Returns: TRUE if the query could be performed.
+ */
+gboolean
+gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur,
+    gint64 * end)
+{
+  GstQuery *query;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (format != NULL, FALSE);
+
+  query = gst_query_new_position (*format);
+  ret = gst_pad_query (pad, query);
+
+  if (ret)
+    gst_query_parse_position (query, format, cur, end);
+
+  gst_query_unref (query);
+
+  return ret;
+}
+
+/**
+ * gst_pad_query_convert:
+ * @pad: a #GstPad to invoke the convert query on.
+ * @src_format: a #GstFormat to convert from.
+ * @src_val: a value to convert.
+ * @dest_format: a pointer to the #GstFormat to convert to. 
+ * @dest_val: a pointer to the result.
+ *
+ * Queries a pad to convert @src_val in @src_format to @dest_format.
+ *
+ * Returns: TRUE if the query could be performed.
+ */
+gboolean
+gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
+    GstFormat * dest_fmt, gint64 * dest_val)
+{
+  GstQuery *query;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (dest_fmt != NULL, FALSE);
+  g_return_val_if_fail (dest_val != NULL, FALSE);
+
+  if (*dest_fmt == src_format) {
+    *dest_val = src_val;
+    return TRUE;
+  }
+
+  query = gst_query_new_convert (src_format, src_val, *dest_fmt);
+  ret = gst_pad_query (pad, query);
+
+  if (ret)
+    gst_query_parse_convert (query, NULL, NULL, dest_fmt, dest_val);
+
+  gst_query_unref (query);
+
+  return ret;
+}
 
 /**
  * gst_atomic_int_set:
index d5b17ca..a278517 100644 (file)
@@ -251,10 +251,15 @@ gboolean          gst_element_link_pads           (GstElement *src, const gchar *srcpadn
                                                         GstElement *dest, const gchar *destpadname);
 void                    gst_element_unlink_pads         (GstElement *src, const gchar *srcpadname,
                                                         GstElement *dest, const gchar *destpadname);
+/* util query functions */
+gboolean                gst_element_query_position      (GstElement *element, GstFormat *format,
+                                                        gint64 *cur, gint64 *end);
+gboolean                gst_element_query_convert       (GstElement *element, GstFormat src_format, gint64 src_val,
+                                                        GstFormat *dest_fmt, gint64 *dest_val);
 
 /* element class functions */
-void gst_element_class_install_std_props (GstElementClass * klass,
-    const gchar * first_name, ...);
+void                   gst_element_class_install_std_props (GstElementClass * klass,
+                                                        const gchar * first_name, ...);
 
 /* pad functions */
 gboolean                gst_pad_can_link                (GstPad *srcpad, GstPad *sinkpad);
@@ -264,6 +269,12 @@ GstCaps*           gst_pad_get_fixed_caps_func     (GstPad *pad);
 GstCaps*               gst_pad_proxy_getcaps           (GstPad * pad);
 gboolean               gst_pad_proxy_setcaps           (GstPad * pad, GstCaps * caps);
 
+/* util query functions */
+gboolean                gst_pad_query_position          (GstPad *pad, GstFormat *format,
+                                                        gint64 *cur, gint64 *end);
+gboolean                gst_pad_query_convert           (GstPad *pad, GstFormat src_format, gint64 src_val,
+                                                        GstFormat *dest_fmt, gint64 *dest_val);
+
 /* bin functions */
 void                   gst_bin_add_many                (GstBin *bin, GstElement *element_1, ...);
 void                   gst_bin_remove_many             (GstBin *bin, GstElement *element_1, ...);
index 5031568..2d7b966 100644 (file)
@@ -89,9 +89,11 @@ static void gst_basesrc_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 static gboolean gst_basesrc_event_handler (GstPad * pad, GstEvent * event);
 
-static gboolean gst_basesrc_query2 (GstPad * pad, GstQuery * query);
+static gboolean gst_basesrc_query (GstPad * pad, GstQuery * query);
 
+#if 0
 static const GstEventMask *gst_basesrc_get_event_mask (GstPad * pad);
+#endif
 
 static gboolean gst_basesrc_unlock (GstBaseSrc * basesrc);
 static gboolean gst_basesrc_get_size (GstBaseSrc * basesrc, guint64 * size);
@@ -158,9 +160,7 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class)
 
   gst_pad_set_activate_function (pad, gst_basesrc_activate);
   gst_pad_set_event_function (pad, gst_basesrc_event_handler);
-  gst_pad_set_event_mask_function (pad, gst_basesrc_get_event_mask);
-
-  gst_pad_set_query2_function (pad, gst_basesrc_query2);
+  gst_pad_set_query_function (pad, gst_basesrc_query);
 
   gst_pad_set_checkgetrange_function (pad, gst_basesrc_check_get_range);
 
@@ -193,7 +193,7 @@ gst_basesrc_set_dataflow_funcs (GstBaseSrc * this)
 }
 
 static gboolean
-gst_basesrc_query2 (GstPad * pad, GstQuery * query)
+gst_basesrc_query (GstPad * pad, GstQuery * query)
 {
   gboolean b;
   guint64 ui64;
@@ -207,7 +207,7 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query)
     {
       GstFormat format;
 
-      gst_query_parse_position_query (query, &format);
+      gst_query_parse_position (query, &format, NULL, NULL);
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
@@ -243,10 +243,11 @@ gst_basesrc_query2 (GstPad * pad, GstQuery * query)
     case GST_QUERY_RATE:
     case GST_QUERY_CONVERT:
     default:
-      return gst_pad_query2_default (pad, query);
+      return gst_pad_query_default (pad, query);
   }
 }
 
+#if 0
 static const GstEventMask *
 gst_basesrc_get_event_mask (GstPad * pad)
 {
@@ -260,6 +261,7 @@ gst_basesrc_get_event_mask (GstPad * pad)
   };
   return masks;
 }
+#endif
 
 static gboolean
 gst_basesrc_do_seek (GstBaseSrc * src, GstEvent * event)
index c0da0e3..cc44e97 100644 (file)
@@ -80,7 +80,7 @@ static gboolean gst_filesink_event (GstBaseSink * sink, GstEvent * event);
 static GstFlowReturn gst_filesink_render (GstBaseSink * sink,
     GstBuffer * buffer);
 
-static gboolean gst_filesink_query2 (GstPad * pad, GstQuery * query);
+static gboolean gst_filesink_query (GstPad * pad, GstQuery * query);
 
 static void gst_filesink_uri_handler_init (gpointer g_iface,
     gpointer iface_data);
@@ -144,7 +144,7 @@ gst_filesink_init (GstFileSink * filesink)
 
   pad = GST_BASESINK_PAD (filesink);
 
-  gst_pad_set_query2_function (pad, gst_filesink_query2);
+  gst_pad_set_query_function (pad, gst_filesink_query);
 
   filesink->filename = NULL;
   filesink->file = NULL;
@@ -255,7 +255,7 @@ gst_filesink_close_file (GstFileSink * sink)
 }
 
 static gboolean
-gst_filesink_query2 (GstPad * pad, GstQuery * query)
+gst_filesink_query (GstPad * pad, GstQuery * query)
 {
   GstFileSink *self;
   GstFormat format;
@@ -264,7 +264,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
-      gst_query_parse_position_query (query, &format);
+      gst_query_parse_position (query, &format, NULL, NULL);
       switch (format) {
         case GST_FORMAT_DEFAULT:
         case GST_FORMAT_BYTES:
@@ -280,7 +280,7 @@ gst_filesink_query2 (GstPad * pad, GstQuery * query)
       return TRUE;
 
     default:
-      return gst_pad_query2_default (pad, query);
+      return gst_pad_query_default (pad, query);
   }
 }
 
index 0596538..aa2b905 100644 (file)
@@ -133,8 +133,7 @@ static void gst_queue_loop (GstPad * pad);
 static gboolean gst_queue_handle_sink_event (GstPad * pad, GstEvent * event);
 
 static gboolean gst_queue_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_queue_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value);
+static gboolean gst_queue_handle_src_query (GstPad * pad, GstQuery * query);
 
 static GstCaps *gst_queue_getcaps (GstPad * pad);
 static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
@@ -811,29 +810,42 @@ gst_queue_handle_src_event (GstPad * pad, GstEvent * event)
 }
 
 static gboolean
-gst_queue_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value)
+gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
 {
   GstQueue *queue = GST_QUEUE (GST_PAD_PARENT (pad));
 
   if (!GST_PAD_PEER (queue->sinkpad))
     return FALSE;
-  if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), type, fmt, value))
+  if (!gst_pad_query (GST_PAD_PEER (queue->sinkpad), query))
     return FALSE;
 
-  if (type == GST_QUERY_POSITION) {
-    /* FIXME: this code assumes that there's no discont in the queue */
-    switch (*fmt) {
-      case GST_FORMAT_BYTES:
-        *value -= queue->cur_level.bytes;
-        break;
-      case GST_FORMAT_TIME:
-        *value -= queue->cur_level.time;
-        break;
-      default:
-        /* FIXME */
-        break;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+    {
+      gint64 peer_pos, peer_total;
+      GstFormat format;
+
+      /* get peer position */
+      gst_query_parse_position (query, &format, &peer_pos, &peer_total);
+
+      /* FIXME: this code assumes that there's no discont in the queue */
+      switch (format) {
+        case GST_FORMAT_BYTES:
+          peer_pos -= queue->cur_level.bytes;
+          break;
+        case GST_FORMAT_TIME:
+          peer_pos -= queue->cur_level.time;
+          break;
+        default:
+          /* FIXME */
+          break;
+      }
+      /* set updated positions */
+      gst_query_set_position (query, format, peer_pos, peer_total);
+      break;
     }
+    default:
+      break;
   }
 
   return TRUE;
index 994e04f..5aeece8 100644 (file)
@@ -115,11 +115,13 @@ static void gst_type_find_element_set_property (GObject * object,
 static void gst_type_find_element_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
+#if 0
 static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
+#endif
+
 static gboolean gst_type_find_element_src_event (GstPad * pad,
     GstEvent * event);
-static gboolean gst_type_find_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value);
+static gboolean gst_type_find_handle_src_query (GstPad * pad, GstQuery * query);
 static GstFlowReturn push_buffer_store (GstTypeFindElement * typefind);
 
 static gboolean gst_type_find_element_handle_event (GstPad * pad,
@@ -219,8 +221,6 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
       gst_type_find_element_checkgetrange);
   gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange);
   gst_pad_set_event_function (typefind->src, gst_type_find_element_src_event);
-  gst_pad_set_event_mask_function (typefind->src,
-      gst_type_find_element_src_event_mask);
   gst_pad_set_query_function (typefind->src,
       GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
   gst_pad_use_fixed_caps (typefind->src);
@@ -295,32 +295,48 @@ gst_type_find_element_get_property (GObject * object, guint prop_id,
 }
 
 static gboolean
-gst_type_find_handle_src_query (GstPad * pad,
-    GstQueryType type, GstFormat * fmt, gint64 * value)
+gst_type_find_handle_src_query (GstPad * pad, GstQuery * query)
 {
-  GstTypeFindElement *typefind =
-      GST_TYPE_FIND_ELEMENT (gst_pad_get_parent (pad));
+  GstTypeFindElement *typefind;
   gboolean res;
 
-  res = gst_pad_query (GST_PAD_PEER (typefind->sink), type, fmt, value);
+  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
+
+  res = gst_pad_query (GST_PAD_PEER (typefind->sink), query);
   if (!res)
     return FALSE;
 
-  if (type == GST_QUERY_POSITION && typefind->store != NULL) {
-    /* FIXME: this code assumes that there's no discont in the queue */
-    switch (*fmt) {
-      case GST_FORMAT_BYTES:
-        *value -= gst_buffer_store_get_size (typefind->store, 0);
-        break;
-      default:
-        /* FIXME */
-        break;
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_POSITION:
+    {
+      gint64 peer_pos, peer_total;
+      GstFormat format;
+
+      if (typefind->store == NULL)
+        return TRUE;
+
+      gst_query_parse_position (query, &format, &peer_pos, &peer_total);
+
+      /* FIXME: this code assumes that there's no discont in the queue */
+      switch (format) {
+        case GST_FORMAT_BYTES:
+          peer_pos -= gst_buffer_store_get_size (typefind->store, 0);
+          break;
+        default:
+          /* FIXME */
+          break;
+      }
+      gst_query_set_position (query, format, peer_pos, peer_total);
+      break;
     }
+    default:
+      break;
   }
 
   return TRUE;
 }
 
+#if 0
 static const GstEventMask *
 gst_type_find_element_src_event_mask (GstPad * pad)
 {
@@ -334,6 +350,7 @@ gst_type_find_element_src_event_mask (GstPad * pad)
 
   return mask;
 }
+#endif
 
 static gboolean
 gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
@@ -462,24 +479,29 @@ find_element_get_length (gpointer data)
     return 0;
   }
   if (entry->self->stream_length == 0) {
-    typefind->stream_length_available =
-        gst_pad_query (GST_PAD_PEER (entry->self->sink), GST_QUERY_TOTAL,
-        &format, (gint64 *) & entry->self->stream_length);
-    if (format != GST_FORMAT_BYTES)
+    if (!gst_pad_query_position (GST_PAD_PEER (entry->self->sink), &format,
+            NULL, (gint64 *) & entry->self->stream_length))
+      goto no_length;
+
+    if (format != GST_FORMAT_BYTES) {
       typefind->stream_length_available = FALSE;
-    if (!typefind->stream_length_available) {
-      GST_DEBUG_OBJECT (entry->self,
-          "'%s' called get_length () but it's not available",
-          GST_PLUGIN_FEATURE_NAME (entry->factory));
-      return 0;
+      entry->self->stream_length = 0;
     } else {
       GST_DEBUG_OBJECT (entry->self,
           "'%s' called get_length () and it's %" G_GUINT64_FORMAT " bytes",
           GST_PLUGIN_FEATURE_NAME (entry->factory), entry->self->stream_length);
     }
   }
-
   return entry->self->stream_length;
+
+no_length:
+  {
+    typefind->stream_length_available = FALSE;
+    GST_DEBUG_OBJECT (entry->self,
+        "'%s' called get_length () but it's not available",
+        GST_PLUGIN_FEATURE_NAME (entry->factory));
+    return 0;
+  }
 }
 
 static gboolean
index 67b25d6..e0aca2e 100644 (file)
@@ -87,6 +87,7 @@ print_caps (const GstCaps * caps, const gchar * pfx)
   }
 }
 
+#if 0
 static void
 print_formats (const GstFormat * formats)
 {
@@ -103,6 +104,7 @@ print_formats (const GstFormat * formats)
     formats++;
   }
 }
+#endif
 
 static void
 print_query_types (const GstQueryType * types)
@@ -122,6 +124,7 @@ print_query_types (const GstQueryType * types)
 }
 
 #ifndef GST_DISABLE_ENUMTYPES
+#if 0
 static void
 print_event_masks (const GstEventMask * masks)
 {
@@ -169,6 +172,7 @@ print_event_masks (const GstEventMask * masks)
     masks++;
   }
 }
+#endif
 #else
 static void
 print_event_masks (const GstEventMask * masks)
@@ -631,20 +635,9 @@ print_pad_info (GstElement * element)
     if (realpad->getrangefunc)
       n_print ("      Has getrangefunc(): %s\n",
           GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc));
-    if (realpad->formatsfunc != gst_pad_get_formats_default) {
-      n_print ("      Supports seeking/conversion/query formats:\n");
-      print_formats (gst_pad_get_formats (GST_PAD (realpad)));
-    }
-    if (realpad->convertfunc != gst_pad_convert_default)
-      n_print ("      Has custom convertfunc(): %s\n",
-          GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc));
     if (realpad->eventfunc != gst_pad_event_default)
       n_print ("      Has custom eventfunc(): %s\n",
           GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc));
-    if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) {
-      n_print ("        Provides event masks:\n");
-      print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)));
-    }
     if (realpad->queryfunc != gst_pad_query_default)
       n_print ("      Has custom queryfunc(): %s\n",
           GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc));
index fd478a6..2548437 100644 (file)
@@ -73,6 +73,7 @@ print_caps (const GstCaps * caps, gint pfx)
   g_free (s);
 }
 
+#if 0
 static void
 print_formats (const GstFormat * formats, gint pfx)
 {
@@ -89,6 +90,7 @@ print_formats (const GstFormat * formats, gint pfx)
     formats++;
   }
 }
+#endif
 
 static void
 print_query_types (const GstQueryType * types, gint pfx)
@@ -107,6 +109,7 @@ print_query_types (const GstQueryType * types, gint pfx)
   }
 }
 
+#if 0
 static void
 print_event_masks (const GstEventMask * masks, gint pfx)
 {
@@ -156,6 +159,7 @@ print_event_masks (const GstEventMask * masks, gint pfx)
   }
 #endif
 }
+#endif
 
 static void
 output_hierarchy (GType type, gint level, gint * maxlevel)
@@ -606,24 +610,9 @@ print_element_info (GstElementFactory * factory)
       if (realpad->getrangefunc)
         PUT_STRING (4, "<get-range-based function=\"%s\"/>",
             GST_DEBUG_FUNCPTR_NAME (realpad->getrangefunc));
-      if (realpad->formatsfunc != gst_pad_get_formats_default) {
-        PUT_STRING (4, "<formats-function function=\"%s\">",
-            GST_DEBUG_FUNCPTR_NAME (realpad->formatsfunc));
-        print_formats (gst_pad_get_formats (GST_PAD (realpad)), 5);
-        PUT_END_TAG (4, "formats-function");
-      }
-      if (realpad->convertfunc != gst_pad_convert_default)
-        PUT_STRING (4, "<convert-function function=\"%s\"/>",
-            GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc));
       if (realpad->eventfunc != gst_pad_event_default)
         PUT_STRING (4, "<event-function function=\"%s\"/>",
             GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc));
-      if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) {
-        PUT_STRING (4, "<event-mask-func function=\"%s\">",
-            GST_DEBUG_FUNCPTR_NAME (realpad->eventmaskfunc));
-        print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)), 5);
-        PUT_END_TAG (4, "event-mask-func");
-      }
       if (realpad->queryfunc != gst_pad_query_default)
         PUT_STRING (4, "<query-function function=\"%s\"/>",
             GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc));