pad: Rename and rework the dispatcher function
authorWim Taymans <wim.taymans@collabora.co.uk>
Tue, 7 Jun 2011 08:02:06 +0000 (10:02 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 7 Jun 2011 08:02:06 +0000 (10:02 +0200)
Rename gst_pad_dispatcher() to gst_pad_forward() and make it more useful by
iterating the internal links of a pad and handling resync properly.
Add a method gst_pad_event_forward() that unconditionally forwards an event to
all internally linked pads.
Update some pad code to use the new forward function.

gst/gstpad.c
gst/gstpad.h

index 068cbcd..8a0a07f 100644 (file)
@@ -1448,8 +1448,12 @@ no_func:
 static gboolean
 gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data)
 {
-  *data = gst_pad_get_query_types (pad);
+  GstPad *peer;
 
+  if ((peer = gst_pad_get_peer (pad))) {
+    *data = gst_pad_get_query_types (peer);
+    gst_object_unref (peer);
+  }
   return TRUE;
 }
 
@@ -1457,8 +1461,8 @@ gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data)
  * gst_pad_get_query_types_default:
  * @pad: a #GstPad.
  *
- * Invoke the default dispatcher for the query types on
- * the pad.
+ * Invoke the default query types function on the pad. This function will get
+ * the supported query type from the peer of an internally linked pad of @pad.
  *
  * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
  *     of #GstQueryType, or NULL if none of the internally-linked pads has a
@@ -1471,7 +1475,7 @@ gst_pad_get_query_types_default (GstPad * pad)
 
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
 
-  gst_pad_dispatcher (pad, (GstPadDispatcherFunction)
+  gst_pad_forward (pad, (GstPadForwardFunction)
       gst_pad_get_query_types_dispatcher, &result);
 
   return result;
@@ -3086,19 +3090,30 @@ gst_pad_iterate_internal_links (GstPad * pad)
   return res;
 }
 
-static gboolean
-gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
+/**
+ * gst_pad_forward:
+ * @pad: a #GstPad
+ * @forward: a #GstPadForwardFunction
+ * @user_data: user data passed to @forward
+ *
+ * Calls @forward for all internally linked pads of @pad. This function deals with
+ * dynamically changing internal pads and will make sure that the @forward
+ * function is only called once for each pad.
+ *
+ * When @forward returns TRUE, no further pads will be processed.
+ *
+ * Returns: TRUE if one of the dispatcher functions returned TRUE.
+ */
+gboolean
+gst_pad_forward (GstPad * pad, GstPadForwardFunction forward,
+    gpointer user_data)
 {
   gboolean result = FALSE;
   GstIterator *iter;
   gboolean done = FALSE;
   GValue item = { 0, };
-  GstPad *eventpad;
   GList *pushed_pads = NULL;
 
-  GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
-      event, GST_EVENT_TYPE_NAME (event));
-
   iter = gst_pad_iterate_internal_links (pad);
 
   if (!iter)
