added code for downstream events, reviewed docs in gstevent.c

Original commit message from CVS:
* 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
This commit is contained in:
Stefan Kost 2006-01-26 06:57:14 +00:00
parent 8791aa4fbc
commit b352cee4f7
7 changed files with 134 additions and 31 deletions

View file

@ -1,3 +1,14 @@
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):

View file

@ -46,6 +46,7 @@ gst_bin_iterate_elements
gst_bin_iterate_recurse
gst_bin_iterate_sinks
gst_bin_iterate_sorted
gst_bin_iterate_sources
gst_bin_iterate_all_by_interface
<SUBSECTION>

View file

@ -167,6 +167,7 @@ static void bin_remove_messages (GstBin * bin, GstObject * src,
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);
@ -1143,6 +1144,71 @@ gst_bin_iterate_sinks (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
*/
@ -1788,8 +1854,15 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
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;
@ -1797,22 +1870,24 @@ gst_bin_send_event (GstElement * element, GstEvent * event)
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);

View file

@ -169,6 +169,7 @@ GstIterator* gst_bin_iterate_sorted (GstBin *bin);
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

View file

@ -446,7 +446,7 @@ gst_element_get_clock (GstElement * element)
* @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.
*/
@ -1197,21 +1197,26 @@ gst_element_send_event (GstElement * element, GstEvent * event)
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;

View file

@ -1,6 +1,7 @@
/* 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
*
@ -26,27 +27,30 @@
* 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.
* 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. 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.
* 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>
@ -68,7 +72,7 @@
* </programlisting>
* </example>
*
* Last reviewed on 2005-11-23 (0.9.5)
* Last reviewed on 2006-01-24 (0.10.2)
*/
#include <string.h> /* memcpy */

View file

@ -3526,6 +3526,9 @@ dropping:
* 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.
@ -3619,6 +3622,9 @@ not_linked:
* 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
@ -3696,8 +3702,8 @@ gst_pad_send_event (GstPad * pad, GstEvent * event)
/* 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;