gstutils: Fix linear regression comparision
[platform/upstream/gstreamer.git] / gst / gstmessage.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  *
4  * gstmessage.c: GstMessage subsystem
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:gstmessage
24  * @title: GstMessage
25  * @short_description: Lightweight objects to signal the application of
26  *                     pipeline events
27  * @see_also: #GstBus, #GstMiniObject, #GstElement
28  *
29  * Messages are implemented as a subclass of #GstMiniObject with a generic
30  * #GstStructure as the content. This allows for writing custom messages without
31  * requiring an API change while allowing a wide range of different types
32  * of messages.
33  *
34  * Messages are posted by objects in the pipeline and are passed to the
35  * application using the #GstBus.
36  *
37  * The basic use pattern of posting a message on a #GstBus is as follows:
38  * |[<!-- language="C" -->
39  *   gst_bus_post (bus, gst_message_new_eos());
40  * ]|
41  *
42  * A #GstElement usually posts messages on the bus provided by the parent
43  * container using gst_element_post_message().
44  */
45
46
47 #include "gst_private.h"
48 #include <string.h>             /* memcpy */
49 #include "gsterror.h"
50 #include "gstenumtypes.h"
51 #include "gstinfo.h"
52 #include "gstmessage.h"
53 #include "gsttaglist.h"
54 #include "gstutils.h"
55 #include "gstquark.h"
56 #include "gstvalue.h"
57
58
59 typedef struct
60 {
61   GstMessage message;
62
63   GstStructure *structure;
64 } GstMessageImpl;
65
66 #define GST_MESSAGE_STRUCTURE(m)  (((GstMessageImpl *)(m))->structure)
67
68 typedef struct
69 {
70   const gint type;
71   const gchar *name;
72   GQuark quark;
73 } GstMessageQuarks;
74
75 static GstMessageQuarks message_quarks[] = {
76   {GST_MESSAGE_UNKNOWN, "unknown", 0},
77   {GST_MESSAGE_EOS, "eos", 0},
78   {GST_MESSAGE_ERROR, "error", 0},
79   {GST_MESSAGE_WARNING, "warning", 0},
80   {GST_MESSAGE_INFO, "info", 0},
81   {GST_MESSAGE_TAG, "tag", 0},
82   {GST_MESSAGE_BUFFERING, "buffering", 0},
83   {GST_MESSAGE_STATE_CHANGED, "state-changed", 0},
84   {GST_MESSAGE_STATE_DIRTY, "state-dirty", 0},
85   {GST_MESSAGE_STEP_DONE, "step-done", 0},
86   {GST_MESSAGE_CLOCK_PROVIDE, "clock-provide", 0},
87   {GST_MESSAGE_CLOCK_LOST, "clock-lost", 0},
88   {GST_MESSAGE_NEW_CLOCK, "new-clock", 0},
89   {GST_MESSAGE_STRUCTURE_CHANGE, "structure-change", 0},
90   {GST_MESSAGE_STREAM_STATUS, "stream-status", 0},
91   {GST_MESSAGE_APPLICATION, "application", 0},
92   {GST_MESSAGE_ELEMENT, "element", 0},
93   {GST_MESSAGE_SEGMENT_START, "segment-start", 0},
94   {GST_MESSAGE_SEGMENT_DONE, "segment-done", 0},
95   {GST_MESSAGE_DURATION_CHANGED, "duration-changed", 0},
96   {GST_MESSAGE_LATENCY, "latency", 0},
97   {GST_MESSAGE_ASYNC_START, "async-start", 0},
98   {GST_MESSAGE_ASYNC_DONE, "async-done", 0},
99   {GST_MESSAGE_REQUEST_STATE, "request-state", 0},
100   {GST_MESSAGE_STEP_START, "step-start", 0},
101   {GST_MESSAGE_QOS, "qos", 0},
102   {GST_MESSAGE_PROGRESS, "progress", 0},
103   {GST_MESSAGE_TOC, "toc", 0},
104   {GST_MESSAGE_RESET_TIME, "reset-time", 0},
105   {GST_MESSAGE_STREAM_START, "stream-start", 0},
106   {GST_MESSAGE_NEED_CONTEXT, "need-context", 0},
107   {GST_MESSAGE_HAVE_CONTEXT, "have-context", 0},
108   {GST_MESSAGE_DEVICE_ADDED, "device-added", 0},
109   {GST_MESSAGE_DEVICE_REMOVED, "device-removed", 0},
110   {GST_MESSAGE_PROPERTY_NOTIFY, "property-notify", 0},
111   {GST_MESSAGE_STREAM_COLLECTION, "stream-collection", 0},
112   {GST_MESSAGE_STREAMS_SELECTED, "streams-selected", 0},
113   {GST_MESSAGE_REDIRECT, "redirect", 0},
114   {0, NULL, 0}
115 };
116
117 static GQuark details_quark = 0;
118
119 GType _gst_message_type = 0;
120 GST_DEFINE_MINI_OBJECT_TYPE (GstMessage, gst_message);
121
122 void
123 _priv_gst_message_initialize (void)
124 {
125   gint i;
126
127   GST_CAT_INFO (GST_CAT_GST_INIT, "init messages");
128
129   for (i = 0; message_quarks[i].name; i++) {
130     message_quarks[i].quark =
131         g_quark_from_static_string (message_quarks[i].name);
132   }
133   details_quark = g_quark_from_static_string ("details");
134
135   _gst_message_type = gst_message_get_type ();
136 }
137
138 /**
139  * gst_message_type_get_name:
140  * @type: the message type
141  *
142  * Get a printable name for the given message type. Do not modify or free.
143  *
144  * Returns: a reference to the static name of the message.
145  */
146 const gchar *
147 gst_message_type_get_name (GstMessageType type)
148 {
149   gint i;
150
151   for (i = 0; message_quarks[i].name; i++) {
152     if (type == message_quarks[i].type)
153       return message_quarks[i].name;
154   }
155   return "unknown";
156 }
157
158 /**
159  * gst_message_type_to_quark:
160  * @type: the message type
161  *
162  * Get the unique quark for the given message type.
163  *
164  * Returns: the quark associated with the message type
165  */
166 GQuark
167 gst_message_type_to_quark (GstMessageType type)
168 {
169   gint i;
170
171   for (i = 0; message_quarks[i].name; i++) {
172     if (type == message_quarks[i].type)
173       return message_quarks[i].quark;
174   }
175   return 0;
176 }
177
178 static gboolean
179 _gst_message_dispose (GstMessage * message)
180 {
181   gboolean do_free = TRUE;
182
183   if (GST_MINI_OBJECT_FLAG_IS_SET (message, GST_MESSAGE_FLAG_ASYNC_DELIVERY)) {
184     /* revive message, so bus can finish with it and clean it up */
185     gst_message_ref (message);
186
187     GST_INFO ("[msg %p] signalling async free", message);
188
189     GST_MESSAGE_LOCK (message);
190     GST_MESSAGE_SIGNAL (message);
191     GST_MESSAGE_UNLOCK (message);
192
193     /* don't free it yet, let bus finish with it first */
194     do_free = FALSE;
195   }
196
197   return do_free;
198 }
199
200 static void
201 _gst_message_free (GstMessage * message)
202 {
203   GstStructure *structure;
204
205   g_return_if_fail (message != NULL);
206
207   GST_CAT_LOG (GST_CAT_MESSAGE, "finalize message %p, %s from %s", message,
208       GST_MESSAGE_TYPE_NAME (message), GST_MESSAGE_SRC_NAME (message));
209
210   if (GST_MESSAGE_SRC (message)) {
211     gst_object_unref (GST_MESSAGE_SRC (message));
212     GST_MESSAGE_SRC (message) = NULL;
213   }
214
215   structure = GST_MESSAGE_STRUCTURE (message);
216   if (structure) {
217     gst_structure_set_parent_refcount (structure, NULL);
218     gst_structure_free (structure);
219   }
220
221   g_slice_free1 (sizeof (GstMessageImpl), message);
222 }
223
224 static void
225 gst_message_init (GstMessageImpl * message, GstMessageType type,
226     GstObject * src);
227
228 static GstMessage *
229 _gst_message_copy (GstMessage * message)
230 {
231   GstMessageImpl *copy;
232   GstStructure *structure;
233
234   GST_CAT_LOG (GST_CAT_MESSAGE, "copy message %p, %s from %s", message,
235       GST_MESSAGE_TYPE_NAME (message),
236       GST_OBJECT_NAME (GST_MESSAGE_SRC (message)));
237
238   copy = g_slice_new0 (GstMessageImpl);
239
240   gst_message_init (copy, GST_MESSAGE_TYPE (message),
241       GST_MESSAGE_SRC (message));
242
243   GST_MESSAGE_TIMESTAMP (copy) = GST_MESSAGE_TIMESTAMP (message);
244   GST_MESSAGE_SEQNUM (copy) = GST_MESSAGE_SEQNUM (message);
245
246   structure = GST_MESSAGE_STRUCTURE (message);
247   if (structure) {
248     GST_MESSAGE_STRUCTURE (copy) = gst_structure_copy (structure);
249     gst_structure_set_parent_refcount (GST_MESSAGE_STRUCTURE (copy),
250         &copy->message.mini_object.refcount);
251   } else {
252     GST_MESSAGE_STRUCTURE (copy) = NULL;
253   }
254
255   return GST_MESSAGE_CAST (copy);
256 }
257
258 static void
259 gst_message_init (GstMessageImpl * message, GstMessageType type,
260     GstObject * src)
261 {
262   gst_mini_object_init (GST_MINI_OBJECT_CAST (message), 0, _gst_message_type,
263       (GstMiniObjectCopyFunction) _gst_message_copy,
264       (GstMiniObjectDisposeFunction) _gst_message_dispose,
265       (GstMiniObjectFreeFunction) _gst_message_free);
266
267   GST_MESSAGE_TYPE (message) = type;
268   if (src)
269     gst_object_ref (src);
270   GST_MESSAGE_SRC (message) = src;
271   GST_MESSAGE_TIMESTAMP (message) = GST_CLOCK_TIME_NONE;
272   GST_MESSAGE_SEQNUM (message) = gst_util_seqnum_next ();
273 }
274
275
276 /**
277  * gst_message_new_custom:
278  * @type: The #GstMessageType to distinguish messages
279  * @src: (transfer none) (allow-none): The object originating the message.
280  * @structure: (transfer full) (allow-none): the structure for the
281  *     message. The message will take ownership of the structure.
282  *
283  * Create a new custom-typed message. This can be used for anything not
284  * handled by other message-specific functions to pass a message to the
285  * app. The structure field can be %NULL.
286  *
287  * Returns: (transfer full): The new message.
288  *
289  * MT safe.
290  */
291 GstMessage *
292 gst_message_new_custom (GstMessageType type, GstObject * src,
293     GstStructure * structure)
294 {
295   GstMessageImpl *message;
296
297   message = g_slice_new0 (GstMessageImpl);
298
299   GST_CAT_LOG (GST_CAT_MESSAGE, "source %s: creating new message %p %s",
300       (src ? GST_OBJECT_NAME (src) : "NULL"), message,
301       gst_message_type_get_name (type));
302
303   if (structure) {
304     /* structure must not have a parent */
305     if (!gst_structure_set_parent_refcount (structure,
306             &message->message.mini_object.refcount))
307       goto had_parent;
308   }
309   gst_message_init (message, type, src);
310
311   GST_MESSAGE_STRUCTURE (message) = structure;
312
313   return GST_MESSAGE_CAST (message);
314
315   /* ERRORS */
316 had_parent:
317   {
318     g_slice_free1 (sizeof (GstMessageImpl), message);
319     g_warning ("structure is already owned by another object");
320     return NULL;
321   }
322 }
323
324 /**
325  * gst_message_get_seqnum:
326  * @message: A #GstMessage.
327  *
328  * Retrieve the sequence number of a message.
329  *
330  * Messages have ever-incrementing sequence numbers, which may also be set
331  * explicitly via gst_message_set_seqnum(). Sequence numbers are typically used
332  * to indicate that a message corresponds to some other set of messages or
333  * events, for example a SEGMENT_DONE message corresponding to a SEEK event. It
334  * is considered good practice to make this correspondence when possible, though
335  * it is not required.
336  *
337  * Note that events and messages share the same sequence number incrementor;
338  * two events or messages will never have the same sequence number unless
339  * that correspondence was made explicitly.
340  *
341  * Returns: The message's sequence number.
342  *
343  * MT safe.
344  */
345 guint32
346 gst_message_get_seqnum (GstMessage * message)
347 {
348   g_return_val_if_fail (GST_IS_MESSAGE (message), -1);
349
350   return GST_MESSAGE_SEQNUM (message);
351 }
352
353 /**
354  * gst_message_set_seqnum:
355  * @message: A #GstMessage.
356  * @seqnum: A sequence number.
357  *
358  * Set the sequence number of a message.
359  *
360  * This function might be called by the creator of a message to indicate that
361  * the message relates to other messages or events. See gst_message_get_seqnum()
362  * for more information.
363  *
364  * MT safe.
365  */
366 void
367 gst_message_set_seqnum (GstMessage * message, guint32 seqnum)
368 {
369   g_return_if_fail (GST_IS_MESSAGE (message));
370
371   GST_MESSAGE_SEQNUM (message) = seqnum;
372 }
373
374 /**
375  * gst_message_new_eos:
376  * @src: (transfer none) (allow-none): The object originating the message.
377  *
378  * Create a new eos message. This message is generated and posted in
379  * the sink elements of a GstBin. The bin will only forward the EOS
380  * message to the application if all sinks have posted an EOS message.
381  *
382  * Returns: (transfer full): The new eos message.
383  *
384  * MT safe.
385  */
386 GstMessage *
387 gst_message_new_eos (GstObject * src)
388 {
389   GstMessage *message;
390
391   message = gst_message_new_custom (GST_MESSAGE_EOS, src, NULL);
392
393   return message;
394 }
395
396 /**
397  * gst_message_new_error_with_details:
398  * @src: (transfer none) (allow-none): The object originating the message.
399  * @error: (transfer none): The GError for this message.
400  * @debug: A debugging string.
401  * @details: (transfer full): (allow-none): A GstStructure with details
402  *
403  * Create a new error message. The message will copy @error and
404  * @debug. This message is posted by element when a fatal event
405  * occurred. The pipeline will probably (partially) stop. The application
406  * receiving this message should stop the pipeline.
407  *
408  * Returns: (transfer full): the new error message.
409  *
410  * Since: 1.10
411  */
412 GstMessage *
413 gst_message_new_error_with_details (GstObject * src, GError * error,
414     const gchar * debug, GstStructure * details)
415 {
416   GstMessage *message;
417   GstStructure *structure;
418
419   if (debug && !g_utf8_validate (debug, -1, NULL)) {
420     debug = NULL;
421     g_warning ("Trying to set debug field of error message, but "
422         "string is not valid UTF-8. Please file a bug.");
423   }
424
425   structure = gst_structure_new_id (GST_QUARK (MESSAGE_ERROR),
426       GST_QUARK (GERROR), G_TYPE_ERROR, error,
427       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
428   message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure);
429   if (details) {
430     GValue v = G_VALUE_INIT;
431
432     g_value_init (&v, GST_TYPE_STRUCTURE);
433     g_value_take_boxed (&v, details);
434     gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
435         &v);
436   }
437
438   return message;
439 }
440
441 /**
442  * gst_message_new_error:
443  * @src: (transfer none) (allow-none): The object originating the message.
444  * @error: (transfer none): The GError for this message.
445  * @debug: A debugging string.
446  *
447  * Create a new error message. The message will copy @error and
448  * @debug. This message is posted by element when a fatal event
449  * occurred. The pipeline will probably (partially) stop. The application
450  * receiving this message should stop the pipeline.
451  *
452  * Returns: (transfer full): the new error message.
453  *
454  * MT safe.
455  */
456 GstMessage *
457 gst_message_new_error (GstObject * src, GError * error, const gchar * debug)
458 {
459   return gst_message_new_error_with_details (src, error, debug, NULL);
460 }
461
462 /**
463  * gst_message_parse_error_details:
464  * @message: The message object
465  * @structure: (out): A pointer to the returned details
466  *
467  * Returns the optional details structure, may be NULL if none.
468  * The returned structure must not be freed.
469  *
470  * Since: 1.10
471  */
472 void
473 gst_message_parse_error_details (GstMessage * message,
474     const GstStructure ** structure)
475 {
476   const GValue *v;
477
478   g_return_if_fail (GST_IS_MESSAGE (message));
479   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
480   g_return_if_fail (structure != NULL);
481
482   *structure = NULL;
483   v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
484       details_quark);
485   if (v) {
486     *structure = g_value_get_boxed (v);
487   }
488 }
489
490 /**
491  * gst_message_new_warning_with_details:
492  * @src: (transfer none) (allow-none): The object originating the message.
493  * @error: (transfer none): The GError for this message.
494  * @debug: A debugging string.
495  * @details: (transfer full): (allow-none): A GstStructure with details
496  *
497  * Create a new warning message. The message will make copies of @error and
498  * @debug.
499  *
500  * Returns: (transfer full): the new warning message.
501  *
502  * Since: 1.10
503  */
504 GstMessage *
505 gst_message_new_warning_with_details (GstObject * src, GError * error,
506     const gchar * debug, GstStructure * details)
507 {
508   GstMessage *message;
509   GstStructure *structure;
510
511   if (debug && !g_utf8_validate (debug, -1, NULL)) {
512     debug = NULL;
513     g_warning ("Trying to set debug field of warning message, but "
514         "string is not valid UTF-8. Please file a bug.");
515   }
516
517   structure = gst_structure_new_id (GST_QUARK (MESSAGE_WARNING),
518       GST_QUARK (GERROR), G_TYPE_ERROR, error,
519       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
520   message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure);
521   if (details) {
522     GValue v = G_VALUE_INIT;
523
524     g_value_init (&v, GST_TYPE_STRUCTURE);
525     g_value_take_boxed (&v, details);
526     gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
527         &v);
528   }
529
530   return message;
531 }
532
533 /**
534  * gst_message_new_warning:
535  * @src: (transfer none) (allow-none): The object originating the message.
536  * @error: (transfer none): The GError for this message.
537  * @debug: A debugging string.
538  *
539  * Create a new warning message. The message will make copies of @error and
540  * @debug.
541  *
542  * Returns: (transfer full): the new warning message.
543  *
544  * MT safe.
545  */
546 GstMessage *
547 gst_message_new_warning (GstObject * src, GError * error, const gchar * debug)
548 {
549   return gst_message_new_warning_with_details (src, error, debug, NULL);
550 }
551
552 /**
553  * gst_message_parse_warning_details:
554  * @message: The message object
555  * @structure: (out): A pointer to the returned details structure
556  *
557  * Returns the optional details structure, may be NULL if none
558  * The returned structure must not be freed.
559  *
560  * Since: 1.10
561  */
562 void
563 gst_message_parse_warning_details (GstMessage * message,
564     const GstStructure ** structure)
565 {
566   const GValue *v;
567
568   g_return_if_fail (GST_IS_MESSAGE (message));
569   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
570   g_return_if_fail (structure != NULL);
571
572   *structure = NULL;
573   v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
574       details_quark);
575   if (v) {
576     *structure = g_value_get_boxed (v);
577   }
578 }
579
580 /**
581  * gst_message_new_info_with_details:
582  * @src: (transfer none) (allow-none): The object originating the message.
583  * @error: (transfer none): The GError for this message.
584  * @debug: A debugging string.
585  * @details: (transfer full): (allow-none): A GstStructure with details
586  *
587  * Create a new info message. The message will make copies of @error and
588  * @debug.
589  *
590  * Returns: (transfer full): the new warning message.
591  *
592  * Since: 1.10
593  */
594 GstMessage *
595 gst_message_new_info_with_details (GstObject * src, GError * error,
596     const gchar * debug, GstStructure * details)
597 {
598   GstMessage *message;
599   GstStructure *structure;
600
601   if (debug && !g_utf8_validate (debug, -1, NULL)) {
602     debug = NULL;
603     g_warning ("Trying to set debug field of info message, but "
604         "string is not valid UTF-8. Please file a bug.");
605   }
606
607   structure = gst_structure_new_id (GST_QUARK (MESSAGE_INFO),
608       GST_QUARK (GERROR), G_TYPE_ERROR, error,
609       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
610   message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure);
611   if (details) {
612     GValue v = G_VALUE_INIT;
613
614     g_value_init (&v, GST_TYPE_STRUCTURE);
615     g_value_take_boxed (&v, details);
616     gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
617         &v);
618   }
619
620   return message;
621 }
622
623 /**
624  * gst_message_new_info:
625  * @src: (transfer none) (allow-none): The object originating the message.
626  * @error: (transfer none): The GError for this message.
627  * @debug: A debugging string.
628  *
629  * Create a new info message. The message will make copies of @error and
630  * @debug.
631  *
632  * Returns: (transfer full): the new info message.
633  *
634  * MT safe.
635  */
636 GstMessage *
637 gst_message_new_info (GstObject * src, GError * error, const gchar * debug)
638 {
639   return gst_message_new_info_with_details (src, error, debug, NULL);
640 }
641
642 /**
643  * gst_message_parse_info_details:
644  * @message: The message object
645  * @structure: (out): A pointer to the returned details structure
646  *
647  * Returns the optional details structure, may be NULL if none
648  * The returned structure must not be freed.
649  *
650  * Since: 1.10
651  */
652 void
653 gst_message_parse_info_details (GstMessage * message,
654     const GstStructure ** structure)
655 {
656   const GValue *v;
657
658   g_return_if_fail (GST_IS_MESSAGE (message));
659   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
660   g_return_if_fail (structure != NULL);
661
662   *structure = NULL;
663   v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
664       details_quark);
665   if (v) {
666     *structure = g_value_get_boxed (v);
667   }
668 }
669
670 /**
671  * gst_message_new_tag:
672  * @src: (transfer none) (allow-none): The object originating the message.
673  * @tag_list: (transfer full): the tag list for the message.
674  *
675  * Create a new tag message. The message will take ownership of the tag list.
676  * The message is posted by elements that discovered a new taglist.
677  *
678  * Returns: (transfer full): the new tag message.
679  *
680  * MT safe.
681  */
682 GstMessage *
683 gst_message_new_tag (GstObject * src, GstTagList * tag_list)
684 {
685   GstStructure *s;
686   GstMessage *message;
687   GValue val = G_VALUE_INIT;
688
689   g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), NULL);
690
691   s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_TAG));
692   g_value_init (&val, GST_TYPE_TAG_LIST);
693   g_value_take_boxed (&val, tag_list);
694   gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val);
695   message = gst_message_new_custom (GST_MESSAGE_TAG, src, s);
696   return message;
697 }
698
699 /**
700  * gst_message_new_buffering:
701  * @src: (transfer none) (allow-none): The object originating the message.
702  * @percent: The buffering percent
703  *
704  * Create a new buffering message. This message can be posted by an element that
705  * needs to buffer data before it can continue processing. @percent should be a
706  * value between 0 and 100. A value of 100 means that the buffering completed.
707  *
708  * When @percent is < 100 the application should PAUSE a PLAYING pipeline. When
709  * @percent is 100, the application can set the pipeline (back) to PLAYING.
710  * The application must be prepared to receive BUFFERING messages in the
711  * PREROLLING state and may only set the pipeline to PLAYING after receiving a
712  * message with @percent set to 100, which can happen after the pipeline
713  * completed prerolling.
714  *
715  * MT safe.
716  *
717  * Returns: (transfer full): The new buffering message.
718  */
719 GstMessage *
720 gst_message_new_buffering (GstObject * src, gint percent)
721 {
722   GstMessage *message;
723   GstStructure *structure;
724   gint64 buffering_left;
725
726   g_return_val_if_fail (percent >= 0 && percent <= 100, NULL);
727
728   buffering_left = (percent == 100 ? 0 : -1);
729
730   structure = gst_structure_new_id (GST_QUARK (MESSAGE_BUFFERING),
731       GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent,
732       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
733       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
734       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
735       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
736   message = gst_message_new_custom (GST_MESSAGE_BUFFERING, src, structure);
737
738   return message;
739 }
740
741 /**
742  * gst_message_new_state_changed:
743  * @src: (transfer none) (allow-none): The object originating the message.
744  * @oldstate: the previous state
745  * @newstate: the new (current) state
746  * @pending: the pending (target) state
747  *
748  * Create a state change message. This message is posted whenever an element
749  * changed its state.
750  *
751  * Returns: (transfer full): the new state change message.
752  *
753  * MT safe.
754  */
755 GstMessage *
756 gst_message_new_state_changed (GstObject * src,
757     GstState oldstate, GstState newstate, GstState pending)
758 {
759   GstMessage *message;
760   GstStructure *structure;
761
762   structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE_CHANGED),
763       GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate,
764       GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate,
765       GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL);
766   message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src, structure);
767
768   return message;
769 }
770
771 /**
772  * gst_message_new_state_dirty:
773  * @src: (transfer none) (allow-none): The object originating the message
774  *
775  * Create a state dirty message. This message is posted whenever an element
776  * changed its state asynchronously and is used internally to update the
777  * states of container objects.
778  *
779  * Returns: (transfer full): the new state dirty message.
780  *
781  * MT safe.
782  */
783 GstMessage *
784 gst_message_new_state_dirty (GstObject * src)
785 {
786   GstMessage *message;
787
788   message = gst_message_new_custom (GST_MESSAGE_STATE_DIRTY, src, NULL);
789
790   return message;
791 }
792
793 /**
794  * gst_message_new_clock_provide:
795  * @src: (transfer none) (allow-none): The object originating the message.
796  * @clock: (transfer none): the clock it provides
797  * @ready: %TRUE if the sender can provide a clock
798  *
799  * Create a clock provide message. This message is posted whenever an
800  * element is ready to provide a clock or lost its ability to provide
801  * a clock (maybe because it paused or became EOS).
802  *
803  * This message is mainly used internally to manage the clock
804  * selection.
805  *
806  * Returns: (transfer full): the new provide clock message.
807  *
808  * MT safe.
809  */
810 GstMessage *
811 gst_message_new_clock_provide (GstObject * src, GstClock * clock,
812     gboolean ready)
813 {
814   GstMessage *message;
815   GstStructure *structure;
816
817   structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_PROVIDE),
818       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock,
819       GST_QUARK (READY), G_TYPE_BOOLEAN, ready, NULL);
820   message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src, structure);
821
822   return message;
823 }
824
825 /**
826  * gst_message_new_clock_lost:
827  * @src: (transfer none) (allow-none): The object originating the message.
828  * @clock: (transfer none): the clock that was lost
829  *
830  * Create a clock lost message. This message is posted whenever the
831  * clock is not valid anymore.
832  *
833  * If this message is posted by the pipeline, the pipeline will
834  * select a new clock again when it goes to PLAYING. It might therefore
835  * be needed to set the pipeline to PAUSED and PLAYING again.
836  *
837  * Returns: (transfer full): The new clock lost message.
838  *
839  * MT safe.
840  */
841 GstMessage *
842 gst_message_new_clock_lost (GstObject * src, GstClock * clock)
843 {
844   GstMessage *message;
845   GstStructure *structure;
846
847   structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_LOST),
848       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
849   message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src, structure);
850
851   return message;
852 }
853
854 /**
855  * gst_message_new_new_clock:
856  * @src: (transfer none) (allow-none): The object originating the message.
857  * @clock: (transfer none): the new selected clock
858  *
859  * Create a new clock message. This message is posted whenever the
860  * pipeline selects a new clock for the pipeline.
861  *
862  * Returns: (transfer full): The new new clock message.
863  *
864  * MT safe.
865  */
866 GstMessage *
867 gst_message_new_new_clock (GstObject * src, GstClock * clock)
868 {
869   GstMessage *message;
870   GstStructure *structure;
871
872   structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEW_CLOCK),
873       GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
874   message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src, structure);
875
876   return message;
877 }
878
879 /**
880  * gst_message_new_structure_change:
881  * @src: (transfer none) (allow-none): The object originating the message.
882  * @type: The change type.
883  * @owner: (transfer none): The owner element of @src.
884  * @busy: Whether the structure change is busy.
885  *
886  * Create a new structure change message. This message is posted when the
887  * structure of a pipeline is in the process of being changed, for example
888  * when pads are linked or unlinked.
889  *
890  * @src should be the sinkpad that unlinked or linked.
891  *
892  * Returns: (transfer full): the new structure change message.
893  *
894  * MT safe.
895  */
896 GstMessage *
897 gst_message_new_structure_change (GstObject * src, GstStructureChangeType type,
898     GstElement * owner, gboolean busy)
899 {
900   GstMessage *message;
901   GstStructure *structure;
902
903   g_return_val_if_fail (GST_IS_PAD (src), NULL);
904   /* g_return_val_if_fail (GST_PAD_DIRECTION (src) == GST_PAD_SINK, NULL); */
905   g_return_val_if_fail (GST_IS_ELEMENT (owner), NULL);
906
907   structure = gst_structure_new_id (GST_QUARK (MESSAGE_STRUCTURE_CHANGE),
908       GST_QUARK (TYPE), GST_TYPE_STRUCTURE_CHANGE_TYPE, type,
909       GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner,
910       GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, NULL);
911
912   message = gst_message_new_custom (GST_MESSAGE_STRUCTURE_CHANGE, src,
913       structure);
914
915   return message;
916 }
917
918 /**
919  * gst_message_new_segment_start:
920  * @src: (transfer none) (allow-none): The object originating the message.
921  * @format: The format of the position being played
922  * @position: The position of the segment being played
923  *
924  * Create a new segment message. This message is posted by elements that
925  * start playback of a segment as a result of a segment seek. This message
926  * is not received by the application but is used for maintenance reasons in
927  * container elements.
928  *
929  * Returns: (transfer full): the new segment start message.
930  *
931  * MT safe.
932  */
933 GstMessage *
934 gst_message_new_segment_start (GstObject * src, GstFormat format,
935     gint64 position)
936 {
937   GstMessage *message;
938   GstStructure *structure;
939
940   structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_START),
941       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
942       GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
943   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src, structure);
944
945   return message;
946 }
947
948 /**
949  * gst_message_new_segment_done:
950  * @src: (transfer none) (allow-none): The object originating the message.
951  * @format: The format of the position being done
952  * @position: The position of the segment being done
953  *
954  * Create a new segment done message. This message is posted by elements that
955  * finish playback of a segment as a result of a segment seek. This message
956  * is received by the application after all elements that posted a segment_start
957  * have posted the segment_done.
958  *
959  * Returns: (transfer full): the new segment done message.
960  *
961  * MT safe.
962  */
963 GstMessage *
964 gst_message_new_segment_done (GstObject * src, GstFormat format,
965     gint64 position)
966 {
967   GstMessage *message;
968   GstStructure *structure;
969
970   structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_DONE),
971       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
972       GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
973   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src, structure);
974
975   return message;
976 }
977
978 /**
979  * gst_message_new_application:
980  * @src: (transfer none) (allow-none): The object originating the message.
981  * @structure: (transfer full): the structure for the message. The message
982  *     will take ownership of the structure.
983  *
984  * Create a new application-typed message. GStreamer will never create these
985  * messages; they are a gift from us to you. Enjoy.
986  *
987  * Returns: (transfer full): The new application message.
988  *
989  * MT safe.
990  */
991 GstMessage *
992 gst_message_new_application (GstObject * src, GstStructure * structure)
993 {
994   g_return_val_if_fail (structure != NULL, NULL);
995
996   return gst_message_new_custom (GST_MESSAGE_APPLICATION, src, structure);
997 }
998
999 /**
1000  * gst_message_new_element:
1001  * @src: (transfer none) (allow-none): The object originating the message.
1002  * @structure: (transfer full): The structure for the
1003  *     message. The message will take ownership of the structure.
1004  *
1005  * Create a new element-specific message. This is meant as a generic way of
1006  * allowing one-way communication from an element to an application, for example
1007  * "the firewire cable was unplugged". The format of the message should be
1008  * documented in the element's documentation. The structure field can be %NULL.
1009  *
1010  * Returns: (transfer full): The new element message.
1011  *
1012  * MT safe.
1013  */
1014 GstMessage *
1015 gst_message_new_element (GstObject * src, GstStructure * structure)
1016 {
1017   g_return_val_if_fail (structure != NULL, NULL);
1018
1019   return gst_message_new_custom (GST_MESSAGE_ELEMENT, src, structure);
1020 }
1021
1022 /**
1023  * gst_message_new_duration_changed:
1024  * @src: (transfer none) (allow-none): The object originating the message.
1025  *
1026  * Create a new duration changed message. This message is posted by elements
1027  * that know the duration of a stream when the duration changes. This message
1028  * is received by bins and is used to calculate the total duration of a
1029  * pipeline.
1030  *
1031  * Returns: (transfer full): The new duration-changed message.
1032  *
1033  * MT safe.
1034  */
1035 GstMessage *
1036 gst_message_new_duration_changed (GstObject * src)
1037 {
1038   GstMessage *message;
1039
1040   message = gst_message_new_custom (GST_MESSAGE_DURATION_CHANGED, src,
1041       gst_structure_new_id_empty (GST_QUARK (MESSAGE_DURATION_CHANGED)));
1042
1043   return message;
1044 }
1045
1046 /**
1047  * gst_message_new_async_start:
1048  * @src: (transfer none) (allow-none): The object originating the message.
1049  *
1050  * This message is posted by elements when they start an ASYNC state change.
1051  *
1052  * Returns: (transfer full): The new async_start message.
1053  *
1054  * MT safe.
1055  */
1056 GstMessage *
1057 gst_message_new_async_start (GstObject * src)
1058 {
1059   GstMessage *message;
1060
1061   message = gst_message_new_custom (GST_MESSAGE_ASYNC_START, src, NULL);
1062
1063   return message;
1064 }
1065
1066 /**
1067  * gst_message_new_async_done:
1068  * @src: (transfer none) (allow-none): The object originating the message.
1069  * @running_time: the desired running_time
1070  *
1071  * The message is posted when elements completed an ASYNC state change.
1072  * @running_time contains the time of the desired running_time when this
1073  * elements goes to PLAYING. A value of #GST_CLOCK_TIME_NONE for @running_time
1074  * means that the element has no clock interaction and thus doesn't care about
1075  * the running_time of the pipeline.
1076  *
1077  * Returns: (transfer full): The new async_done message.
1078  *
1079  * MT safe.
1080  */
1081 GstMessage *
1082 gst_message_new_async_done (GstObject * src, GstClockTime running_time)
1083 {
1084   GstMessage *message;
1085   GstStructure *structure;
1086
1087   structure = gst_structure_new_id (GST_QUARK (MESSAGE_ASYNC_DONE),
1088       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
1089   message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure);
1090
1091   return message;
1092 }
1093
1094 /**
1095  * gst_message_new_latency:
1096  * @src: (transfer none) (allow-none): The object originating the message.
1097  *
1098  * This message can be posted by elements when their latency requirements have
1099  * changed.
1100  *
1101  * Returns: (transfer full): The new latency message.
1102  *
1103  * MT safe.
1104  */
1105 GstMessage *
1106 gst_message_new_latency (GstObject * src)
1107 {
1108   GstMessage *message;
1109
1110   message = gst_message_new_custom (GST_MESSAGE_LATENCY, src, NULL);
1111
1112   return message;
1113 }
1114
1115 /**
1116  * gst_message_new_request_state:
1117  * @src: (transfer none) (allow-none): The object originating the message.
1118  * @state: The new requested state
1119  *
1120  * This message can be posted by elements when they want to have their state
1121  * changed. A typical use case would be an audio server that wants to pause the
1122  * pipeline because a higher priority stream is being played.
1123  *
1124  * Returns: (transfer full): the new request state message.
1125  *
1126  * MT safe.
1127  */
1128 GstMessage *
1129 gst_message_new_request_state (GstObject * src, GstState state)
1130 {
1131   GstMessage *message;
1132   GstStructure *structure;
1133
1134   structure = gst_structure_new_id (GST_QUARK (MESSAGE_REQUEST_STATE),
1135       GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) state, NULL);
1136   message = gst_message_new_custom (GST_MESSAGE_REQUEST_STATE, src, structure);
1137
1138   return message;
1139 }
1140
1141 /**
1142  * gst_message_get_structure:
1143  * @message: The #GstMessage.
1144  *
1145  * Access the structure of the message.
1146  *
1147  * Returns: (transfer none): The structure of the message. The structure is
1148  * still owned by the message, which means that you should not free it and
1149  * that the pointer becomes invalid when you free the message.
1150  *
1151  * MT safe.
1152  */
1153 const GstStructure *
1154 gst_message_get_structure (GstMessage * message)
1155 {
1156   g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
1157
1158   return GST_MESSAGE_STRUCTURE (message);
1159 }
1160
1161 /**
1162  * gst_message_has_name:
1163  * @message: The #GstMessage.
1164  * @name: name to check
1165  *
1166  * Checks if @message has the given @name. This function is usually used to
1167  * check the name of a custom message.
1168  *
1169  * Returns: %TRUE if @name matches the name of the message structure.
1170  */
1171 gboolean
1172 gst_message_has_name (GstMessage * message, const gchar * name)
1173 {
1174   GstStructure *structure;
1175
1176   g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
1177
1178   structure = GST_MESSAGE_STRUCTURE (message);
1179   if (structure == NULL)
1180     return FALSE;
1181
1182   return gst_structure_has_name (structure, name);
1183 }
1184
1185 /**
1186  * gst_message_parse_tag:
1187  * @message: A valid #GstMessage of type GST_MESSAGE_TAG.
1188  * @tag_list: (out callee-allocates): return location for the tag-list.
1189  *
1190  * Extracts the tag list from the GstMessage. The tag list returned in the
1191  * output argument is a copy; the caller must free it when done.
1192  *
1193  * Typical usage of this function might be:
1194  * |[<!-- language="C" -->
1195  *   ...
1196  *   switch (GST_MESSAGE_TYPE (msg)) {
1197  *     case GST_MESSAGE_TAG: {
1198  *       GstTagList *tags = NULL;
1199  *
1200  *       gst_message_parse_tag (msg, &amp;tags);
1201  *       g_print ("Got tags from element %s\n", GST_OBJECT_NAME (msg->src));
1202  *       handle_tags (tags);
1203  *       gst_tag_list_unref (tags);
1204  *       break;
1205  *     }
1206  *     ...
1207  *   }
1208  *   ...
1209  * ]|
1210  *
1211  * MT safe.
1212  */
1213 void
1214 gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
1215 {
1216   g_return_if_fail (GST_IS_MESSAGE (message));
1217   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
1218   g_return_if_fail (tag_list != NULL);
1219
1220   gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
1221       GST_QUARK (TAGLIST), GST_TYPE_TAG_LIST, tag_list, NULL);
1222 }
1223
1224 /**
1225  * gst_message_parse_buffering:
1226  * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING.
1227  * @percent: (out) (allow-none): Return location for the percent.
1228  *
1229  * Extracts the buffering percent from the GstMessage. see also
1230  * gst_message_new_buffering().
1231  *
1232  * MT safe.
1233  */
1234 void
1235 gst_message_parse_buffering (GstMessage * message, gint * percent)
1236 {
1237   g_return_if_fail (GST_IS_MESSAGE (message));
1238   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
1239
1240   if (percent)
1241     *percent =
1242         g_value_get_int (gst_structure_id_get_value (GST_MESSAGE_STRUCTURE
1243             (message), GST_QUARK (BUFFER_PERCENT)));
1244 }
1245
1246 /**
1247  * gst_message_set_buffering_stats:
1248  * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING.
1249  * @mode: a buffering mode
1250  * @avg_in: the average input rate
1251  * @avg_out: the average output rate
1252  * @buffering_left: amount of buffering time left in milliseconds
1253  *
1254  * Configures the buffering stats values in @message.
1255  */
1256 void
1257 gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode,
1258     gint avg_in, gint avg_out, gint64 buffering_left)
1259 {
1260   g_return_if_fail (GST_IS_MESSAGE (message));
1261   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
1262
1263   gst_structure_id_set (GST_MESSAGE_STRUCTURE (message),
1264       GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
1265       GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
1266       GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
1267       GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
1268 }
1269
1270 /**
1271  * gst_message_parse_buffering_stats:
1272  * @message: A valid #GstMessage of type GST_MESSAGE_BUFFERING.
1273  * @mode: (out) (allow-none): a buffering mode, or %NULL
1274  * @avg_in: (out) (allow-none): the average input rate, or %NULL
1275  * @avg_out: (out) (allow-none): the average output rate, or %NULL
1276  * @buffering_left: (out) (allow-none): amount of buffering time left in
1277  *     milliseconds, or %NULL
1278  *
1279  * Extracts the buffering stats values from @message.
1280  */
1281 void
1282 gst_message_parse_buffering_stats (GstMessage * message,
1283     GstBufferingMode * mode, gint * avg_in, gint * avg_out,
1284     gint64 * buffering_left)
1285 {
1286   GstStructure *structure;
1287
1288   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
1289
1290   structure = GST_MESSAGE_STRUCTURE (message);
1291   if (mode)
1292     *mode = (GstBufferingMode)
1293         g_value_get_enum (gst_structure_id_get_value (structure,
1294             GST_QUARK (BUFFERING_MODE)));
1295   if (avg_in)
1296     *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
1297             GST_QUARK (AVG_IN_RATE)));
1298   if (avg_out)
1299     *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
1300             GST_QUARK (AVG_OUT_RATE)));
1301   if (buffering_left)
1302     *buffering_left =
1303         g_value_get_int64 (gst_structure_id_get_value (structure,
1304             GST_QUARK (BUFFERING_LEFT)));
1305 }
1306
1307 /**
1308  * gst_message_parse_state_changed:
1309  * @message: a valid #GstMessage of type GST_MESSAGE_STATE_CHANGED
1310  * @oldstate: (out) (allow-none): the previous state, or %NULL
1311  * @newstate: (out) (allow-none): the new (current) state, or %NULL
1312  * @pending: (out) (allow-none): the pending (target) state, or %NULL
1313  *
1314  * Extracts the old and new states from the GstMessage.
1315  *
1316  * Typical usage of this function might be:
1317  * |[<!-- language="C" -->
1318  *   ...
1319  *   switch (GST_MESSAGE_TYPE (msg)) {
1320  *     case GST_MESSAGE_STATE_CHANGED: {
1321  *       GstState old_state, new_state;
1322  *
1323  *       gst_message_parse_state_changed (msg, &amp;old_state, &amp;new_state, NULL);
1324  *       g_print ("Element %s changed state from %s to %s.\n",
1325  *           GST_OBJECT_NAME (msg->src),
1326  *           gst_element_state_get_name (old_state),
1327  *           gst_element_state_get_name (new_state));
1328  *       break;
1329  *     }
1330  *     ...
1331  *   }
1332  *   ...
1333  * ]|
1334  *
1335  * MT safe.
1336  */
1337 void
1338 gst_message_parse_state_changed (GstMessage * message,
1339     GstState * oldstate, GstState * newstate, GstState * pending)
1340 {
1341   GstStructure *structure;
1342
1343   g_return_if_fail (GST_IS_MESSAGE (message));
1344   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED);
1345
1346   structure = GST_MESSAGE_STRUCTURE (message);
1347   if (oldstate)
1348     *oldstate = (GstState)
1349         g_value_get_enum (gst_structure_id_get_value (structure,
1350             GST_QUARK (OLD_STATE)));
1351   if (newstate)
1352     *newstate = (GstState)
1353         g_value_get_enum (gst_structure_id_get_value (structure,
1354             GST_QUARK (NEW_STATE)));
1355   if (pending)
1356     *pending = (GstState)
1357         g_value_get_enum (gst_structure_id_get_value (structure,
1358             GST_QUARK (PENDING_STATE)));
1359 }
1360
1361 /**
1362  * gst_message_parse_clock_provide:
1363  * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_PROVIDE.
1364  * @clock: (out) (allow-none) (transfer none): a pointer to  hold a clock
1365  *     object, or %NULL
1366  * @ready: (out) (allow-none): a pointer to hold the ready flag, or %NULL
1367  *
1368  * Extracts the clock and ready flag from the GstMessage.
1369  * The clock object returned remains valid until the message is freed.
1370  *
1371  * MT safe.
1372  */
1373 void
1374 gst_message_parse_clock_provide (GstMessage * message, GstClock ** clock,
1375     gboolean * ready)
1376 {
1377   const GValue *clock_gvalue;
1378   GstStructure *structure;
1379
1380   g_return_if_fail (GST_IS_MESSAGE (message));
1381   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);
1382
1383   structure = GST_MESSAGE_STRUCTURE (message);
1384   clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
1385   g_return_if_fail (clock_gvalue != NULL);
1386   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
1387
1388   if (ready)
1389     *ready =
1390         g_value_get_boolean (gst_structure_id_get_value (structure,
1391             GST_QUARK (READY)));
1392   if (clock)
1393     *clock = (GstClock *) g_value_get_object (clock_gvalue);
1394 }
1395
1396 /**
1397  * gst_message_parse_clock_lost:
1398  * @message: A valid #GstMessage of type GST_MESSAGE_CLOCK_LOST.
1399  * @clock: (out) (allow-none) (transfer none): a pointer to hold the lost clock
1400  *
1401  * Extracts the lost clock from the GstMessage.
1402  * The clock object returned remains valid until the message is freed.
1403  *
1404  * MT safe.
1405  */
1406 void
1407 gst_message_parse_clock_lost (GstMessage * message, GstClock ** clock)
1408 {
1409   const GValue *clock_gvalue;
1410   GstStructure *structure;
1411
1412   g_return_if_fail (GST_IS_MESSAGE (message));
1413   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_LOST);
1414
1415   structure = GST_MESSAGE_STRUCTURE (message);
1416   clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
1417   g_return_if_fail (clock_gvalue != NULL);
1418   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
1419
1420   if (clock)
1421     *clock = (GstClock *) g_value_get_object (clock_gvalue);
1422 }
1423
1424 /**
1425  * gst_message_parse_new_clock:
1426  * @message: A valid #GstMessage of type GST_MESSAGE_NEW_CLOCK.
1427  * @clock: (out) (allow-none) (transfer none): a pointer to hold the selected
1428  *     new clock
1429  *
1430  * Extracts the new clock from the GstMessage.
1431  * The clock object returned remains valid until the message is freed.
1432  *
1433  * MT safe.
1434  */
1435 void
1436 gst_message_parse_new_clock (GstMessage * message, GstClock ** clock)
1437 {
1438   const GValue *clock_gvalue;
1439   GstStructure *structure;
1440
1441   g_return_if_fail (GST_IS_MESSAGE (message));
1442   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);
1443
1444   structure = GST_MESSAGE_STRUCTURE (message);
1445   clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
1446   g_return_if_fail (clock_gvalue != NULL);
1447   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
1448
1449   if (clock)
1450     *clock = (GstClock *) g_value_get_object (clock_gvalue);
1451 }
1452
1453 /**
1454  * gst_message_parse_structure_change:
1455  * @message: A valid #GstMessage of type GST_MESSAGE_STRUCTURE_CHANGE.
1456  * @type: (out): A pointer to hold the change type
1457  * @owner: (out) (allow-none) (transfer none): The owner element of the
1458  *     message source
1459  * @busy: (out) (allow-none): a pointer to hold whether the change is in
1460  *     progress or has been completed
1461  *
1462  * Extracts the change type and completion status from the GstMessage.
1463  *
1464  * MT safe.
1465  */
1466 void
1467 gst_message_parse_structure_change (GstMessage * message,
1468     GstStructureChangeType * type, GstElement ** owner, gboolean * busy)
1469 {
1470   const GValue *owner_gvalue;
1471   GstStructure *structure;
1472
1473   g_return_if_fail (GST_IS_MESSAGE (message));
1474   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STRUCTURE_CHANGE);
1475
1476   structure = GST_MESSAGE_STRUCTURE (message);
1477   owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
1478   g_return_if_fail (owner_gvalue != NULL);
1479   g_return_if_fail (G_VALUE_TYPE (owner_gvalue) == GST_TYPE_ELEMENT);
1480
1481   if (type)
1482     *type = (GstStructureChangeType)
1483         g_value_get_enum (gst_structure_id_get_value (structure,
1484             GST_QUARK (TYPE)));
1485   if (owner)
1486     *owner = (GstElement *) g_value_get_object (owner_gvalue);
1487   if (busy)
1488     *busy =
1489         g_value_get_boolean (gst_structure_id_get_value (structure,
1490             GST_QUARK (BUSY)));
1491 }
1492
1493 /**
1494  * gst_message_parse_error:
1495  * @message: A valid #GstMessage of type GST_MESSAGE_ERROR.
1496  * @gerror: (out) (allow-none) (transfer full): location for the GError
1497  * @debug: (out) (allow-none) (transfer full): location for the debug message,
1498  *     or %NULL
1499  *
1500  * Extracts the GError and debug string from the GstMessage. The values returned
1501  * in the output arguments are copies; the caller must free them when done.
1502  *
1503  * Typical usage of this function might be:
1504  * |[<!-- language="C" -->
1505  *   ...
1506  *   switch (GST_MESSAGE_TYPE (msg)) {
1507  *     case GST_MESSAGE_ERROR: {
1508  *       GError *err = NULL;
1509  *       gchar *dbg_info = NULL;
1510  *
1511  *       gst_message_parse_error (msg, &amp;err, &amp;dbg_info);
1512  *       g_printerr ("ERROR from element %s: %s\n",
1513  *           GST_OBJECT_NAME (msg->src), err->message);
1514  *       g_printerr ("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
1515  *       g_error_free (err);
1516  *       g_free (dbg_info);
1517  *       break;
1518  *     }
1519  *     ...
1520  *   }
1521  *   ...
1522  * ]|
1523  *
1524  * MT safe.
1525  */
1526 void
1527 gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
1528 {
1529   g_return_if_fail (GST_IS_MESSAGE (message));
1530   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
1531
1532   gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
1533       GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
1534       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
1535 }
1536
1537 /**
1538  * gst_message_parse_warning:
1539  * @message: A valid #GstMessage of type GST_MESSAGE_WARNING.
1540  * @gerror: (out) (allow-none) (transfer full): location for the GError
1541  * @debug: (out) (allow-none) (transfer full): location for the debug message,
1542  *     or %NULL
1543  *
1544  * Extracts the GError and debug string from the GstMessage. The values returned
1545  * in the output arguments are copies; the caller must free them when done.
1546  *
1547  * MT safe.
1548  */
1549 void
1550 gst_message_parse_warning (GstMessage * message, GError ** gerror,
1551     gchar ** debug)
1552 {
1553   g_return_if_fail (GST_IS_MESSAGE (message));
1554   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
1555
1556   gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
1557       GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
1558       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
1559 }
1560
1561 /**
1562  * gst_message_parse_info:
1563  * @message: A valid #GstMessage of type GST_MESSAGE_INFO.
1564  * @gerror: (out) (allow-none) (transfer full): location for the GError
1565  * @debug: (out) (allow-none) (transfer full): location for the debug message,
1566  *     or %NULL
1567  *
1568  * Extracts the GError and debug string from the GstMessage. The values returned
1569  * in the output arguments are copies; the caller must free them when done.
1570  *
1571  * MT safe.
1572  */
1573 void
1574 gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug)
1575 {
1576   g_return_if_fail (GST_IS_MESSAGE (message));
1577   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
1578
1579   gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
1580       GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
1581       GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
1582 }
1583
1584 /**
1585  * gst_message_parse_segment_start:
1586  * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_START.
1587  * @format: (out) (allow-none): Result location for the format, or %NULL
1588  * @position: (out) (allow-none): Result location for the position, or %NULL
1589  *
1590  * Extracts the position and format from the segment start message.
1591  *
1592  * MT safe.
1593  */
1594 void
1595 gst_message_parse_segment_start (GstMessage * message, GstFormat * format,
1596     gint64 * position)
1597 {
1598   GstStructure *structure;
1599
1600   g_return_if_fail (GST_IS_MESSAGE (message));
1601   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_START);
1602
1603   structure = GST_MESSAGE_STRUCTURE (message);
1604   if (format)
1605     *format = (GstFormat)
1606         g_value_get_enum (gst_structure_id_get_value (structure,
1607             GST_QUARK (FORMAT)));
1608   if (position)
1609     *position =
1610         g_value_get_int64 (gst_structure_id_get_value (structure,
1611             GST_QUARK (POSITION)));
1612 }
1613
1614 /**
1615  * gst_message_parse_segment_done:
1616  * @message: A valid #GstMessage of type GST_MESSAGE_SEGMENT_DONE.
1617  * @format: (out) (allow-none): Result location for the format, or %NULL
1618  * @position: (out) (allow-none): Result location for the position, or %NULL
1619  *
1620  * Extracts the position and format from the segment done message.
1621  *
1622  * MT safe.
1623  */
1624 void
1625 gst_message_parse_segment_done (GstMessage * message, GstFormat * format,
1626     gint64 * position)
1627 {
1628   GstStructure *structure;
1629
1630   g_return_if_fail (GST_IS_MESSAGE (message));
1631   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_SEGMENT_DONE);
1632
1633   structure = GST_MESSAGE_STRUCTURE (message);
1634   if (format)
1635     *format = (GstFormat)
1636         g_value_get_enum (gst_structure_id_get_value (structure,
1637             GST_QUARK (FORMAT)));
1638   if (position)
1639     *position =
1640         g_value_get_int64 (gst_structure_id_get_value (structure,
1641             GST_QUARK (POSITION)));
1642 }
1643
1644 /**
1645  * gst_message_parse_async_done:
1646  * @message: A valid #GstMessage of type GST_MESSAGE_ASYNC_DONE.
1647  * @running_time: (out) (allow-none): Result location for the running_time or %NULL
1648  *
1649  * Extract the running_time from the async_done message.
1650  *
1651  * MT safe.
1652  */
1653 void
1654 gst_message_parse_async_done (GstMessage * message, GstClockTime * running_time)
1655 {
1656   GstStructure *structure;
1657
1658   g_return_if_fail (GST_IS_MESSAGE (message));
1659   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ASYNC_DONE);
1660
1661   structure = GST_MESSAGE_STRUCTURE (message);
1662   if (running_time)
1663     *running_time =
1664         g_value_get_uint64 (gst_structure_id_get_value (structure,
1665             GST_QUARK (RUNNING_TIME)));
1666 }
1667
1668 /**
1669  * gst_message_parse_request_state:
1670  * @message: A valid #GstMessage of type GST_MESSAGE_REQUEST_STATE.
1671  * @state: (out) (allow-none): Result location for the requested state or %NULL
1672  *
1673  * Extract the requested state from the request_state message.
1674  *
1675  * MT safe.
1676  */
1677 void
1678 gst_message_parse_request_state (GstMessage * message, GstState * state)
1679 {
1680   GstStructure *structure;
1681
1682   g_return_if_fail (GST_IS_MESSAGE (message));
1683   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REQUEST_STATE);
1684
1685   structure = GST_MESSAGE_STRUCTURE (message);
1686   if (state)
1687     *state = (GstState)
1688         g_value_get_enum (gst_structure_id_get_value (structure,
1689             GST_QUARK (NEW_STATE)));
1690 }
1691
1692 /**
1693  * gst_message_new_stream_status:
1694  * @src: The object originating the message.
1695  * @type: The stream status type.
1696  * @owner: (transfer none): the owner element of @src.
1697  *
1698  * Create a new stream status message. This message is posted when a streaming
1699  * thread is created/destroyed or when the state changed.
1700  *
1701  * Returns: (transfer full): the new stream status message.
1702  *
1703  * MT safe.
1704  */
1705 GstMessage *
1706 gst_message_new_stream_status (GstObject * src, GstStreamStatusType type,
1707     GstElement * owner)
1708 {
1709   GstMessage *message;
1710   GstStructure *structure;
1711
1712   structure = gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_STATUS),
1713       GST_QUARK (TYPE), GST_TYPE_STREAM_STATUS_TYPE, (gint) type,
1714       GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, NULL);
1715   message = gst_message_new_custom (GST_MESSAGE_STREAM_STATUS, src, structure);
1716
1717   return message;
1718 }
1719
1720 /**
1721  * gst_message_parse_stream_status:
1722  * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
1723  * @type: (out): A pointer to hold the status type
1724  * @owner: (out) (transfer none): The owner element of the message source
1725  *
1726  * Extracts the stream status type and owner the GstMessage. The returned
1727  * owner remains valid for as long as the reference to @message is valid and
1728  * should thus not be unreffed.
1729  *
1730  * MT safe.
1731  */
1732 void
1733 gst_message_parse_stream_status (GstMessage * message,
1734     GstStreamStatusType * type, GstElement ** owner)
1735 {
1736   const GValue *owner_gvalue;
1737   GstStructure *structure;
1738
1739   g_return_if_fail (GST_IS_MESSAGE (message));
1740   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
1741
1742   structure = GST_MESSAGE_STRUCTURE (message);
1743   owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
1744   g_return_if_fail (owner_gvalue != NULL);
1745
1746   if (type)
1747     *type = (GstStreamStatusType)
1748         g_value_get_enum (gst_structure_id_get_value (structure,
1749             GST_QUARK (TYPE)));
1750   if (owner)
1751     *owner = (GstElement *) g_value_get_object (owner_gvalue);
1752 }
1753
1754 /**
1755  * gst_message_set_stream_status_object:
1756  * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
1757  * @object: the object controlling the streaming
1758  *
1759  * Configures the object handling the streaming thread. This is usually a
1760  * GstTask object but other objects might be added in the future.
1761  */
1762 void
1763 gst_message_set_stream_status_object (GstMessage * message,
1764     const GValue * object)
1765 {
1766   GstStructure *structure;
1767
1768   g_return_if_fail (GST_IS_MESSAGE (message));
1769   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
1770
1771   structure = GST_MESSAGE_STRUCTURE (message);
1772   gst_structure_id_set_value (structure, GST_QUARK (OBJECT), object);
1773 }
1774
1775 /**
1776  * gst_message_get_stream_status_object:
1777  * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_STATUS.
1778  *
1779  * Extracts the object managing the streaming thread from @message.
1780  *
1781  * Returns: a GValue containing the object that manages the streaming thread.
1782  * This object is usually of type GstTask but other types can be added in the
1783  * future. The object remains valid as long as @message is valid.
1784  */
1785 const GValue *
1786 gst_message_get_stream_status_object (GstMessage * message)
1787 {
1788   const GValue *result;
1789   GstStructure *structure;
1790
1791   g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
1792   g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS,
1793       NULL);
1794
1795   structure = GST_MESSAGE_STRUCTURE (message);
1796   result = gst_structure_id_get_value (structure, GST_QUARK (OBJECT));
1797
1798   return result;
1799 }
1800
1801 /**
1802  * gst_message_new_step_done:
1803  * @src: The object originating the message.
1804  * @format: the format of @amount
1805  * @amount: the amount of stepped data
1806  * @rate: the rate of the stepped amount
1807  * @flush: is this an flushing step
1808  * @intermediate: is this an intermediate step
1809  * @duration: the duration of the data
1810  * @eos: the step caused EOS
1811  *
1812  * This message is posted by elements when they complete a part, when @intermediate set
1813  * to %TRUE, or a complete step operation.
1814  *
1815  * @duration will contain the amount of time (in GST_FORMAT_TIME) of the stepped
1816  * @amount of media in format @format.
1817  *
1818  * Returns: (transfer full): the new step_done message.
1819  *
1820  * MT safe.
1821  */
1822 GstMessage *
1823 gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
1824     gdouble rate, gboolean flush, gboolean intermediate, guint64 duration,
1825     gboolean eos)
1826 {
1827   GstMessage *message;
1828   GstStructure *structure;
1829
1830   structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_DONE),
1831       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1832       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
1833       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1834       GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
1835       GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
1836       GST_QUARK (DURATION), G_TYPE_UINT64, duration,
1837       GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
1838   message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
1839
1840   return message;
1841 }
1842
1843 /**
1844  * gst_message_parse_step_done:
1845  * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE.
1846  * @format: (out) (allow-none): result location for the format
1847  * @amount: (out) (allow-none): result location for the amount
1848  * @rate: (out) (allow-none): result location for the rate
1849  * @flush: (out) (allow-none): result location for the flush flag
1850  * @intermediate: (out) (allow-none): result location for the intermediate flag
1851  * @duration: (out) (allow-none): result location for the duration
1852  * @eos: (out) (allow-none): result location for the EOS flag
1853  *
1854  * Extract the values the step_done message.
1855  *
1856  * MT safe.
1857  */
1858 void
1859 gst_message_parse_step_done (GstMessage * message, GstFormat * format,
1860     guint64 * amount, gdouble * rate, gboolean * flush, gboolean * intermediate,
1861     guint64 * duration, gboolean * eos)
1862 {
1863   GstStructure *structure;
1864
1865   g_return_if_fail (GST_IS_MESSAGE (message));
1866   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
1867
1868   structure = GST_MESSAGE_STRUCTURE (message);
1869   gst_structure_id_get (structure,
1870       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1871       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
1872       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1873       GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
1874       GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
1875       GST_QUARK (DURATION), G_TYPE_UINT64, duration,
1876       GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
1877 }
1878
1879 /**
1880  * gst_message_new_step_start:
1881  * @src: The object originating the message.
1882  * @active: if the step is active or queued
1883  * @format: the format of @amount
1884  * @amount: the amount of stepped data
1885  * @rate: the rate of the stepped amount
1886  * @flush: is this an flushing step
1887  * @intermediate: is this an intermediate step
1888  *
1889  * This message is posted by elements when they accept or activate a new step
1890  * event for @amount in @format.
1891  *
1892  * @active is set to %FALSE when the element accepted the new step event and has
1893  * queued it for execution in the streaming threads.
1894  *
1895  * @active is set to %TRUE when the element has activated the step operation and
1896  * is now ready to start executing the step in the streaming thread. After this
1897  * message is emitted, the application can queue a new step operation in the
1898  * element.
1899  *
1900  * Returns: (transfer full): The new step_start message.
1901  *
1902  * MT safe.
1903  */
1904 GstMessage *
1905 gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
1906     guint64 amount, gdouble rate, gboolean flush, gboolean intermediate)
1907 {
1908   GstMessage *message;
1909   GstStructure *structure;
1910
1911   structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_START),
1912       GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
1913       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1914       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
1915       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1916       GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
1917       GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
1918   message = gst_message_new_custom (GST_MESSAGE_STEP_START, src, structure);
1919
1920   return message;
1921 }
1922
1923 /**
1924  * gst_message_parse_step_start:
1925  * @message: A valid #GstMessage of type GST_MESSAGE_STEP_DONE.
1926  * @active: (out) (allow-none): result location for the active flag
1927  * @format: (out) (allow-none): result location for the format
1928  * @amount: (out) (allow-none): result location for the amount
1929  * @rate: (out) (allow-none): result location for the rate
1930  * @flush: (out) (allow-none): result location for the flush flag
1931  * @intermediate: (out) (allow-none): result location for the intermediate flag
1932  *
1933  * Extract the values from step_start message.
1934  *
1935  * MT safe.
1936  */
1937 void
1938 gst_message_parse_step_start (GstMessage * message, gboolean * active,
1939     GstFormat * format, guint64 * amount, gdouble * rate, gboolean * flush,
1940     gboolean * intermediate)
1941 {
1942   GstStructure *structure;
1943
1944   g_return_if_fail (GST_IS_MESSAGE (message));
1945   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START);
1946
1947   structure = GST_MESSAGE_STRUCTURE (message);
1948   gst_structure_id_get (structure,
1949       GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
1950       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
1951       GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
1952       GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
1953       GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
1954       GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
1955 }
1956
1957 /**
1958  * gst_message_new_qos:
1959  * @src: The object originating the message.
1960  * @live: if the message was generated by a live element
1961  * @running_time: the running time of the buffer that generated the message
1962  * @stream_time: the stream time of the buffer that generated the message
1963  * @timestamp: the timestamps of the buffer that generated the message
1964  * @duration: the duration of the buffer that generated the message
1965  *
1966  * A QOS message is posted on the bus whenever an element decides to drop a
1967  * buffer because of QoS reasons or whenever it changes its processing strategy
1968  * because of QoS reasons (quality adjustments such as processing at lower
1969  * accuracy).
1970  *
1971  * This message can be posted by an element that performs synchronisation against the
1972  * clock (live) or it could be dropped by an element that performs QoS because of QOS
1973  * events received from a downstream element (!live).
1974  *
1975  * @running_time, @stream_time, @timestamp, @duration should be set to the
1976  * respective running-time, stream-time, timestamp and duration of the (dropped)
1977  * buffer that generated the QoS event. Values can be left to
1978  * GST_CLOCK_TIME_NONE when unknown.
1979  *
1980  * Returns: (transfer full): The new qos message.
1981  *
1982  * MT safe.
1983  */
1984 GstMessage *
1985 gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time,
1986     guint64 stream_time, guint64 timestamp, guint64 duration)
1987 {
1988   GstMessage *message;
1989   GstStructure *structure;
1990
1991   structure = gst_structure_new_id (GST_QUARK (MESSAGE_QOS),
1992       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
1993       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
1994       GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
1995       GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
1996       GST_QUARK (DURATION), G_TYPE_UINT64, duration,
1997       GST_QUARK (JITTER), G_TYPE_INT64, (gint64) 0,
1998       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, (gdouble) 1.0,
1999       GST_QUARK (QUALITY), G_TYPE_INT, (gint) 1000000,
2000       GST_QUARK (FORMAT), GST_TYPE_FORMAT, GST_FORMAT_UNDEFINED,
2001       GST_QUARK (PROCESSED), G_TYPE_UINT64, (guint64) - 1,
2002       GST_QUARK (DROPPED), G_TYPE_UINT64, (guint64) - 1, NULL);
2003   message = gst_message_new_custom (GST_MESSAGE_QOS, src, structure);
2004
2005   return message;
2006 }
2007
2008 /**
2009  * gst_message_set_qos_values:
2010  * @message: A valid #GstMessage of type GST_MESSAGE_QOS.
2011  * @jitter: The difference of the running-time against the deadline.
2012  * @proportion: Long term prediction of the ideal rate relative to normal rate
2013  * to get optimal quality.
2014  * @quality: An element dependent integer value that specifies the current
2015  * quality level of the element. The default maximum quality is 1000000.
2016  *
2017  * Set the QoS values that have been calculated/analysed from the QoS data
2018  *
2019  * MT safe.
2020  */
2021 void
2022 gst_message_set_qos_values (GstMessage * message, gint64 jitter,
2023     gdouble proportion, gint quality)
2024 {
2025   GstStructure *structure;
2026
2027   g_return_if_fail (GST_IS_MESSAGE (message));
2028   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
2029
2030   structure = GST_MESSAGE_STRUCTURE (message);
2031   gst_structure_id_set (structure,
2032       GST_QUARK (JITTER), G_TYPE_INT64, jitter,
2033       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
2034       GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
2035 }
2036
2037 /**
2038  * gst_message_set_qos_stats:
2039  * @message: A valid #GstMessage of type GST_MESSAGE_QOS.
2040  * @format: Units of the 'processed' and 'dropped' fields. Video sinks and video
2041  * filters will use GST_FORMAT_BUFFERS (frames). Audio sinks and audio filters
2042  * will likely use GST_FORMAT_DEFAULT (samples).
2043  * @processed: Total number of units correctly processed since the last state
2044  * change to READY or a flushing operation.
2045  * @dropped: Total number of units dropped since the last state change to READY
2046  * or a flushing operation.
2047  *
2048  * Set the QoS stats representing the history of the current continuous pipeline
2049  * playback period.
2050  *
2051  * When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are
2052  * invalid. Values of -1 for either @processed or @dropped mean unknown values.
2053  *
2054  * MT safe.
2055  */
2056 void
2057 gst_message_set_qos_stats (GstMessage * message, GstFormat format,
2058     guint64 processed, guint64 dropped)
2059 {
2060   GstStructure *structure;
2061
2062   g_return_if_fail (GST_IS_MESSAGE (message));
2063   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
2064
2065   structure = GST_MESSAGE_STRUCTURE (message);
2066   gst_structure_id_set (structure,
2067       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
2068       GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
2069       GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
2070 }
2071
2072 /**
2073  * gst_message_parse_qos:
2074  * @message: A valid #GstMessage of type GST_MESSAGE_QOS.
2075  * @live: (out) (allow-none): if the message was generated by a live element
2076  * @running_time: (out) (allow-none): the running time of the buffer that
2077  *     generated the message
2078  * @stream_time: (out) (allow-none): the stream time of the buffer that
2079  *     generated the message
2080  * @timestamp: (out) (allow-none): the timestamps of the buffer that
2081  *     generated the message
2082  * @duration: (out) (allow-none): the duration of the buffer that
2083  *     generated the message
2084  *
2085  * Extract the timestamps and live status from the QoS message.
2086  *
2087  * The returned values give the running_time, stream_time, timestamp and
2088  * duration of the dropped buffer. Values of GST_CLOCK_TIME_NONE mean unknown
2089  * values.
2090  *
2091  * MT safe.
2092  */
2093 void
2094 gst_message_parse_qos (GstMessage * message, gboolean * live,
2095     guint64 * running_time, guint64 * stream_time, guint64 * timestamp,
2096     guint64 * duration)
2097 {
2098   GstStructure *structure;
2099
2100   g_return_if_fail (GST_IS_MESSAGE (message));
2101   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
2102
2103   structure = GST_MESSAGE_STRUCTURE (message);
2104   gst_structure_id_get (structure,
2105       GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
2106       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
2107       GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
2108       GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
2109       GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL);
2110 }
2111
2112 /**
2113  * gst_message_parse_qos_values:
2114  * @message: A valid #GstMessage of type GST_MESSAGE_QOS.
2115  * @jitter: (out) (allow-none): The difference of the running-time against
2116  *     the deadline.
2117  * @proportion: (out) (allow-none): Long term prediction of the ideal rate
2118  *     relative to normal rate to get optimal quality.
2119  * @quality: (out) (allow-none): An element dependent integer value that
2120  *     specifies the current quality level of the element. The default
2121  *     maximum quality is 1000000.
2122  *
2123  * Extract the QoS values that have been calculated/analysed from the QoS data
2124  *
2125  * MT safe.
2126  */
2127 void
2128 gst_message_parse_qos_values (GstMessage * message, gint64 * jitter,
2129     gdouble * proportion, gint * quality)
2130 {
2131   GstStructure *structure;
2132
2133   g_return_if_fail (GST_IS_MESSAGE (message));
2134   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
2135
2136   structure = GST_MESSAGE_STRUCTURE (message);
2137   gst_structure_id_get (structure,
2138       GST_QUARK (JITTER), G_TYPE_INT64, jitter,
2139       GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
2140       GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
2141 }
2142
2143 /**
2144  * gst_message_parse_qos_stats:
2145  * @message: A valid #GstMessage of type GST_MESSAGE_QOS.
2146  * @format: (out) (allow-none): Units of the 'processed' and 'dropped' fields.
2147  *     Video sinks and video filters will use GST_FORMAT_BUFFERS (frames).
2148  *     Audio sinks and audio filters will likely use GST_FORMAT_DEFAULT
2149  *     (samples).
2150  * @processed: (out) (allow-none): Total number of units correctly processed
2151  *     since the last state change to READY or a flushing operation.
2152  * @dropped: (out) (allow-none): Total number of units dropped since the last
2153  *     state change to READY or a flushing operation.
2154  *
2155  * Extract the QoS stats representing the history of the current continuous
2156  * pipeline playback period.
2157  *
2158  * When @format is @GST_FORMAT_UNDEFINED both @dropped and @processed are
2159  * invalid. Values of -1 for either @processed or @dropped mean unknown values.
2160  *
2161  * MT safe.
2162  */
2163 void
2164 gst_message_parse_qos_stats (GstMessage * message, GstFormat * format,
2165     guint64 * processed, guint64 * dropped)
2166 {
2167   GstStructure *structure;
2168
2169   g_return_if_fail (GST_IS_MESSAGE (message));
2170   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
2171
2172   structure = GST_MESSAGE_STRUCTURE (message);
2173   gst_structure_id_get (structure,
2174       GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
2175       GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
2176       GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
2177 }
2178
2179 /**
2180  * gst_message_new_progress:
2181  * @src: The object originating the message.
2182  * @type: a #GstProgressType
2183  * @code: a progress code
2184  * @text: free, user visible text describing the progress
2185  *
2186  * Progress messages are posted by elements when they use an asynchronous task
2187  * to perform actions triggered by a state change.
2188  *
2189  * @code contains a well defined string describing the action.
2190  * @text should contain a user visible string detailing the current action.
2191  *
2192  * Returns: (transfer full): The new qos message.
2193  */
2194 GstMessage *
2195 gst_message_new_progress (GstObject * src, GstProgressType type,
2196     const gchar * code, const gchar * text)
2197 {
2198   GstMessage *message;
2199   GstStructure *structure;
2200   gint percent = 100, timeout = -1;
2201
2202   g_return_val_if_fail (code != NULL, NULL);
2203   g_return_val_if_fail (text != NULL, NULL);
2204
2205   if (type == GST_PROGRESS_TYPE_START || type == GST_PROGRESS_TYPE_CONTINUE)
2206     percent = 0;
2207
2208   structure = gst_structure_new_id (GST_QUARK (MESSAGE_PROGRESS),
2209       GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
2210       GST_QUARK (CODE), G_TYPE_STRING, code,
2211       GST_QUARK (TEXT), G_TYPE_STRING, text,
2212       GST_QUARK (PERCENT), G_TYPE_INT, percent,
2213       GST_QUARK (TIMEOUT), G_TYPE_INT, timeout, NULL);
2214   message = gst_message_new_custom (GST_MESSAGE_PROGRESS, src, structure);
2215
2216   return message;
2217 }
2218
2219 /**
2220  * gst_message_parse_progress:
2221  * @message: A valid #GstMessage of type GST_MESSAGE_PROGRESS.
2222  * @type: (out) (allow-none): location for the type
2223  * @code: (out) (allow-none) (transfer full): location for the code
2224  * @text: (out) (allow-none) (transfer full): location for the text
2225  *
2226  * Parses the progress @type, @code and @text.
2227  */
2228 void
2229 gst_message_parse_progress (GstMessage * message, GstProgressType * type,
2230     gchar ** code, gchar ** text)
2231 {
2232   GstStructure *structure;
2233
2234   g_return_if_fail (GST_IS_MESSAGE (message));
2235   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROGRESS);
2236
2237   structure = GST_MESSAGE_STRUCTURE (message);
2238   gst_structure_id_get (structure,
2239       GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
2240       GST_QUARK (CODE), G_TYPE_STRING, code,
2241       GST_QUARK (TEXT), G_TYPE_STRING, text, NULL);
2242 }
2243
2244 /**
2245  * gst_message_new_toc:
2246  * @src: the object originating the message.
2247  * @toc: (transfer none): #GstToc structure for the message.
2248  * @updated: whether TOC was updated or not.
2249  *
2250  * Create a new TOC message. The message is posted by elements
2251  * that discovered or updated a TOC.
2252  *
2253  * Returns: (transfer full): a new TOC message.
2254  *
2255  * MT safe.
2256  */
2257 GstMessage *
2258 gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated)
2259 {
2260   GstStructure *toc_struct;
2261
2262   g_return_val_if_fail (toc != NULL, NULL);
2263
2264   toc_struct = gst_structure_new_id (GST_QUARK (MESSAGE_TOC),
2265       GST_QUARK (TOC), GST_TYPE_TOC, toc,
2266       GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
2267
2268   return gst_message_new_custom (GST_MESSAGE_TOC, src, toc_struct);
2269 }
2270
2271 /**
2272  * gst_message_parse_toc:
2273  * @message: a valid #GstMessage of type GST_MESSAGE_TOC.
2274  * @toc: (out) (transfer full): return location for the TOC.
2275  * @updated: (out): return location for the updated flag.
2276  *
2277  * Extract the TOC from the #GstMessage. The TOC returned in the
2278  * output argument is a copy; the caller must free it with
2279  * gst_toc_unref() when done.
2280  *
2281  * MT safe.
2282  */
2283 void
2284 gst_message_parse_toc (GstMessage * message, GstToc ** toc, gboolean * updated)
2285 {
2286   g_return_if_fail (GST_IS_MESSAGE (message));
2287   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TOC);
2288   g_return_if_fail (toc != NULL);
2289
2290   gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2291       GST_QUARK (TOC), GST_TYPE_TOC, toc,
2292       GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
2293 }
2294
2295 /**
2296  * gst_message_new_reset_time:
2297  * @src: (transfer none) (allow-none): The object originating the message.
2298  * @running_time: the requested running-time
2299  *
2300  * This message is posted when the pipeline running-time should be reset to
2301  * @running_time, like after a flushing seek.
2302  *
2303  * Returns: (transfer full): The new reset_time message.
2304  *
2305  * MT safe.
2306  */
2307 GstMessage *
2308 gst_message_new_reset_time (GstObject * src, GstClockTime running_time)
2309 {
2310   GstMessage *message;
2311   GstStructure *structure;
2312
2313   structure = gst_structure_new_id (GST_QUARK (MESSAGE_RESET_TIME),
2314       GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
2315   message = gst_message_new_custom (GST_MESSAGE_RESET_TIME, src, structure);
2316
2317   return message;
2318 }
2319
2320 /**
2321  * gst_message_parse_reset_time:
2322  * @message: A valid #GstMessage of type GST_MESSAGE_RESET_TIME.
2323  * @running_time: (out) (allow-none): Result location for the running_time or
2324  *      %NULL
2325  *
2326  * Extract the running-time from the RESET_TIME message.
2327  *
2328  * MT safe.
2329  */
2330 void
2331 gst_message_parse_reset_time (GstMessage * message, GstClockTime * running_time)
2332 {
2333   GstStructure *structure;
2334
2335   g_return_if_fail (GST_IS_MESSAGE (message));
2336   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_RESET_TIME);
2337
2338   structure = GST_MESSAGE_STRUCTURE (message);
2339   if (running_time)
2340     *running_time =
2341         g_value_get_uint64 (gst_structure_id_get_value (structure,
2342             GST_QUARK (RUNNING_TIME)));
2343 }
2344
2345 /**
2346  * gst_message_new_stream_start:
2347  * @src: (transfer none) (allow-none): The object originating the message.
2348  *
2349  * Create a new stream_start message. This message is generated and posted in
2350  * the sink elements of a GstBin. The bin will only forward the STREAM_START
2351  * message to the application if all sinks have posted an STREAM_START message.
2352  *
2353  * Returns: (transfer full): The new stream_start message.
2354  *
2355  * MT safe.
2356  */
2357 GstMessage *
2358 gst_message_new_stream_start (GstObject * src)
2359 {
2360   GstMessage *message;
2361   GstStructure *s;
2362
2363   s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_STREAM_START));
2364   message = gst_message_new_custom (GST_MESSAGE_STREAM_START, src, s);
2365
2366   return message;
2367 }
2368
2369
2370 /**
2371  * gst_message_set_group_id:
2372  * @message: the message
2373  * @group_id: the group id
2374  *
2375  * Sets the group id on the stream-start message.
2376  *
2377  * All streams that have the same group id are supposed to be played
2378  * together, i.e. all streams inside a container file should have the
2379  * same group id but different stream ids. The group id should change
2380  * each time the stream is started, resulting in different group ids
2381  * each time a file is played for example.
2382  *
2383  * MT safe.
2384  *
2385  * Since: 1.2
2386  */
2387 void
2388 gst_message_set_group_id (GstMessage * message, guint group_id)
2389 {
2390   GstStructure *structure;
2391
2392   g_return_if_fail (GST_IS_MESSAGE (message));
2393   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START);
2394   g_return_if_fail (gst_message_is_writable (message));
2395
2396   structure = GST_MESSAGE_STRUCTURE (message);
2397   gst_structure_id_set (structure, GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id,
2398       NULL);
2399 }
2400
2401 /**
2402  * gst_message_parse_group_id:
2403  * @message: A valid #GstMessage of type GST_MESSAGE_STREAM_START.
2404  * @group_id: (out) (allow-none): Result location for the group id or
2405  *      %NULL
2406  *
2407  * Extract the group from the STREAM_START message.
2408  *
2409  * Returns: %TRUE if the message had a group id set, %FALSE otherwise
2410  *
2411  * MT safe.
2412  *
2413  * Since: 1.2
2414  */
2415 gboolean
2416 gst_message_parse_group_id (GstMessage * message, guint * group_id)
2417 {
2418   GstStructure *structure;
2419   const GValue *v;
2420
2421   g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
2422   g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_START,
2423       FALSE);
2424
2425   if (!group_id)
2426     return TRUE;
2427
2428   structure = GST_MESSAGE_STRUCTURE (message);
2429
2430   v = gst_structure_id_get_value (structure, GST_QUARK (GROUP_ID));
2431   if (!v)
2432     return FALSE;
2433
2434   *group_id = g_value_get_uint (v);
2435   return TRUE;
2436 }
2437
2438 /**
2439  * gst_message_new_need_context:
2440  * @src: (transfer none) (allow-none): The object originating the message.
2441  * @context_type: The context type that is needed
2442  *
2443  * This message is posted when an element needs a specific #GstContext.
2444  *
2445  * Returns: (transfer full): The new need-context message.
2446  *
2447  * MT safe.
2448  *
2449  * Since: 1.2
2450  */
2451 GstMessage *
2452 gst_message_new_need_context (GstObject * src, const gchar * context_type)
2453 {
2454   GstMessage *message;
2455   GstStructure *structure;
2456
2457   g_return_val_if_fail (context_type != NULL, NULL);
2458
2459   structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEED_CONTEXT),
2460       GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL);
2461   message = gst_message_new_custom (GST_MESSAGE_NEED_CONTEXT, src, structure);
2462
2463   return message;
2464 }
2465
2466 /**
2467  * gst_message_parse_context_type:
2468  * @message: a GST_MESSAGE_NEED_CONTEXT type message
2469  * @context_type: (out) (allow-none): the context type, or %NULL
2470  *
2471  * Parse a context type from an existing GST_MESSAGE_NEED_CONTEXT message.
2472  *
2473  * Returns: a #gboolean indicating if the parsing succeeded.
2474  *
2475  * Since: 1.2
2476  */
2477 gboolean
2478 gst_message_parse_context_type (GstMessage * message,
2479     const gchar ** context_type)
2480 {
2481   GstStructure *structure;
2482   const GValue *value;
2483
2484   g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEED_CONTEXT,
2485       FALSE);
2486
2487   structure = GST_MESSAGE_STRUCTURE (message);
2488
2489   if (context_type) {
2490     value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE));
2491     *context_type = g_value_get_string (value);
2492   }
2493
2494   return TRUE;
2495 }
2496
2497 /**
2498  * gst_message_new_have_context:
2499  * @src: (transfer none) (allow-none): The object originating the message.
2500  * @context: (transfer full): the context
2501  *
2502  * This message is posted when an element has a new local #GstContext.
2503  *
2504  * Returns: (transfer full): The new have-context message.
2505  *
2506  * MT safe.
2507  *
2508  * Since: 1.2
2509  */
2510 GstMessage *
2511 gst_message_new_have_context (GstObject * src, GstContext * context)
2512 {
2513   GstMessage *message;
2514   GstStructure *structure;
2515
2516   structure = gst_structure_new_id (GST_QUARK (MESSAGE_HAVE_CONTEXT),
2517       GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
2518   message = gst_message_new_custom (GST_MESSAGE_HAVE_CONTEXT, src, structure);
2519   gst_context_unref (context);
2520
2521   return message;
2522 }
2523
2524 /**
2525  * gst_message_parse_have_context:
2526  * @message: A valid #GstMessage of type GST_MESSAGE_HAVE_CONTEXT.
2527  * @context: (out) (transfer full) (allow-none): Result location for the
2528  *      context or %NULL
2529  *
2530  * Extract the context from the HAVE_CONTEXT message.
2531  *
2532  * MT safe.
2533  *
2534  * Since: 1.2
2535  */
2536 void
2537 gst_message_parse_have_context (GstMessage * message, GstContext ** context)
2538 {
2539   g_return_if_fail (GST_IS_MESSAGE (message));
2540   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_HAVE_CONTEXT);
2541
2542   if (context)
2543     gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2544         GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
2545 }
2546
2547 /**
2548  * gst_message_new_device_added:
2549  * @src: The #GstObject that created the message
2550  * @device: (transfer none): The new #GstDevice
2551  *
2552  * Creates a new device-added message. The device-added message is produced by
2553  * #GstDeviceProvider or a #GstDeviceMonitor. They announce the appearance
2554  * of monitored devices.
2555  *
2556  * Returns: a newly allocated #GstMessage
2557  *
2558  * Since: 1.4
2559  */
2560 GstMessage *
2561 gst_message_new_device_added (GstObject * src, GstDevice * device)
2562 {
2563   GstMessage *message;
2564   GstStructure *structure;
2565
2566   g_return_val_if_fail (device != NULL, NULL);
2567   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
2568
2569   structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_ADDED),
2570       GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
2571   message = gst_message_new_custom (GST_MESSAGE_DEVICE_ADDED, src, structure);
2572
2573   return message;
2574 }
2575
2576 /**
2577  * gst_message_parse_device_added:
2578  * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_ADDED
2579  * @device: (out) (allow-none) (transfer full): A location where to store a
2580  *  pointer to the new #GstDevice, or %NULL
2581  *
2582  * Parses a device-added message. The device-added message is produced by
2583  * #GstDeviceProvider or a #GstDeviceMonitor. It announces the appearance
2584  * of monitored devices.
2585  *
2586  * Since: 1.4
2587  */
2588 void
2589 gst_message_parse_device_added (GstMessage * message, GstDevice ** device)
2590 {
2591   g_return_if_fail (GST_IS_MESSAGE (message));
2592   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_ADDED);
2593
2594   if (device)
2595     gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2596         GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
2597 }
2598
2599 /**
2600  * gst_message_new_device_removed:
2601  * @src: The #GstObject that created the message
2602  * @device: (transfer none): The removed #GstDevice
2603  *
2604  * Creates a new device-removed message. The device-removed message is produced
2605  * by #GstDeviceProvider or a #GstDeviceMonitor. They announce the
2606  * disappearance of monitored devices.
2607  *
2608  * Returns: a newly allocated #GstMessage
2609  *
2610  * Since: 1.4
2611  */
2612 GstMessage *
2613 gst_message_new_device_removed (GstObject * src, GstDevice * device)
2614 {
2615   GstMessage *message;
2616   GstStructure *structure;
2617
2618   g_return_val_if_fail (device != NULL, NULL);
2619   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
2620
2621   structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_REMOVED),
2622       GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
2623   message = gst_message_new_custom (GST_MESSAGE_DEVICE_REMOVED, src, structure);
2624
2625   return message;
2626 }
2627
2628 /**
2629  * gst_message_parse_device_removed:
2630  * @message: a #GstMessage of type %GST_MESSAGE_DEVICE_REMOVED
2631  * @device: (out) (allow-none) (transfer full): A location where to store a
2632  *  pointer to the removed #GstDevice, or %NULL
2633  *
2634  * Parses a device-removed message. The device-removed message is produced by
2635  * #GstDeviceProvider or a #GstDeviceMonitor. It announces the
2636  * disappearance of monitored devices.
2637  *
2638  * Since: 1.4
2639  */
2640 void
2641 gst_message_parse_device_removed (GstMessage * message, GstDevice ** device)
2642 {
2643   g_return_if_fail (GST_IS_MESSAGE (message));
2644   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_REMOVED);
2645
2646   if (device)
2647     gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2648         GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
2649 }
2650
2651 /**
2652  * gst_message_new_property_notify:
2653  * @src: The #GstObject whose property changed (may or may not be a #GstElement)
2654  * @property_name: name of the property that changed
2655  * @val: (allow-none) (transfer full): new property value, or %NULL
2656  *
2657  * Returns: a newly allocated #GstMessage
2658  *
2659  * Since: 1.10
2660  */
2661 GstMessage *
2662 gst_message_new_property_notify (GstObject * src, const gchar * property_name,
2663     GValue * val)
2664 {
2665   GstStructure *structure;
2666   GValue name_val = G_VALUE_INIT;
2667
2668   g_return_val_if_fail (property_name != NULL, NULL);
2669
2670   structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_PROPERTY_NOTIFY));
2671   g_value_init (&name_val, G_TYPE_STRING);
2672   /* should already be interned, but let's make sure */
2673   g_value_set_static_string (&name_val, g_intern_string (property_name));
2674   gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_NAME), &name_val);
2675   if (val != NULL)
2676     gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_VALUE), val);
2677
2678   return gst_message_new_custom (GST_MESSAGE_PROPERTY_NOTIFY, src, structure);
2679 }
2680
2681 /**
2682  * gst_message_parse_property_notify:
2683  * @message: a #GstMessage of type %GST_MESSAGE_PROPERTY_NOTIFY
2684  * @object: (out) (allow-none) (transfer none): location where to store a
2685  *     pointer to the object whose property got changed, or %NULL
2686  * @property_name: (out) (allow-none): return location for the name of the
2687  *     property that got changed, or %NULL
2688  * @property_value: (out) (allow-none): return location for the new value of
2689  *     the property that got changed, or %NULL. This will only be set if the
2690  *     property notify watch was told to include the value when it was set up
2691  *
2692  * Parses a property-notify message. These will be posted on the bus only
2693  * when set up with gst_element_add_property_notify_watch() or
2694  * gst_element_add_property_deep_notify_watch().
2695  *
2696  * Since: 1.10
2697  */
2698 void
2699 gst_message_parse_property_notify (GstMessage * message, GstObject ** object,
2700     const gchar ** property_name, const GValue ** property_value)
2701 {
2702   const GstStructure *s = GST_MESSAGE_STRUCTURE (message);
2703
2704   g_return_if_fail (GST_IS_MESSAGE (message));
2705   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROPERTY_NOTIFY);
2706
2707   if (object)
2708     *object = GST_MESSAGE_SRC (message);
2709
2710   if (property_name) {
2711     const GValue *name_value;
2712
2713     name_value = gst_structure_id_get_value (s, GST_QUARK (PROPERTY_NAME));
2714     *property_name = g_value_get_string (name_value);
2715   }
2716
2717   if (property_value)
2718     *property_value =
2719         gst_structure_id_get_value (s, GST_QUARK (PROPERTY_VALUE));
2720 }
2721
2722 /**
2723  * gst_message_new_stream_collection:
2724  * @src: The #GstObject that created the message
2725  * @collection: (transfer none): The #GstStreamCollection
2726  *
2727  * Creates a new stream-collection message. The message is used to announce new
2728  * #GstStreamCollection
2729  *
2730  * Returns: a newly allocated #GstMessage
2731  *
2732  * Since: 1.10
2733  */
2734 GstMessage *
2735 gst_message_new_stream_collection (GstObject * src,
2736     GstStreamCollection * collection)
2737 {
2738   GstMessage *message;
2739   GstStructure *structure;
2740
2741   g_return_val_if_fail (collection != NULL, NULL);
2742   g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL);
2743
2744   structure =
2745       gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_COLLECTION),
2746       GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
2747   message =
2748       gst_message_new_custom (GST_MESSAGE_STREAM_COLLECTION, src, structure);
2749
2750   return message;
2751 }
2752
2753 /**
2754  * gst_message_parse_stream_collection:
2755  * @message: a #GstMessage of type %GST_MESSAGE_STREAM_COLLECTION
2756  * @collection: (out) (allow-none) (transfer full): A location where to store a
2757  *  pointer to the #GstStreamCollection, or %NULL
2758  *
2759  * Parses a stream-collection message.
2760  *
2761  * Since: 1.10
2762  */
2763 void
2764 gst_message_parse_stream_collection (GstMessage * message,
2765     GstStreamCollection ** collection)
2766 {
2767   g_return_if_fail (GST_IS_MESSAGE (message));
2768   g_return_if_fail (GST_MESSAGE_TYPE (message) ==
2769       GST_MESSAGE_STREAM_COLLECTION);
2770
2771   if (collection)
2772     gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2773         GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
2774 }
2775
2776 /**
2777  * gst_message_new_streams_selected:
2778  * @src: The #GstObject that created the message
2779  * @collection: (transfer none): The #GstStreamCollection
2780  *
2781  * Creates a new steams-selected message. The message is used to announce
2782  * that an array of streams has been selected. This is generally in response
2783  * to a #GST_EVENT_SELECT_STREAMS event, or when an element (such as decodebin3)
2784  * makes an initial selection of streams.
2785  *
2786  * The message also contains the #GstStreamCollection to which the various streams
2787  * belong to.
2788  *
2789  * Users of gst_message_new_streams_selected() can add the selected streams with
2790  * gst_message_streams_selected_add().
2791  *
2792  * Returns: a newly allocated #GstMessage
2793  *
2794  * Since: 1.10
2795  */
2796 GstMessage *
2797 gst_message_new_streams_selected (GstObject * src,
2798     GstStreamCollection * collection)
2799 {
2800   GstMessage *message;
2801   GstStructure *structure;
2802   GValue val = G_VALUE_INIT;
2803
2804   g_return_val_if_fail (collection != NULL, NULL);
2805   g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL);
2806
2807   structure =
2808       gst_structure_new_id (GST_QUARK (MESSAGE_STREAMS_SELECTED),
2809       GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
2810   g_value_init (&val, GST_TYPE_ARRAY);
2811   gst_structure_id_take_value (structure, GST_QUARK (STREAMS), &val);
2812   message =
2813       gst_message_new_custom (GST_MESSAGE_STREAMS_SELECTED, src, structure);
2814
2815   return message;
2816 }
2817
2818 /**
2819  * gst_message_streams_selected_get_size:
2820  * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED
2821  *
2822  * Returns the number of streams contained in the @message.
2823  *
2824  * Returns: The number of streams contained within.
2825  *
2826  * Since: 1.10
2827  */
2828 guint
2829 gst_message_streams_selected_get_size (GstMessage * msg)
2830 {
2831   const GValue *val;
2832
2833   g_return_val_if_fail (GST_IS_MESSAGE (msg), 0);
2834   g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED,
2835       0);
2836
2837   val =
2838       gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
2839       GST_QUARK (STREAMS));
2840   return gst_value_array_get_size (val);
2841 }
2842
2843 /**
2844  * gst_message_streams_selected_add:
2845  * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED
2846  * @stream: (transfer none): a #GstStream to add to @message
2847  *
2848  * Adds the @stream to the @message.
2849  *
2850  * Since: 1.10
2851  */
2852 void
2853 gst_message_streams_selected_add (GstMessage * msg, GstStream * stream)
2854 {
2855   GValue *val;
2856   GValue to_add = G_VALUE_INIT;
2857
2858   g_return_if_fail (GST_IS_MESSAGE (msg));
2859   g_return_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED);
2860   g_return_if_fail (GST_IS_STREAM (stream));
2861
2862   val =
2863       (GValue *) gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
2864       GST_QUARK (STREAMS));
2865   g_value_init (&to_add, GST_TYPE_STREAM);
2866   g_value_set_object (&to_add, stream);
2867   gst_value_array_append_and_take_value (val, &to_add);
2868 }
2869
2870 /**
2871  * gst_message_streams_selected_get_stream:
2872  * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED
2873  * @idx: Index of the stream to retrieve
2874  *
2875  * Retrieves the #GstStream with index @index from the @message.
2876  *
2877  * Returns: (transfer full): A #GstStream
2878  *
2879  * Since: 1.10
2880  */
2881 GstStream *
2882 gst_message_streams_selected_get_stream (GstMessage * msg, guint idx)
2883 {
2884   const GValue *streams, *val;
2885
2886   g_return_val_if_fail (GST_IS_MESSAGE (msg), NULL);
2887   g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED,
2888       NULL);
2889
2890   streams =
2891       gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
2892       GST_QUARK (STREAMS));
2893   val = gst_value_array_get_value (streams, idx);
2894   if (val) {
2895     return (GstStream *) g_value_dup_object (val);
2896   }
2897
2898   return NULL;
2899 }
2900
2901 /**
2902  * gst_message_parse_streams_selected:
2903  * @message: a #GstMessage of type %GST_MESSAGE_STREAMS_SELECTED
2904  * @collection: (out) (allow-none) (transfer full): A location where to store a
2905  *  pointer to the #GstStreamCollection, or %NULL
2906  *
2907  * Parses a streams-selected message.
2908  *
2909  * Since: 1.10
2910  */
2911 void
2912 gst_message_parse_streams_selected (GstMessage * message,
2913     GstStreamCollection ** collection)
2914 {
2915   g_return_if_fail (GST_IS_MESSAGE (message));
2916   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAMS_SELECTED);
2917
2918   if (collection)
2919     gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
2920         GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
2921 }
2922
2923 /**
2924  * gst_message_new_redirect:
2925  * @src: The #GstObject whose property changed (may or may not be a #GstElement)
2926  * @location: (transfer none): location string for the new entry
2927  * @tag_list: (transfer full) (allow-none): tag list for the new entry
2928  * @entry_struct: (transfer full) (allow-none): structure for the new entry
2929  *
2930  * Creates a new redirect message and adds a new entry to it. Redirect messages
2931  * are posted when an element detects that the actual data has to be retrieved
2932  * from a different location. This is useful if such a redirection cannot be
2933  * handled inside a source element, for example when HTTP 302/303 redirects
2934  * return a non-HTTP URL.
2935  *
2936  * The redirect message can hold multiple entries. The first one is added
2937  * when the redirect message is created, with the given location, tag_list,
2938  * entry_struct arguments. Use gst_message_add_redirect_entry() to add more
2939  * entries.
2940  *
2941  * Each entry has a location, a tag list, and a structure. All of these are
2942  * optional. The tag list and structure are useful for additional metadata,
2943  * such as bitrate statistics for the given location.
2944  *
2945  * By default, message recipients should treat entries in the order they are
2946  * stored. The recipient should therefore try entry #0 first, and if this
2947  * entry is not acceptable or working, try entry #1 etc. Senders must make
2948  * sure that they add entries in this order. However, recipients are free to
2949  * ignore the order and pick an entry that is "best" for them. One example
2950  * would be a recipient that scans the entries for the one with the highest
2951  * bitrate tag.
2952  *
2953  * The specified location string is copied. However, ownership over the tag
2954  * list and structure are transferred to the message.
2955  *
2956  * Returns: a newly allocated #GstMessage
2957  *
2958  * Since: 1.10
2959  */
2960 GstMessage *
2961 gst_message_new_redirect (GstObject * src, const gchar * location,
2962     GstTagList * tag_list, const GstStructure * entry_struct)
2963 {
2964   GstStructure *structure;
2965   GstMessage *message;
2966   GValue entry_locations_gvalue = G_VALUE_INIT;
2967   GValue entry_taglists_gvalue = G_VALUE_INIT;
2968   GValue entry_structures_gvalue = G_VALUE_INIT;
2969
2970   g_return_val_if_fail (location != NULL, NULL);
2971
2972   g_value_init (&entry_locations_gvalue, GST_TYPE_LIST);
2973   g_value_init (&entry_taglists_gvalue, GST_TYPE_LIST);
2974   g_value_init (&entry_structures_gvalue, GST_TYPE_LIST);
2975
2976   structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_REDIRECT));
2977   gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_LOCATIONS),
2978       &entry_locations_gvalue);
2979   gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_TAGLISTS),
2980       &entry_taglists_gvalue);
2981   gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_STRUCTURES),
2982       &entry_structures_gvalue);
2983
2984   message = gst_message_new_custom (GST_MESSAGE_REDIRECT, src, structure);
2985   g_assert (message != NULL);
2986
2987   gst_message_add_redirect_entry (message, location, tag_list, entry_struct);
2988
2989   return message;
2990 }
2991
2992 /**
2993  * gst_message_add_redirect_entry:
2994  * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
2995  * @location: (transfer none): location string for the new entry
2996  * @tag_list: (transfer full) (allow-none): tag list for the new entry
2997  * @entry_struct: (transfer full) (allow-none): structure for the new entry
2998  *
2999  * Creates and appends a new entry.
3000  *
3001  * The specified location string is copied. However, ownership over the tag
3002  * list and structure are transferred to the message.
3003  *
3004  * Since: 1.10
3005  */
3006 void
3007 gst_message_add_redirect_entry (GstMessage * message, const gchar * location,
3008     GstTagList * tag_list, const GstStructure * entry_struct)
3009 {
3010   GValue val = G_VALUE_INIT;
3011   GstStructure *structure;
3012   GValue *entry_locations_gvalue;
3013   GValue *entry_taglists_gvalue;
3014   GValue *entry_structures_gvalue;
3015
3016   g_return_if_fail (location != NULL);
3017   g_return_if_fail (GST_IS_MESSAGE (message));
3018   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT);
3019
3020   structure = GST_MESSAGE_STRUCTURE (message);
3021
3022   entry_locations_gvalue =
3023       (GValue *) gst_structure_id_get_value (structure,
3024       GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
3025   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
3026   entry_taglists_gvalue =
3027       (GValue *) gst_structure_id_get_value (structure,
3028       GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
3029   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
3030   entry_structures_gvalue =
3031       (GValue *) gst_structure_id_get_value (structure,
3032       GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
3033   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
3034
3035   g_value_init (&val, G_TYPE_STRING);
3036   if (location)
3037     g_value_set_string (&val, location);
3038   gst_value_list_append_and_take_value (entry_locations_gvalue, &val);
3039
3040   g_value_init (&val, GST_TYPE_TAG_LIST);
3041   if (tag_list)
3042     g_value_take_boxed (&val, tag_list);
3043   gst_value_list_append_and_take_value (entry_taglists_gvalue, &val);
3044
3045   g_value_init (&val, GST_TYPE_STRUCTURE);
3046   if (entry_struct)
3047     g_value_take_boxed (&val, entry_struct);
3048   gst_value_list_append_and_take_value (entry_structures_gvalue, &val);
3049 }
3050
3051 /**
3052  * gst_message_parse_redirect_entry:
3053  * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
3054  * @entry_index: index of the entry to parse
3055  * @location: (out) (transfer none) (allow-none): return location for
3056  *     the pointer to the entry's location string, or %NULL
3057  * @tag_list: (out) (transfer none) (allow-none): return location for
3058  *     the pointer to the entry's tag list, or %NULL
3059  * @entry_struct: (out) (transfer none) (allow-none): return location
3060  *     for the pointer to the entry's structure, or %NULL
3061  *
3062  * Parses the location and/or structure from the entry with the given index.
3063  * The index must be between 0 and gst_message_get_num_redirect_entries() - 1.
3064  * Returned pointers are valid for as long as this message exists.
3065  *
3066  * Since: 1.10
3067  */
3068 void
3069 gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index,
3070     const gchar ** location, GstTagList ** tag_list,
3071     const GstStructure ** entry_struct)
3072 {
3073   const GValue *val;
3074   GstStructure *structure;
3075   const GValue *entry_locations_gvalue;
3076   const GValue *entry_taglists_gvalue;
3077   const GValue *entry_structures_gvalue;
3078
3079   g_return_if_fail (GST_IS_MESSAGE (message));
3080   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT);
3081
3082   if (G_UNLIKELY (!location && !tag_list && !entry_struct))
3083     return;
3084
3085   structure = GST_MESSAGE_STRUCTURE (message);
3086
3087   entry_locations_gvalue =
3088       gst_structure_id_get_value (structure,
3089       GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
3090   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
3091   entry_taglists_gvalue =
3092       gst_structure_id_get_value (structure,
3093       GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
3094   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
3095   entry_structures_gvalue =
3096       gst_structure_id_get_value (structure,
3097       GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
3098   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
3099
3100   if (location) {
3101     val = gst_value_list_get_value (entry_locations_gvalue, entry_index);
3102     g_return_if_fail (val != NULL);
3103     *location = g_value_get_string (val);
3104   }
3105
3106   if (tag_list) {
3107     val = gst_value_list_get_value (entry_taglists_gvalue, entry_index);
3108     g_return_if_fail (val != NULL);
3109     *tag_list = (GstTagList *) g_value_get_boxed (val);
3110   }
3111
3112   if (entry_struct) {
3113     val = gst_value_list_get_value (entry_structures_gvalue, entry_index);
3114     g_return_if_fail (val != NULL);
3115     *entry_struct = (const GstStructure *) g_value_get_boxed (val);
3116   }
3117 }
3118
3119 /**
3120  * gst_message_get_num_redirect_entries:
3121  * @message: a #GstMessage of type %GST_MESSAGE_REDIRECT
3122  *
3123  * Returns: the number of entries stored in the message
3124  *
3125  * Since: 1.10
3126  */
3127 gsize
3128 gst_message_get_num_redirect_entries (GstMessage * message)
3129 {
3130   GstStructure *structure;
3131   const GValue *entry_locations_gvalue;
3132   const GValue *entry_taglists_gvalue;
3133   const GValue *entry_structures_gvalue;
3134   gsize size;
3135
3136   g_return_val_if_fail (GST_IS_MESSAGE (message), 0);
3137   g_return_val_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_REDIRECT, 0);
3138
3139   structure = GST_MESSAGE_STRUCTURE (message);
3140
3141   entry_locations_gvalue =
3142       gst_structure_id_get_value (structure,
3143       GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
3144   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue), 0);
3145   entry_taglists_gvalue =
3146       gst_structure_id_get_value (structure,
3147       GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
3148   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue), 0);
3149   entry_structures_gvalue =
3150       gst_structure_id_get_value (structure,
3151       GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
3152   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue), 0);
3153
3154   size = gst_value_list_get_size (entry_locations_gvalue);
3155
3156   g_return_val_if_fail ((size ==
3157           gst_value_list_get_size (entry_structures_gvalue))
3158       && (size == gst_value_list_get_size (entry_taglists_gvalue)), 0);
3159
3160   return size;
3161 }