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