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 ©->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, &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, &old_state, &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, &err, &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