This is the current implementation of events, based on an earlier
document, in this same directory, called "events".

Definition 
----------

The event system is designed to be a mechanism for _inter_plugin_
communication. Their scope is therefore limited in a way that they do
not serve as a way to communicate between plugins and the app (signals
and properties are still used for plugin-app communication).

Events will be generated by either a plugin or the app. It should be
possible for a plugin to generate an event on one of its pads and it
should be possible for an app to insert an event on an arbitrary pad or
element in the pipeline.


Event handling 
--------------

Events can both travel upstream or downstream. Some events, by nature,
only travel in one direction.

* downstream events

  - Travel in the same way buffers do. This includes that they are handled
    by the scheduler. The rationale is that the events should be kept
    as close to the buffers are possible.

  - plugins should check the type of the GstData passed in the _chain
    or _loop function and act appropriately. This can be done by either
    doing their own stuff or by calling the default handler.

  - are handled on the sink pad.

* upstream events

  - are handled with an event handler attached to the srcpad. A default
    handler is implemented for pads that don't implement their own 
    handler.

  - travel as fast as possible. the rationale is that a seek event should
    get to the src element ASAP.



Plugin generated events
-----------------------

We cover the range of events a plugin can generate and how they
are supposed to handle them.

* EOS

  when the plugin has no more data to push, it pushes an EOS
  event and calls gst_element_set_eos.

  _get based plugins should call gst_element_set_eos() before
  returning the EOS event.

  gst_element_set_eos() will put an element into the PAUSED state
  and will emit the eos signal to the app.

  Elements receiving the EOS event on a pad should not pull anymore
  data from that pad (in case of a loop based element).
  If the plugin cannot operate when it doesn't receive data on that
  pad, the element should go to EOS too. It does this by pushing 
  any data it might still have, to the srcpad after which it 
  pushes an EOS event on thet pad and calls gst_element_set_eos().

  The EOS event will typically originate from a source element, it 
  will eventually put all elements into the PAUSED state so that the
  pipeline stops.

  The EOS event is strictly a downstream event.

* DISCONTINUOUS

  The discontinuous event is used to indicate a discontinuity in the
  stream to downstream elements.  A disctontinuity happens for the
  following reasons:

   - a source element is sending the first buffers of a stream.
   - an element has performed a seek operation resulting in a 
     discontinuity in the data.

  elements that receive a discontinuity event should flush any state
  they might have and treat the new data as the start of new data.
  Before sending out the new data the element must send a discont event
  to the downstream element with at least a GST_FORMAT_TIME or
  GST_FORMAT_BYTES as the format/value pair (see below).

  a DISCONTINUOUS event has a flush flag. If that flag is set, the
  element should also remove any buffered data it might have.

  In addition to the flush flag, a DISCONTINUOUS event also caries up
  to GST_DISCONTINUOUS_MAX_FORMATS format/value pairs. These values
  might be used by the receiver of the event to resynchronize itself.

  elements that are using a clock must take special actions upon 
  receiving the DISCONTINUOUS event: they must call 
  gst_clock_handle_discont() with the GST_FORMAT_TIME value of
  the discont event.
  
  The DISCONTINUOUS event is strictly a downstream event.


* SEEK
 
  The seek event is used to reposition  the upstream elements to
  a new position in the media stream. 

  The seek event caries a bitwise-or of a GstFormat and a GstSeekType.

  An element receiving the seek event on its srcpad should try to
  reposition itself as closely to the requested location as possible.
  if the ACCURATE flag is set and it cannot reposition itself with
  absolute certainty, it should reposition itself well before the 
  requested position. If the ACCURATE flag is not set, the element
  is free to choose a suitable position in the stream before or after
  the requested time.

  If the flush flag is set it should make sure that it pushes the
  DISCONTINUOUS event the next time it is scheduled, clearing any
  data it might have buffered.

  The element is free to set the ACCURACY field in the event to notify
  the originator of the event of the result. If no accuracy is set, it
  defaults to FUZZY.

  The SEEK event is stricly an upstream event.
  
* QOS

  QoS is sent to indicate Quality of Service to the upstream element(s).

  The QOS event is stricly an upstream event.

* FLUSH

  A plugin can send a flush event to its src or sink peer to clear the
  buffered contents in the pipeline.


application generated events 
----------------------------

The application can insert events into the pipeline at arbitrary
places. This is done by calling gst_pad_send_event() on a pad.

An application can also insert events on any element. The element
can implement its own handler for these events or it can use
the default handler, which simply forwards the event to the first
connected sinkpad of the element. Events to an element are send using
gst_element_send_event().

This first implementation only covers inserting events on src pads
since inserting events on sinkpads needs changes to the scheduler.


* FLUSH

  A flush event is used to clear any buffered data an element might 
  have. It is a downstream and upstream event.

  Flush events are typically inserted into the pipeline by the app.
  Elements that buffer data should implement an event handler on 
  both the sink and src pads it might have and respond to the flush
  event by clearing all data they have buffered.

* SEEK

  The application can insert the seek event into the pipeline on
  a srcpad with gst_pad_send_event () or on an element with 
  gst_element_send_event().

  The semantics of the seek parameters are described above.
  

Thread safety
-------------

All upstream events can occur outside the element's thread context. 
It is not required to protect the element's data structures with
mutexes because in principal we don't support sending events to
a running threaded pipeline.

GstQueue in its current form will refuse to pass events upstream if
it is in the PLAYING state. Future versions might pass the event
on as soon as the element is scheduled again on the sinkpad.

An application cannot insert an event on an element that is PLAYING
in another thread context. It is therefore strongly recommended to
PAUSE the threaded pipeline before inserting an event.


use cases 
---------

1) filesrc ! fakesink

<< explain EOS >>


2) filesrc ! fakesink

The app wants to perform a seek on filesrc. It'll call the gst_pad_send_event()
on filesrcs src pad with the SEEK event type. The event handler will
react and change filesrcs internal status. filesrc will return a DISCONT
event before returning the buffer with the new offset.

3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }

lost of possibilities here: The app can choose to insert a seek event
on the filesrc element (byte offset), it can insert a byte/time offset
seek on the video_0 pad of mpeg2parse or it can insert a time seek event
on mpeg2decs src pad.

the event will travel upstream using the handlers and the intermediate
elements can convert the event from a time to a byte offset (possibly
using GstTimeCache to speed up things).

Filesrc will get a byte seek event on its src pad and will proceed as
in case 2.

As can be seen from this example the app will generate an event in another
context than those of the plugins, so this will need proper locking.

The app can also choose to insert a flush event on one of the src
pads. The plugins would clear their cached data and forward the event
to their upstream peer pad(s).

4)...

Insert impossible case here..