@@ -3107,37 +3122,26 @@ gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
   while (!done) {
     switch (gst_iterator_next (iter, &item)) {
       case GST_ITERATOR_OK:
-        eventpad = g_value_get_object (&item);
+      {
+        GstPad *intpad;
+
+        intpad = g_value_get_object (&item);
 
-        /* if already pushed,  skip */
-        if (g_list_find (pushed_pads, eventpad)) {
+        /* if already pushed, skip. FIXME, find something faster to tag pads */
+        if (g_list_find (pushed_pads, intpad)) {
           g_value_reset (&item);
           break;
         }
 
-        if (GST_PAD_IS_SRC (eventpad)) {
-          /* 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 (%s) to %s:%s",
-              event, GST_EVENT_TYPE_NAME (event),
-              GST_DEBUG_PAD_NAME (eventpad));
-          gst_event_ref (event);
-          result |= 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 (%s) to one sink pad %s:%s",
-              event, GST_EVENT_TYPE_NAME (event),
-              GST_DEBUG_PAD_NAME (eventpad));
-          result = gst_pad_push_event (eventpad, event);
-          done = TRUE;
-          event = NULL;
-        }
+        GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s",
+            GST_DEBUG_PAD_NAME (intpad));
+        done = result = forward (intpad, user_data);
 
-        pushed_pads = g_list_prepend (pushed_pads, eventpad);
+        pushed_pads = g_list_prepend (pushed_pads, intpad);
 
         g_value_reset (&item);
         break;
+      }
       case GST_ITERATOR_RESYNC:
         /* We don't reset the result here because we don't push the event
          * again on pads that got the event already and because we need
@@ -3156,23 +3160,55 @@ gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
   g_value_unset (&item);
   gst_iterator_free (iter);
 
+  g_list_free (pushed_pads);
+
 no_iter:
+  return result;
+}
 
-  /* If this is a sinkpad and we don't have pads to send the event to, we
-   * return TRUE. This is so that when using the default handler on a sink
-   * element, we don't fail to push it. */
-  if (!pushed_pads)
-    result = GST_PAD_IS_SINK (pad);
+typedef struct
+{
+  GstEvent *event;
+  gboolean res;
+} EventData;
 
-  g_list_free (pushed_pads);
+static gboolean
+event_forward_func (GstPad * pad, EventData * data)
+{
+  /* 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 pushing event %p (%s) to %s:%s",
+      data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad));
 
-  /* we handled the incoming event so we unref once */
-  if (event) {
-    GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
-    gst_event_unref (event);
-  }
+  data->res |= gst_pad_push_event (pad, gst_event_ref (data->event));
 
-  return result;
+  /* don't stop */
+  return FALSE;
+}
+
+/**
+ * gst_pad_event_forward:
+ * @pad: a #GstPad
+ * @event: (transfer full): the #GstEvent to handle.
+ *
+ * Forward @event to all internally linked pads of @pad.
+ *
+ * Returns: TRUE if the event was sent succesfully.
+ */
+gboolean
+gst_pad_event_forward (GstPad * pad, GstEvent * event)
+{
+  EventData data;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  data.event = event;
+  data.res = FALSE;
+
+  gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);
+
+  return data.res;
 }
 
 /**
@@ -3180,11 +3216,14 @@ no_iter:
  * @pad: a #GstPad to call the default event handler on.
  * @event: (transfer full): the #GstEvent to handle.
  *
- * 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.
+ * Invokes the default event handler for the given pad.
+ *
+ * The EOS event will pause the task associated with @pad before it is forwarded
+ * to all internally linked pads,
+ *
+ * The CAPS event will never be forwarded.
+ *
+ * The the event is sent to all pads internally linked to @pad.
  *
  * Returns: TRUE if the event was sent succesfully.
  */
@@ -3216,7 +3255,7 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
   }
 
   if (forward)
-    result = gst_pad_event_default_dispatch (pad, event);
+    result = gst_pad_event_forward (pad, event);
   else
     gst_event_unref (event);
 
@@ -3224,76 +3263,6 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
 }
 
 /**
- * gst_pad_dispatcher:
- * @pad: a #GstPad to dispatch.
- * @dispatch: the #GstPadDispatcherFunction to call.
- * @data: (closure): gpointer user data passed to the dispatcher function.
- *
- * Invokes the given dispatcher function on each respective peer of
- * 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;
-  GstIterator *iter = NULL;
-  gboolean done = FALSE;
-  GValue item = { 0, };
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (dispatch != NULL, FALSE);
-
-  iter = gst_pad_iterate_internal_links (pad);
-
-  if (!iter)
-    goto no_iter;
-
-  while (!done) {
-    switch (gst_iterator_next (iter, &item)) {
-      case GST_ITERATOR_OK:
-      {
-        GstPad *int_pad = g_value_get_object (&item);
-        GstPad *int_peer = gst_pad_get_peer (int_pad);
-
-        if (int_peer) {
-          GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
-              GST_DEBUG_PAD_NAME (int_peer));
-          done = res = dispatch (int_peer, data);
-          gst_object_unref (int_peer);
-        } else {
-          GST_DEBUG_OBJECT (int_pad, "no peer");
-        }
-        g_value_reset (&item);
-      }
-        break;
-      case GST_ITERATOR_RESYNC:
-        gst_iterator_resync (iter);
-        break;
-      case GST_ITERATOR_ERROR:
-        done = TRUE;
-        GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
-        break;
-      case GST_ITERATOR_DONE:
-        done = TRUE;
-        break;
-    }
-  }
-  g_value_unset (&item);
-  gst_iterator_free (iter);
-
-  GST_DEBUG_OBJECT (pad, "done, result %d", res);
-
-no_iter:
-
-  return res;
-}
-
-/**
  * gst_pad_query:
  * @pad: a #GstPad to invoke the default query on.
  * @query: (transfer none): the #GstQuery to perform.
@@ -3416,8 +3385,8 @@ gst_pad_query_default (GstPad * pad, GstQuery * query)
     case GST_QUERY_RATE:
     case GST_QUERY_CONVERT:
     default:
-      return gst_pad_dispatcher
-          (pad, (GstPadDispatcherFunction) gst_pad_query, query);
+      return gst_pad_forward
+          (pad, (GstPadForwardFunction) gst_pad_peer_query, query);
   }
 }
 
index 7f0a73f..349f075 100644 (file)
@@ -459,16 +459,16 @@ typedef void                      (*GstPadFixateCapsFunction)     (GstPad *pad, GstCaps *caps);
 
 /* misc */
 /**
- * GstPadDispatcherFunction:
- * @pad: the #GstPad that is dispatched.
- * @data: the gpointer to optional user data.
+ * GstPadForwardFunction:
+ * @pad: the #GstPad that is forwarded.
+ * @user_data: the gpointer to optional user data.
  *
- * A dispatcher function is called for all internally linked pads, see
- * gst_pad_dispatcher().
+ * A forward function is called for all internally linked pads, see
+ * gst_pad_forward().
  *
  * Returns: TRUE if the dispatching procedure has to be stopped.
  */
-typedef gboolean               (*GstPadDispatcherFunction)     (GstPad *pad, gpointer data);
+typedef gboolean               (*GstPadForwardFunction)        (GstPad *pad, gpointer user_data);
 
 /**
  * GstProbeType:
@@ -912,6 +912,7 @@ GstFlowReturn               gst_pad_pull_range                      (GstPad *pad, guint64 offset, guint size,
                                                                 GstBuffer **buffer);
 gboolean               gst_pad_push_event                      (GstPad *pad, GstEvent *event);
 gboolean               gst_pad_event_default                   (GstPad *pad, GstEvent *event);
+gboolean               gst_pad_event_forward                   (GstPad *pad, GstEvent *event);
 
 /* data passing functions on pad */
 GstFlowReturn          gst_pad_chain                           (GstPad *pad, GstBuffer *buffer);
@@ -946,8 +947,8 @@ 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,
-                                                                gpointer data);
+gboolean               gst_pad_forward                         (GstPad *pad, GstPadForwardFunction forward,
+                                                                gpointer user_data);
 
 G_END_DECLS