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