+2006-01-26 Stefan Kost <ensonic@users.sf.net>
+
+ * docs/gst/gstreamer-sections.txt:
+ * gst/gstbin.c: (bin_element_is_src), (src_iterator_filter),
+ (gst_bin_iterate_sources), (gst_bin_send_event):
+ * gst/gstbin.h:
+ * gst/gstelement.c: (gst_element_send_event):
+ * gst/gstevent.c:
+ * gst/gstpad.c: (gst_pad_send_event):
+ added code for downstream events, reviewed docs in gstevent.c
+
2006-01-25 Julien MOUTTE <julien@moutte.net>
* libs/gst/base/gstbasesink.c: (gst_base_sink_get_position):
gst_bin_iterate_recurse
gst_bin_iterate_sinks
gst_bin_iterate_sorted
+gst_bin_iterate_sources
gst_bin_iterate_all_by_interface
<SUBSECTION>
GstMessageType types);
static void gst_bin_recalc_func (GstBin * child, gpointer data);
static gint bin_element_is_sink (GstElement * child, GstBin * bin);
+static gint bin_element_is_src (GstElement * child, GstBin * bin);
static GstIterator *gst_bin_sort_iterator_new (GstBin * bin);
return result;
}
+/* returns 0 when TRUE because this is a GCompareFunc */
+/* MT safe */
+static gint
+bin_element_is_src (GstElement * child, GstBin * bin)
+{
+ gboolean is_src = FALSE;
+
+ /* we lock the child here for the remainder of the function to
+ * get its name and flag safely. */
+ GST_OBJECT_LOCK (child);
+ if (!GST_OBJECT_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK) &&
+ !child->numsinkpads) {
+ is_src = TRUE;
+ }
+
+ GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
+ "child %s %s src", GST_OBJECT_NAME (child), is_src ? "is" : "is not");
+
+ GST_OBJECT_UNLOCK (child);
+ return is_src ? 0 : 1;
+}
+
+static gint
+src_iterator_filter (GstElement * child, GstBin * bin)
+{
+ if (bin_element_is_src (child, bin) == 0) {
+ /* returns 0 because this is a GCompareFunc */
+ return 0;
+ } else {
+ /* child carries a ref from gst_bin_iterate_elements -- drop if not passing
+ through */
+ gst_object_unref (child);
+ return 1;
+ }
+}
+
+/**
+ * gst_bin_iterate_sources:
+ * @bin: a #GstBin
+ *
+ * Gets an iterator for all elements in the bin that have the
+ * #GST_ELEMENT_IS_SRC flag set.
+ *
+ * Each element yielded by the iterator will have its refcount increased, so
+ * unref after use.
+ *
+ * MT safe. Caller owns returned value.
+ *
+ * Returns: a #GstIterator of #GstElement, or NULL
+ */
+GstIterator *
+gst_bin_iterate_sources (GstBin * bin)
+{
+ GstIterator *children;
+ GstIterator *result;
+
+ g_return_val_if_fail (GST_IS_BIN (bin), NULL);
+
+ children = gst_bin_iterate_elements (bin);
+ result = gst_iterator_filter (children,
+ (GCompareFunc) src_iterator_filter, bin);
+
+ return result;
+}
+
/*
* MT safe
*/
gboolean res = TRUE;
gboolean done = FALSE;
- iter = gst_bin_iterate_sinks (bin);
- GST_DEBUG_OBJECT (bin, "Sending event to sink children");
+ if (GST_EVENT_IS_DOWNSTREAM (event)) {
+ iter = gst_bin_iterate_sources (bin);
+ GST_DEBUG_OBJECT (bin, "Sending %s event to src children",
+ GST_EVENT_TYPE_NAME (event));
+ } else {
+ iter = gst_bin_iterate_sinks (bin);
+ GST_DEBUG_OBJECT (bin, "Sending %s event to sink children",
+ GST_EVENT_TYPE_NAME (event));
+ }
while (!done) {
gpointer data;
switch (gst_iterator_next (iter, &data)) {
case GST_ITERATOR_OK:
{
- GstElement *sink;
+ GstElement *child;
gst_event_ref (event);
- sink = GST_ELEMENT_CAST (data);
- res &= gst_element_send_event (sink, event);
- gst_object_unref (sink);
+ child = GST_ELEMENT_CAST (data);
+ res &= gst_element_send_event (child, event);
+ gst_object_unref (child);
break;
}
case GST_ITERATOR_RESYNC:
gst_iterator_resync (iter);
res = TRUE;
break;
- default:
case GST_ITERATOR_DONE:
done = TRUE;
break;
+ case GST_ITERATOR_ERROR:
+ g_assert_not_reached ();
+ break;
}
}
gst_iterator_free (iter);
GstIterator* gst_bin_iterate_recurse (GstBin *bin);
GstIterator* gst_bin_iterate_sinks (GstBin *bin);
+GstIterator* gst_bin_iterate_sources (GstBin *bin);
GstIterator* gst_bin_iterate_all_by_interface (GstBin *bin, GType interface);
G_END_DECLS
* @element: a #GstElement.
* @time: the base time to set.
*
- * Set the base time of an element. See @gst_element_get_base_time().
+ * Set the base time of an element. See gst_element_get_base_time().
*
* MT safe.
*/
oclass = GST_ELEMENT_GET_CLASS (element);
if (oclass->send_event) {
- GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send event on element %s",
- GST_ELEMENT_NAME (element));
+ GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
+ GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
result = oclass->send_event (element, event);
} else {
- GstPad *pad = gst_element_get_random_pad (element, GST_PAD_SINK);
+ GstPad *pad = GST_EVENT_IS_DOWNSTREAM (event) ?
+ gst_element_get_random_pad (element, GST_PAD_SRC) :
+ gst_element_get_random_pad (element, GST_PAD_SINK);
if (pad) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
- "pushing event to random pad %s:%s", GST_DEBUG_PAD_NAME (pad));
+ "pushing %s event to random %s pad %s:%s",
+ GST_EVENT_TYPE_NAME (event),
+ (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
+ GST_DEBUG_PAD_NAME (pad));
result = gst_pad_push_event (pad, event);
gst_object_unref (pad);
} else {
- GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send event on element %s",
- GST_ELEMENT_NAME (element));
+ GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
+ GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
}
}
return result;
/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wim.taymans@chello.be>
+ * 2005 Wim Taymans <wim@fluendo.com>
*
* gstevent.c: GstEvent subsystem
*
* a pipeline
* @see_also: #GstPad, #GstElement
*
- * The event classes are used to construct and query events.
+ * The event class provides factory methods to construct and functions query
+ * (parse) events.
*
- * Events are usually created with gst_event_new_*() which takes the extra
- * event parameters as arguments.
- * Events can be parsed with their respective gst_event_parse_*() functions.
- * The event should be unreffed with gst_event_unref().
+ * Events are usually created with gst_event_new_*() which takes event-type
+ * specific parameters as arguments.
+ * To send an event use gst_element_send_event(),gst_pad_send_event() or
+ * gst_pad_push_event().
+ * The event should be unreffed with gst_event_unref() if it has not been sent.
+ *
+ * Events that have been received can be parsed with their respective
+ * gst_event_parse_*() functions.
*
* Events are passed between elements in parallel to the data stream. Some events
* are serialized with buffers, others are not. Some events only travel downstream,
* others only upstream. Some events can travel both upstream and downstream.
*
- * The events are used to signal special conditions in the datastream such as EOS
- * or the start of a new segment. Events are also used to flush the pipeline of
- * any pending data.
- *
- * Most of the event API is used inside plugins. The application usually only
- * constructs and uses the seek event API when it wants to perform a seek in the
- * pipeline.
-
- * gst_event_new_seek() is usually used to create a seek event and it takes
- * the needed parameters for a seek event.
+ * The events are used to signal special conditions in the datastream such as
+ * EOS (end of stream) or the start of a new stream-segment.
+ * Events are also used to flush the pipeline of any pending data.
+ *
+ * Most of the event API is used inside plugins. Applications usually only
+ * construct and use seek events.
+ * To do that gst_event_new_seek() is used to create a seek event. It takes
+ * the needed parameters to specity seeking time and mode.
* <example>
* <title>performing a seek on a pipeline</title>
* <programlisting>
* </programlisting>
* </example>
*
- * Last reviewed on 2005-11-23 (0.9.5)
+ * Last reviewed on 2006-01-24 (0.10.2)
*/
#include <string.h> /* memcpy */
* mainly used by elements to send events to their peer
* elements.
*
+ * This function takes owership of the provided event so you should
+ * gst_event_ref() it if you want to reuse the event after this call.
+ *
* Returns: TRUE if the event was handled.
*
* MT safe.
* doesn't need to bother itself with this information; the core handles all
* necessary locks and checks.
*
+ * This function takes owership of the provided event so you should
+ * gst_event_ref() it if you want to reuse the event after this call.
+ *
* Returns: TRUE if the event was handled.
*/
gboolean
/* ERROR handling */
wrong_direction:
{
- g_warning ("pad %s:%s sending event in wrong direction",
- GST_DEBUG_PAD_NAME (pad));
+ g_warning ("pad %s:%s sending %s event in wrong direction",
+ GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
GST_OBJECT_UNLOCK (pad);
gst_event_unref (event);
return FALSE;