+ <sect1 id="section-events-downstream" xreflabel="Downstream events">
+ <title>Downstream events</title>
+ <para>
+ Downstream events are received through the sink pad's dataflow. Depending
+ if your element is loop or chain based you will receive events in your
+ loop/chain function as a GstData with <function>gst_pad_pull</function>
+ or directly in the function call arguments. So when receiving dataflow
+ from the sink pad you have to check first if this data chunk is an event.
+ If that's the case you check what kind of event it is to react on relevant
+ ones and then forward others dowstream using
+ <function>gst_pad_event_default</function>. Here is an example for both
+ loop and chain based elements.
+ </para>
+ <programlisting><![CDATA[
+/* Chain based element */
+static void
+gst_my_filter_chain (GstPad *pad,
+ GstData *data)
+{
+ GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
+ ...
+ if (GST_IS_EVENT (data)) {
+ GstEvent *event = GST_EVENT (data);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ /* end-of-stream, we should close down all stream leftovers here */
+ gst_my_filter_stop_processing (filter);
+ /* fall-through to default event handling */
+ default:
+ gst_pad_event_default (pad, event);
+ break;
+ }
+ return;
+ }
+ ...
+}
+
+/* Loop based element */
+static void
+gst_my_filter_loop (GstElement *element)
+{
+ GstMyFilter *filter = GST_MY_FILTER (element);
+ GstData *data = NULL;
+
+ data = gst_pad_pull (filter->sinkpad);
+
+ if (GST_IS_EVENT (data)) {
+ GstEvent *event = GST_EVENT (data);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ /* end-of-stream, we should close down all stream leftovers here */
+ gst_my_filter_stop_processing (filter);
+ /* fall-through to default event handling */
+ default:
+ gst_pad_event_default (filter->sinkpad, event);
+ break;
+ }
+ return;
+ }
+ ...
+}
+ ]]></programlisting>
+ </sect1>
+ <sect1 id="section-events-upstream" xreflabel="Upstream events">
+ <title>Upstream events</title>
+ <para>
+ Upstream events are generated by an element somewhere in the pipeline and
+ sent using the <function>gst_pad_send_event</function> function. This
+ function simply realizes the pad and call the default event handler of that
+ pad. The default event handler of pads is <function>gst_pad_event_default</function>
+ , it basically sends the event to the peer pad. So upstream events always
+ arrive on the src pad of your element and are handled by the default event
+ handler except if you override that handler to handle it yourself. There
+ are some specific cases where you have to do that :
+ </para>
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ If you have multiple sink pads in your element. In that case you will
+ have to decide which one of the sink pads you will send the event to.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If you need to handle that event locally. For example a navigation
+ event that you will want to convert before sending it upstream.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The processing you will do in that event handler does not really matter
+ but there are important rules you have to absolutely respect because
+ one broken element event handler is breaking the whole pipeline event
+ handling. Here they are :
+ </para>
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ Always forward events you won't handle upstream using the default
+ <function>gst_pad_event_default</function> method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If you are generating some new event based on the one you received
+ don't forget to gst_event_unref the event you received.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Event handler function are supposed to return TRUE or FALSE indicating
+ if the event has been handled or not. Never simply return TRUE/FALSE
+ in that handler except if you really know that you have handled that
+ event.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Here is an example of correct upstream event handling for a plugin
+ that wants to modify navigation events.
+ </para>
+ <programlisting><![CDATA[
+static gboolean
+gst_my_plugin_handle_src_event (GstPad *pad, GstEvent *event)
+{
+ GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_NAVIGATION:
+ GstEvent *new_event = gst_event_new (GST_EVENT_NAVIGATION);;
+ /* Create a new event based on received one and then send it */
+ ...
+ gst_event_unref (event);
+ return gst_pad_event_default (pad, new_event);
+ default:
+ /* Falling back to default event handling for that pad */
+ return gst_pad_event_default (pad, event);
+ }
+}
+ ]]></programlisting>
+ </sect1>