segment: remove _full version
[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 events for sending
31  * and functions to query (parse) received 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 static GType _gst_event_type = 0;
89
90 typedef struct
91 {
92   const gint type;
93   const gchar *name;
94   GQuark quark;
95 } GstEventQuarks;
96
97 static GstEventQuarks event_quarks[] = {
98   {GST_EVENT_UNKNOWN, "unknown", 0},
99   {GST_EVENT_FLUSH_START, "flush-start", 0},
100   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
101   {GST_EVENT_EOS, "eos", 0},
102   {GST_EVENT_CAPS, "caps", 0},
103   {GST_EVENT_NEWSEGMENT, "newsegment", 0},
104   {GST_EVENT_TAG, "tag", 0},
105   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
106   {GST_EVENT_SINK_MESSAGE, "sink-message", 0},
107   {GST_EVENT_QOS, "qos", 0},
108   {GST_EVENT_SEEK, "seek", 0},
109   {GST_EVENT_NAVIGATION, "navigation", 0},
110   {GST_EVENT_LATENCY, "latency", 0},
111   {GST_EVENT_STEP, "step", 0},
112   {GST_EVENT_RECONFIGURE, "reconfigure", 0},
113   {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
114   {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
115   {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
116   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
117   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
118
119   {0, NULL, 0}
120 };
121
122 void
123 _gst_event_initialize (void)
124 {
125   gint i;
126
127   gst_event_get_type ();
128   g_type_class_ref (gst_seek_flags_get_type ());
129   g_type_class_ref (gst_seek_type_get_type ());
130
131   for (i = 0; event_quarks[i].name; i++) {
132     event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
133   }
134 }
135
136 /**
137  * gst_event_type_get_name:
138  * @type: the event type
139  *
140  * Get a printable name for the given event type. Do not modify or free.
141  *
142  * Returns: a reference to the static name of the event.
143  */
144 const gchar *
145 gst_event_type_get_name (GstEventType type)
146 {
147   gint i;
148
149   for (i = 0; event_quarks[i].name; i++) {
150     if (type == event_quarks[i].type)
151       return event_quarks[i].name;
152   }
153   return "unknown";
154 }
155
156 /**
157  * gst_event_type_to_quark:
158  * @type: the event type
159  *
160  * Get the unique quark for the given event type.
161  *
162  * Returns: the quark associated with the event type
163  */
164 GQuark
165 gst_event_type_to_quark (GstEventType type)
166 {
167   gint i;
168
169   for (i = 0; event_quarks[i].name; i++) {
170     if (type == event_quarks[i].type)
171       return event_quarks[i].quark;
172   }
173   return 0;
174 }
175
176 /**
177  * gst_event_type_get_flags:
178  * @type: a #GstEventType
179  *
180  * Gets the #GstEventTypeFlags associated with @type.
181  *
182  * Returns: a #GstEventTypeFlags.
183  */
184 GstEventTypeFlags
185 gst_event_type_get_flags (GstEventType type)
186 {
187   GstEventTypeFlags ret;
188
189   ret = type & ((1 << GST_EVENT_STICKY_SHIFT) - 1);
190
191   return ret;
192 }
193
194 GType
195 gst_event_get_type (void)
196 {
197   if (G_UNLIKELY (_gst_event_type == 0)) {
198     _gst_event_type = gst_mini_object_register ("GstEvent");
199   }
200   return _gst_event_type;
201 }
202
203 static void
204 _gst_event_free (GstEvent * event)
205 {
206   g_return_if_fail (event != NULL);
207   g_return_if_fail (GST_IS_EVENT (event));
208
209   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
210       GST_EVENT_TYPE_NAME (event));
211
212   if (event->structure) {
213     gst_structure_set_parent_refcount (event->structure, NULL);
214     gst_structure_free (event->structure);
215   }
216
217   g_slice_free1 (GST_MINI_OBJECT_SIZE (event), event);
218 }
219
220 static void gst_event_init (GstEvent * event, gsize size, GstEventType type);
221
222 static GstEvent *
223 _gst_event_copy (GstEvent * event)
224 {
225   GstEvent *copy;
226
227   copy = g_slice_new0 (GstEvent);
228
229   gst_event_init (copy, sizeof (GstEvent), GST_EVENT_TYPE (event));
230
231   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
232   GST_EVENT_SEQNUM (copy) = GST_EVENT_SEQNUM (event);
233
234   if (event->structure) {
235     copy->structure = gst_structure_copy (event->structure);
236     gst_structure_set_parent_refcount (copy->structure,
237         &copy->mini_object.refcount);
238   }
239   return copy;
240 }
241
242 static void
243 gst_event_init (GstEvent * event, gsize size, GstEventType type)
244 {
245   gst_mini_object_init (GST_MINI_OBJECT_CAST (event), _gst_event_type, size);
246
247   event->mini_object.copy = (GstMiniObjectCopyFunction) _gst_event_copy;
248   event->mini_object.free = (GstMiniObjectFreeFunction) _gst_event_free;
249
250   GST_EVENT_TYPE (event) = type;
251   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
252   GST_EVENT_SEQNUM (event) = gst_util_seqnum_next ();
253 }
254
255 static GstEvent *
256 gst_event_new (GstEventType type)
257 {
258   GstEvent *event;
259
260   event = g_slice_new0 (GstEvent);
261
262   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
263       gst_event_type_get_name (type), type);
264
265   gst_event_init (event, sizeof (GstEvent), type);
266
267   return event;
268 }
269
270 /**
271  * gst_event_new_custom:
272  * @type: The type of the new event
273  * @structure: (transfer full): the structure for the event. The event will
274  *     take ownership of the structure.
275  *
276  * Create a new custom-typed event. This can be used for anything not
277  * handled by other event-specific functions to pass an event to another
278  * element.
279  *
280  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
281  * assigning a free number and filling in the correct direction and
282  * serialization flags.
283  *
284  * New custom events can also be created by subclassing the event type if
285  * needed.
286  *
287  * Returns: (transfer full): the new custom event.
288  */
289 GstEvent *
290 gst_event_new_custom (GstEventType type, GstStructure * structure)
291 {
292   GstEvent *event;
293
294   /* structure must not have a parent */
295   if (structure)
296     g_return_val_if_fail (structure->parent_refcount == NULL, NULL);
297
298   event = gst_event_new (type);
299   if (structure) {
300     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
301     event->structure = structure;
302   }
303   return event;
304 }
305
306 /**
307  * gst_event_get_structure:
308  * @event: The #GstEvent.
309  *
310  * Access the structure of the event.
311  *
312  * Returns: The structure of the event. The structure is still
313  * owned by the event, which means that you should not free it and
314  * that the pointer becomes invalid when you free the event.
315  *
316  * MT safe.
317  */
318 const GstStructure *
319 gst_event_get_structure (GstEvent * event)
320 {
321   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
322
323   return event->structure;
324 }
325
326 /**
327  * gst_event_has_name:
328  * @event: The #GstEvent.
329  * @name: name to check
330  *
331  * Checks if @event has the given @name. This function is usually used to
332  * check the name of a custom event.
333  *
334  * Returns: %TRUE if @name matches the name of the event structure.
335  *
336  * Since: 0.10.20
337  */
338 gboolean
339 gst_event_has_name (GstEvent * event, const gchar * name)
340 {
341   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
342
343   if (event->structure == NULL)
344     return FALSE;
345
346   return gst_structure_has_name (event->structure, name);
347 }
348
349 /**
350  * gst_event_get_seqnum:
351  * @event: A #GstEvent.
352  *
353  * Retrieve the sequence number of a event.
354  *
355  * Events have ever-incrementing sequence numbers, which may also be set
356  * explicitly via gst_event_set_seqnum(). Sequence numbers are typically used to
357  * indicate that a event corresponds to some other set of events or messages,
358  * for example an EOS event corresponding to a SEEK event. It is considered good
359  * practice to make this correspondence when possible, though it is not
360  * required.
361  *
362  * Note that events and messages share the same sequence number incrementor;
363  * two events or messages will never not have the same sequence number unless
364  * that correspondence was made explicitly.
365  *
366  * Returns: The event's sequence number.
367  *
368  * MT safe.
369  *
370  * Since: 0.10.22
371  */
372 guint32
373 gst_event_get_seqnum (GstEvent * event)
374 {
375   g_return_val_if_fail (GST_IS_EVENT (event), -1);
376
377   return GST_EVENT_SEQNUM (event);
378 }
379
380 /**
381  * gst_event_set_seqnum:
382  * @event: A #GstEvent.
383  * @seqnum: A sequence number.
384  *
385  * Set the sequence number of a event.
386  *
387  * This function might be called by the creator of a event to indicate that the
388  * event relates to other events or messages. See gst_event_get_seqnum() for
389  * more information.
390  *
391  * MT safe.
392  *
393  * Since: 0.10.22
394  */
395 void
396 gst_event_set_seqnum (GstEvent * event, guint32 seqnum)
397 {
398   g_return_if_fail (GST_IS_EVENT (event));
399
400   GST_EVENT_SEQNUM (event) = seqnum;
401 }
402
403 /* FIXME 0.11: It would be nice to have flush events
404  * that don't reset the running time in the sinks
405  */
406
407 /**
408  * gst_event_new_flush_start:
409  *
410  * Allocate a new flush start event. The flush start event can be sent
411  * upstream and downstream and travels out-of-bounds with the dataflow.
412  *
413  * It marks pads as being flushing and will make them return
414  * #GST_FLOW_WRONG_STATE when used for data flow with gst_pad_push(),
415  * gst_pad_chain(), gst_pad_alloc_buffer(), gst_pad_get_range() and
416  * gst_pad_pull_range(). Any event (except a #GST_EVENT_FLUSH_STOP) received
417  * on a flushing pad will return %FALSE immediately.
418  *
419  * Elements should unlock any blocking functions and exit their streaming
420  * functions as fast as possible when this event is received.
421  *
422  * This event is typically generated after a seek to flush out all queued data
423  * in the pipeline so that the new media is played as soon as possible.
424  *
425  * Returns: (transfer full): a new flush start event.
426  */
427 GstEvent *
428 gst_event_new_flush_start (void)
429 {
430   return gst_event_new (GST_EVENT_FLUSH_START);
431 }
432
433 /**
434  * gst_event_new_flush_stop:
435  *
436  * Allocate a new flush stop event. The flush stop event can be sent
437  * upstream and downstream and travels serialized with the dataflow.
438  * It is typically sent after sending a FLUSH_START event to make the
439  * pads accept data again.
440  *
441  * Elements can process this event synchronized with the dataflow since
442  * the preceeding FLUSH_START event stopped the dataflow.
443  *
444  * This event is typically generated to complete a seek and to resume
445  * dataflow.
446  *
447  * Returns: (transfer full): a new flush stop event.
448  */
449 GstEvent *
450 gst_event_new_flush_stop (void)
451 {
452   return gst_event_new (GST_EVENT_FLUSH_STOP);
453 }
454
455 /**
456  * gst_event_new_eos:
457  *
458  * Create a new EOS event. The eos event can only travel downstream
459  * synchronized with the buffer flow. Elements that receive the EOS
460  * event on a pad can return #GST_FLOW_UNEXPECTED as a #GstFlowReturn
461  * when data after the EOS event arrives.
462  *
463  * The EOS event will travel down to the sink elements in the pipeline
464  * which will then post the #GST_MESSAGE_EOS on the bus after they have
465  * finished playing any buffered data.
466  *
467  * When all sinks have posted an EOS message, an EOS message is
468  * forwarded to the application.
469  *
470  * The EOS event itself will not cause any state transitions of the pipeline.
471  *
472  * Returns: (transfer full): the new EOS event.
473  */
474 GstEvent *
475 gst_event_new_eos (void)
476 {
477   return gst_event_new (GST_EVENT_EOS);
478 }
479
480 /**
481  * gst_event_new_caps:
482  * @caps: a #GstCaps
483  *
484  * Create a new CAPS event for @caps. The caps event can only travel downstream
485  * synchronized with the buffer flow and contain the format of the buffers
486  * that will follow after the event.
487  *
488  * Returns: (transfer full): the new CAPS event.
489  */
490 GstEvent *
491 gst_event_new_caps (GstCaps * caps)
492 {
493   GstEvent *event;
494
495   g_return_val_if_fail (caps != NULL && gst_caps_is_fixed (caps), NULL);
496
497   GST_CAT_INFO (GST_CAT_EVENT, "creating caps event %" GST_PTR_FORMAT, caps);
498
499   event = gst_event_new_custom (GST_EVENT_CAPS,
500       gst_structure_id_new (GST_QUARK (EVENT_CAPS),
501           GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL));
502
503   return event;
504 }
505
506 /**
507  * gst_event_parse_caps:
508  * @event: The event to parse
509  * @caps: (out): A pointer to the caps
510  *
511  * Get the caps from @event. The caps remains valid as long as @event remains
512  * valid.
513  */
514 void
515 gst_event_parse_caps (GstEvent * event, GstCaps ** caps)
516 {
517   GstStructure *structure;
518
519   g_return_if_fail (GST_IS_EVENT (event));
520   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_CAPS);
521
522   structure = event->structure;
523   if (G_LIKELY (caps))
524     *caps =
525         g_value_get_boxed (gst_structure_id_get_value (structure,
526             GST_QUARK (CAPS)));
527 }
528
529 /**
530  * gst_event_new_new_segment:
531  * @update: Whether this segment is an update to a previous one
532  * @rate: A new rate for playback
533  * @applied_rate: The rate factor which has already been applied
534  * @format: The format of the segment values
535  * @start: The start value of the segment
536  * @stop: The stop value of the segment
537  * @time: the time value of the segment
538  *
539  * Allocate a new newsegment event with the given format/values triplets.
540  *
541  * The newsegment event marks the range of buffers to be processed. All
542  * data not within the segment range is not to be processed. This can be
543  * used intelligently by plugins to apply more efficient methods of skipping
544  * unneeded data. The valid range is expressed with the @start and @stop
545  * values.
546  *
547  * The time value of the segment is used in conjunction with the start
548  * value to convert the buffer timestamps into the stream time. This is 
549  * usually done in sinks to report the current stream_time. 
550  * @time represents the stream_time of a buffer carrying a timestamp of 
551  * @start. @time cannot be -1.
552  *
553  * @start cannot be -1, @stop can be -1. If there
554  * is a valid @stop given, it must be greater or equal the @start, including 
555  * when the indicated playback @rate is < 0.
556  *
557  * The @applied_rate value provides information about any rate adjustment that
558  * has already been made to the timestamps and content on the buffers of the 
559  * stream. (@rate * @applied_rate) should always equal the rate that has been 
560  * requested for playback. For example, if an element has an input segment 
561  * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust 
562  * incoming timestamps and buffer content by half and output a newsegment event 
563  * with @rate of 1.0 and @applied_rate of 2.0
564  *
565  * After a newsegment event, the buffer stream time is calculated with:
566  *
567  *   time + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
568  *
569  * Returns: (transfer full): a new newsegment event.
570  *
571  * Since: 0.10.6
572  */
573 GstEvent *
574 gst_event_new_new_segment (gboolean update, gdouble rate,
575     gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
576     gint64 time)
577 {
578   GstEvent *event;
579   GstStructure *structure;
580
581   g_return_val_if_fail (rate != 0.0, NULL);
582   g_return_val_if_fail (applied_rate != 0.0, NULL);
583
584   if (format == GST_FORMAT_TIME) {
585     GST_CAT_INFO (GST_CAT_EVENT,
586         "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
587         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
588         ", time %" GST_TIME_FORMAT,
589         update, rate, GST_TIME_ARGS (start),
590         GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
591   } else {
592     GST_CAT_INFO (GST_CAT_EVENT,
593         "creating newsegment update %d, rate %lf, format %s, "
594         "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", time %"
595         G_GINT64_FORMAT, update, rate, gst_format_get_name (format), start,
596         stop, time);
597   }
598
599   g_return_val_if_fail (time != -1, NULL);
600   g_return_val_if_fail (start != -1, NULL);
601   if (stop != -1)
602     g_return_val_if_fail (start <= stop, NULL);
603
604   structure = gst_structure_id_new (GST_QUARK (EVENT_NEWSEGMENT),
605       GST_QUARK (UPDATE), G_TYPE_BOOLEAN, update,
606       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
607       GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, applied_rate,
608       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
609       GST_QUARK (START), G_TYPE_INT64, start,
610       GST_QUARK (STOP), G_TYPE_INT64, stop,
611       GST_QUARK (TIME), G_TYPE_INT64, time, NULL);
612   event = gst_event_new_custom (GST_EVENT_NEWSEGMENT, structure);
613
614   return event;
615 }
616
617 /**
618  * gst_event_parse_new_segment:
619  * @event: The event to query
620  * @update: (out): A pointer to the update flag of the segment
621  * @rate: (out): A pointer to the rate of the segment
622  * @applied_rate: (out): A pointer to the applied_rate of the segment
623  * @format: (out): A pointer to the format of the newsegment values
624  * @start: (out): A pointer to store the start value in
625  * @stop: (out): A pointer to store the stop value in
626  * @time: (out): A pointer to store the time value in
627  *
628  * Get the update, rate, applied_rate, format, start, stop and 
629  * time in the newsegment event. See gst_event_new_new_segment() 
630  * for a full description of the newsegment event.
631  *
632  * Since: 0.10.6
633  */
634 void
635 gst_event_parse_new_segment (GstEvent * event, gboolean * update,
636     gdouble * rate, gdouble * applied_rate, GstFormat * format,
637     gint64 * start, gint64 * stop, gint64 * time)
638 {
639   const GstStructure *structure;
640
641   g_return_if_fail (GST_IS_EVENT (event));
642   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
643
644   structure = event->structure;
645   if (G_LIKELY (update))
646     *update =
647         g_value_get_boolean (gst_structure_id_get_value (structure,
648             GST_QUARK (UPDATE)));
649   if (G_LIKELY (rate))
650     *rate =
651         g_value_get_double (gst_structure_id_get_value (structure,
652             GST_QUARK (RATE)));
653   if (G_LIKELY (applied_rate))
654     *applied_rate =
655         g_value_get_double (gst_structure_id_get_value (structure,
656             GST_QUARK (APPLIED_RATE)));
657   if (G_LIKELY (format))
658     *format =
659         g_value_get_enum (gst_structure_id_get_value (structure,
660             GST_QUARK (FORMAT)));
661   if (G_LIKELY (start))
662     *start =
663         g_value_get_int64 (gst_structure_id_get_value (structure,
664             GST_QUARK (START)));
665   if (G_LIKELY (stop))
666     *stop =
667         g_value_get_int64 (gst_structure_id_get_value (structure,
668             GST_QUARK (STOP)));
669   if (G_LIKELY (time))
670     *time =
671         g_value_get_int64 (gst_structure_id_get_value (structure,
672             GST_QUARK (TIME)));
673 }
674
675 /**
676  * gst_event_new_tag:
677  * @taglist: (transfer full): metadata list. The event will take ownership
678  *     of the taglist.
679  *
680  * Generates a metadata tag event from the given @taglist.
681  *
682  * Returns: (transfer full): 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: (out) (transfer none): pointer to metadata list
696  *
697  * Parses a tag @event and stores the results in the given @taglist location.
698  * No reference to the taglist will be returned, it remains valid only until
699  * the @event is freed. Don't modify or free the taglist, make a copy if you
700  * want to modify it or store it for later use.
701  */
702 void
703 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
704 {
705   g_return_if_fail (GST_IS_EVENT (event));
706   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
707
708   if (taglist)
709     *taglist = (GstTagList *) event->structure;
710 }
711
712 /* buffersize event */
713 /**
714  * gst_event_new_buffer_size:
715  * @format: buffer format
716  * @minsize: minimum buffer size
717  * @maxsize: maximum buffer size
718  * @async: thread behavior
719  *
720  * Create a new buffersize event. The event is sent downstream and notifies
721  * elements that they should provide a buffer of the specified dimensions.
722  *
723  * When the @async flag is set, a thread boundary is prefered.
724  *
725  * Returns: (transfer full): a new #GstEvent
726  */
727 GstEvent *
728 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
729     gint64 maxsize, gboolean async)
730 {
731   GstEvent *event;
732   GstStructure *structure;
733
734   GST_CAT_INFO (GST_CAT_EVENT,
735       "creating buffersize format %s, minsize %" G_GINT64_FORMAT
736       ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
737       minsize, maxsize, async);
738
739   structure = gst_structure_id_new (GST_QUARK (EVENT_BUFFER_SIZE),
740       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
741       GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
742       GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
743       GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL);
744   event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure);
745
746   return event;
747 }
748
749 /**
750  * gst_event_parse_buffer_size:
751  * @event: The event to query
752  * @format: (out): A pointer to store the format in
753  * @minsize: (out): A pointer to store the minsize in
754  * @maxsize: (out): A pointer to store the maxsize in
755  * @async: (out): A pointer to store the async-flag in
756  *
757  * Get the format, minsize, maxsize and async-flag in the buffersize event.
758  */
759 void
760 gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
761     gint64 * minsize, gint64 * maxsize, gboolean * async)
762 {
763   const GstStructure *structure;
764
765   g_return_if_fail (GST_IS_EVENT (event));
766   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
767
768   structure = event->structure;
769   if (format)
770     *format =
771         g_value_get_enum (gst_structure_id_get_value (structure,
772             GST_QUARK (FORMAT)));
773   if (minsize)
774     *minsize =
775         g_value_get_int64 (gst_structure_id_get_value (structure,
776             GST_QUARK (MINSIZE)));
777   if (maxsize)
778     *maxsize =
779         g_value_get_int64 (gst_structure_id_get_value (structure,
780             GST_QUARK (MAXSIZE)));
781   if (async)
782     *async =
783         g_value_get_boolean (gst_structure_id_get_value (structure,
784             GST_QUARK (ASYNC)));
785 }
786
787 /**
788  * gst_event_new_qos:
789  * @proportion: the proportion of the qos message
790  * @diff: The time difference of the last Clock sync
791  * @timestamp: The timestamp of the buffer
792  *
793  * Allocate a new qos event with the given values. This function calls
794  * gst_event_new_qos_full() with the type set to #GST_QOS_TYPE_OVERFLOW
795  * when diff is negative (buffers are in time) and #GST_QOS_TYPE_UNDERFLOW
796  * when @diff is positive (buffers are late).
797  *
798  * Returns: (transfer full): a new QOS event.
799  */
800 GstEvent *
801 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
802     GstClockTime timestamp)
803 {
804   GstQOSType type;
805
806   if (diff <= 0)
807     type = GST_QOS_TYPE_OVERFLOW;
808   else
809     type = GST_QOS_TYPE_UNDERFLOW;
810
811   return gst_event_new_qos_full (type, proportion, diff, timestamp);
812 }
813
814 /**
815  * gst_event_new_qos_full:
816  * @type: the QoS type
817  * @proportion: the proportion of the qos message
818  * @diff: The time difference of the last Clock sync
819  * @timestamp: The timestamp of the buffer
820  *
821  * Allocate a new qos event with the given values.
822  * The QOS event is generated in an element that wants an upstream
823  * element to either reduce or increase its rate because of
824  * high/low CPU load or other resource usage such as network performance or
825  * throttling. Typically sinks generate these events for each buffer
826  * they receive.
827  *
828  * @type indicates the reason for the QoS event. #GST_QOS_TYPE_OVERFLOW is
829  * used when a buffer arrived in time or when the sink cannot keep up with
830  * the upstream datarate. #GST_QOS_TYPE_UNDERFLOW is when the sink is not
831  * receiving buffers fast enough and thus has to drop late buffers. 
832  * #GST_QOS_TYPE_THROTTLE is used when the datarate is artificially limited
833  * by the application, for example to reduce power consumption.
834  *
835  * @proportion indicates the real-time performance of the streaming in the
836  * element that generated the QoS event (usually the sink). The value is
837  * generally computed based on more long term statistics about the streams
838  * timestamps compared to the clock.
839  * A value < 1.0 indicates that the upstream element is producing data faster
840  * than real-time. A value > 1.0 indicates that the upstream element is not
841  * producing data fast enough. 1.0 is the ideal @proportion value. The
842  * proportion value can safely be used to lower or increase the quality of
843  * the element.
844  *
845  * @diff is the difference against the clock in running time of the last
846  * buffer that caused the element to generate the QOS event. A negative value
847  * means that the buffer with @timestamp arrived in time. A positive value
848  * indicates how late the buffer with @timestamp was. When throttling is
849  * enabled, @diff will be set to the requested throttling interval.
850  *
851  * @timestamp is the timestamp of the last buffer that cause the element
852  * to generate the QOS event. It is expressed in running time and thus an ever
853  * increasing value.
854  *
855  * The upstream element can use the @diff and @timestamp values to decide
856  * whether to process more buffers. For possitive @diff, all buffers with
857  * timestamp <= @timestamp + @diff will certainly arrive late in the sink
858  * as well. A (negative) @diff value so that @timestamp + @diff would yield a
859  * result smaller than 0 is not allowed.
860  *
861  * The application can use general event probes to intercept the QoS
862  * event and implement custom application specific QoS handling.
863  *
864  * Returns: (transfer full): a new QOS event.
865  *
866  * Since: 0.10.33
867  */
868 GstEvent *
869 gst_event_new_qos_full (GstQOSType type, gdouble proportion,
870     GstClockTimeDiff diff, GstClockTime timestamp)
871 {
872   GstEvent *event;
873   GstStructure *structure;
874
875   /* diff must be positive or timestamp + diff must be positive */
876   g_return_val_if_fail (diff >= 0 || -diff <= timestamp, NULL);
877
878   GST_CAT_INFO (GST_CAT_EVENT,
879       "creating qos type %d, proportion %lf, diff %" G_GINT64_FORMAT
880       ", timestamp %" GST_TIME_FORMAT, type, proportion,
881       diff, GST_TIME_ARGS (timestamp));
882
883   structure = gst_structure_id_new (GST_QUARK (EVENT_QOS),
884       GST_QUARK (TYPE), GST_TYPE_QOS_TYPE, type,
885       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
886       GST_QUARK (DIFF), G_TYPE_INT64, diff,
887       GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL);
888   event = gst_event_new_custom (GST_EVENT_QOS, structure);
889
890   return event;
891 }
892
893 /**
894  * gst_event_parse_qos:
895  * @event: The event to query
896  * @proportion: (out): A pointer to store the proportion in
897  * @diff: (out): A pointer to store the diff in
898  * @timestamp: (out): A pointer to store the timestamp in
899  *
900  * Get the proportion, diff and timestamp in the qos event. See
901  * gst_event_new_qos() for more information about the different QoS values.
902  */
903 void
904 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
905     GstClockTimeDiff * diff, GstClockTime * timestamp)
906 {
907   gst_event_parse_qos_full (event, NULL, proportion, diff, timestamp);
908 }
909
910 /**
911  * gst_event_parse_qos_full:
912  * @event: The event to query
913  * @type: (out): A pointer to store the QoS type in
914  * @proportion: (out): A pointer to store the proportion in
915  * @diff: (out): A pointer to store the diff in
916  * @timestamp: (out): A pointer to store the timestamp in
917  *
918  * Get the type, proportion, diff and timestamp in the qos event. See
919  * gst_event_new_qos_full() for more information about the different QoS values.
920  *
921  * Since: 0.10.33
922  */
923 void
924 gst_event_parse_qos_full (GstEvent * event, GstQOSType * type,
925     gdouble * proportion, GstClockTimeDiff * diff, GstClockTime * timestamp)
926 {
927   const GstStructure *structure;
928
929   g_return_if_fail (GST_IS_EVENT (event));
930   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
931
932   structure = event->structure;
933   if (type)
934     *type =
935         g_value_get_enum (gst_structure_id_get_value (structure,
936             GST_QUARK (TYPE)));
937   if (proportion)
938     *proportion =
939         g_value_get_double (gst_structure_id_get_value (structure,
940             GST_QUARK (PROPORTION)));
941   if (diff)
942     *diff =
943         g_value_get_int64 (gst_structure_id_get_value (structure,
944             GST_QUARK (DIFF)));
945   if (timestamp)
946     *timestamp =
947         g_value_get_uint64 (gst_structure_id_get_value (structure,
948             GST_QUARK (TIMESTAMP)));
949 }
950
951 /**
952  * gst_event_new_seek:
953  * @rate: The new playback rate
954  * @format: The format of the seek values
955  * @flags: The optional seek flags
956  * @start_type: The type and flags for the new start position
957  * @start: The value of the new start position
958  * @stop_type: The type and flags for the new stop position
959  * @stop: The value of the new stop position
960  *
961  * Allocate a new seek event with the given parameters.
962  *
963  * The seek event configures playback of the pipeline between @start to @stop
964  * at the speed given in @rate, also called a playback segment.
965  * The @start and @stop values are expressed in @format.
966  *
967  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
968  * Negatives values means backwards playback. A value of 0.0 for the
969  * rate is not allowed and should be accomplished instead by PAUSING the
970  * pipeline.
971  *
972  * A pipeline has a default playback segment configured with a start
973  * position of 0, a stop position of -1 and a rate of 1.0. The currently
974  * configured playback segment can be queried with #GST_QUERY_SEGMENT. 
975  *
976  * @start_type and @stop_type specify how to adjust the currently configured 
977  * start and stop fields in playback segment. Adjustments can be made relative
978  * or absolute to the last configured values. A type of #GST_SEEK_TYPE_NONE
979  * means that the position should not be updated.
980  *
981  * When the rate is positive and @start has been updated, playback will start
982  * from the newly configured start position. 
983  *
984  * For negative rates, playback will start from the newly configured stop
985  * position (if any). If the stop position if updated, it must be different from
986  * -1 for negative rates.
987  *
988  * It is not possible to seek relative to the current playback position, to do
989  * this, PAUSE the pipeline, query the current playback position with
990  * #GST_QUERY_POSITION and update the playback segment current position with a
991  * #GST_SEEK_TYPE_SET to the desired position. 
992  *
993  * Returns: (transfer full): a new seek event.
994  */
995 GstEvent *
996 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
997     GstSeekType start_type, gint64 start, GstSeekType stop_type, gint64 stop)
998 {
999   GstEvent *event;
1000   GstStructure *structure;
1001
1002   g_return_val_if_fail (rate != 0.0, NULL);
1003
1004   if (format == GST_FORMAT_TIME) {
1005     GST_CAT_INFO (GST_CAT_EVENT,
1006         "creating seek rate %lf, format TIME, flags %d, "
1007         "start_type %d, start %" GST_TIME_FORMAT ", "
1008         "stop_type %d, stop %" GST_TIME_FORMAT,
1009         rate, flags, start_type, GST_TIME_ARGS (start),
1010         stop_type, GST_TIME_ARGS (stop));
1011   } else {
1012     GST_CAT_INFO (GST_CAT_EVENT,
1013         "creating seek rate %lf, format %s, flags %d, "
1014         "start_type %d, start %" G_GINT64_FORMAT ", "
1015         "stop_type %d, stop %" G_GINT64_FORMAT,
1016         rate, gst_format_get_name (format), flags, start_type, start, stop_type,
1017         stop);
1018   }
1019
1020   structure = gst_structure_id_new (GST_QUARK (EVENT_SEEK),
1021       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1022       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1023       GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
1024       GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
1025       GST_QUARK (CUR), G_TYPE_INT64, start,
1026       GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
1027       GST_QUARK (STOP), G_TYPE_INT64, stop, NULL);
1028   event = gst_event_new_custom (GST_EVENT_SEEK, structure);
1029
1030   return event;
1031 }
1032
1033 /**
1034  * gst_event_parse_seek:
1035  * @event: a seek event
1036  * @rate: (out): result location for the rate
1037  * @format: (out): result location for the stream format
1038  * @flags:  (out): result location for the #GstSeekFlags
1039  * @start_type: (out): result location for the #GstSeekType of the start position
1040  * @start: (out): result location for the start postion expressed in @format
1041  * @stop_type:  (out): result location for the #GstSeekType of the stop position
1042  * @stop: (out): result location for the stop postion expressed in @format
1043  *
1044  * Parses a seek @event and stores the results in the given result locations.
1045  */
1046 void
1047 gst_event_parse_seek (GstEvent * event, gdouble * rate,
1048     GstFormat * format, GstSeekFlags * flags, GstSeekType * start_type,
1049     gint64 * start, GstSeekType * stop_type, gint64 * stop)
1050 {
1051   const GstStructure *structure;
1052
1053   g_return_if_fail (GST_IS_EVENT (event));
1054   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
1055
1056   structure = event->structure;
1057   if (rate)
1058     *rate =
1059         g_value_get_double (gst_structure_id_get_value (structure,
1060             GST_QUARK (RATE)));
1061   if (format)
1062     *format =
1063         g_value_get_enum (gst_structure_id_get_value (structure,
1064             GST_QUARK (FORMAT)));
1065   if (flags)
1066     *flags =
1067         g_value_get_flags (gst_structure_id_get_value (structure,
1068             GST_QUARK (FLAGS)));
1069   if (start_type)
1070     *start_type =
1071         g_value_get_enum (gst_structure_id_get_value (structure,
1072             GST_QUARK (CUR_TYPE)));
1073   if (start)
1074     *start =
1075         g_value_get_int64 (gst_structure_id_get_value (structure,
1076             GST_QUARK (CUR)));
1077   if (stop_type)
1078     *stop_type =
1079         g_value_get_enum (gst_structure_id_get_value (structure,
1080             GST_QUARK (STOP_TYPE)));
1081   if (stop)
1082     *stop =
1083         g_value_get_int64 (gst_structure_id_get_value (structure,
1084             GST_QUARK (STOP)));
1085 }
1086
1087 /**
1088  * gst_event_new_navigation:
1089  * @structure: (transfer full): description of the event. The event will take
1090  *     ownership of the structure.
1091  *
1092  * Create a new navigation event from the given description.
1093  *
1094  * Returns: (transfer full): a new #GstEvent
1095  */
1096 GstEvent *
1097 gst_event_new_navigation (GstStructure * structure)
1098 {
1099   g_return_val_if_fail (structure != NULL, NULL);
1100
1101   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
1102 }
1103
1104 /**
1105  * gst_event_new_latency:
1106  * @latency: the new latency value
1107  *
1108  * Create a new latency event. The event is sent upstream from the sinks and
1109  * notifies elements that they should add an additional @latency to the
1110  * running time before synchronising against the clock.
1111  *
1112  * The latency is mostly used in live sinks and is always expressed in
1113  * the time format.
1114  *
1115  * Returns: (transfer full): a new #GstEvent
1116  *
1117  * Since: 0.10.12
1118  */
1119 GstEvent *
1120 gst_event_new_latency (GstClockTime latency)
1121 {
1122   GstEvent *event;
1123   GstStructure *structure;
1124
1125   GST_CAT_INFO (GST_CAT_EVENT,
1126       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
1127
1128   structure = gst_structure_id_new (GST_QUARK (EVENT_LATENCY),
1129       GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
1130   event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
1131
1132   return event;
1133 }
1134
1135 /**
1136  * gst_event_parse_latency:
1137  * @event: The event to query
1138  * @latency: (out): A pointer to store the latency in.
1139  *
1140  * Get the latency in the latency event.
1141  *
1142  * Since: 0.10.12
1143  */
1144 void
1145 gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
1146 {
1147   g_return_if_fail (GST_IS_EVENT (event));
1148   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_LATENCY);
1149
1150   if (latency)
1151     *latency =
1152         g_value_get_uint64 (gst_structure_id_get_value (event->structure,
1153             GST_QUARK (LATENCY)));
1154 }
1155
1156 /**
1157  * gst_event_new_step:
1158  * @format: the format of @amount
1159  * @amount: the amount of data to step
1160  * @rate: the step rate
1161  * @flush: flushing steps
1162  * @intermediate: intermediate steps
1163  *
1164  * Create a new step event. The purpose of the step event is to instruct a sink
1165  * to skip @amount (expressed in @format) of media. It can be used to implement
1166  * stepping through the video frame by frame or for doing fast trick modes.
1167  *
1168  * A rate of <= 0.0 is not allowed, pause the pipeline or reverse the playback
1169  * direction of the pipeline to get the same effect.
1170  *
1171  * The @flush flag will clear any pending data in the pipeline before starting
1172  * the step operation.
1173  *
1174  * The @intermediate flag instructs the pipeline that this step operation is
1175  * part of a larger step operation.
1176  *
1177  * Returns: (transfer full): a new #GstEvent
1178  *
1179  * Since: 0.10.24
1180  */
1181 GstEvent *
1182 gst_event_new_step (GstFormat format, guint64 amount, gdouble rate,
1183     gboolean flush, gboolean intermediate)
1184 {
1185   GstEvent *event;
1186   GstStructure *structure;
1187
1188   g_return_val_if_fail (rate > 0.0, NULL);
1189
1190   GST_CAT_INFO (GST_CAT_EVENT, "creating step event");
1191
1192   structure = gst_structure_id_new (GST_QUARK (EVENT_STEP),
1193       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1194       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
1195       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1196       GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
1197       GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
1198   event = gst_event_new_custom (GST_EVENT_STEP, structure);
1199
1200   return event;
1201 }
1202
1203 /**
1204  * gst_event_parse_step:
1205  * @event: The event to query
1206  * @format: (out) (allow-none): a pointer to store the format in
1207  * @amount: (out) (allow-none): a pointer to store the amount in
1208  * @rate: (out) (allow-none): a pointer to store the rate in
1209  * @flush: (out) (allow-none): a pointer to store the flush boolean in
1210  * @intermediate: (out) (allow-none): a pointer to store the intermediate
1211  *     boolean in
1212  *
1213  * Parse the step event.
1214  *
1215  * Since: 0.10.24
1216  */
1217 void
1218 gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
1219     gdouble * rate, gboolean * flush, gboolean * intermediate)
1220 {
1221   const GstStructure *structure;
1222
1223   g_return_if_fail (GST_IS_EVENT (event));
1224   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STEP);
1225
1226   structure = event->structure;
1227   if (format)
1228     *format = g_value_get_enum (gst_structure_id_get_value (structure,
1229             GST_QUARK (FORMAT)));
1230   if (amount)
1231     *amount = g_value_get_uint64 (gst_structure_id_get_value (structure,
1232             GST_QUARK (AMOUNT)));
1233   if (rate)
1234     *rate = g_value_get_double (gst_structure_id_get_value (structure,
1235             GST_QUARK (RATE)));
1236   if (flush)
1237     *flush = g_value_get_boolean (gst_structure_id_get_value (structure,
1238             GST_QUARK (FLUSH)));
1239   if (intermediate)
1240     *intermediate = g_value_get_boolean (gst_structure_id_get_value (structure,
1241             GST_QUARK (INTERMEDIATE)));
1242 }
1243
1244 /**
1245  * gst_event_new_reconfigure:
1246
1247  * Create a new reconfigure event. The purpose of the reconfingure event is
1248  * to travel upstream and make elements renegotiate their caps or reconfigure
1249  * their buffer pools. This is useful when changing properties on elements
1250  * or changing the topology of the pipeline.
1251  *
1252  * Returns: (transfer full): a new #GstEvent
1253  *
1254  * Since: 0.10.34
1255  */
1256 GstEvent *
1257 gst_event_new_reconfigure (void)
1258 {
1259   GstEvent *event;
1260
1261   GST_CAT_INFO (GST_CAT_EVENT, "creating reconfigure event");
1262
1263   event = gst_event_new_custom (GST_EVENT_RECONFIGURE, NULL);
1264
1265   return event;
1266 }
1267
1268 /**
1269  * gst_event_new_sink_message:
1270  * @msg: (transfer none): the #GstMessage to be posted
1271  *
1272  * Create a new sink-message event. The purpose of the sink-message event is
1273  * to instruct a sink to post the message contained in the event synchronized
1274  * with the stream.
1275  *
1276  * Returns: (transfer full): a new #GstEvent
1277  *
1278  * Since: 0.10.26
1279  */
1280 /* FIXME 0.11: take ownership of msg for consistency? */
1281 GstEvent *
1282 gst_event_new_sink_message (GstMessage * msg)
1283 {
1284   GstEvent *event;
1285   GstStructure *structure;
1286
1287   g_return_val_if_fail (msg != NULL, NULL);
1288
1289   GST_CAT_INFO (GST_CAT_EVENT, "creating sink-message event");
1290
1291   structure = gst_structure_id_new (GST_QUARK (EVENT_SINK_MESSAGE),
1292       GST_QUARK (MESSAGE), GST_TYPE_MESSAGE, msg, NULL);
1293   event = gst_event_new_custom (GST_EVENT_SINK_MESSAGE, structure);
1294
1295   return event;
1296 }
1297
1298 /**
1299  * gst_event_parse_sink_message:
1300  * @event: The event to query
1301  * @msg: (out) (transfer full): a pointer to store the #GstMessage in.
1302  *
1303  * Parse the sink-message event. Unref @msg after usage.
1304  *
1305  * Since: 0.10.26
1306  */
1307 void
1308 gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
1309 {
1310   const GstStructure *structure;
1311
1312   g_return_if_fail (GST_IS_EVENT (event));
1313   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SINK_MESSAGE);
1314
1315   structure = event->structure;
1316   if (msg)
1317     *msg =
1318         GST_MESSAGE (g_value_dup_boxed (gst_structure_id_get_value
1319             (structure, GST_QUARK (MESSAGE))));
1320 }