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