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