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