structure: add gst_structure_id_new() convenience function
[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. It is valid to pass %NULL for unwanted details.
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 #include "gstquark.h"
87
88 #define GST_EVENT_SEQNUM(e) ((GstEvent*)e)->abidata.seqnum
89
90 static void gst_event_finalize (GstEvent * event);
91 static GstEvent *_gst_event_copy (GstEvent * event);
92
93 static GstMiniObjectClass *parent_class = NULL;
94
95 void
96 _gst_event_initialize (void)
97 {
98   g_type_class_ref (gst_event_get_type ());
99   g_type_class_ref (gst_seek_flags_get_type ());
100   g_type_class_ref (gst_seek_type_get_type ());
101 }
102
103 typedef struct
104 {
105   const gint type;
106   const gchar *name;
107   GQuark quark;
108 } GstEventQuarks;
109
110 static GstEventQuarks event_quarks[] = {
111   {GST_EVENT_UNKNOWN, "unknown", 0},
112   {GST_EVENT_FLUSH_START, "flush-start", 0},
113   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
114   {GST_EVENT_EOS, "eos", 0},
115   {GST_EVENT_NEWSEGMENT, "newsegment", 0},
116   {GST_EVENT_TAG, "tag", 0},
117   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
118   {GST_EVENT_QOS, "qos", 0},
119   {GST_EVENT_SEEK, "seek", 0},
120   {GST_EVENT_NAVIGATION, "navigation", 0},
121   {GST_EVENT_LATENCY, "latency", 0},
122   {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
123   {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
124   {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
125   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
126   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
127
128   {0, NULL, 0}
129 };
130
131 /**
132  * gst_event_type_get_name:
133  * @type: the event type
134  *
135  * Get a printable name for the given event type. Do not modify or free.
136  *
137  * Returns: a reference to the static name of the event.
138  */
139 const gchar *
140 gst_event_type_get_name (GstEventType type)
141 {
142   gint i;
143
144   for (i = 0; event_quarks[i].name; i++) {
145     if (type == event_quarks[i].type)
146       return event_quarks[i].name;
147   }
148   return "unknown";
149 }
150
151 /**
152  * gst_event_type_to_quark:
153  * @type: the event type
154  *
155  * Get the unique quark for the given event type.
156  *
157  * Returns: the quark associated with the event type
158  */
159 GQuark
160 gst_event_type_to_quark (GstEventType type)
161 {
162   gint i;
163
164   for (i = 0; event_quarks[i].name; i++) {
165     if (type == event_quarks[i].type)
166       return event_quarks[i].quark;
167   }
168   return 0;
169 }
170
171 /**
172  * gst_event_type_get_flags:
173  * @type: a #GstEventType
174  *
175  * Gets the #GstEventTypeFlags associated with @type.
176  *
177  * Returns: a #GstEventTypeFlags.
178  */
179 GstEventTypeFlags
180 gst_event_type_get_flags (GstEventType type)
181 {
182   GstEventTypeFlags ret;
183
184   ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);
185
186   return ret;
187 }
188
189 #define _do_init \
190 { \
191   gint i; \
192   \
193   for (i = 0; event_quarks[i].name; i++) { \
194     event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name); \
195   } \
196 }
197
198 G_DEFINE_TYPE_WITH_CODE (GstEvent, gst_event, GST_TYPE_MINI_OBJECT, _do_init);
199
200 static void
201 gst_event_class_init (GstEventClass * klass)
202 {
203   parent_class = g_type_class_peek_parent (klass);
204
205   klass->mini_object_class.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
206   klass->mini_object_class.finalize =
207       (GstMiniObjectFinalizeFunction) gst_event_finalize;
208 }
209
210 static void
211 gst_event_init (GstEvent * event)
212 {
213   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
214 }
215
216 static void
217 gst_event_finalize (GstEvent * event)
218 {
219   g_return_if_fail (event != NULL);
220   g_return_if_fail (GST_IS_EVENT (event));
221
222   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
223       GST_EVENT_TYPE_NAME (event));
224
225   if (GST_EVENT_SRC (event)) {
226     gst_object_unref (GST_EVENT_SRC (event));
227     GST_EVENT_SRC (event) = NULL;
228   }
229   if (event->structure) {
230     gst_structure_set_parent_refcount (event->structure, NULL);
231     gst_structure_free (event->structure);
232   }
233
234   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (event));
235 }
236
237 static GstEvent *
238 _gst_event_copy (GstEvent * event)
239 {
240   GstEvent *copy;
241
242   copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
243
244   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
245   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
246   GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event);
247
248   if (GST_EVENT_SRC (event)) {
249     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
250   }
251   if (event->structure) {
252     copy->structure = gst_structure_copy (event->structure);
253     gst_structure_set_parent_refcount (copy->structure,
254         &copy->mini_object.refcount);
255   }
256   return copy;
257 }
258
259 static GstEvent *
260 gst_event_new (GstEventType type)
261 {
262   GstEvent *event;
263
264   event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
265
266   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
267       gst_event_type_get_name (type), type);
268
269   event->type = type;
270   event->src = NULL;
271   event->structure = NULL;
272   GST_EVENT_SEQNUM (event) = gst_util_seqnum_next ();
273
274   return event;
275 }
276
277 /**
278  * gst_event_new_custom:
279  * @type: The type of the new event
280  * @structure: The structure for the event. The event will take ownership of
281  * the structure.
282  *
283  * Create a new custom-typed event. This can be used for anything not
284  * handled by other event-specific functions to pass an event to another
285  * element.
286  *
287  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
288  * assigning a free number and filling in the correct direction and
289  * serialization flags.
290  *
291  * New custom events can also be created by subclassing the event type if
292  * needed.
293  *
294  * Returns: The new custom event.
295  */
296 GstEvent *
297 gst_event_new_custom (GstEventType type, GstStructure * structure)
298 {
299   GstEvent *event;
300
301   /* structure must not have a parent */
302   if (structure)
303     g_return_val_if_fail (structure->parent_refcount == NULL, NULL);
304
305   event = gst_event_new (type);
306   if (structure) {
307     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
308     event->structure = structure;
309   }
310   return event;
311 }
312
313 /**
314  * gst_event_get_structure:
315  * @event: The #GstEvent.
316  *
317  * Access the structure of the event.
318  *
319  * Returns: The structure of the event. The structure is still
320  * owned by the event, which means that you should not free it and
321  * that the pointer becomes invalid when you free the event.
322  *
323  * MT safe.
324  */
325 const GstStructure *
326 gst_event_get_structure (GstEvent * event)
327 {
328   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
329
330   return event->structure;
331 }
332
333 /**
334  * gst_event_has_name:
335  * @event: The #GstEvent.
336  * @name: name to check
337  *
338  * Checks if @event has the given @name. This function is usually used to
339  * check the name of a custom event.
340  *
341  * Returns: %TRUE if @name matches the name of the event structure.
342  *
343  * Since: 0.10.20
344  */
345 gboolean
346 gst_event_has_name (GstEvent * event, const gchar * name)
347 {
348   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
349
350   if (event->structure == NULL)
351     return FALSE;
352
353   return gst_structure_has_name (event->structure, name);
354 }
355
356 /**
357  * gst_event_get_seqnum:
358  * @event: A #GstEvent.
359  *
360  * Retrieve the sequence number of a event.
361  *
362  * Events have ever-incrementing sequence numbers, which may also be set
363  * explicitly via gst_event_set_seqnum(). Sequence numbers are typically used to
364  * indicate that a event corresponds to some other set of events or messages,
365  * for example an EOS event corresponding to a SEEK event. It is considered good
366  * practice to make this correspondence when possible, though it is not
367  * required.
368  *
369  * Note that events and messages share the same sequence number incrementor;
370  * two events or messages will never not have the same sequence number unless
371  * that correspondence was made explicitly.
372  *
373  * Returns: The event's sequence number.
374  *
375  * MT safe.
376  *
377  * Since: 0.10.22
378  */
379 guint32
380 gst_event_get_seqnum (GstEvent * event)
381 {
382   g_return_val_if_fail (GST_IS_EVENT (event), -1);
383
384   return GST_EVENT_SEQNUM (event);
385 }
386
387 /**
388  * gst_event_set_seqnum:
389  * @event: A #GstEvent.
390  * @seqnum: A sequence number.
391  *
392  * Set the sequence number of a event.
393  *
394  * This function might be called by the creator of a event to indicate that the
395  * event relates to other events or messages. See gst_event_get_seqnum() for
396  * more information.
397  *
398  * MT safe.
399  *
400  * Since: 0.10.22
401  */
402 void
403 gst_event_set_seqnum (GstEvent * event, guint32 seqnum)
404 {
405   g_return_if_fail (GST_IS_EVENT (event));
406
407   GST_EVENT_SEQNUM (event) = seqnum;
408 }
409
410 /**
411  * gst_event_new_flush_start:
412  *
413  * Allocate a new flush start event. The flush start event can be sent
414  * upstream and downstream and travels out-of-bounds with the dataflow.
415  *
416  * It marks pads as being flushing and will make them return
417  * #GST_FLOW_WRONG_STATE when used for data flow with gst_pad_push(),
418  * gst_pad_chain(), gst_pad_alloc_buffer(), gst_pad_get_range() and
419  * gst_pad_pull_range(). Any event (except a #GST_EVENT_FLUSH_STOP) received
420  * on a flushing pad will return %FALSE immediately.
421  *
422  * Elements should unlock any blocking functions and exit their streaming
423  * functions as fast as possible when this event is received.
424  *
425  * This event is typically generated after a seek to flush out all queued data
426  * in the pipeline so that the new media is played as soon as possible.
427  *
428  * Returns: A new flush start event.
429  */
430 GstEvent *
431 gst_event_new_flush_start (void)
432 {
433   return gst_event_new (GST_EVENT_FLUSH_START);
434 }
435
436 /**
437  * gst_event_new_flush_stop:
438  *
439  * Allocate a new flush stop event. The flush stop event can be sent
440  * upstream and downstream and travels out-of-bounds with the dataflow.
441  * It is typically sent after sending a FLUSH_START event to make the
442  * pads accept data again.
443  *
444  * Elements can process this event synchronized with the dataflow since
445  * the preceeding FLUSH_START event stopped the dataflow.
446  *
447  * This event is typically generated to complete a seek and to resume
448  * dataflow.
449  *
450  * Returns: A new flush stop event.
451  */
452 GstEvent *
453 gst_event_new_flush_stop (void)
454 {
455   return gst_event_new (GST_EVENT_FLUSH_STOP);
456 }
457
458 /**
459  * gst_event_new_eos:
460  *
461  * Create a new EOS event. The eos event can only travel downstream
462  * synchronized with the buffer flow. Elements that receive the EOS
463  * event on a pad can return #GST_FLOW_UNEXPECTED as a #GstFlowReturn
464  * when data after the EOS event arrives.
465  *
466  * The EOS event will travel down to the sink elements in the pipeline
467  * which will then post the #GST_MESSAGE_EOS on the bus after they have
468  * finished playing any buffered data.
469  *
470  * When all sinks have posted an EOS message, an EOS message is
471  * forwarded to the application.
472  *
473  * Returns: The new EOS event.
474  */
475 GstEvent *
476 gst_event_new_eos (void)
477 {
478   return gst_event_new (GST_EVENT_EOS);
479 }
480
481 /**
482  * gst_event_new_new_segment:
483  * @update: is this segment an update to a previous one
484  * @rate: a new rate for playback
485  * @format: The format of the segment values
486  * @start: the start value of the segment
487  * @stop: the stop value of the segment
488  * @position: stream position
489  *
490  * Allocate a new newsegment event with the given format/values tripplets
491  *
492  * This method calls gst_event_new_new_segment_full() passing a default
493  * value of 1.0 for applied_rate
494  *
495  * Returns: A new newsegment event.
496  */
497 GstEvent *
498 gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
499     gint64 start, gint64 stop, gint64 position)
500 {
501   return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
502       stop, position);
503 }
504
505 /**
506  * gst_event_parse_new_segment:
507  * @event: The event to query
508  * @update: A pointer to the update flag of the segment
509  * @rate: A pointer to the rate of the segment
510  * @format: A pointer to the format of the newsegment values
511  * @start: A pointer to store the start value in
512  * @stop: A pointer to store the stop value in
513  * @position: A pointer to store the stream time in
514  *
515  * Get the update flag, rate, format, start, stop and position in the 
516  * newsegment event. In general, gst_event_parse_new_segment_full() should
517  * be used instead of this, to also retrieve the applied_rate value of the
518  * segment. See gst_event_new_new_segment_full() for a full description 
519  * of the newsegment event.
520  */
521 void
522 gst_event_parse_new_segment (GstEvent * event, gboolean * update,
523     gdouble * rate, GstFormat * format, gint64 * start,
524     gint64 * stop, gint64 * position)
525 {
526   gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
527       stop, position);
528 }
529
530 /**
531  * gst_event_new_new_segment_full:
532  * @update: Whether this segment is an update to a previous one
533  * @rate: A new rate for playback
534  * @applied_rate: The rate factor which has already been applied
535  * @format: The format of the segment values
536  * @start: The start value of the segment
537  * @stop: The stop value of the segment
538  * @position: stream position
539  *
540  * Allocate a new newsegment event with the given format/values triplets.
541  *
542  * The newsegment event marks the range of buffers to be processed. All
543  * data not within the segment range is not to be processed. This can be
544  * used intelligently by plugins to apply more efficient methods of skipping
545  * unneeded data. The valid range is expressed with the @start and @stop
546  * values.
547  *
548  * The position value of the segment is used in conjunction with the start
549  * value to convert the buffer timestamps into the stream time. This is 
550  * usually done in sinks to report the current stream_time. 
551  * @position represents the stream_time of a buffer carrying a timestamp of 
552  * @start. @position cannot be -1.
553  *
554  * @start cannot be -1, @stop can be -1. If there
555  * is a valid @stop given, it must be greater or equal the @start, including 
556  * when the indicated playback @rate is < 0.
557  *
558  * The @applied_rate value provides information about any rate adjustment that
559  * has already been made to the timestamps and content on the buffers of the 
560  * stream. (@rate * @applied_rate) should always equal the rate that has been 
561  * requested for playback. For example, if an element has an input segment 
562  * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust 
563  * incoming timestamps and buffer content by half and output a newsegment event 
564  * with @rate of 1.0 and @applied_rate of 2.0
565  *
566  * After a newsegment event, the buffer stream time is calculated with:
567  *
568  *   position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
569  *
570  * Returns: A new newsegment event.
571  *
572  * Since: 0.10.6
573  */
574 GstEvent *
575 gst_event_new_new_segment_full (gboolean update, gdouble rate,
576     gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
577     gint64 position)
578 {
579   GstEvent *event;
580   GstStructure *structure;
581
582   g_return_val_if_fail (rate != 0.0, NULL);
583   g_return_val_if_fail (applied_rate != 0.0, NULL);
584
585   if (format == GST_FORMAT_TIME) {
586     GST_CAT_INFO (GST_CAT_EVENT,
587         "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
588         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
589         ", position %" GST_TIME_FORMAT,
590         update, rate, GST_TIME_ARGS (start),
591         GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
592   } else {
593     GST_CAT_INFO (GST_CAT_EVENT,
594         "creating newsegment update %d, rate %lf, format %s, "
595         "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
596         G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
597         stop, position);
598   }
599
600   g_return_val_if_fail (position != -1, NULL);
601   g_return_val_if_fail (start != -1, NULL);
602   if (stop != -1)
603     g_return_val_if_fail (start <= stop, NULL);
604
605   structure = gst_structure_id_new (GST_QUARK (EVENT_NEWSEGMENT),
606       GST_QUARK (UPDATE), G_TYPE_BOOLEAN, update,
607       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
608       GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, applied_rate,
609       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
610       GST_QUARK (START), G_TYPE_INT64, start,
611       GST_QUARK (STOP), G_TYPE_INT64, stop,
612       GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
613   event = gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure);
614
615   return event;
616 }
617
618 /**
619  * gst_event_parse_new_segment_full:
620  * @event: The event to query
621  * @update: A pointer to the update flag of the segment
622  * @rate: A pointer to the rate of the segment
623  * @applied_rate: A pointer to the applied_rate of the segment
624  * @format: A pointer to the format of the newsegment values
625  * @start: A pointer to store the start value in
626  * @stop: A pointer to store the stop value in
627  * @position: A pointer to store the stream time in
628  *
629  * Get the update, rate, applied_rate, format, start, stop and 
630  * position in the newsegment event. See gst_event_new_new_segment_full() 
631  * for a full description of the newsegment event.
632  *
633  * Since: 0.10.6
634  */
635 void
636 gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
637     gdouble * rate, gdouble * applied_rate, GstFormat * format,
638     gint64 * start, gint64 * stop, gint64 * position)
639 {
640   const GstStructure *structure;
641
642   g_return_if_fail (GST_IS_EVENT (event));
643   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
644
645   structure = gst_event_get_structure (event);
646   if (G_LIKELY (update))
647     *update =
648         g_value_get_boolean (gst_structure_id_get_value (structure,
649             GST_QUARK (UPDATE)));
650   if (G_LIKELY (rate))
651     *rate =
652         g_value_get_double (gst_structure_id_get_value (structure,
653             GST_QUARK (RATE)));
654   if (G_LIKELY (applied_rate))
655     *applied_rate =
656         g_value_get_double (gst_structure_id_get_value (structure,
657             GST_QUARK (APPLIED_RATE)));
658   if (G_LIKELY (format))
659     *format =
660         g_value_get_enum (gst_structure_id_get_value (structure,
661             GST_QUARK (FORMAT)));
662   if (G_LIKELY (start))
663     *start =
664         g_value_get_int64 (gst_structure_id_get_value (structure,
665             GST_QUARK (START)));
666   if (G_LIKELY (stop))
667     *stop =
668         g_value_get_int64 (gst_structure_id_get_value (structure,
669             GST_QUARK (STOP)));
670   if (G_LIKELY (position))
671     *position =
672         g_value_get_int64 (gst_structure_id_get_value (structure,
673             GST_QUARK (POSITION)));
674 }
675
676 /**
677  * gst_event_new_tag:
678  * @taglist: metadata list. The event will take ownership of @taglist.
679  *
680  * Generates a metadata tag event from the given @taglist.
681  *
682  * Returns: a new #GstEvent
683  */
684 GstEvent *
685 gst_event_new_tag (GstTagList * taglist)
686 {
687   g_return_val_if_fail (taglist != NULL, NULL);
688
689   return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
690 }
691
692 /**
693  * gst_event_parse_tag:
694  * @event: a tag event
695  * @taglist: pointer to metadata list
696  *
697  * Parses a tag @event and stores the results in the given @taglist location.
698  */
699 void
700 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
701 {
702   g_return_if_fail (GST_IS_EVENT (event));
703   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
704
705   if (taglist)
706     *taglist = (GstTagList *) event->structure;
707 }
708
709 /* buffersize event */
710 /**
711  * gst_event_new_buffer_size:
712  * @format: buffer format
713  * @minsize: minimum buffer size
714  * @maxsize: maximum buffer size
715  * @async: thread behavior
716  *
717  * Create a new buffersize event. The event is sent downstream and notifies
718  * elements that they should provide a buffer of the specified dimensions.
719  *
720  * When the @async flag is set, a thread boundary is prefered.
721  *
722  * Returns: a new #GstEvent
723  */
724 GstEvent *
725 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
726     gint64 maxsize, gboolean async)
727 {
728   GstEvent *event;
729   GstStructure *structure;
730
731   GST_CAT_INFO (GST_CAT_EVENT,
732       "creating buffersize format %s, minsize %" G_GINT64_FORMAT
733       ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
734       minsize, maxsize, async);
735
736   structure = gst_structure_id_new (GST_QUARK (EVENT_BUFFER_SIZE),
737       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
738       GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
739       GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
740       GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL);
741   event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure);
742
743   return event;
744 }
745
746 /**
747  * gst_event_parse_buffer_size:
748  * @event: The event to query
749  * @format: A pointer to store the format in
750  * @minsize: A pointer to store the minsize in
751  * @maxsize: A pointer to store the maxsize in
752  * @async: A pointer to store the async-flag in
753  *
754  * Get the format, minsize, maxsize and async-flag in the buffersize event.
755  */
756 void
757 gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
758     gint64 * minsize, gint64 * maxsize, gboolean * async)
759 {
760   const GstStructure *structure;
761
762   g_return_if_fail (GST_IS_EVENT (event));
763   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
764
765   structure = gst_event_get_structure (event);
766   if (format)
767     *format =
768         g_value_get_enum (gst_structure_id_get_value (structure,
769             GST_QUARK (FORMAT)));
770   if (minsize)
771     *minsize =
772         g_value_get_int64 (gst_structure_id_get_value (structure,
773             GST_QUARK (MINSIZE)));
774   if (maxsize)
775     *maxsize =
776         g_value_get_int64 (gst_structure_id_get_value (structure,
777             GST_QUARK (MAXSIZE)));
778   if (async)
779     *async =
780         g_value_get_boolean (gst_structure_id_get_value (structure,
781             GST_QUARK (ASYNC)));
782 }
783
784 /**
785  * gst_event_new_qos:
786  * @proportion: the proportion of the qos message
787  * @diff: The time difference of the last Clock sync
788  * @timestamp: The timestamp of the buffer
789  *
790  * Allocate a new qos event with the given values.
791  * The QOS event is generated in an element that wants an upstream
792  * element to either reduce or increase its rate because of
793  * high/low CPU load or other resource usage such as network performance.
794  * Typically sinks generate these events for each buffer they receive.
795  *
796  * @proportion indicates the real-time performance of the streaming in the
797  * element that generated the QoS event (usually the sink). The value is
798  * generally computed based on more long term statistics about the streams
799  * timestamps compared to the clock.
800  * A value < 1.0 indicates that the upstream element is producing data faster
801  * than real-time. A value > 1.0 indicates that the upstream element is not
802  * producing data fast enough. 1.0 is the ideal @proportion value. The
803  * proportion value can safely be used to lower or increase the quality of
804  * the element.
805  *
806  * @diff is the difference against the clock in running time of the last
807  * buffer that caused the element to generate the QOS event. A negative value
808  * means that the buffer with @timestamp arrived in time. A positive value
809  * indicates how late the buffer with @timestamp was.
810  *
811  * @timestamp is the timestamp of the last buffer that cause the element
812  * to generate the QOS event. It is expressed in running time and thus an ever
813  * increasing value.
814  *
815  * The upstream element can use the @diff and @timestamp values to decide
816  * whether to process more buffers. For possitive @diff, all buffers with
817  * timestamp <= @timestamp + @diff will certainly arrive late in the sink
818  * as well. A (negative) @diff value so that @timestamp + @diff would yield a
819  * result smaller than 0 is not allowed.
820  *
821  * The application can use general event probes to intercept the QoS
822  * event and implement custom application specific QoS handling.
823  *
824  * Returns: A new QOS event.
825  */
826 GstEvent *
827 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
828     GstClockTime timestamp)
829 {
830   GstEvent *event;
831   GstStructure *structure;
832
833   /* diff must be positive or timestamp + diff must be positive */
834   g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL);
835
836   GST_CAT_INFO (GST_CAT_EVENT,
837       "creating qos proportion %lf, diff %" G_GINT64_FORMAT
838       ", timestamp %" GST_TIME_FORMAT, proportion,
839       diff, GST_TIME_ARGS (timestamp));
840
841   structure = gst_structure_id_new (GST_QUARK (EVENT_QOS),
842       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
843       GST_QUARK (DIFF), G_TYPE_INT64, diff,
844       GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL);
845   event = gst_event_new_custom (GST_EVENT_QOS, structure);
846
847   return event;
848 }
849
850 /**
851  * gst_event_parse_qos:
852  * @event: The event to query
853  * @proportion: A pointer to store the proportion in
854  * @diff: A pointer to store the diff in
855  * @timestamp: A pointer to store the timestamp in
856  *
857  * Get the proportion, diff and timestamp in the qos event. See
858  * gst_event_new_qos() for more information about the different QoS values.
859  */
860 void
861 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
862     GstClockTimeDiff * diff, GstClockTime * timestamp)
863 {
864   const GstStructure *structure;
865
866   g_return_if_fail (GST_IS_EVENT (event));
867   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
868
869   structure = gst_event_get_structure (event);
870   if (proportion)
871     *proportion =
872         g_value_get_double (gst_structure_id_get_value (structure,
873             GST_QUARK (PROPORTION)));
874   if (diff)
875     *diff =
876         g_value_get_int64 (gst_structure_id_get_value (structure,
877             GST_QUARK (DIFF)));
878   if (timestamp)
879     *timestamp =
880         g_value_get_uint64 (gst_structure_id_get_value (structure,
881             GST_QUARK (TIMESTAMP)));
882 }
883
884 /**
885  * gst_event_new_seek:
886  * @rate: The new playback rate
887  * @format: The format of the seek values
888  * @flags: The optional seek flags
889  * @start_type: The type and flags for the new start position
890  * @start: The value of the new start position
891  * @stop_type: The type and flags for the new stop position
892  * @stop: The value of the new stop position
893  *
894  * Allocate a new seek event with the given parameters.
895  *
896  * The seek event configures playback of the pipeline between @start to @stop
897  * at the speed given in @rate, also called a playback segment.
898  * The @start and @stop values are expressed in @format.
899  *
900  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
901  * Negatives values means backwards playback. A value of 0.0 for the
902  * rate is not allowed and should be accomplished instead by PAUSING the
903  * pipeline.
904  *
905  * A pipeline has a default playback segment configured with a start
906  * position of 0, a stop position of -1 and a rate of 1.0. The currently
907  * configured playback segment can be queried with #GST_QUERY_SEGMENT. 
908  *
909  * @start_type and @stop_type specify how to adjust the currently configured 
910  * start and stop fields in playback segment. Adjustments can be made relative
911  * or absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE
912  * means that the position should not be updated.
913  *
914  * When the rate is positive and @start has been updated, playback will start
915  * from the newly configured start position. 
916  *
917  * For negative rates, playback will start from the newly configured stop
918  * position (if any). If the stop position if updated, it must be different from
919  * -1 for negative rates.
920  *
921  * It is not possible to seek relative to the current playback position, to do
922  * this, PAUSE the pipeline, query the current playback position with
923  * #GST_QUERY_POSITION and update the playback segment current position with a
924  * #GST_SEEK_TYPE_SET to the desired position. 
925  *
926  * Returns: A new seek event.
927  */
928 GstEvent *
929 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
930     GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop)
931 {
932   GstEvent *event;
933   GstStructure *structure;
934
935   g_return_val_if_fail (rate != 0.0, NULL);
936
937   if (format == GST_FORMAT_TIME) {
938     GST_CAT_INFO (GST_CAT_EVENT,
939         "creating seek rate %lf, format TIME, flags %d, "
940         "start_type %d, start %" GST_TIME_FORMAT ", "
941         "stop_type %d, stop %" GST_TIME_FORMAT,
942         rate, flags, start_type, GST_TIME_ARGS (start),
943         stop_type, GST_TIME_ARGS (stop));
944   } else {
945     GST_CAT_INFO (GST_CAT_EVENT,
946         "creating seek rate %lf, format %s, flags %d, "
947         "start_type %d, start %" G_GINT64_FORMAT ", "
948         "stop_type %d, stop %" G_GINT64_FORMAT,
949         rate, gst_format_get_name (format), flags, start_type, start, stop_type,
950         stop);
951   }
952
953   structure = gst_structure_id_new (GST_QUARK (EVENT_SEEK),
954       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
955       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
956       GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
957       GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
958       GST_QUARK (CUR), G_TYPE_INT64, start,
959       GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
960       GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
961   event = gst_event_new_custom (GST_EVENT_SEEK, structure);
962
963   return event;
964 }
965
966 /**
967  * gst_event_parse_seek:
968  * @event: a seek event
969  * @rate: result location for the rate
970  * @format: result location for the stream format
971  * @flags:  result location for the #GstSeekFlags
972  * @start_type: result location for the #GstSeekType of the start position
973  * @start: result location for the start postion expressed in @format
974  * @stop_type:  result location for the #GstSeekType of the stop position
975  * @stop: result location for the stop postion expressed in @format
976  *
977  * Parses a seek @event and stores the results in the given result locations.
978  */
979 void
980 gst_event_parse_seek (GstEvent * event, gdouble * rate,
981     GstFormat * format, GstSeekFlags * flags, GstSeekType * start_type,
982     gint64 * start, GstSeekType * stop_type, gint64 * stop)
983 {
984   const GstStructure *structure;
985
986   g_return_if_fail (GST_IS_EVENT (event));
987   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
988
989   structure = gst_event_get_structure (event);
990   if (rate)
991     *rate =
992         g_value_get_double (gst_structure_id_get_value (structure,
993             GST_QUARK (RATE)));
994   if (format)
995     *format =
996         g_value_get_enum (gst_structure_id_get_value (structure,
997             GST_QUARK (FORMAT)));
998   if (flags)
999     *flags =
1000         g_value_get_flags (gst_structure_id_get_value (structure,
1001             GST_QUARK (FLAGS)));
1002   if (start_type)
1003     *start_type =
1004         g_value_get_enum (gst_structure_id_get_value (structure,
1005             GST_QUARK (CUR_TYPE)));
1006   if (start)
1007     *start =
1008         g_value_get_int64 (gst_structure_id_get_value (structure,
1009             GST_QUARK (CUR)));
1010   if (stop_type)
1011     *stop_type =
1012         g_value_get_enum (gst_structure_id_get_value (structure,
1013             GST_QUARK (STOP_TYPE)));
1014   if (stop)
1015     *stop =
1016         g_value_get_int64 (gst_structure_id_get_value (structure,
1017             GST_QUARK (STOP)));
1018 }
1019
1020 /**
1021  * gst_event_new_navigation:
1022  * @structure: description of the event. The event will take ownership of the
1023  *     structure.
1024  *
1025  * Create a new navigation event from the given description.
1026  *
1027  * Returns: a new #GstEvent
1028  */
1029 GstEvent *
1030 gst_event_new_navigation (GstStructure * structure)
1031 {
1032   g_return_val_if_fail (structure != NULL, NULL);
1033
1034   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
1035 }
1036
1037 /**
1038  * gst_event_new_latency:
1039  * @latency: the new latency value
1040  *
1041  * Create a new latency event. The event is sent upstream from the sinks and
1042  * notifies elements that they should add an additional @latency to the
1043  * running time before synchronising against the clock.
1044  *
1045  * The latency is mostly used in live sinks and is always expressed in
1046  * the time format.
1047  *
1048  * Returns: a new #GstEvent
1049  *
1050  * Since: 0.10.12
1051  */
1052 GstEvent *
1053 gst_event_new_latency (GstClockTime latency)
1054 {
1055   GstEvent *event;
1056   GstStructure *structure;
1057
1058   GST_CAT_INFO (GST_CAT_EVENT,
1059       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
1060
1061   structure = gst_structure_id_new (GST_QUARK (EVENT_LATENCY),
1062       GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
1063   event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
1064
1065   return event;
1066 }
1067
1068 /**
1069  * gst_event_parse_latency:
1070  * @event: The event to query
1071  * @latency: A pointer to store the latency in.
1072  *
1073  * Get the latency in the latency event.
1074  *
1075  * Since: 0.10.12
1076  */
1077 void
1078 gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
1079 {
1080   const GstStructure *structure;
1081
1082   g_return_if_fail (GST_IS_EVENT (event));
1083   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_LATENCY);
1084
1085   structure = gst_event_get_structure (event);
1086   if (latency)
1087     *latency =
1088         g_value_get_uint64 (gst_structure_id_get_value (structure,
1089             GST_QUARK (LATENCY)));
1090 }