09d01e3cf884f6111893aca2c0b84cb8449fc0a3
[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 event type as
30  * an argument. Properties specific to the event can be set afterwards with the
31  * provided macros. The event should be unreferenced with gst_event_unref().
32  *
33  * gst_event_new_seek() is a usually used to create a seek event and it takes
34  * the needed parameters for a seek event. 
35  *
36  * gst_event_new_flush() creates a new flush event.
37  */
38
39 #include <string.h>             /* memcpy */
40
41 #include "gst_private.h"
42
43 #include "gstinfo.h"
44 #include "gstevent.h"
45 #include "gstenumtypes.h"
46 #include "gstutils.h"
47
48 static void gst_event_init (GTypeInstance * instance, gpointer g_class);
49 static void gst_event_class_init (gpointer g_class, gpointer class_data);
50 static void gst_event_finalize (GstEvent * event);
51 static GstEvent *_gst_event_copy (GstEvent * event);
52
53 void
54 _gst_event_initialize (void)
55 {
56   gst_event_get_type ();
57 }
58
59 GType
60 gst_event_get_type (void)
61 {
62   static GType _gst_event_type;
63
64   if (G_UNLIKELY (_gst_event_type == 0)) {
65     static const GTypeInfo event_info = {
66       sizeof (GstEventClass),
67       NULL,
68       NULL,
69       gst_event_class_init,
70       NULL,
71       NULL,
72       sizeof (GstEvent),
73       0,
74       gst_event_init,
75       NULL
76     };
77
78     _gst_event_type = g_type_register_static (GST_TYPE_MINI_OBJECT,
79         "GstEvent", &event_info, 0);
80   }
81
82   return _gst_event_type;
83 }
84
85 static void
86 gst_event_class_init (gpointer g_class, gpointer class_data)
87 {
88   GstEventClass *event_class = GST_EVENT_CLASS (g_class);
89
90   event_class->mini_object_class.copy =
91       (GstMiniObjectCopyFunction) _gst_event_copy;
92   event_class->mini_object_class.finalize =
93       (GstMiniObjectFinalizeFunction) gst_event_finalize;
94 }
95
96 static void
97 gst_event_init (GTypeInstance * instance, gpointer g_class)
98 {
99   GstEvent *event;
100
101   event = GST_EVENT (instance);
102
103   GST_EVENT_TIMESTAMP (event) = GST_CLOCK_TIME_NONE;
104 }
105
106 static void
107 gst_event_finalize (GstEvent * event)
108 {
109   g_return_if_fail (event != NULL);
110   g_return_if_fail (GST_IS_EVENT (event));
111
112   GST_CAT_INFO (GST_CAT_EVENT, "freeing event %p", event);
113
114   if (GST_EVENT_SRC (event)) {
115     gst_object_unref (GST_EVENT_SRC (event));
116     GST_EVENT_SRC (event) = NULL;
117   }
118   if (event->structure) {
119     gst_structure_set_parent_refcount (event->structure, NULL);
120     gst_structure_free (event->structure);
121   }
122 }
123
124 static GstEvent *
125 _gst_event_copy (GstEvent * event)
126 {
127   GstEvent *copy;
128
129   copy = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
130
131   GST_EVENT_TYPE (copy) = GST_EVENT_TYPE (event);
132   GST_EVENT_TIMESTAMP (copy) = GST_EVENT_TIMESTAMP (event);
133
134   if (GST_EVENT_SRC (event)) {
135     GST_EVENT_SRC (copy) = gst_object_ref (GST_EVENT_SRC (event));
136   }
137   if (event->structure) {
138     copy->structure = gst_structure_copy (event->structure);
139     gst_structure_set_parent_refcount (copy->structure,
140         &event->mini_object.refcount);
141   }
142   return copy;
143 }
144
145 static GstEvent *
146 gst_event_new (GstEventType type)
147 {
148   GstEvent *event;
149
150   event = (GstEvent *) gst_mini_object_new (GST_TYPE_EVENT);
151
152   GST_CAT_INFO (GST_CAT_EVENT, "creating new event %p %d", event, type);
153
154   event->type = type;
155   event->src = NULL;
156   event->structure = NULL;
157
158   return event;
159 }
160
161 /**
162  * gst_event_new_custom:
163  * @type: The type of the new event
164  * @structure: The structure for the event. The event will take ownership of
165  * the structure.
166  *
167  * Create a new custom-typed event. This can be used for anything not
168  * handled by other event-specific functions to pass an event to another
169  * element.
170  *
171  * Make sure to allocate an event type with the #GST_EVENT_MAKE_TYPE macro,
172  * assigning a free number and filling in the correct direction and
173  * serialization flags.
174  *
175  * New custom events can also be created by subclassing the event type if
176  * needed.
177  *
178  * Returns: The new custom event.
179  */
180 GstEvent *
181 gst_event_new_custom (GstEventType type, GstStructure * structure)
182 {
183   GstEvent *event;
184
185   event = gst_event_new (type);
186   if (structure) {
187     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
188     event->structure = structure;
189   }
190   return event;
191 }
192
193 /**
194  * gst_event_get_structure:
195  * @event: The #GstEvent.
196  *
197  * Access the structure of the event.
198  *
199  * Returns: The structure of the event. The structure is still
200  * owned by the event, which means that you should not free it and
201  * that the pointer becomes invalid when you free the event.
202  *
203  * MT safe.
204  */
205 const GstStructure *
206 gst_event_get_structure (GstEvent * event)
207 {
208   g_return_val_if_fail (GST_IS_EVENT (event), NULL);
209
210   return event->structure;
211 }
212
213 /**
214  * gst_event_new_flush_start:
215  *
216  * Allocate a new flush start event. The flush start event can be send
217  * upstream and downstream and travels out-of-bounds with the dataflow.
218  * It marks pads as being in a WRONG_STATE to process more data.
219  *
220  * Elements unlock and blocking functions and exit their streaming functions
221  * as fast as possible. 
222  *
223  * This event is typically generated after a seek to minimize the latency
224  * after the seek.
225  *
226  * Returns: A new flush start event.
227  */
228 GstEvent *
229 gst_event_new_flush_start (void)
230 {
231   return gst_event_new (GST_EVENT_FLUSH_START);
232 }
233
234 /**
235  * gst_event_new_flush_stop:
236  *
237  * Allocate a new flush stop event. The flush start event can be send
238  * upstream and downstream and travels out-of-bounds with the dataflow.
239  * It is typically send after sending a FLUSH_START event to make the
240  * pads accept data again.
241  *
242  * Elements can process this event synchronized with the dataflow since
243  * the preceeding FLUSH_START event stopped the dataflow.
244  *
245  * This event is typically generated to complete a seek and to resume
246  * dataflow.
247  *
248  * Returns: A new flush stop event.
249  */
250 GstEvent *
251 gst_event_new_flush_stop (void)
252 {
253   return gst_event_new (GST_EVENT_FLUSH_STOP);
254 }
255
256 /**
257  * gst_event_new_eos:
258  *
259  * Create a new EOS event. The eos event can only travel downstream
260  * synchronized with the buffer flow. Elements that receive the EOS
261  * event on a pad can return UNEXPECTED as a GstFlowReturn when data
262  * after the EOS event arrives.
263  *
264  * The EOS event will travel up to the sink elements in the pipeline
265  * which will then post the GST_MESSAGE_EOS on the bus.
266  *
267  * When all sinks have posted an EOS message, the EOS message is
268  * forwarded to the application.
269  *
270  * Returns: The new EOS event.
271  */
272 GstEvent *
273 gst_event_new_eos (void)
274 {
275   return gst_event_new (GST_EVENT_EOS);
276 }
277
278 /**
279  * gst_event_new_newsegment:
280  * @rate: a new rate for playback
281  * @format: The format of the segment values
282  * @start_val: the start value of the segment
283  * @stop_val: the stop value of the segment
284  * @base: base value for buffer timestamps.
285  *
286  * Allocate a new newsegment event with the given format/values tripplets.
287  *
288  * The newsegment event marks the range of buffers to be processed. All
289  * data not within the segment range is not to be processed.
290  *
291  * The base time of the segment is used to convert the buffer timestamps
292  * into the stream time again.
293  *
294  * After a newsegment event, the buffer stream time is calculated with:
295  *
296  *   TIMESTAMP(buf) - start_time + base
297  *
298  * Returns: A new newsegment event.
299  */
300 GstEvent *
301 gst_event_new_newsegment (gdouble rate, GstFormat format,
302     gint64 start_val, gint64 stop_val, gint64 base)
303 {
304   if (format == GST_FORMAT_TIME) {
305     GST_CAT_INFO (GST_CAT_EVENT,
306         "creating newsegment rate %lf, format GST_FORMAT_TIME, "
307         "start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
308         ", base %" GST_TIME_FORMAT,
309         rate, GST_TIME_ARGS (start_val),
310         GST_TIME_ARGS (stop_val), GST_TIME_ARGS (base));
311   } else {
312     GST_CAT_INFO (GST_CAT_EVENT,
313         "creating newsegment rate %lf, format %d, "
314         "start %lld, stop %lld, base %lld",
315         rate, format, start_val, stop_val, base);
316   }
317
318   if (start_val != -1 && stop_val != -1)
319     g_return_val_if_fail (start_val < stop_val, NULL);
320
321   return gst_event_new_custom (GST_EVENT_NEWSEGMENT,
322       gst_structure_new ("GstEventNewsegment", "rate", G_TYPE_DOUBLE, rate,
323           "format", GST_TYPE_FORMAT, format,
324           "start_val", G_TYPE_INT64, start_val,
325           "stop_val", G_TYPE_INT64, stop_val,
326           "base", G_TYPE_INT64, base, NULL));
327 }
328
329 /**
330  * gst_event_parse_newsegment:
331  * @event: The event to query
332  * @rate: A pointer to the rate of the segment
333  * @format: A pointer to the format of the newsegment values
334  * @start_value: A pointer to store the start value in
335  * @stop_value: A pointer to store the stop value in
336  * @base: A pointer to store the base time in
337  *
338  * Get the start, stop and format in the newsegment event.
339  */
340 void
341 gst_event_parse_newsegment (GstEvent * event, gdouble * rate,
342     GstFormat * format, gint64 * start_value, gint64 * stop_value,
343     gint64 * base)
344 {
345   const GstStructure *structure;
346
347   g_return_if_fail (GST_IS_EVENT (event));
348   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
349
350   structure = gst_event_get_structure (event);
351   if (rate)
352     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
353   if (format)
354     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
355   if (start_value)
356     *start_value =
357         g_value_get_int64 (gst_structure_get_value (structure, "start_val"));
358   if (stop_value)
359     *stop_value =
360         g_value_get_int64 (gst_structure_get_value (structure, "stop_val"));
361   if (base)
362     *base = g_value_get_int64 (gst_structure_get_value (structure, "base"));
363 }
364
365 /**
366  * gst_event_new_tag:
367  * @taglist: metadata list
368  *
369  * Generates a metadata tag event from the given @taglist.
370  * 
371  * Returns: a new #GstEvent
372  */
373 GstEvent *
374 gst_event_new_tag (GstTagList * taglist)
375 {
376   g_return_val_if_fail (taglist != NULL, NULL);
377
378   return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
379 }
380
381 /**
382  * gst_event_parse_tag:
383  * @event: a tag event
384  * @taglist: pointer to metadata list
385  *
386  * Parses a tag @event and stores the results in the given @taglist location.
387  */
388 void
389 gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
390 {
391   g_return_if_fail (GST_IS_EVENT (event));
392   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
393
394   if (taglist)
395     *taglist = (GstTagList *) event->structure;
396 }
397
398 /* filler event */
399 /**
400  * gst_event_new_filler:
401  *
402  * Create a new dummy event that should be ignored.
403  *
404  * Returns: a new #GstEvent
405  */
406 GstEvent *
407 gst_event_new_filler (void)
408 {
409   return gst_event_new (GST_EVENT_FILLER);
410 }
411
412 /**
413  * gst_event_new_qos:
414  * @proportion: the proportion of the qos message
415  * @diff: The time difference of the last Clock sync
416  * @timestamp: The timestamp of the buffer
417  *
418  * Allocate a new qos event with the given values.
419  * The QOS event is generated in an element that wants an upstream
420  * element to either reduce or increase its rate because of
421  * high/low CPU load.
422  *
423  * proportion is the requested adjustment in datarate, 1.0 is the normal
424  * datarate, 0.75 means increase datarate by 75%, 1.5 is 150%. Negative
425  * values request a slow down, so -0.75 means a decrease by 75%.
426  *
427  * diff is the difference against the clock in stream time of the last 
428  * buffer that caused the element to generate the QOS event.
429  *
430  * timestamp is the timestamp of the last buffer that cause the element
431  * to generate the QOS event.
432  *
433  * Returns: A new QOS event.
434  */
435 GstEvent *
436 gst_event_new_qos (gdouble proportion, GstClockTimeDiff diff,
437     GstClockTime timestamp)
438 {
439   GST_CAT_INFO (GST_CAT_EVENT,
440       "creating qos proportion %lf, diff %" GST_TIME_FORMAT
441       ", timestamp %" GST_TIME_FORMAT, proportion,
442       GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
443
444   return gst_event_new_custom (GST_EVENT_QOS,
445       gst_structure_new ("GstEventQOS",
446           "proportion", G_TYPE_DOUBLE, proportion,
447           "diff", G_TYPE_INT64, diff,
448           "timestamp", G_TYPE_UINT64, timestamp, NULL));
449 }
450
451 /**
452  * gst_event_parse_qos:
453  * @event: The event to query
454  * @proportion: A pointer to store the proportion in
455  * @diff: A pointer to store the diff in
456  * @timestamp: A pointer to store the timestamp in
457  *
458  * Get the proportion, diff and timestamp in the qos event.
459  */
460 void
461 gst_event_parse_qos (GstEvent * event, gdouble * proportion,
462     GstClockTimeDiff * diff, GstClockTime * timestamp)
463 {
464   const GstStructure *structure;
465
466   g_return_if_fail (GST_IS_EVENT (event));
467   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
468
469   structure = gst_event_get_structure (event);
470   if (proportion)
471     *proportion =
472         g_value_get_double (gst_structure_get_value (structure, "proportion"));
473   if (diff)
474     *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
475   if (timestamp)
476     *timestamp =
477         g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
478 }
479
480 /**
481  * gst_event_new_seek:
482  * @rate: The new playback rate
483  * @format: The format of the seek values
484  * @flags: The optional seek flags.
485  * @cur_type: The type and flags for the new current position
486  * @cur: The value of the new current position
487  * @stop_type: The type and flags for the new stop position
488  * @stop: The value of the new stop position
489  *
490  * Allocate a new seek event with the given parameters.
491  *
492  * The seek event configures playback of the pipeline from 
493  * @cur to @stop at the speed given in @rate.
494  * The @cur and @stop values are expressed in format @format.
495  *
496  * A @rate of 1.0 means normal playback rate, 2.0 means double speed.
497  * Negatives values means backwards playback. A value of 0.0 for the
498  * rate is not allowed.
499  *
500  * @cur_type and @stop_type specify how to adjust the current and stop
501  * time, relative or absolute. A type of #GST_EVENT_TYPE_NONE means that
502  * the position should not be updated.
503  *
504  * Returns: A new seek event.
505  */
506 GstEvent *
507 gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
508     GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
509 {
510   if (format == GST_FORMAT_TIME) {
511     GST_CAT_INFO (GST_CAT_EVENT,
512         "creating seek rate %lf, format TIME, flags %d, "
513         "cur_type %d, cur %" GST_TIME_FORMAT ", "
514         "stop_type %d, stop %" GST_TIME_FORMAT,
515         rate, flags, cur_type, GST_TIME_ARGS (cur),
516         stop_type, GST_TIME_ARGS (stop));
517   } else {
518     GST_CAT_INFO (GST_CAT_EVENT,
519         "creating seek rate %lf, format %d, flags %d, "
520         "cur_type %d, cur %" G_GINT64_FORMAT ", "
521         "stop_type %d, stop %" G_GINT64_FORMAT,
522         rate, format, flags, cur_type, cur, stop_type, stop);
523   }
524
525   return gst_event_new_custom (GST_EVENT_SEEK,
526       gst_structure_new ("GstEventSeek", "rate", G_TYPE_DOUBLE, rate,
527           "format", GST_TYPE_FORMAT, format,
528           "flags", GST_TYPE_SEEK_FLAGS, flags,
529           "cur_type", GST_TYPE_SEEK_TYPE, cur_type,
530           "cur", G_TYPE_INT64, cur,
531           "stop_type", GST_TYPE_SEEK_TYPE, stop_type,
532           "stop", G_TYPE_INT64, stop, NULL));
533 }
534
535 /**
536  * gst_event_parse_seek:
537  * @event: a seek event
538  * @rate: result location for the rate
539  * @format: result location for the stream format
540  * @flags:  result location for the #GstSeekFlags
541  * @cur_type: result location for the #GstSeekType of the current position
542  * @cur: result location for the current postion expressed in @format
543  * @stop_type:  result location for the #GstSeekType of the stop position
544  * @stop: result location for the stop postion expressed in @format
545  *
546  * Parses a seek @event and stores the results in the given result locations.
547  */
548 void
549 gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
550     GstSeekFlags * flags,
551     GstSeekType * cur_type, gint64 * cur,
552     GstSeekType * stop_type, gint64 * stop)
553 {
554   const GstStructure *structure;
555
556   g_return_if_fail (GST_IS_EVENT (event));
557   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
558
559   structure = gst_event_get_structure (event);
560   if (rate)
561     *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
562   if (format)
563     *format = g_value_get_enum (gst_structure_get_value (structure, "format"));
564   if (flags)
565     *flags = g_value_get_flags (gst_structure_get_value (structure, "flags"));
566   if (cur_type)
567     *cur_type =
568         g_value_get_enum (gst_structure_get_value (structure, "cur_type"));
569   if (cur)
570     *cur = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
571   if (stop_type)
572     *stop_type =
573         g_value_get_enum (gst_structure_get_value (structure, "stop_type"));
574   if (stop)
575     *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
576 }
577
578 /**
579  * gst_event_new_navigation:
580  * @structure: description of the event
581  *
582  * Create a new navigation event from the given description.
583  *
584  * Returns: a new #GstEvent
585  */
586 GstEvent *
587 gst_event_new_navigation (GstStructure * structure)
588 {
589   g_return_val_if_fail (structure != NULL, NULL);
590
591   return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
592 }