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