gst/gstevent.c: Rename some more @cur to @start to fix docs.
[platform/upstream/gstreamer.git] / gst / gstevent.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstevent.c: GstEvent subsystem
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:gstevent
26  * @short_description: Structure describing events that are passed up and down
27  *                     a pipeline
28  * @see_also: #GstPad, #GstElement
29  *
30  * The event class provides factory methods to construct and functions query
31  * (parse) events.
32  *
33  * Events are usually created with gst_event_new_*() which takes event-type
34  * specific parameters as arguments.
35  * To send an event application will usually use gst_element_send_event() and
36  * elements will use gst_pad_send_event() or gst_pad_push_event().
37  * The event should be unreffed with gst_event_unref() if it has not been sent.
38  *
39  * Events that have been received can be parsed with their respective 
40  * gst_event_parse_*() functions.
41  *
42  * Events are passed between elements in parallel to the data stream. Some events
43  * are serialized with buffers, others are not. Some events only travel downstream,
44  * others only upstream. Some events can travel both upstream and downstream. 
45  * 
46  * The events are used to signal special conditions in the datastream such as
47  * EOS (end of stream) or the start of a new stream-segment.
48  * Events are also used to flush the pipeline of any pending data.
49  *
50  * Most of the event API is used inside plugins. Applications usually only 
51  * construct and use seek events. 
52  * To do that gst_event_new_seek() is used to create a seek event. It takes
53  * the needed parameters to specity seeking time and mode.
54  * <example>
55  * <title>performing a seek on a pipeline</title>
56  *   <programlisting>
57  *   GstEvent *event;
58  *   gboolean result;
59  *   ...
60  *   // construct a seek event to play the media from second 2 to 5, flush
61  *   // the pipeline to decrease latency.
62  *   event = gst_event_new_seek (1.0, 
63  *      GST_FORMAT_TIME, 
64  *      GST_SEEK_FLAG_FLUSH,
65  *      GST_SEEK_TYPE_SET, 2 * GST_SECOND,
66  *      GST_SEEK_TYPE_SET, 5 * GST_SECOND);
67  *   ...
68  *   result = gst_element_send_event (pipeline, event);
69  *   if (!result)
70  *     g_warning ("seek failed");
71  *   ...
72  *   </programlisting>
73  * </example>
74  *
75  * Last reviewed on 2006-09-6 (0.10.10)
76  */
77
78
79 #include "gst_private.h"
80 #include <string.h>             /* memcpy */
81
82 #include "gstinfo.h"
83 #include "gstevent.h"
84 #include "gstenumtypes.h"
85 #include "gstutils.h"
86
87 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
88 static void gst_event_class_init (gpointer g_class, gpointer class_data);
89 static void gst_event_finalize (GstEvent * event);
90 static GstEvent *_gst_event_copy (GstEvent * event);
91
92 void
93 _gst_event_initialize (void)
94 {
95   gst_event_get_type ();
96   gst_seek_flags_get_type ();
97   gst_seek_type_get_type ();
98 }
99
100 typedef struct
101 {
102   const gint type;
103   const gchar *name;
104   GQuark quark;
105 } GstEventQuarks;
106
107 static GstEventQuarks event_quarks[] = {
108   {GST_EVENT_UNKNOWN, "unknown", 0},
109   {GST_EVENT_FLUSH_START, "flush-start", 0},
110   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
111   {GST_EVENT_EOS, "eos", 0},
112   {GST_EVENT_NEWSEGMENT, "newsegment", 0},
113   {GST_EVENT_TAG, "tag", 0},
114   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
115   {GST_EVENT_QOS, "qos", 0},
116   {GST_EVENT_SEEK, "seek", 0},
117   {GST_EVENT_NAVIGATION, "navigation", 0},
118   {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
119   {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
120   {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
121   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
122   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
123
124   {0, NULL, 0}
125 };
126
127 /**
128  * gst_event_type_get_name:
129  * @type: the event type
130  *
131  * Get a printable name for the given event type. Do not modify or free.
132  *
133  * Returns: a reference to the static name of the event.
134  */
135 const gchar *
136 gst_event_type_get_name (GstEventType type)
137 {
138   gint i;
139
140   for (i = 0; event_quarks[i].name; i++) {
141     if (type == event_quarks[i].type)
142       return event_quarks[i].name;
143   }
144   return "unknown";
145 }
146
147 /**
148  * gst_event_type_to_quark:
149  * @type: the event type
150  *
151  * Get the unique quark for the given event type.
152  *
153  * Returns: the quark associated with the event type
154  */
155 GQuark
156 gst_event_type_to_quark (GstEventType type)
157 {
158   gint i;
159
160   for (i = 0; event_quarks[i].name; i++) {
161     if (type == event_quarks[i].type)
162       return event_quarks[i].quark;
163   }
164   return 0;
165 }
166
167 /**
168  * gst_event_type_get_flags:
169  * @type: a #GstEventType
170  *
171  * Gets the #GstEventTypeFlags associated with @type.
172  *
173  * Returns: a #GstEventTypeFlags.
174  */
175 GstEventTypeFlags
176 gst_event_type_get_flags (GstEventType type)
177 {
178   GstEventTypeFlags ret;
179
180   ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);
181
182   return ret;
183 }
184
185 GType
186 gst_event_get_type (void)
187 {
188   static GType _gst_event_type = 0;
189   int i;
190
191   if (G_UNLIKELY (_gst_event_type == 0)) {
192     static const GTypeInfo event_info = {
193       sizeof (GstEventClass),
194       NULL,
195       NULL,
196       gst_event_class_init,
197       NULL,
198       NULL,
199       sizeof (GstEvent),
200       0,
201       gst_event_init,
202       NULL
203     };
204
205     _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
206         "GstEvent", &event_info, 0);
207
208     for (i = 0; event_quarks[i].name; i++) {
209       event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
210     }
211   }
212
213   return _gst_event_type;
214 }
215
216 static void
217 gst_event_class_init (gpointer g_class, gpointer class_data)
218 {
219   GstEventClass *event_class = GST_EVENT_CLASS (g_class);
220
221   event_class->mini_object_class.copy =
222       (GstMiniObjectCopyFunction) _gst_event_copy;
223   event_class->mini_object_class.finalize =
224       (GstMiniObjectFinalizeFunction) gst_event_finalize;
225 }
226
227 static void
228 gst_event_init (GTypeInstance * instance, gpointer g_class)
229 {
230   GstEvent *event;
231
232   event = GST_EVENT (instance);
233
234   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
235 }
236
237 static void
238 gst_event_finalize (GstEvent * event)
239 {
240   g_return_if_fail (event != NULL);
241   g_return_if_fail (GST_IS_EVENT (event));
242
243   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
244       GST_EVENT_TYPE_NAME (event));
245
246   if (GST_EVENT_SRC (event)) {
247     gst_object_unref (GST_EVENT_SRC (event));
248     GST_EVENT_SRC (event) = NULL;
249   }
250   if (event->structure) {
251     gst_structure_set_parent_refcount (event->structure, NULL);
252     gst_structure_free (event->structure);
253   }
254 }
255
256 static GstEvent *
257 _gst_event_copy (GstEvent * event)
258 {
259   GstEvent *copy;
260
261   copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
262
263   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
264   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
265
266   if (GST_EVENT_SRC (event)) {
267     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
268   }
269   if (event->structure) {
270     copy->structure = gst_structure_copy (event->structure);
271     gst_structure_set_parent_refcount (copy->structure,
272         &copy->mini_object.refcount);
273   }
274   return copy;
275 }
276
277 static GstEvent *
278 gst_event_new (GstEventType type)
279 {
280   GstEvent *event;
281
282   event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
283
284   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
285       gst_event_type_get_name (type), type);
286
287   event->type = type;
288   event->src = NULL;
289   event->structure = NULL;
290
291   return event;
292 }
293
294 /**
295  * gst_event_new_custom:
296  * @type: The type of the new event
297  * @structure: The structure for the event. The event will take ownership of
298  * the structure.
299  *
300  * Create a new custom-typed event. This can be used for anything not
301  * handled by other event-specific functions to pass an event to another
302  * element.
303  *
304  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
305  * assigning a free number and filling in the correct direction and
306  * serialization flags.
307  *
308  * New custom events can also be created by subclassing the event type if
309  * needed.
310  *
311  * Returns: The new custom event.
312  */
313 GstEvent *
314 gst_event_new_custom (GstEventType type, GstStructure * structure)
315 {
316   GstEvent *event;
317
318   /* structure must not have a parent */
319   if (structure)
320     g_return_val_if_fail (structure->parent_refcount == NULL, NULL);
321
322   event = gst_event_new (type);
323   if (structure) {
324     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
325     event->structure = structure;
326   }
327   return event;
328 }
329
330 /**
331  * gst_event_get_structure:
332  * @event: The #GstEvent.
333  *
334  * Access the structure of the event.
335  *
336  * Returns: The structure of the event. The structure is still
337  * owned by the event, which means that you should not free it and
338  * that the pointer becomes invalid when you free the event.
339  *
340  * MT safe.
341  */
342 const GstStructure *
343 gst_event_get_structure (GstEvent * event)
344 {
345   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
346
347   return event->structure;
348 }
349
350 /**
351  * gst_event_new_flush_start:
352  *
353  * Allocate a new flush start event. The flush start event can be send
354  * upstream and downstream and travels out-of-bounds with the dataflow.
355  *
356  * It marks pads as being flushing and will make them return
357  * #GST_FLOW_WRONG_STATE when used for data flow with gst_pad_push(),
358  * gst_pad_chain(), gst_pad_alloc_buffer(), gst_pad_get_range() and
359  * gst_pad_pull_range(). Any event (except a #GST_EVENT_FLUSH_STOP) received
360  * on a flushing pad will return %FALSE immediatly.
361  *
362  * Elements unlock and blocking functions and exit their streaming functions
363  * as fast as possible.
364  *
365  * This event is typically generated after a seek to minimize the latency
366  * after the seek.
367  *
368  * Returns: A new flush start event.
369  */
370 GstEvent *
371 gst_event_new_flush_start (void)
372 {
373   return gst_event_new (GST_EVENT_FLUSH_START);
374 }
375
376 /**
377  * gst_event_new_flush_stop:
378  *
379  * Allocate a new flush stop event. The flush start event can be send
380  * upstream and downstream and travels out-of-bounds with the dataflow.
381  * It is typically send after sending a FLUSH_START event to make the
382  * pads accept data again.
383  *
384  * Elements can process this event synchronized with the dataflow since
385  * the preceeding FLUSH_START event stopped the dataflow.
386  *
387  * This event is typically generated to complete a seek and to resume
388  * dataflow.
389  *
390  * Returns: A new flush stop event.
391  */
392 GstEvent *
393 gst_event_new_flush_stop (void)
394 {
395   return gst_event_new (GST_EVENT_FLUSH_STOP);
396 }
397
398 /**
399  * gst_event_new_eos:
400  *
401  * Create a new EOS event. The eos event can only travel downstream
402  * synchronized with the buffer flow. Elements that receive the EOS
403  * event on a pad can return #GST_FLOW_UNEXPECTED as a #GstFlowReturn
404  * when data after the EOS event arrives.
405  *
406  * The EOS event will travel down to the sink elements in the pipeline
407  * which will then post the #GST_MESSAGE_EOS on the bus after they have
408  * finished playing any buffered data.
409  *
410  * When all sinks have posted an EOS message, the EOS message is
411  * forwarded to the application.
412  *
413  * Returns: The new EOS event.
414  */
415 GstEvent *
416 gst_event_new_eos (void)
417 {
418   return gst_event_new (GST_EVENT_EOS);
419 }
420
421 /**
422  * gst_event_new_new_segment:
423  * @update: is this segment an update to a previous one
424  * @rate: a new rate for playback
425  * @format: The format of the segment values
426  * @start: the start value of the segment
427  * @stop: the stop value of the segment
428  * @position: stream position
429  *
430  * Allocate a new newsegment event with the given format/values tripplets
431  *
432  * This method calls gst_event_new_new_segment_full() passing a default
433  * value of 1.0 for applied_rate
434  *
435  * Returns: A new newsegment event.
436  */
437 GstEvent *
438 gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
439     gint64 start, gint64 stop, gint64 position)
440 {
441   return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
442       stop, position);
443 }
444
445 /**
446  * gst_event_parse_new_segment:
447  * @event: The event to query
448  * @update: A pointer to the update flag of the segment
449  * @rate: A pointer to the rate of the segment
450  * @format: A pointer to the format of the newsegment values
451  * @start: A pointer to store the start value in
452  * @stop: A pointer to store the stop value in
453  * @position: A pointer to store the stream time in
454  *
455  * Get the update flag, rate, format, start, stop and position in the 
456  * newsegment event. In general, gst_event_parse_new_segment_full() should
457  * be used instead of this, to also retrieve the applied_rate value of the
458  * segment. See gst_event_new_new_segment_full() for a full description 
459  * of the newsegment event.
460  */
461 void
462 gst_event_parse_new_segment (GstEvent * event, gboolean * update,
463     gdouble * rate, GstFormat * format, gint64 * start,
464     gint64 * stop, gint64 * position)
465 {
466   gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
467       stop, position);
468 }
469
470 /**
471  * gst_event_new_new_segment_full:
472  * @update: Whether this segment is an update to a previous one
473  * @rate: A new rate for playback
474  * @applied_rate: The rate factor which has already been applied
475  * @format: The format of the segment values
476  * @start: The start value of the segment
477  * @stop: The stop value of the segment
478  * @position: stream position
479  *
480  * Allocate a new newsegment event with the given format/values triplets.
481  *
482  * The newsegment event marks the range of buffers to be processed. All
483  * data not within the segment range is not to be processed. This can be
484  * used intelligently by plugins to apply more efficient methods of skipping
485  * unneeded data.
486  *
487  * The position value of the segment is used in conjunction with the start
488  * value to convert the buffer timestamps into the stream time. This is 
489  * usually done in sinks to report the current stream_time. 
490  * @position represents the stream_time of a buffer carrying a timestamp of 
491  * @start. @position cannot be -1.
492  *
493  * @start cannot be -1, @stop can be -1. If there
494  * is a valid @stop given, it must be greater or equal the @start, including 
495  * when the indicated playback @rate is < 0
496  *
497  * The @applied_rate value provides information about any rate adjustment that
498  * has already been made to the timestamps and content on the buffers of the 
499  * stream. (@rate * @applied_rate) should always equal the rate that has been 
500  * requested for playback. For example, if an element has an input segment 
501  * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust 
502  * incoming timestamps and buffer content by half and output a newsegment event 
503  * with @rate of 1.0 and @applied_rate of 2.0
504  *
505  * After a newsegment event, the buffer stream time is calculated with:
506  *
507  *   position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
508  *
509  * Returns: A new newsegment event.
510  *
511  * Since: 0.10.6
512  */
513 GstEvent *
514 gst_event_new_new_segment_full (gboolean update, gdouble rate,
515     gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
516     gint64 position)
517 {
518   g_return_val_if_fail (rate != 0.0, NULL);
519   g_return_val_if_fail (applied_rate != 0.0, NULL);
520
521   if (format == GST_FORMAT_TIME) {
522     GST_CAT_INFO (GST_CAT_EVENT,
523         "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
524         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
525         ", position %" GST_TIME_FORMAT,
526         update, rate, GST_TIME_ARGS (start),
527         GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
528   } else {
529     GST_CAT_INFO (GST_CAT_EVENT,
530         "creating newsegment update %d, rate %lf, format %d, "
531         "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
532         G_GINT64_FORMAT, update, rate, format, start, stop, position);
533   }
534
535   g_return_val_if_fail (position != -1, NULL);
536   g_return_val_if_fail (start != -1, NULL);
537   if (stop != -1)
538     g_return_val_if_fail (start <= stop, NULL);
539
540   return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
541       gst_structure_new ("GstEventNewsegment",
542           "update", G_TYPE_BOOLEAN, update,
543           "rate", G_TYPE_DOUBLE, rate,
544           "applied_rate", G_TYPE_DOUBLE, applied_rate,
545           "format", GST_TYPE_FORMAT, format,
546           "start", G_TYPE_INT64, start,
547           "stop", G_TYPE_INT64, stop,
548           "position", G_TYPE_INT64, position, NULL));
549 }
550
551 /**
552  * gst_event_parse_new_segment_full:
553  * @event: The event to query
554  * @update: A pointer to the update flag of the segment
555  * @rate: A pointer to the rate of the segment
556  * @applied_rate: A pointer to the applied_rate of the segment
557  * @format: A pointer to the format of the newsegment values
558  * @start: A pointer to store the start value in
559  * @stop: A pointer to store the stop value in
560  * @position: A pointer to store the stream time in
561  *
562  * Get the update, rate, applied_rate, format, start, stop and 
563  * position in the newsegment event. See gst_event_new_new_segment_full() 
564  * for a full description of the newsegment event.
565  *
566  * Since: 0.10.6
567  */
568 void
569 gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
570     gdouble * rate, gdouble * applied_rate, GstFormat * format,
571     gint64 * start, gint64 * stop, gint64 * position)
572 {
573   const GstStructure *structure;
574
575   g_return_if_fail (GST_IS_EVENT (event));
576   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
577
578   structure = gst_event_get_structure (event);
579   if (G_LIKELY (update))
580     *update =
581         g_value_get_boolean (gst_structure_get_value (structure, "update"));
582   if (G_LIKELY (rate))
583     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
584   if (G_LIKELY (applied_rate))
585     *applied_rate =
586         g_value_get_double (gst_structure_get_value (structure,
587             "applied_rate"));
588   if (G_LIKELY (format))
589     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
590   if (G_LIKELY (start))
591     *start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
592   if (G_LIKELY (stop))
593     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
594   if (G_LIKELY (position))
595     *position =
596         g_value_get_int64 (gst_structure_get_value (structure, "position"));
597 }
598
599 /**
600  * gst_event_new_tag:
601  * @taglist: metadata list
602  *
603  * Generates a metadata tag event from the given @taglist.
604  *
605  * Returns: a new #GstEvent
606  */
607 GstEvent *
608 gst_event_new_tag (GstTagList * taglist)
609 {
610   g_return_val_if_fail (taglist != NULL, NULL);
611
612   return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
613 }
614
615 /**
616  * gst_event_parse_tag:
617  * @event: a tag event
618  * @taglist: pointer to metadata list
619  *
620  * Parses a tag @event and stores the results in the given @taglist location.
621  */
622 void
623 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
624 {
625   g_return_if_fail (GST_IS_EVENT (event));
626   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
627
628   if (taglist)
629     *taglist = (GstTagList *) event->structure;
630 }
631
632 /* buffersize event */
633 /**
634  * gst_event_new_buffer_size:
635  * @format: buffer format
636  * @minsize: minimum buffer size
637  * @maxsize: maximum buffer size
638  * @async: thread behavior
639  *
640  * Create a new buffersize event. The event is sent downstream and notifies
641  * elements that they should provide a buffer of the specified dimensions.
642  *
643  * When the @async flag is set, a thread boundary is prefered.
644  *
645  * Returns: a new #GstEvent
646  */
647 GstEvent *
648 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
649     gint64 maxsize, gboolean async)
650 {
651   GST_CAT_INFO (GST_CAT_EVENT,
652       "creating buffersize format %d, minsize %" G_GINT64_FORMAT
653       ", maxsize %" G_GINT64_FORMAT ", async %d", format,
654       minsize, maxsize, async);
655
656   return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
657       gst_structure_new ("GstEventBufferSize",
658           "format", GST_TYPE_FORMAT, format,
659           "minsize", G_TYPE_INT64, minsize,
660           "maxsize", G_TYPE_INT64, maxsize,
661           "async", G_TYPE_BOOLEAN, async, NULL));
662 }
663
664 /**
665  * gst_event_parse_buffer_size:
666  * @event: The event to query
667  * @format: A pointer to store the format in
668  * @minsize: A pointer to store the minsize in
669  * @maxsize: A pointer to store the maxsize in
670  * @async: A pointer to store the async-flag in
671  *
672  * Get the format, minsize, maxsize and async-flag in the buffersize event.
673  */
674 void
675 gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
676     gint64 * minsize, gint64 * maxsize, gboolean * async)
677 {
678   const GstStructure *structure;
679
680   g_return_if_fail (GST_IS_EVENT (event));
681   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
682
683   structure = gst_event_get_structure (event);
684   if (format)
685     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
686   if (minsize)
687     *minsize =
688         g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
689   if (maxsize)
690     *maxsize =
691         g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
692   if (async)
693     *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
694 }
695
696 /**
697  * gst_event_new_qos:
698  * @proportion: the proportion of the qos message
699  * @diff: The time difference of the last Clock sync
700  * @timestamp: The timestamp of the buffer
701  *
702  * Allocate a new qos event with the given values.
703  * The QOS event is generated in an element that wants an upstream
704  * element to either reduce or increase its rate because of
705  * high/low CPU load or other resource usage such as network performance.
706  * Typically sinks generate these events for each buffer they receive.
707  *
708  * @proportion indicates the real-time performance of the streaming in the
709  * element that generated the QoS event (usually the sink). The value is
710  * generally computed based on more long term statistics about the streams
711  * timestamps compared to the clock.
712  * A value < 1.0 indicates that the upstream element is producing data faster
713  * than real-time. A value > 1.0 indicates that the upstream element is not
714  * producing data fast enough. 1.0 is the ideal @proportion value. The
715  * proportion value can safely be used to lower or increase the quality of
716  * the element.
717  *
718  * @diff is the difference against the clock in running time of the last
719  * buffer that caused the element to generate the QOS event. A negative value
720  * means that the buffer with @timestamp arrived in time. A positive value
721  * indicates how late the buffer with @timestamp was.
722  *
723  * @timestamp is the timestamp of the last buffer that cause the element
724  * to generate the QOS event. It is expressed in running time and thus an ever
725  * increasing value.
726  *
727  * The upstream element can use the @diff and @timestamp values to decide
728  * whether to process more buffers. For possitive @diff, all buffers with
729  * timestamp <= @timestamp + @diff will certainly arrive late in the sink
730  * as well. 
731  *
732  * The application can use general event probes to intercept the QoS
733  * event and implement custom application specific QoS handling.
734  *
735  * Returns: A new QOS event.
736  */
737 GstEvent *
738 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
739     GstClockTime timestamp)
740 {
741   GST_CAT_INFO (GST_CAT_EVENT,
742       "creating qos proportion %lf, diff %" G_GINT64_FORMAT
743       ", timestamp %" GST_TIME_FORMAT, proportion,
744       diff, GST_TIME_ARGS (timestamp));
745
746   return gst_event_new_custom (GST_EVENT_QOS,
747       gst_structure_new ("GstEventQOS",
748           "proportion", G_TYPE_DOUBLE, proportion,
749           "diff", G_TYPE_INT64, diff,
750           "timestamp", G_TYPE_UINT64, timestamp, NULL));
751 }
752
753 /**
754  * gst_event_parse_qos:
755  * @event: The event to query
756  * @proportion: A pointer to store the proportion in
757  * @diff: A pointer to store the diff in
758  * @timestamp: A pointer to store the timestamp in
759  *
760  * Get the proportion, diff and timestamp in the qos event. See
761  * gst_event_new_qos() for more information about the different QoS values.
762  */
763 void
764 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
765     GstClockTimeDiff * diff, GstClockTime * timestamp)
766 {
767   const GstStructure *structure;
768
769   g_return_if_fail (GST_IS_EVENT (event));
770   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
771
772   structure = gst_event_get_structure (event);
773   if (proportion)
774     *proportion =
775         g_value_get_double (gst_structure_get_value (structure, "proportion"));
776   if (diff)
777     *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
778   if (timestamp)
779     *timestamp =
780         g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
781 }
782
783 /**
784  * gst_event_new_seek:
785  * @rate: The new playback rate
786  * @format: The format of the seek values
787  * @flags: The optional seek flags
788  * @start_type: The type and flags for the new start position
789  * @start: The value of the new start position
790  * @stop_type: The type and flags for the new stop position
791  * @stop: The value of the new stop position
792  *
793  * Allocate a new seek event with the given parameters.
794  *
795  * The seek event configures playback of the pipeline between @start to @stop
796  * at the speed given in @rate, also called a playback segment.
797  * The @start and @stop values are expressed in @format.
798  *
799  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
800  * Negatives values means backwards playback. A value of 0.0 for the
801  * rate is not allowed and should be accomplished instead by PAUSING the
802  * pipeline.
803  *
804  * A pipeline has a default playback segment configured with a start
805  * position of 0, a stop position of -1 and a rate of 1.0. The currently
806  * configured playback segment can be queried with #GST_QUERY_SEGMENT. 
807  *
808  * @start_type and @stop_type specify how to adjust the currently configured 
809  * start and stop fields in @segment. Adjustments can be made relative or
810  * absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE means
811  * that the position should not be updated.
812  *
813  * When the rate is positive and @start has been updated, playback will start
814  * from the newly configured start position. For negative rates, playback will
815  * start from the newly configured stop position.
816  *
817  * It is not possible to seek relative to the current playback position, to do
818  * this, PAUSE the pipeline, query the current playback position with
819  * #GST_QUERY_POSITION and update the playback segment current position with a
820  * #GST_SEEK_TYPE_SET to the desired position.
821  *
822  * Returns: A new seek event.
823  */
824 GstEvent *
825 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
826     GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop)
827 {
828   g_return_val_if_fail (rate != 0.0, NULL);
829
830   if (format == GST_FORMAT_TIME) {
831     GST_CAT_INFO (GST_CAT_EVENT,
832         "creating seek rate %lf, format TIME, flags %d, "
833         "start_type %d, start %" GST_TIME_FORMAT ", "
834         "stop_type %d, stop %" GST_TIME_FORMAT,
835         rate, flags, start_type, GST_TIME_ARGS (start),
836         stop_type, GST_TIME_ARGS (stop));
837   } else {
838     GST_CAT_INFO (GST_CAT_EVENT,
839         "creating seek rate %lf, format %d, flags %d, "
840         "start_type %d, start %" G_GINT64_FORMAT ", "
841         "stop_type %d, stop %" G_GINT64_FORMAT,
842         rate, format, flags, start_type, start, stop_type, stop);
843   }
844
845   return gst_event_new_custom (GST_EVENT_SEEK,
846       gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
847           "format", GST_TYPE_FORMAT, format,
848           "flags", GST_TYPE_SEEK_FLAGS, flags,
849           "cur_type", GST_TYPE_SEEK_TYPE, start_type,
850           "cur", G_TYPE_INT64, start,
851           "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
852           "stop", G_TYPE_INT64, stop, NULL));
853 }
854
855 /**
856  * gst_event_parse_seek:
857  * @event: a seek event
858  * @rate: result location for the rate
859  * @format: result location for the stream format
860  * @flags:  result location for the #GstSeekFlags
861  * @start_type: result location for the #GstSeekType of the start position
862  * @start: result location for the start postion expressed in @format
863  * @stop_type:  result location for the #GstSeekType of the stop position
864  * @stop: result location for the stop postion expressed in @format
865  *
866  * Parses a seek @event and stores the results in the given result locations.
867  */
868 void
869 gst_event_parse_seek (GstEvent * event, gdouble * rate,
870     GstFormat * format, GstSeekFlags * flags, GstSeekType * start_type,
871     gint64 * start, GstSeekType * stop_type, gint64 * stop)
872 {
873   const GstStructure *structure;
874
875   g_return_if_fail (GST_IS_EVENT (event));
876   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
877
878   structure = gst_event_get_structure (event);
879   if (rate)
880     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
881   if (format)
882     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
883   if (flags)
884     *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
885   if (start_type)
886     *start_type =
887         g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
888   if (start)
889     *start = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
890   if (stop_type)
891     *stop_type =
892         g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
893   if (stop)
894     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
895 }
896
897 /**
898  * gst_event_new_navigation:
899  * @structure: description of the event
900  *
901  * Create a new navigation event from the given description.
902  *
903  * Returns: a new #GstEvent
904  */
905 GstEvent *
906 gst_event_new_navigation (GstStructure * structure)
907 {
908   g_return_val_if_fail (structure != NULL, NULL);
909
910   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
911 }