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