gst/: constify quark registration strings. Fixes #344115
[platform/upstream/gstreamer.git] / gst / gstevent.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstevent.c: GstEvent subsystem
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:gstevent
26  * @short_description: Structure describing events that are passed up and down
27  *                     a pipeline
28  * @see_also: #GstPad, #GstElement
29  *
30  * The event class provides factory methods to construct and functions query
31  * (parse) events.
32  *
33  * Events are usually created with gst_event_new_*() which takes event-type
34  * specific parameters as arguments.
35  * To send an event application will usually use gst_element_send_event() and
36  * elements will use gst_pad_send_event() or gst_pad_push_event().
37  * The event should be unreffed with gst_event_unref() if it has not been sent.
38  *
39  * Events that have been received can be parsed with their respective 
40  * gst_event_parse_*() functions.
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-01-24 (0.10.2)
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
87 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
88 static void gst_event_class_init (gpointer g_class, gpointer class_data);
89 static void gst_event_finalize (GstEvent * event);
90 static GstEvent *_gst_event_copy (GstEvent * event);
91
92 void
93 _gst_event_initialize (void)
94 {
95   gst_event_get_type ();
96   gst_seek_flags_get_type ();
97   gst_seek_type_get_type ();
98 }
99
100 typedef struct
101 {
102   const gint type;
103   const gchar *name;
104   GQuark quark;
105 } GstEventQuarks;
106
107 static GstEventQuarks event_quarks[] = {
108   {GST_EVENT_UNKNOWN, "unknown", 0},
109   {GST_EVENT_FLUSH_START, "flush-start", 0},
110   {GST_EVENT_FLUSH_STOP, "flush-stop", 0},
111   {GST_EVENT_EOS, "eos", 0},
112   {GST_EVENT_NEWSEGMENT, "newsegment", 0},
113   {GST_EVENT_TAG, "tag", 0},
114   {GST_EVENT_BUFFERSIZE, "buffersize", 0},
115   {GST_EVENT_QOS, "qos", 0},
116   {GST_EVENT_SEEK, "seek", 0},
117   {GST_EVENT_NAVIGATION, "navigation", 0},
118   {GST_EVENT_CUSTOM_UPSTREAM, "custom-upstream", 0},
119   {GST_EVENT_CUSTOM_DOWNSTREAM, "custom-downstream", 0},
120   {GST_EVENT_CUSTOM_DOWNSTREAM_OOB, "custom-downstream-oob", 0},
121   {GST_EVENT_CUSTOM_BOTH, "custom-both", 0},
122   {GST_EVENT_CUSTOM_BOTH_OOB, "custom-both-oob", 0},
123
124   {0, NULL, 0}
125 };
126
127 /**
128  * gst_event_type_get_name:
129  * @type: the event type
130  *
131  * Get a printable name for the given event type. Do not modify or free.
132  *
133  * Returns: a reference to the static name of the event.
134  */
135 const gchar *
136 gst_event_type_get_name (GstEventType type)
137 {
138   gint i;
139
140   for (i = 0; event_quarks[i].name; i++) {
141     if (type == event_quarks[i].type)
142       return event_quarks[i].name;
143   }
144   return "unknown";
145 }
146
147 /**
148  * gst_event_type_to_quark:
149  * @type: the event type
150  *
151  * Get the unique quark for the given event type.
152  *
153  * Returns: the quark associated with the event type
154  */
155 GQuark
156 gst_event_type_to_quark (GstEventType type)
157 {
158   gint i;
159
160   for (i = 0; event_quarks[i].name; i++) {
161     if (type == event_quarks[i].type)
162       return event_quarks[i].quark;
163   }
164   return 0;
165 }
166
167 /**
168  * gst_event_type_get_flags:
169  * @type: a #GstEventType
170  *
171  * Gets the #GstEventTypeFlags associated with @type.
172  *
173  * Returns: a #GstEventTypeFlags.
174  */
175 GstEventTypeFlags
176 gst_event_type_get_flags (GstEventType type)
177 {
178   GstEventTypeFlags ret;
179
180   ret = type & ((1 << GST_EVENT_TYPE_SHIFT) - 1);
181
182   return ret;
183 }
184
185 GType
186 gst_event_get_type (void)
187 {
188   static GType _gst_event_type = 0;
189   int i;
190
191   if (G_UNLIKELY (_gst_event_type == 0)) {
192     static const GTypeInfo event_info = {
193       sizeof (GstEventClass),
194       NULL,
195       NULL,
196       gst_event_class_init,
197       NULL,
198       NULL,
199       sizeof (GstEvent),
200       0,
201       gst_event_init,
202       NULL
203     };
204
205     _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
206         "GstEvent", &event_info, 0);
207
208     for (i = 0; event_quarks[i].name; i++) {
209       event_quarks[i].quark = g_quark_from_static_string (event_quarks[i].name);
210     }
211   }
212
213   return _gst_event_type;
214 }
215
216 static void
217 gst_event_class_init (gpointer g_class, gpointer class_data)
218 {
219   GstEventClass *event_class = GST_EVENT_CLASS (g_class);
220
221   event_class->mini_object_class.copy =
222       (GstMiniObjectCopyFunction) _gst_event_copy;
223   event_class->mini_object_class.finalize =
224       (GstMiniObjectFinalizeFunction) gst_event_finalize;
225 }
226
227 static void
228 gst_event_init (GTypeInstance * instance, gpointer g_class)
229 {
230   GstEvent *event;
231
232   event = GST_EVENT (instance);
233
234   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
235 }
236
237 static void
238 gst_event_finalize (GstEvent * event)
239 {
240   g_return_if_fail (event != NULL);
241   g_return_if_fail (GST_IS_EVENT (event));
242
243   GST_CAT_LOG (GST_CAT_EVENT, "freeing event %p type %s", event,
244       GST_EVENT_TYPE_NAME (event));
245
246   if (GST_EVENT_SRC (event)) {
247     gst_object_unref (GST_EVENT_SRC (event));
248     GST_EVENT_SRC (event) = NULL;
249   }
250   if (event->structure) {
251     gst_structure_set_parent_refcount (event->structure, NULL);
252     gst_structure_free (event->structure);
253   }
254 }
255
256 static GstEvent *
257 _gst_event_copy (GstEvent * event)
258 {
259   GstEvent *copy;
260
261   copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
262
263   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
264   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
265
266   if (GST_EVENT_SRC (event)) {
267     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
268   }
269   if (event->structure) {
270     copy->structure = gst_structure_copy (event->structure);
271     gst_structure_set_parent_refcount (copy->structure,
272         &event->mini_object.refcount);
273   }
274   return copy;
275 }
276
277 static GstEvent *
278 gst_event_new (GstEventType type)
279 {
280   GstEvent *event;
281
282   event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
283
284   GST_CAT_DEBUG (GST_CAT_EVENT, "creating new event %p %s %d", event,
285       gst_event_type_get_name (type), type);
286
287   event->type = type;
288   event->src = NULL;
289   event->structure = NULL;
290
291   return event;
292 }
293
294 /**
295  * gst_event_new_custom:
296  * @type: The type of the new event
297  * @structure: The structure for the event. The event will take ownership of
298  * the structure.
299  *
300  * Create a new custom-typed event. This can be used for anything not
301  * handled by other event-specific functions to pass an event to another
302  * element.
303  *
304  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
305  * assigning a free number and filling in the correct direction and
306  * serialization flags.
307  *
308  * New custom events can also be created by subclassing the event type if
309  * needed.
310  *
311  * Returns: The new custom event.
312  */
313 GstEvent *
314 gst_event_new_custom (GstEventType type, GstStructure * structure)
315 {
316   GstEvent *event;
317
318   event = gst_event_new (type);
319   if (structure) {
320     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
321     event->structure = structure;
322   }
323   return event;
324 }
325
326 /**
327  * gst_event_get_structure:
328  * @event: The #GstEvent.
329  *
330  * Access the structure of the event.
331  *
332  * Returns: The structure of the event. The structure is still
333  * owned by the event, which means that you should not free it and
334  * that the pointer becomes invalid when you free the event.
335  *
336  * MT safe.
337  */
338 const GstStructure *
339 gst_event_get_structure (GstEvent * event)
340 {
341   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
342
343   return event->structure;
344 }
345
346 /**
347  * gst_event_new_flush_start:
348  *
349  * Allocate a new flush start event. The flush start event can be send
350  * upstream and downstream and travels out-of-bounds with the dataflow.
351  * It marks pads as being in a WRONG_STATE to process more data.
352  *
353  * Elements unlock and blocking functions and exit their streaming functions
354  * as fast as possible.
355  *
356  * This event is typically generated after a seek to minimize the latency
357  * after the seek.
358  *
359  * Returns: A new flush start event.
360  */
361 GstEvent *
362 gst_event_new_flush_start (void)
363 {
364   return gst_event_new (GST_EVENT_FLUSH_START);
365 }
366
367 /**
368  * gst_event_new_flush_stop:
369  *
370  * Allocate a new flush stop event. The flush start event can be send
371  * upstream and downstream and travels out-of-bounds with the dataflow.
372  * It is typically send after sending a FLUSH_START event to make the
373  * pads accept data again.
374  *
375  * Elements can process this event synchronized with the dataflow since
376  * the preceeding FLUSH_START event stopped the dataflow.
377  *
378  * This event is typically generated to complete a seek and to resume
379  * dataflow.
380  *
381  * Returns: A new flush stop event.
382  */
383 GstEvent *
384 gst_event_new_flush_stop (void)
385 {
386   return gst_event_new (GST_EVENT_FLUSH_STOP);
387 }
388
389 /**
390  * gst_event_new_eos:
391  *
392  * Create a new EOS event. The eos event can only travel downstream
393  * synchronized with the buffer flow. Elements that receive the EOS
394  * event on a pad can return UNEXPECTED as a GstFlowReturn when data
395  * after the EOS event arrives.
396  *
397  * The EOS event will travel down to the sink elements in the pipeline
398  * which will then post the GST_MESSAGE_EOS on the bus after they have
399  * finished playing any buffered data.
400  *
401  * When all sinks have posted an EOS message, the EOS message is
402  * forwarded to the application.
403  *
404  * Returns: The new EOS event.
405  */
406 GstEvent *
407 gst_event_new_eos (void)
408 {
409   return gst_event_new (GST_EVENT_EOS);
410 }
411
412 /**
413  * gst_event_new_new_segment:
414  * @update: is this segment an update to a previous one
415  * @rate: a new rate for playback
416  * @format: The format of the segment values
417  * @start: the start value of the segment
418  * @stop: the stop value of the segment
419  * @position: stream position
420  *
421  * Allocate a new newsegment event with the given format/values tripplets
422  *
423  * This method calls gst_event_new_new_segment_full() passing a default
424  * value of 1.0 for applied_rate
425  *
426  * Returns: A new newsegment event.
427  */
428 GstEvent *
429 gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
430     gint64 start, gint64 stop, gint64 position)
431 {
432   return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
433       stop, position);
434 }
435
436 /**
437  * gst_event_parse_new_segment:
438  * @event: The event to query
439  * @update: A pointer to the update flag of the segment
440  * @rate: A pointer to the rate of the segment
441  * @format: A pointer to the format of the newsegment values
442  * @start: A pointer to store the start value in
443  * @stop: A pointer to store the stop value in
444  * @position: A pointer to store the stream time in
445  *
446  * Get the update flag, rate, format, start, stop and position in the 
447  * newsegment event. In general, gst_event_parse_new_segment_full() should
448  * be used instead of this, to also retrieve the applied_rate value of the
449  * segment. See gst_event_new_new_segment_full() for a full description 
450  * of the newsegment event.
451  */
452 void
453 gst_event_parse_new_segment (GstEvent * event, gboolean * update,
454     gdouble * rate, GstFormat * format, gint64 * start,
455     gint64 * stop, gint64 * position)
456 {
457   gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
458       stop, position);
459 }
460
461 /**
462  * gst_event_new_new_segment_full:
463  * @update: Whether this segment is an update to a previous one
464  * @rate: A new rate for playback
465  * @applied_rate: The rate factor which has already been applied
466  * @format: The format of the segment values
467  * @start: The start value of the segment
468  * @stop: The stop value of the segment
469  * @position: stream position
470  *
471  * Allocate a new newsegment event with the given format/values triplets.
472  *
473  * The newsegment event marks the range of buffers to be processed. All
474  * data not within the segment range is not to be processed. This can be
475  * used intelligently by plugins to apply more efficient methods of skipping
476  * unneeded packets.
477  *
478  * The position value of the segment is used in conjunction with the start
479  * value to convert the buffer timestamps into the stream time. This is 
480  * usually done in sinks to report the current stream_time. 
481  * @position represents the stream_time of a buffer carrying a timestamp of 
482  * @start. @position cannot be -1.
483  *
484  * @start cannot be -1, @stop can be -1. If there
485  * is a valid @stop given, it must be greater or equal the @start, including 
486  * when the indicated playback @rate is < 0
487  *
488  * The @applied_rate value provides information about any rate adjustment that
489  * has already been made to the timestamps and content on the buffers of the 
490  * stream. (@rate * @applied_rate) should always equal the rate that has been 
491  * requested for playback. For example, if an element has an input segment 
492  * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust 
493  * incoming timestamps and buffer content by half and output a newsegment event 
494  * with @rate of 1.0 and @applied_rate of 2.0
495  *
496  * After a newsegment event, the buffer stream time is calculated with:
497  *
498  *   position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
499  *
500  * Returns: A new newsegment event.
501  *
502  * Since: 0.10.6
503  */
504 GstEvent *
505 gst_event_new_new_segment_full (gboolean update, gdouble rate,
506     gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
507     gint64 position)
508 {
509   g_return_val_if_fail (rate != 0.0, NULL);
510   g_return_val_if_fail (applied_rate != 0.0, NULL);
511
512   if (format == GST_FORMAT_TIME) {
513     GST_CAT_INFO (GST_CAT_EVENT,
514         "creating newsegment update %d, rate %lf, format GST_FORMAT_TIME, "
515         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
516         ", position %" GST_TIME_FORMAT,
517         update, rate, GST_TIME_ARGS (start),
518         GST_TIME_ARGS (stop), GST_TIME_ARGS (position));
519   } else {
520     GST_CAT_INFO (GST_CAT_EVENT,
521         "creating newsegment update %d, rate %lf, format %d, "
522         "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
523         G_GINT64_FORMAT, update, rate, format, start, stop, position);
524   }
525
526   g_return_val_if_fail (position != -1, NULL);
527   g_return_val_if_fail (start != -1, NULL);
528   if (stop != -1)
529     g_return_val_if_fail (start <= stop, NULL);
530
531   return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
532       gst_structure_new ("GstEventNewsegment",
533           "update", G_TYPE_BOOLEAN, update,
534           "rate", G_TYPE_DOUBLE, rate,
535           "applied_rate", G_TYPE_DOUBLE, applied_rate,
536           "format", GST_TYPE_FORMAT, format,
537           "start", G_TYPE_INT64, start,
538           "stop", G_TYPE_INT64, stop,
539           "position", G_TYPE_INT64, position, NULL));
540 }
541
542 /**
543  * gst_event_parse_new_segment_full:
544  * @event: The event to query
545  * @update: A pointer to the update flag of the segment
546  * @rate: A pointer to the rate of the segment
547  * @applied_rate: A pointer to the applied_rate of the segment
548  * @format: A pointer to the format of the newsegment values
549  * @start: A pointer to store the start value in
550  * @stop: A pointer to store the stop value in
551  * @position: A pointer to store the stream time in
552  *
553  * Get the update, rate, applied_rate, format, start, stop and 
554  * position in the newsegment event. See gst_event_new_new_segment_full() 
555  * for a full description of the newsegment event.
556  *
557  * Since: 0.10.6
558  */
559 void
560 gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
561     gdouble * rate, gdouble * applied_rate, GstFormat * format,
562     gint64 * start, gint64 * stop, gint64 * position)
563 {
564   const GstStructure *structure;
565
566   g_return_if_fail (GST_IS_EVENT (event));
567   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
568
569   structure = gst_event_get_structure (event);
570   if (G_LIKELY (update))
571     *update =
572         g_value_get_boolean (gst_structure_get_value (structure, "update"));
573   if (G_LIKELY (rate))
574     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
575   if (G_LIKELY (applied_rate))
576     *applied_rate =
577         g_value_get_double (gst_structure_get_value (structure,
578             "applied_rate"));
579   if (G_LIKELY (format))
580     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
581   if (G_LIKELY (start))
582     *start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
583   if (G_LIKELY (stop))
584     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
585   if (G_LIKELY (position))
586     *position =
587         g_value_get_int64 (gst_structure_get_value (structure, "position"));
588 }
589
590 /**
591  * gst_event_new_tag:
592  * @taglist: metadata list
593  *
594  * Generates a metadata tag event from the given @taglist.
595  *
596  * Returns: a new #GstEvent
597  */
598 GstEvent *
599 gst_event_new_tag (GstTagList * taglist)
600 {
601   g_return_val_if_fail (taglist != NULL, NULL);
602   return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
603 }
604
605 /**
606  * gst_event_parse_tag:
607  * @event: a tag event
608  * @taglist: pointer to metadata list
609  *
610  * Parses a tag @event and stores the results in the given @taglist location.
611  */
612 void
613 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
614 {
615   g_return_if_fail (GST_IS_EVENT (event));
616   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
617   if (taglist)
618     *taglist = (GstTagList *) event->structure;
619 }
620
621 /* buffersize event */
622 /**
623  * gst_event_new_buffer_size:
624  * @format: buffer format
625  * @minsize: minimum buffer size
626  * @maxsize: maximum buffer size
627  * @async: thread behavior
628  *
629  * Create a new buffersize event. The event is sent downstream and notifies
630  * elements that they should provide a buffer of the specified dimensions.
631  *
632  * When the async flag is set, a thread boundary is prefered.
633  *
634  * Returns: a new #GstEvent
635  */
636 GstEvent *
637 gst_event_new_buffer_size (GstFormat format, gint64 minsize,
638     gint64 maxsize, gboolean async)
639 {
640   GST_CAT_INFO (GST_CAT_EVENT,
641       "creating buffersize format %d, minsize %" G_GINT64_FORMAT
642       ", maxsize %" G_GINT64_FORMAT ", async %d", format,
643       minsize, maxsize, async);
644   return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
645       gst_structure_new ("GstEventBufferSize",
646           "format", GST_TYPE_FORMAT, format,
647           "minsize", G_TYPE_INT64, minsize,
648           "maxsize", G_TYPE_INT64, maxsize,
649           "async", G_TYPE_BOOLEAN, async, NULL));
650 }
651
652 /**
653  * gst_event_parse_buffer_size:
654  * @event: The event to query
655  * @format: A pointer to store the format in
656  * @minsize: A pointer to store the minsize in
657  * @maxsize: A pointer to store the maxsize in
658  * @async: A pointer to store the async-flag in
659  *
660  * Get the format, minsize, maxsize and async-flag in the buffersize event.
661  */
662 void
663 gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
664     gint64 * minsize, gint64 * maxsize, gboolean * async)
665 {
666   const GstStructure *structure;
667
668   g_return_if_fail (GST_IS_EVENT (event));
669   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
670   structure = gst_event_get_structure (event);
671   if (format)
672     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
673   if (minsize)
674     *minsize =
675         g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
676   if (maxsize)
677     *maxsize =
678         g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
679   if (async)
680     *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
681 }
682
683 /**
684  * gst_event_new_qos:
685  * @proportion: the proportion of the qos message
686  * @diff: The time difference of the last Clock sync
687  * @timestamp: The timestamp of the buffer
688  *
689  * Allocate a new qos event with the given values.
690  * The QOS event is generated in an element that wants an upstream
691  * element to either reduce or increase its rate because of
692  * high/low CPU load or other resource usage such as network performance.
693  *
694  * @proportion is the requested adjustment in datarate, 1.0 is the normal
695  * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
696  * values request a slow down, so -0.75 means a decrease by 75%.
697  *
698  * @diff is the difference against the clock in stream time of the last
699  * buffer that caused the element to generate the QOS event.
700  *
701  * @timestamp is the timestamp of the last buffer that cause the element
702  * to generate the QOS event. 
703  *
704  * The upstream element can use the @diff and @timestamp values to decide
705  * whether to process more buffers. All buffers with timestamp <=
706  * @timestamp + @diff will certainly arrive late in the sink as well. 
707  *
708  * The @proportion value is generally computed based on more long
709  * term statistics about the stream quality and can be used in various ways
710  * such as lowering or increasing processing quality.
711  *
712  * The application can use general event probes to intercept the QoS
713  * event and implement custom application specific QoS handling.
714  *
715  * Returns: A new QOS event.
716  */
717 GstEvent *
718 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
719     GstClockTime timestamp)
720 {
721   GST_CAT_INFO (GST_CAT_EVENT,
722       "creating qos proportion %lf, diff %" G_GINT64_FORMAT
723       ", timestamp %" GST_TIME_FORMAT, proportion,
724       diff, GST_TIME_ARGS (timestamp));
725
726   return gst_event_new_custom (GST_EVENT_QOS,
727       gst_structure_new ("GstEventQOS",
728           "proportion", G_TYPE_DOUBLE, proportion,
729           "diff", G_TYPE_INT64, diff,
730           "timestamp", G_TYPE_UINT64, timestamp, NULL));
731 }
732
733 /**
734  * gst_event_parse_qos:
735  * @event: The event to query
736  * @proportion: A pointer to store the proportion in
737  * @diff: A pointer to store the diff in
738  * @timestamp: A pointer to store the timestamp in
739  *
740  * Get the proportion, diff and timestamp in the qos event.
741  */
742 void
743 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
744     GstClockTimeDiff * diff, GstClockTime * timestamp)
745 {
746   const GstStructure *structure;
747
748   g_return_if_fail (GST_IS_EVENT (event));
749   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
750   structure = gst_event_get_structure (event);
751   if (proportion)
752     *proportion =
753         g_value_get_double (gst_structure_get_value (structure, "proportion"));
754   if (diff)
755     *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
756   if (timestamp)
757     *timestamp =
758         g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
759 }
760
761 /**
762  * gst_event_new_seek:
763  * @rate: The new playback rate
764  * @format: The format of the seek values
765  * @flags: The optional seek flags
766  * @cur_type: The type and flags for the new current position
767  * @cur: The value of the new current position
768  * @stop_type: The type and flags for the new stop position
769  * @stop: The value of the new stop position
770  *
771  * Allocate a new seek event with the given parameters.
772  *
773  * The seek event configures playback of the pipeline from
774  * @cur to @stop at the speed given in @rate, also called a segment.
775  * The @cur and @stop values are expressed in format @format.
776  *
777  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
778  * Negatives values means backwards playback. A value of 0.0 for the
779  * rate is not allowed.
780  *
781  * @cur_type and @stop_type specify how to adjust the current and stop
782  * time, relative or absolute. A type of #GST_SEEK_TYPE_NONE means that
783  * the position should not be updated. The currently configured playback
784  * segment can be queried with #GST_QUERY_SEGMENT.
785  *
786  * Note that updating the @cur position will actually move the current
787  * playback pointer to that new position. It is not possible to seek 
788  * relative to the current playing position, to do this, pause the pipeline,
789  * get the current position and perform a GST_SEEK_TYPE_SET to the desired
790  * position.
791  *
792  * Returns: A new seek event.
793  */
794 GstEvent *
795 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
796     GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
797 {
798   if (format == GST_FORMAT_TIME) {
799     GST_CAT_INFO (GST_CAT_EVENT,
800         "creating seek rate %lf, format TIME, flags %d, "
801         "cur_type %d, cur %" GST_TIME_FORMAT ", "
802         "stop_type %d, stop %" GST_TIME_FORMAT,
803         rate, flags, cur_type, GST_TIME_ARGS (cur),
804         stop_type, GST_TIME_ARGS (stop));
805   } else {
806     GST_CAT_INFO (GST_CAT_EVENT,
807         "creating seek rate %lf, format %d, flags %d, "
808         "cur_type %d, cur %" G_GINT64_FORMAT ", "
809         "stop_type %d, stop %" G_GINT64_FORMAT,
810         rate, format, flags, cur_type, cur, stop_type, stop);
811   }
812
813   return gst_event_new_custom (GST_EVENT_SEEK,
814       gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
815           "format", GST_TYPE_FORMAT, format,
816           "flags", GST_TYPE_SEEK_FLAGS, flags,
817           "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
818           "cur", G_TYPE_INT64, cur,
819           "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
820           "stop", G_TYPE_INT64, stop, NULL));
821 }
822
823 /**
824  * gst_event_parse_seek:
825  * @event: a seek event
826  * @rate: result location for the rate
827  * @format: result location for the stream format
828  * @flags:  result location for the #GstSeekFlags
829  * @cur_type: result location for the #GstSeekType of the current position
830  * @cur: result location for the current postion expressed in @format
831  * @stop_type:  result location for the #GstSeekType of the stop position
832  * @stop: result location for the stop postion expressed in @format
833  *
834  * Parses a seek @event and stores the results in the given result locations.
835  */
836 void
837 gst_event_parse_seek (GstEvent * event, gdouble * rate,
838     GstFormat * format, GstSeekFlags * flags, GstSeekType * cur_type,
839     gint64 * cur, GstSeekType * stop_type, gint64 * stop)
840 {
841   const GstStructure *structure;
842
843   g_return_if_fail (GST_IS_EVENT (event));
844   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
845   structure = gst_event_get_structure (event);
846   if (rate)
847     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
848   if (format)
849     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
850   if (flags)
851     *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
852   if (cur_type)
853     *cur_type =
854         g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
855   if (cur)
856     *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
857   if (stop_type)
858     *stop_type =
859         g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
860   if (stop)
861     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
862 }
863
864 /**
865  * gst_event_new_navigation:
866  * @structure: description of the event
867  *
868  * Create a new navigation event from the given description.
869  *
870  * Returns: a new #GstEvent
871  */
872 GstEvent *
873 gst_event_new_navigation (GstStructure * structure)
874 {
875   g_return_val_if_fail (structure != NULL, NULL);
876   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
877 }