e49eea2c7297b0582cab65ff7ea556c0f68116e5
[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  *
5  * gstevent.c: GstEvent subsystem
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 /**
23  * SECTION:gstevent
24  * @short_description: Structure describing events that are passed up and down a pipeline
25  * @see_also: #GstPad, #GstElement
26  *
27  * The event classes are used to construct and query events.
28  *
29  * Events are usually created with gst_event_new_*() which takes the extra event 
30  * paramters as arguments. 
31  * Events can be parsed with their respective gst_event_parse_*() functions.
32  * The event should be unreferenced with gst_event_unref().
33  *
34  * gst_event_new_seek() is a usually used to create a seek event and it takes
35  * the needed parameters for a seek event.
36  *
37  * gst_event_new_flush() creates a new flush event.
38  */
39
40 #include <string.h>             /* memcpy */
41
42 #include "gst_private.h"
43
44 #include "gstinfo.h"
45 #include "gstevent.h"
46 #include "gstenumtypes.h"
47 #include "gstutils.h"
48
49 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
50 static void gst_event_class_init (gpointer g_class, gpointer class_data);
51 static void gst_event_finalize (GstEvent * event);
52 static GstEvent *_gst_event_copy (GstEvent * event);
53
54 void
55 _gst_event_initialize (void)
56 {
57   gst_event_get_type ();
58 }
59
60 typedef struct
61 {
62   gint type;
63   gchar *name;
64   GQuark quark;
65 } GstEventQuarks;
66
67 static GstEventQuarks event_quarks[] = {
68   {GST_EVENT_UNKNOWN, "unknown", 0},
69   {GST_EVENT_FLUSH_START, "flush-start", 0},
70   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
71   {GST_EVENT_EOS, "eos", 0},
72   {GST_EVENT_NEWSEGMENT, "newsegment", 0},
73   {GST_EVENT_TAG, "tag", 0},
74   {GST_EVENT_FILLER, "filler", 0},
75   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
76   {GST_EVENT_QOS, "qos", 0},
77   {GST_EVENT_SEEK, "seek", 0},
78   {GST_EVENT_NAVIGATION, "navigation", 0},
79   {GST_EVENT_CUSTOM_UP, "custom-up", 0},
80   {GST_EVENT_CUSTOM_DS, "custom-ds", 0},
81   {GST_EVENT_CUSTOM_DS_OOB, "custom-ds-oob", 0},
82   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
83   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
84
85   {0, NULL, 0}
86 };
87
88 /**
89  * gst_event_type_get_name:
90  * @type: the event type
91  *
92  * Get a printable name for the given event type. Do not modify or free.
93  *
94  * Returns: a reference to the static name of the event. 
95  */
96 const gchar *
97 gst_event_type_get_name (GstEventType type)
98 {
99   gint i;
100
101   for (i = 0; event_quarks[i].name; i++) {
102     if (type == event_quarks[i].type)
103       return event_quarks[i].name;
104   }
105   return "unknown";
106 }
107
108 /**
109  * gst_event_type_to_quark:
110  * @type: the event type
111  *
112  * Get the unique quark for the given event type.
113  *
114  * Returns: the quark associated with the event type
115  */
116 GQuark
117 gst_event_type_to_quark (GstEventType type)
118 {
119   gint i;
120
121   for (i = 0; event_quarks[i].name; i++) {
122     if (type == event_quarks[i].type)
123       return event_quarks[i].quark;
124   }
125   return 0;
126 }
127
128 GType
129 gst_event_get_type (void)
130 {
131   static GType _gst_event_type;
132   int i;
133
134   if (G_UNLIKELY (_gst_event_type == 0)) {
135     static const GTypeInfo event_info = {
136       sizeof (GstEventClass),
137       NULL,
138       NULL,
139       gst_event_class_init,
140       NULL,
141       NULL,
142       sizeof (GstEvent),
143       0,
144       gst_event_init,
145       NULL
146     };
147
148     _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
149         "GstEvent", &event_info, 0);
150
151     for (i = 0; event_quarks[i].name; i++) {
152       event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
153     }
154   }
155
156   return _gst_event_type;
157 }
158
159 static void
160 gst_event_class_init (gpointer g_class, gpointer class_data)
161 {
162   GstEventClass *event_class = GST_EVENT_CLASS (g_class);
163
164   event_class->mini_object_class.copy =
165       (GstMiniObjectCopyFunction) _gst_event_copy;
166   event_class->mini_object_class.finalize =
167       (GstMiniObjectFinalizeFunction) gst_event_finalize;
168 }
169
170 static void
171 gst_event_init (GTypeInstance * instance, gpointer g_class)
172 {
173   GstEvent *event;
174
175   event = GST_EVENT (instance);
176
177   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
178 }
179
180 static void
181 gst_event_finalize (GstEvent * event)
182 {
183   g_return_if_fail (event != NULL);
184   g_return_if_fail (GST_IS_EVENT (event));
185
186   GST_CAT_INFO (GST_CAT_EVENT, "freeing event %p type %s", event,
187       gst_event_type_get_name (GST_EVENT_TYPE (event)));
188
189   if (GST_EVENT_SRC (event)) {
190     gst_object_unref (GST_EVENT_SRC (event));
191     GST_EVENT_SRC (event) = NULL;
192   }
193   if (event->structure) {
194     gst_structure_set_parent_refcount (event->structure, NULL);
195     gst_structure_free (event->structure);
196   }
197 }
198
199 static GstEvent *
200 _gst_event_copy (GstEvent * event)
201 {
202   GstEvent *copy;
203
204   copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
205
206   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
207   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
208
209   if (GST_EVENT_SRC (event)) {
210     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
211   }
212   if (event->structure) {
213     copy->structure = gst_structure_copy (event->structure);
214     gst_structure_set_parent_refcount (copy->structure,
215         &event->mini_object.refcount);
216   }
217   return copy;
218 }
219
220 static GstEvent *
221 gst_event_new (GstEventType type)
222 {
223   GstEvent *event;
224
225   event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
226
227   GST_CAT_INFO (GST_CAT_EVENT, "creating new event %p %s", event,
228       gst_event_type_get_name (type));
229
230   event->type = type;
231   event->src = NULL;
232   event->structure = NULL;
233
234   return event;
235 }
236
237 /**
238  * gst_event_new_custom:
239  * @type: The type of the new event
240  * @structure: The structure for the event. The event will take ownership of
241  * the structure.
242  *
243  * Create a new custom-typed event. This can be used for anything not
244  * handled by other event-specific functions to pass an event to another
245  * element.
246  *
247  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
248  * assigning a free number and filling in the correct direction and
249  * serialization flags.
250  *
251  * New custom events can also be created by subclassing the event type if
252  * needed.
253  *
254  * Returns: The new custom event.
255  */
256 GstEvent *
257 gst_event_new_custom (GstEventType type, GstStructure * structure)
258 {
259   GstEvent *event;
260
261   event = gst_event_new (type);
262   if (structure) {
263     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
264     event->structure = structure;
265   }
266   return event;
267 }
268
269 /**
270  * gst_event_get_structure:
271  * @event: The #GstEvent.
272  *
273  * Access the structure of the event.
274  *
275  * Returns: The structure of the event. The structure is still
276  * owned by the event, which means that you should not free it and
277  * that the pointer becomes invalid when you free the event.
278  *
279  * MT safe.
280  */
281 const GstStructure *
282 gst_event_get_structure (GstEvent * event)
283 {
284   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
285
286   return event->structure;
287 }
288
289 /**
290  * gst_event_new_flush_start:
291  *
292  * Allocate a new flush start event. The flush start event can be send
293  * upstream and downstream and travels out-of-bounds with the dataflow.
294  * It marks pads as being in a WRONG_STATE to process more data.
295  *
296  * Elements unlock and blocking functions and exit their streaming functions
297  * as fast as possible. 
298  *
299  * This event is typically generated after a seek to minimize the latency
300  * after the seek.
301  *
302  * Returns: A new flush start event.
303  */
304 GstEvent *
305 gst_event_new_flush_start (void)
306 {
307   return gst_event_new (GST_EVENT_FLUSH_START);
308 }
309
310 /**
311  * gst_event_new_flush_stop:
312  *
313  * Allocate a new flush stop event. The flush start event can be send
314  * upstream and downstream and travels out-of-bounds with the dataflow.
315  * It is typically send after sending a FLUSH_START event to make the
316  * pads accept data again.
317  *
318  * Elements can process this event synchronized with the dataflow since
319  * the preceeding FLUSH_START event stopped the dataflow.
320  *
321  * This event is typically generated to complete a seek and to resume
322  * dataflow.
323  *
324  * Returns: A new flush stop event.
325  */
326 GstEvent *
327 gst_event_new_flush_stop (void)
328 {
329   return gst_event_new (GST_EVENT_FLUSH_STOP);
330 }
331
332 /**
333  * gst_event_new_eos:
334  *
335  * Create a new EOS event. The eos event can only travel downstream
336  * synchronized with the buffer flow. Elements that receive the EOS
337  * event on a pad can return UNEXPECTED as a GstFlowReturn when data
338  * after the EOS event arrives.
339  *
340  * The EOS event will travel up to the sink elements in the pipeline
341  * which will then post the GST_MESSAGE_EOS on the bus.
342  *
343  * When all sinks have posted an EOS message, the EOS message is
344  * forwarded to the application.
345  *
346  * Returns: The new EOS event.
347  */
348 GstEvent *
349 gst_event_new_eos (void)
350 {
351   return gst_event_new (GST_EVENT_EOS);
352 }
353
354 /**
355  * gst_event_new_newsegment:
356  * @rate: a new rate for playback
357  * @format: The format of the segment values
358  * @start_value: the start value of the segment
359  * @stop_value: the stop value of the segment
360  * @base: base value for buffer timestamps.
361  *
362  * Allocate a new newsegment event with the given format/values tripplets.
363  *
364  * The newsegment event marks the range of buffers to be processed. All
365  * data not within the segment range is not to be processed. This can be
366  * used intelligently by plugins to use more efficient methods of skipping
367  * unneeded packets.
368  *
369  * The base time of the segment is also used to convert the buffer timestamps
370  * into the stream time again.
371  *
372  * The @start_value cannot be -1, the @stop_value can be -1. If there
373  * is a valid @stop_value given, it must be smaller than @start_value.
374  *
375  * After a newsegment event, the buffer stream time is calculated with:
376  *
377  *   TIMESTAMP(buf) - start_time + base
378  *
379  * Returns: A new newsegment event.
380  */
381 GstEvent *
382 gst_event_new_newsegment (gdouble rate, GstFormat format,
383     gint64 start_value, gint64 stop_value, gint64 base)
384 {
385   if (format == GST_FORMAT_TIME) {
386     GST_CAT_INFO (GST_CAT_EVENT,
387         "creating newsegment rate %lf, format GST_FORMAT_TIME, "
388         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
389         ", base %" GST_TIME_FORMAT,
390         rate, GST_TIME_ARGS (start_value),
391         GST_TIME_ARGS (stop_value), GST_TIME_ARGS (base));
392   } else {
393     GST_CAT_INFO (GST_CAT_EVENT,
394         "creating newsegment rate %lf, format %d, "
395         "start %lld, stop %lld, base %lld",
396         rate, format, start_value, stop_value, base);
397   }
398   if (start_value == -1)
399     g_return_val_if_fail (start_value != -1, NULL);
400
401   if (stop_value != -1)
402     g_return_val_if_fail (start_value <= stop_value, NULL);
403
404   return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
405       gst_structure_new ("GstEventNewsegment", "rate", G_TYPE_DOUBLE, rate,
406           "format", GST_TYPE_FORMAT, format,
407           "start_val", G_TYPE_INT64, start_value,
408           "stop_val", G_TYPE_INT64, stop_value,
409           "base", G_TYPE_INT64, base, NULL));
410 }
411
412 /**
413  * gst_event_parse_newsegment:
414  * @event: The event to query
415  * @rate: A pointer to the rate of the segment
416  * @format: A pointer to the format of the newsegment values
417  * @start_value: A pointer to store the start value in
418  * @stop_value: A pointer to store the stop value in
419  * @base: A pointer to store the base time in
420  *
421  * Get the start, stop and format in the newsegment event.
422  */
423 void
424 gst_event_parse_newsegment (GstEvent * event, gdouble * rate,
425     GstFormat * format, gint64 * start_value, gint64 * stop_value,
426     gint64 * base)
427 {
428   const GstStructure *structure;
429
430   g_return_if_fail (GST_IS_EVENT (event));
431   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
432
433   structure = gst_event_get_structure (event);
434   if (rate)
435     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
436   if (format)
437     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
438   if (start_value)
439     *start_value =
440         g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
441   if (stop_value)
442     *stop_value =
443         g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
444   if (base)
445     *base = g_value_get_int64 (gst_structure_get_value (structure, "base"));
446 }
447
448 /**
449  * gst_event_new_tag:
450  * @taglist: metadata list
451  *
452  * Generates a metadata tag event from the given @taglist.
453  * 
454  * Returns: a new #GstEvent
455  */
456 GstEvent *
457 gst_event_new_tag (GstTagList * taglist)
458 {
459   g_return_val_if_fail (taglist != NULL, NULL);
460
461   return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
462 }
463
464 /**
465  * gst_event_parse_tag:
466  * @event: a tag event
467  * @taglist: pointer to metadata list
468  *
469  * Parses a tag @event and stores the results in the given @taglist location.
470  */
471 void
472 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
473 {
474   g_return_if_fail (GST_IS_EVENT (event));
475   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
476
477   if (taglist)
478     *taglist = (GstTagList *) event->structure;
479 }
480
481 /* filler event */
482 /**
483  * gst_event_new_filler:
484  *
485  * Create a new dummy event that should be ignored.
486  *
487  * Returns: a new #GstEvent
488  */
489 GstEvent *
490 gst_event_new_filler (void)
491 {
492   return gst_event_new (GST_EVENT_FILLER);
493 }
494
495 /* buffersize event */
496 /**
497  * gst_event_new_buffersize:
498  * @format: buffer format
499  * @minsize: minimum buffer size
500  * @maxsize: maximum buffer size
501  * @async: thread behavior
502  *
503  * Create a new buffersize event. The event is sent downstream and notifies
504  * elements that they should provide a buffer of the specified dimensions.
505  *
506  * When the async flag is set, a thread boundary is prefered.
507  *
508  * Returns: a new #GstEvent
509  */
510 GstEvent *
511 gst_event_new_buffersize (GstFormat format, gint64 minsize,
512     gint64 maxsize, gboolean async)
513 {
514   GST_CAT_INFO (GST_CAT_EVENT,
515       "creating buffersize format %d, minsize %" G_GINT64_FORMAT
516       ", maxsize %" G_GINT64_FORMAT ", async %d", format,
517       minsize, maxsize, async);
518
519   return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
520       gst_structure_new ("GstEventBufferSize",
521           "format", GST_TYPE_FORMAT, format,
522           "minsize", G_TYPE_INT64, minsize,
523           "maxsize", G_TYPE_INT64, maxsize,
524           "async", G_TYPE_BOOLEAN, async, NULL));
525 }
526
527 /**
528  * gst_event_parse_buffersize:
529  * @event: The event to query
530  * @format: A pointer to store the format in
531  * @minsize: A pointer to store the minsize in
532  * @maxsize: A pointer to store the maxsize in
533  * @async: A pointer to store the async-flag in
534  *
535  * Get the format, minsize, maxsize and async-flag in the buffersize event.
536  */
537 void
538 gst_event_parse_buffersize (GstEvent * event, GstFormat * format,
539     gint64 * minsize, gint64 * maxsize, gboolean * async)
540 {
541   const GstStructure *structure;
542
543   g_return_if_fail (GST_IS_EVENT (event));
544   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
545
546   structure = gst_event_get_structure (event);
547   if (format)
548     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
549   if (minsize)
550     *minsize =
551         g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
552   if (maxsize)
553     *maxsize =
554         g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
555   if (async)
556     *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
557 }
558
559 /**
560  * gst_event_new_qos:
561  * @proportion: the proportion of the qos message
562  * @diff: The time difference of the last Clock sync
563  * @timestamp: The timestamp of the buffer
564  *
565  * Allocate a new qos event with the given values.
566  * The QOS event is generated in an element that wants an upstream
567  * element to either reduce or increase its rate because of
568  * high/low CPU load.
569  *
570  * proportion is the requested adjustment in datarate, 1.0 is the normal
571  * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
572  * values request a slow down, so -0.75 means a decrease by 75%.
573  *
574  * diff is the difference against the clock in stream time of the last 
575  * buffer that caused the element to generate the QOS event.
576  *
577  * timestamp is the timestamp of the last buffer that cause the element
578  * to generate the QOS event.
579  *
580  * Returns: A new QOS event.
581  */
582 GstEvent *
583 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
584     GstClockTime timestamp)
585 {
586   GST_CAT_INFO (GST_CAT_EVENT,
587       "creating qos proportion %lf, diff %" GST_TIME_FORMAT
588       ", timestamp %" GST_TIME_FORMAT, proportion,
589       GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
590
591   return gst_event_new_custom (GST_EVENT_QOS,
592       gst_structure_new ("GstEventQOS",
593           "proportion", G_TYPE_DOUBLE, proportion,
594           "diff", G_TYPE_INT64, diff,
595           "timestamp", G_TYPE_UINT64, timestamp, NULL));
596 }
597
598 /**
599  * gst_event_parse_qos:
600  * @event: The event to query
601  * @proportion: A pointer to store the proportion in
602  * @diff: A pointer to store the diff in
603  * @timestamp: A pointer to store the timestamp in
604  *
605  * Get the proportion, diff and timestamp in the qos event.
606  */
607 void
608 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
609     GstClockTimeDiff * diff, GstClockTime * timestamp)
610 {
611   const GstStructure *structure;
612
613   g_return_if_fail (GST_IS_EVENT (event));
614   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
615
616   structure = gst_event_get_structure (event);
617   if (proportion)
618     *proportion =
619         g_value_get_double (gst_structure_get_value (structure, "proportion"));
620   if (diff)
621     *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
622   if (timestamp)
623     *timestamp =
624         g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
625 }
626
627 /**
628  * gst_event_new_seek:
629  * @rate: The new playback rate
630  * @format: The format of the seek values
631  * @flags: The optional seek flags.
632  * @cur_type: The type and flags for the new current position
633  * @cur: The value of the new current position
634  * @stop_type: The type and flags for the new stop position
635  * @stop: The value of the new stop position
636  *
637  * Allocate a new seek event with the given parameters.
638  *
639  * The seek event configures playback of the pipeline from
640  * @cur to @stop at the speed given in @rate.
641  * The @cur and @stop values are expressed in format @format.
642  *
643  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
644  * Negatives values means backwards playback. A value of 0.0 for the
645  * rate is not allowed.
646  *
647  * @cur_type and @stop_type specify how to adjust the current and stop
648  * time, relative or absolute. A type of #GST_EVENT_TYPE_NONE means that
649  * the position should not be updated.
650  *
651  * Returns: A new seek event.
652  */
653 GstEvent *
654 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
655     GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
656 {
657   if (format == GST_FORMAT_TIME) {
658     GST_CAT_INFO (GST_CAT_EVENT,
659         "creating seek rate %lf, format TIME, flags %d, "
660         "cur_type %d, cur %" GST_TIME_FORMAT ", "
661         "stop_type %d, stop %" GST_TIME_FORMAT,
662         rate, flags, cur_type, GST_TIME_ARGS (cur),
663         stop_type, GST_TIME_ARGS (stop));
664   } else {
665     GST_CAT_INFO (GST_CAT_EVENT,
666         "creating seek rate %lf, format %d, flags %d, "
667         "cur_type %d, cur %" G_GINT64_FORMAT ", "
668         "stop_type %d, stop %" G_GINT64_FORMAT,
669         rate, format, flags, cur_type, cur, stop_type, stop);
670   }
671
672   return gst_event_new_custom (GST_EVENT_SEEK,
673       gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
674           "format", GST_TYPE_FORMAT, format,
675           "flags", GST_TYPE_SEEK_FLAGS, flags,
676           "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
677           "cur", G_TYPE_INT64, cur,
678           "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
679           "stop", G_TYPE_INT64, stop, NULL));
680 }
681
682 /**
683  * gst_event_parse_seek:
684  * @event: a seek event
685  * @rate: result location for the rate
686  * @format: result location for the stream format
687  * @flags:  result location for the #GstSeekFlags
688  * @cur_type: result location for the #GstSeekType of the current position
689  * @cur: result location for the current postion expressed in @format
690  * @stop_type:  result location for the #GstSeekType of the stop position
691  * @stop: result location for the stop postion expressed in @format
692  *
693  * Parses a seek @event and stores the results in the given result locations.
694  */
695 void
696 gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
697     GstSeekFlags * flags,
698     GstSeekType * cur_type, gint64 * cur,
699     GstSeekType * stop_type, gint64 * stop)
700 {
701   const GstStructure *structure;
702
703   g_return_if_fail (GST_IS_EVENT (event));
704   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
705
706   structure = gst_event_get_structure (event);
707   if (rate)
708     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
709   if (format)
710     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
711   if (flags)
712     *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
713   if (cur_type)
714     *cur_type =
715         g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
716   if (cur)
717     *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
718   if (stop_type)
719     *stop_type =
720         g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
721   if (stop)
722     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
723 }
724
725 /**
726  * gst_event_new_navigation:
727  * @structure: description of the event
728  *
729  * Create a new navigation event from the given description.
730  *
731  * Returns: a new #GstEvent
732  */
733 GstEvent *
734 gst_event_new_navigation (GstStructure * structure)
735 {
736   g_return_val_if_fail (structure != NULL, NULL);
737
738   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
739 }