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