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