1 /* GStreamer
2 * Copyright (C) 2003 David A. Schleef <ds@schleef.org>
3 *
4 * gststructure.c: lists of { GQuark, GValue } tuples
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:gststructure
24 * @title: GstStructure
25 * @short_description: Generic structure containing fields of names and values
26 * @see_also: #GstCaps, #GstMessage, #GstEvent, #GstQuery
27 *
28 * A #GstStructure is a collection of key/value pairs. The keys are expressed
29 * as GQuarks and the values can be of any GType.
30 *
31 * In addition to the key/value pairs, a #GstStructure also has a name. The name
32 * starts with a letter and can be filled by letters, numbers and any of "/-_.:".
33 *
34 * #GstStructure is used by various GStreamer subsystems to store information
35 * in a flexible and extensible way. A #GstStructure does not have a refcount
36 * because it usually is part of a higher level object such as #GstCaps,
37 * #GstMessage, #GstEvent, #GstQuery. It provides a means to enforce mutability
38 * using the refcount of the parent with the gst_structure_set_parent_refcount()
39 * method.
40 *
41 * A #GstStructure can be created with gst_structure_new_empty() or
42 * gst_structure_new(), which both take a name and an optional set of
43 * key/value pairs along with the types of the values.
44 *
45 * Field values can be changed with gst_structure_set_value() or
46 * gst_structure_set().
47 *
48 * Field values can be retrieved with gst_structure_get_value() or the more
49 * convenient gst_structure_get_*() functions.
50 *
51 * Fields can be removed with gst_structure_remove_field() or
52 * gst_structure_remove_fields().
53 *
54 * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are
55 * not allowed. Strings may be %NULL however.
56 *
57 * Be aware that the current #GstCaps / #GstStructure serialization into string
58 * has limited support for nested #GstCaps / #GstStructure fields. It can only
59 * support one level of nesting. Using more levels will lead to unexpected
60 * behavior when using serialization features, such as gst_caps_to_string() or
61 * gst_value_serialize() and their counterparts.
62 */
63
64 #ifdef HAVE_CONFIG_H
65 #include "config.h"
66 #endif
67
68 /* FIXME 2.0: suppress warnings for deprecated API such as GValueArray
69 * with newer GLib versions (>= 2.31.0) */
70 #define GLIB_DISABLE_DEPRECATION_WARNINGS
71
72 #include <string.h>
73
74 #include "gst_private.h"
75 #include "gstquark.h"
76 #include <gst/gst.h>
77 #include <gobject/gvaluecollector.h>
78
79 GST_DEBUG_CATEGORY_STATIC (gst_structure_debug);
80 #define GST_CAT_DEFAULT gst_structure_debug
81
82 typedef struct _GstStructureField GstStructureField;
83
84 struct _GstStructureField
85 {
86 GQuark name;
87 GValue value;
88 };
89
90 typedef struct
91 {
92 GstStructure s;
93
94 /* owned by parent structure, NULL if no parent */
95 gint *parent_refcount;
96
97 GArray *fields;
98 } GstStructureImpl;
99
100 #define GST_STRUCTURE_REFCOUNT(s) (((GstStructureImpl*)(s))->parent_refcount)
101 #define GST_STRUCTURE_FIELDS(s) (((GstStructureImpl*)(s))->fields)
102
103 #define GST_STRUCTURE_FIELD(structure, index) \
104 &g_array_index(GST_STRUCTURE_FIELDS(structure), GstStructureField, (index))
105
106 #define IS_MUTABLE(structure) \
107 (!GST_STRUCTURE_REFCOUNT(structure) || \
108 g_atomic_int_get (GST_STRUCTURE_REFCOUNT(structure)) == 1)
109
110 #define IS_TAGLIST(structure) \
111 (structure->name == GST_QUARK (TAGLIST))
112
113 static void gst_structure_set_field (GstStructure * structure,
114 GstStructureField * field);
115 static GstStructureField *gst_structure_get_field (const GstStructure *
116 structure, const gchar * fieldname);
117 static GstStructureField *gst_structure_id_get_field (const GstStructure *
118 structure, GQuark field);
119 static void gst_structure_transform_to_string (const GValue * src_value,
120 GValue * dest_value);
121 static GstStructure *gst_structure_copy_conditional (const GstStructure *
122 structure);
123
124 GType _gst_structure_type = 0;
125
126
127 G_DEFINE_BOXED_TYPE (GstStructure, gst_structure,
128 gst_structure_copy_conditional, gst_structure_free);
129
130 void
_priv_gst_structure_initialize(void)131 _priv_gst_structure_initialize (void)
132 {
133 _gst_structure_type = gst_structure_get_type ();
134
135 g_value_register_transform_func (_gst_structure_type, G_TYPE_STRING,
136 gst_structure_transform_to_string);
137
138 GST_DEBUG_CATEGORY_INIT (gst_structure_debug, "structure", 0,
139 "GstStructure debug");
140 }
141
142 static GstStructure *
gst_structure_new_id_empty_with_size(GQuark quark,guint prealloc)143 gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
144 {
145 GstStructureImpl *structure;
146
147 structure = g_slice_new (GstStructureImpl);
148 ((GstStructure *) structure)->type = _gst_structure_type;
149 ((GstStructure *) structure)->name = quark;
150 GST_STRUCTURE_REFCOUNT (structure) = NULL;
151 GST_STRUCTURE_FIELDS (structure) =
152 g_array_sized_new (FALSE, FALSE, sizeof (GstStructureField), prealloc);
153
154 GST_TRACE ("created structure %p", structure);
155
156 return GST_STRUCTURE_CAST (structure);
157 }
158
159 /**
160 * gst_structure_new_id_empty:
161 * @quark: name of new structure
162 *
163 * Creates a new, empty #GstStructure with the given name as a GQuark.
164 *
165 * Free-function: gst_structure_free
166 *
167 * Returns: (transfer full): a new, empty #GstStructure
168 */
169 GstStructure *
gst_structure_new_id_empty(GQuark quark)170 gst_structure_new_id_empty (GQuark quark)
171 {
172 g_return_val_if_fail (quark != 0, NULL);
173
174 return gst_structure_new_id_empty_with_size (quark, 0);
175 }
176
177 #ifndef G_DISABLE_CHECKS
178 static gboolean
gst_structure_validate_name(const gchar * name)179 gst_structure_validate_name (const gchar * name)
180 {
181 const gchar *s;
182
183 g_return_val_if_fail (name != NULL, FALSE);
184
185 if (G_UNLIKELY (!g_ascii_isalpha (*name))) {
186 GST_WARNING ("Invalid character '%c' at offset 0 in structure name: %s",
187 *name, name);
188 return FALSE;
189 }
190
191 /* FIXME: test name string more */
192 s = &name[1];
193 while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+", *s) != NULL))
194 s++;
195 if (G_UNLIKELY (*s != '\0')) {
196 GST_WARNING ("Invalid character '%c' at offset %" G_GUINTPTR_FORMAT " in"
197 " structure name: %s", *s, ((guintptr) s - (guintptr) name), name);
198 return FALSE;
199 }
200
201 if (strncmp (name, "video/x-raw-", 12) == 0) {
202 g_warning ("0.10-style raw video caps are being created. Should be "
203 "video/x-raw,format=(string).. now.");
204 } else if (strncmp (name, "audio/x-raw-", 12) == 0) {
205 g_warning ("0.10-style raw audio caps are being created. Should be "
206 "audio/x-raw,format=(string).. now.");
207 }
208
209 return TRUE;
210 }
211 #endif
212
213 /**
214 * gst_structure_new_empty:
215 * @name: name of new structure
216 *
217 * Creates a new, empty #GstStructure with the given @name.
218 *
219 * See gst_structure_set_name() for constraints on the @name parameter.
220 *
221 * Free-function: gst_structure_free
222 *
223 * Returns: (transfer full): a new, empty #GstStructure
224 */
225 GstStructure *
gst_structure_new_empty(const gchar * name)226 gst_structure_new_empty (const gchar * name)
227 {
228 g_return_val_if_fail (gst_structure_validate_name (name), NULL);
229
230 return gst_structure_new_id_empty_with_size (g_quark_from_string (name), 0);
231 }
232
233 /**
234 * gst_structure_new:
235 * @name: name of new structure
236 * @firstfield: name of first field to set
237 * @...: additional arguments
238 *
239 * Creates a new #GstStructure with the given name. Parses the
240 * list of variable arguments and sets fields to the values listed.
241 * Variable arguments should be passed as field name, field type,
242 * and value. Last variable argument should be %NULL.
243 *
244 * Free-function: gst_structure_free
245 *
246 * Returns: (transfer full): a new #GstStructure
247 */
248 GstStructure *
gst_structure_new(const gchar * name,const gchar * firstfield,...)249 gst_structure_new (const gchar * name, const gchar * firstfield, ...)
250 {
251 GstStructure *structure;
252 va_list varargs;
253
254 va_start (varargs, firstfield);
255 structure = gst_structure_new_valist (name, firstfield, varargs);
256 va_end (varargs);
257
258 return structure;
259 }
260
261 /**
262 * gst_structure_new_valist:
263 * @name: name of new structure
264 * @firstfield: name of first field to set
265 * @varargs: variable argument list
266 *
267 * Creates a new #GstStructure with the given @name. Structure fields
268 * are set according to the varargs in a manner similar to
269 * gst_structure_new().
270 *
271 * See gst_structure_set_name() for constraints on the @name parameter.
272 *
273 * Free-function: gst_structure_free
274 *
275 * Returns: (transfer full): a new #GstStructure
276 */
277 GstStructure *
gst_structure_new_valist(const gchar * name,const gchar * firstfield,va_list varargs)278 gst_structure_new_valist (const gchar * name,
279 const gchar * firstfield, va_list varargs)
280 {
281 GstStructure *structure;
282
283 structure = gst_structure_new_empty (name);
284
285 if (structure)
286 gst_structure_set_valist (structure, firstfield, varargs);
287
288 return structure;
289 }
290
291 /**
292 * gst_structure_set_parent_refcount:
293 * @structure: a #GstStructure
294 * @refcount: (in): a pointer to the parent's refcount
295 *
296 * Sets the parent_refcount field of #GstStructure. This field is used to
297 * determine whether a structure is mutable or not. This function should only be
298 * called by code implementing parent objects of #GstStructure, as described in
299 * the MT Refcounting section of the design documents.
300 *
301 * Returns: %TRUE if the parent refcount could be set.
302 */
303 gboolean
gst_structure_set_parent_refcount(GstStructure * structure,gint * refcount)304 gst_structure_set_parent_refcount (GstStructure * structure, gint * refcount)
305 {
306 g_return_val_if_fail (structure != NULL, FALSE);
307
308 /* if we have a parent_refcount already, we can only clear
309 * if with a NULL refcount */
310 if (GST_STRUCTURE_REFCOUNT (structure)) {
311 if (refcount != NULL) {
312 g_return_val_if_fail (refcount == NULL, FALSE);
313 return FALSE;
314 }
315 } else {
316 if (refcount == NULL) {
317 g_return_val_if_fail (refcount != NULL, FALSE);
318 return FALSE;
319 }
320 }
321
322 GST_STRUCTURE_REFCOUNT (structure) = refcount;
323
324 return TRUE;
325 }
326
327 /**
328 * gst_structure_copy:
329 * @structure: a #GstStructure to duplicate
330 *
331 * Duplicates a #GstStructure and all its fields and values.
332 *
333 * Free-function: gst_structure_free
334 *
335 * Returns: (transfer full): a new #GstStructure.
336 */
337 GstStructure *
gst_structure_copy(const GstStructure * structure)338 gst_structure_copy (const GstStructure * structure)
339 {
340 GstStructure *new_structure;
341 GstStructureField *field;
342 guint i, len;
343
344 g_return_val_if_fail (structure != NULL, NULL);
345
346 len = GST_STRUCTURE_FIELDS (structure)->len;
347 new_structure = gst_structure_new_id_empty_with_size (structure->name, len);
348
349 for (i = 0; i < len; i++) {
350 GstStructureField new_field = { 0 };
351
352 field = GST_STRUCTURE_FIELD (structure, i);
353
354 new_field.name = field->name;
355 gst_value_init_and_copy (&new_field.value, &field->value);
356 g_array_append_val (GST_STRUCTURE_FIELDS (new_structure), new_field);
357 }
358 GST_CAT_TRACE (GST_CAT_PERFORMANCE, "doing copy %p -> %p",
359 structure, new_structure);
360
361 return new_structure;
362 }
363
364 /**
365 * gst_structure_free:
366 * @structure: (in) (transfer full): the #GstStructure to free
367 *
368 * Frees a #GstStructure and all its fields and values. The structure must not
369 * have a parent when this function is called.
370 */
371 void
gst_structure_free(GstStructure * structure)372 gst_structure_free (GstStructure * structure)
373 {
374 GstStructureField *field;
375 guint i, len;
376
377 g_return_if_fail (structure != NULL);
378 g_return_if_fail (GST_STRUCTURE_REFCOUNT (structure) == NULL);
379
380 len = GST_STRUCTURE_FIELDS (structure)->len;
381 for (i = 0; i < len; i++) {
382 field = GST_STRUCTURE_FIELD (structure, i);
383
384 if (G_IS_VALUE (&field->value)) {
385 g_value_unset (&field->value);
386 }
387 }
388 g_array_free (GST_STRUCTURE_FIELDS (structure), TRUE);
389 #ifdef USE_POISONING
390 memset (structure, 0xff, sizeof (GstStructure));
391 #endif
392 GST_TRACE ("free structure %p", structure);
393
394 g_slice_free1 (sizeof (GstStructureImpl), structure);
395 }
396
397 /**
398 * gst_clear_structure: (skip)
399 * @structure_ptr: a pointer to a #GstStructure reference
400 *
401 * Clears a reference to a #GstStructure.
402 *
403 * @structure_ptr must not be %NULL.
404 *
405 * If the reference is %NULL then this function does nothing.
406 * Otherwise, the structure is free'd using gst_structure_free() and the
407 * pointer is set to %NULL.
408 *
409 * A macro is also included that allows this function to be used without
410 * pointer casts.
411 *
412 * Since: 1.16
413 **/
414 #undef gst_clear_structure
415 void
gst_clear_structure(GstStructure ** structure_ptr)416 gst_clear_structure (GstStructure ** structure_ptr)
417 {
418 g_clear_pointer (structure_ptr, gst_structure_free);
419 }
420
421 /**
422 * gst_structure_get_name:
423 * @structure: a #GstStructure
424 *
425 * Get the name of @structure as a string.
426 *
427 * Returns: the name of the structure.
428 */
429 const gchar *
gst_structure_get_name(const GstStructure * structure)430 gst_structure_get_name (const GstStructure * structure)
431 {
432 g_return_val_if_fail (structure != NULL, NULL);
433
434 return g_quark_to_string (structure->name);
435 }
436
437 /**
438 * gst_structure_has_name:
439 * @structure: a #GstStructure
440 * @name: structure name to check for
441 *
442 * Checks if the structure has the given name
443 *
444 * Returns: %TRUE if @name matches the name of the structure.
445 */
446 gboolean
gst_structure_has_name(const GstStructure * structure,const gchar * name)447 gst_structure_has_name (const GstStructure * structure, const gchar * name)
448 {
449 const gchar *structure_name;
450
451 g_return_val_if_fail (structure != NULL, FALSE);
452 g_return_val_if_fail (name != NULL, FALSE);
453
454 /* getting the string is cheap and comparing short strings is too
455 * should be faster than getting the quark for name and comparing the quarks
456 */
457 structure_name = g_quark_to_string (structure->name);
458
459 return (structure_name && strcmp (structure_name, name) == 0);
460 }
461
462 /**
463 * gst_structure_get_name_id:
464 * @structure: a #GstStructure
465 *
466 * Get the name of @structure as a GQuark.
467 *
468 * Returns: the quark representing the name of the structure.
469 */
470 GQuark
gst_structure_get_name_id(const GstStructure * structure)471 gst_structure_get_name_id (const GstStructure * structure)
472 {
473 g_return_val_if_fail (structure != NULL, 0);
474
475 return structure->name;
476 }
477
478 /**
479 * gst_structure_set_name:
480 * @structure: a #GstStructure
481 * @name: the new name of the structure
482 *
483 * Sets the name of the structure to the given @name. The string
484 * provided is copied before being used. It must not be empty, start with a
485 * letter and can be followed by letters, numbers and any of "/-_.:".
486 */
487 void
gst_structure_set_name(GstStructure * structure,const gchar * name)488 gst_structure_set_name (GstStructure * structure, const gchar * name)
489 {
490 g_return_if_fail (structure != NULL);
491 g_return_if_fail (IS_MUTABLE (structure));
492 g_return_if_fail (gst_structure_validate_name (name));
493
494 structure->name = g_quark_from_string (name);
495 }
496
497 static inline void
gst_structure_id_set_value_internal(GstStructure * structure,GQuark field,const GValue * value)498 gst_structure_id_set_value_internal (GstStructure * structure, GQuark field,
499 const GValue * value)
500 {
501 GstStructureField gsfield = { 0, {0,} };
502
503 gsfield.name = field;
504 gst_value_init_and_copy (&gsfield.value, value);
505
506 gst_structure_set_field (structure, &gsfield);
507 }
508
509 /**
510 * gst_structure_id_set_value:
511 * @structure: a #GstStructure
512 * @field: a #GQuark representing a field
513 * @value: the new value of the field
514 *
515 * Sets the field with the given GQuark @field to @value. If the field
516 * does not exist, it is created. If the field exists, the previous
517 * value is replaced and freed.
518 */
519 void
gst_structure_id_set_value(GstStructure * structure,GQuark field,const GValue * value)520 gst_structure_id_set_value (GstStructure * structure,
521 GQuark field, const GValue * value)
522 {
523
524 g_return_if_fail (structure != NULL);
525 g_return_if_fail (G_IS_VALUE (value));
526 g_return_if_fail (IS_MUTABLE (structure));
527
528 gst_structure_id_set_value_internal (structure, field, value);
529 }
530
531 /**
532 * gst_structure_set_value:
533 * @structure: a #GstStructure
534 * @fieldname: the name of the field to set
535 * @value: the new value of the field
536 *
537 * Sets the field with the given name @field to @value. If the field
538 * does not exist, it is created. If the field exists, the previous
539 * value is replaced and freed.
540 */
541 void
gst_structure_set_value(GstStructure * structure,const gchar * fieldname,const GValue * value)542 gst_structure_set_value (GstStructure * structure,
543 const gchar * fieldname, const GValue * value)
544 {
545 g_return_if_fail (structure != NULL);
546 g_return_if_fail (fieldname != NULL);
547 g_return_if_fail (G_IS_VALUE (value));
548 g_return_if_fail (IS_MUTABLE (structure));
549
550 gst_structure_id_set_value_internal (structure,
551 g_quark_from_string (fieldname), value);
552 }
553
554 static inline void
gst_structure_id_take_value_internal(GstStructure * structure,GQuark field,GValue * value)555 gst_structure_id_take_value_internal (GstStructure * structure, GQuark field,
556 GValue * value)
557 {
558 GstStructureField gsfield = { 0, {0,} };
559
560 gsfield.name = field;
561 gsfield.value = *value;
562
563 gst_structure_set_field (structure, &gsfield);
564
565 /* we took ownership */
566 #ifdef USE_POISONING
567 memset (value, 0, sizeof (GValue));
568 #else
569 value->g_type = G_TYPE_INVALID;
570 #endif
571 }
572
573 /**
574 * gst_structure_id_take_value:
575 * @structure: a #GstStructure
576 * @field: a #GQuark representing a field
577 * @value: (transfer full): the new value of the field
578 *
579 * Sets the field with the given GQuark @field to @value. If the field
580 * does not exist, it is created. If the field exists, the previous
581 * value is replaced and freed.
582 */
583 void
gst_structure_id_take_value(GstStructure * structure,GQuark field,GValue * value)584 gst_structure_id_take_value (GstStructure * structure, GQuark field,
585 GValue * value)
586 {
587 g_return_if_fail (structure != NULL);
588 g_return_if_fail (G_IS_VALUE (value));
589 g_return_if_fail (IS_MUTABLE (structure));
590
591 gst_structure_id_take_value_internal (structure, field, value);
592 }
593
594 /**
595 * gst_structure_take_value:
596 * @structure: a #GstStructure
597 * @fieldname: the name of the field to set
598 * @value: (transfer full): the new value of the field
599 *
600 * Sets the field with the given name @field to @value. If the field
601 * does not exist, it is created. If the field exists, the previous
602 * value is replaced and freed. The function will take ownership of @value.
603 */
604 void
gst_structure_take_value(GstStructure * structure,const gchar * fieldname,GValue * value)605 gst_structure_take_value (GstStructure * structure, const gchar * fieldname,
606 GValue * value)
607 {
608 g_return_if_fail (structure != NULL);
609 g_return_if_fail (fieldname != NULL);
610 g_return_if_fail (G_IS_VALUE (value));
611 g_return_if_fail (IS_MUTABLE (structure));
612
613 gst_structure_id_take_value_internal (structure,
614 g_quark_from_string (fieldname), value);
615 }
616
617 static void
gst_structure_set_valist_internal(GstStructure * structure,const gchar * fieldname,va_list varargs)618 gst_structure_set_valist_internal (GstStructure * structure,
619 const gchar * fieldname, va_list varargs)
620 {
621 gchar *err = NULL;
622 GType type;
623
624 while (fieldname) {
625 GstStructureField field = { 0 };
626
627 field.name = g_quark_from_string (fieldname);
628
629 type = va_arg (varargs, GType);
630
631 G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
632 if (G_UNLIKELY (err)) {
633 g_critical ("%s", err);
634 g_free (err);
635 return;
636 }
637 gst_structure_set_field (structure, &field);
638
639 fieldname = va_arg (varargs, gchar *);
640 }
641 }
642
643 /**
644 * gst_structure_set:
645 * @structure: a #GstStructure
646 * @fieldname: the name of the field to set
647 * @...: variable arguments
648 *
649 * Parses the variable arguments and sets fields accordingly. Fields that
650 * weren't already part of the structure are added as needed.
651 * Variable arguments should be in the form field name, field type
652 * (as a GType), value(s). The last variable argument should be %NULL.
653 */
654 void
gst_structure_set(GstStructure * structure,const gchar * field,...)655 gst_structure_set (GstStructure * structure, const gchar * field, ...)
656 {
657 va_list varargs;
658
659 g_return_if_fail (structure != NULL);
660 g_return_if_fail (IS_MUTABLE (structure) || field == NULL);
661
662 va_start (varargs, field);
663 gst_structure_set_valist_internal (structure, field, varargs);
664 va_end (varargs);
665 }
666
667 /**
668 * gst_structure_set_valist:
669 * @structure: a #GstStructure
670 * @fieldname: the name of the field to set
671 * @varargs: variable arguments
672 *
673 * va_list form of gst_structure_set().
674 */
675 void
gst_structure_set_valist(GstStructure * structure,const gchar * fieldname,va_list varargs)676 gst_structure_set_valist (GstStructure * structure,
677 const gchar * fieldname, va_list varargs)
678 {
679 g_return_if_fail (structure != NULL);
680 g_return_if_fail (IS_MUTABLE (structure));
681
682 gst_structure_set_valist_internal (structure, fieldname, varargs);
683 }
684
685 static void
gst_structure_id_set_valist_internal(GstStructure * structure,GQuark fieldname,va_list varargs)686 gst_structure_id_set_valist_internal (GstStructure * structure,
687 GQuark fieldname, va_list varargs)
688 {
689 gchar *err = NULL;
690 GType type;
691
692 while (fieldname) {
693 GstStructureField field = { 0 };
694
695 field.name = fieldname;
696 type = va_arg (varargs, GType);
697
698 G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
699 if (G_UNLIKELY (err)) {
700 g_critical ("%s", err);
701 g_free (err);
702 return;
703 }
704 gst_structure_set_field (structure, &field);
705
706 fieldname = va_arg (varargs, GQuark);
707 }
708 }
709
710 /**
711 * gst_structure_id_set:
712 * @structure: a #GstStructure
713 * @fieldname: the GQuark for the name of the field to set
714 * @...: variable arguments
715 *
716 * Identical to gst_structure_set, except that field names are
717 * passed using the GQuark for the field name. This allows more efficient
718 * setting of the structure if the caller already knows the associated
719 * quark values.
720 * The last variable argument must be %NULL.
721 */
722 void
gst_structure_id_set(GstStructure * structure,GQuark field,...)723 gst_structure_id_set (GstStructure * structure, GQuark field, ...)
724 {
725 va_list varargs;
726
727 g_return_if_fail (structure != NULL);
728
729 va_start (varargs, field);
730 gst_structure_id_set_valist_internal (structure, field, varargs);
731 va_end (varargs);
732 }
733
734 /**
735 * gst_structure_id_set_valist:
736 * @structure: a #GstStructure
737 * @fieldname: the name of the field to set
738 * @varargs: variable arguments
739 *
740 * va_list form of gst_structure_id_set().
741 */
742 void
gst_structure_id_set_valist(GstStructure * structure,GQuark fieldname,va_list varargs)743 gst_structure_id_set_valist (GstStructure * structure,
744 GQuark fieldname, va_list varargs)
745 {
746 g_return_if_fail (structure != NULL);
747 g_return_if_fail (IS_MUTABLE (structure));
748
749 gst_structure_id_set_valist_internal (structure, fieldname, varargs);
750 }
751
752 /**
753 * gst_structure_new_id:
754 * @name_quark: name of new structure
755 * @field_quark: the GQuark for the name of the field to set
756 * @...: variable arguments
757 *
758 * Creates a new #GstStructure with the given name as a GQuark, followed by
759 * fieldname quark, GType, argument(s) "triplets" in the same format as
760 * gst_structure_id_set(). Basically a convenience wrapper around
761 * gst_structure_new_id_empty() and gst_structure_id_set().
762 *
763 * The last variable argument must be %NULL (or 0).
764 *
765 * Free-function: gst_structure_free
766 *
767 * Returns: (transfer full): a new #GstStructure
768 */
769 GstStructure *
gst_structure_new_id(GQuark name_quark,GQuark field_quark,...)770 gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
771 {
772 GstStructure *s;
773 va_list varargs;
774
775 g_return_val_if_fail (name_quark != 0, NULL);
776 g_return_val_if_fail (field_quark != 0, NULL);
777
778 s = gst_structure_new_id_empty (name_quark);
779
780 va_start (varargs, field_quark);
781 gst_structure_id_set_valist_internal (s, field_quark, varargs);
782 va_end (varargs);
783
784 return s;
785 }
786
787 #if GST_VERSION_NANO == 1
788 #define GIT_G_WARNING g_warning
789 #else
790 #define GIT_G_WARNING GST_WARNING
791 #endif
792
793 /* If the structure currently contains a field with the same name, it is
794 * replaced with the provided field. Otherwise, the field is added to the
795 * structure. The field's value is not deeply copied.
796 */
797 static void
gst_structure_set_field(GstStructure * structure,GstStructureField * field)798 gst_structure_set_field (GstStructure * structure, GstStructureField * field)
799 {
800 GstStructureField *f;
801 GType field_value_type;
802 guint i, len;
803
804 len = GST_STRUCTURE_FIELDS (structure)->len;
805
806 field_value_type = G_VALUE_TYPE (&field->value);
807 if (field_value_type == G_TYPE_STRING) {
808 const gchar *s;
809
810 s = g_value_get_string (&field->value);
811 /* only check for NULL strings in taglists, as they are allowed in message
812 * structs, e.g. error message debug strings */
813 if (G_UNLIKELY (IS_TAGLIST (structure) && (s == NULL || *s == '\0'))) {
814 if (s == NULL) {
815 GIT_G_WARNING ("Trying to set NULL string on field '%s' on taglist. "
816 "Please file a bug.", g_quark_to_string (field->name));
817 g_value_unset (&field->value);
818 return;
819 } else {
820 /* empty strings never make sense */
821 GIT_G_WARNING ("Trying to set empty string on taglist field '%s'. "
822 "Please file a bug.", g_quark_to_string (field->name));
823 g_value_unset (&field->value);
824 return;
825 }
826 } else if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
827 g_warning ("Trying to set string on %s field '%s', but string is not "
828 "valid UTF-8. Please file a bug.",
829 IS_TAGLIST (structure) ? "taglist" : "structure",
830 g_quark_to_string (field->name));
831 g_value_unset (&field->value);
832 return;
833 }
834 } else if (G_UNLIKELY (field_value_type == G_TYPE_DATE)) {
835 const GDate *d;
836
837 d = g_value_get_boxed (&field->value);
838 /* only check for NULL GDates in taglists, as they might make sense
839 * in other, generic structs */
840 if (G_UNLIKELY ((IS_TAGLIST (structure) && d == NULL))) {
841 GIT_G_WARNING ("Trying to set NULL GDate on field '%s' on taglist. "
842 "Please file a bug.", g_quark_to_string (field->name));
843 g_value_unset (&field->value);
844 return;
845 } else if (G_UNLIKELY (d != NULL && !g_date_valid (d))) {
846 g_warning
847 ("Trying to set invalid GDate on %s field '%s'. Please file a bug.",
848 IS_TAGLIST (structure) ? "taglist" : "structure",
849 g_quark_to_string (field->name));
850 g_value_unset (&field->value);
851 return;
852 }
853 }
854
855 for (i = 0; i < len; i++) {
856 f = GST_STRUCTURE_FIELD (structure, i);
857
858 if (G_UNLIKELY (f->name == field->name)) {
859 g_value_unset (&f->value);
860 memcpy (f, field, sizeof (GstStructureField));
861 return;
862 }
863 }
864
865 g_array_append_val (GST_STRUCTURE_FIELDS (structure), *field);
866 }
867
868 /* If there is no field with the given ID, NULL is returned.
869 */
870 static GstStructureField *
gst_structure_id_get_field(const GstStructure * structure,GQuark field_id)871 gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
872 {
873 GstStructureField *field;
874 guint i, len;
875
876 len = GST_STRUCTURE_FIELDS (structure)->len;
877
878 for (i = 0; i < len; i++) {
879 field = GST_STRUCTURE_FIELD (structure, i);
880
881 if (G_UNLIKELY (field->name == field_id))
882 return field;
883 }
884
885 return NULL;
886 }
887
888 /* If there is no field with the given ID, NULL is returned.
889 */
890 static GstStructureField *
gst_structure_get_field(const GstStructure * structure,const gchar * fieldname)891 gst_structure_get_field (const GstStructure * structure,
892 const gchar * fieldname)
893 {
894 g_return_val_if_fail (structure != NULL, NULL);
895 g_return_val_if_fail (fieldname != NULL, NULL);
896
897 return gst_structure_id_get_field (structure,
898 g_quark_from_string (fieldname));
899 }
900
901 /**
902 * gst_structure_get_value:
903 * @structure: a #GstStructure
904 * @fieldname: the name of the field to get
905 *
906 * Get the value of the field with name @fieldname.
907 *
908 * Returns: (nullable): the #GValue corresponding to the field with the given
909 * name.
910 */
911 const GValue *
gst_structure_get_value(const GstStructure * structure,const gchar * fieldname)912 gst_structure_get_value (const GstStructure * structure,
913 const gchar * fieldname)
914 {
915 GstStructureField *field;
916
917 g_return_val_if_fail (structure != NULL, NULL);
918 g_return_val_if_fail (fieldname != NULL, NULL);
919
920 field = gst_structure_get_field (structure, fieldname);
921 if (field == NULL)
922 return NULL;
923
924 return &field->value;
925 }
926
927 /**
928 * gst_structure_id_get_value:
929 * @structure: a #GstStructure
930 * @field: the #GQuark of the field to get
931 *
932 * Get the value of the field with GQuark @field.
933 *
934 * Returns: (nullable): the #GValue corresponding to the field with the given
935 * name identifier.
936 */
937 const GValue *
gst_structure_id_get_value(const GstStructure * structure,GQuark field)938 gst_structure_id_get_value (const GstStructure * structure, GQuark field)
939 {
940 GstStructureField *gsfield;
941
942 g_return_val_if_fail (structure != NULL, NULL);
943
944 gsfield = gst_structure_id_get_field (structure, field);
945 if (gsfield == NULL)
946 return NULL;
947
948 return &gsfield->value;
949 }
950
951 /**
952 * gst_structure_remove_field:
953 * @structure: a #GstStructure
954 * @fieldname: the name of the field to remove
955 *
956 * Removes the field with the given name. If the field with the given
957 * name does not exist, the structure is unchanged.
958 */
959 void
gst_structure_remove_field(GstStructure * structure,const gchar * fieldname)960 gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
961 {
962 GstStructureField *field;
963 GQuark id;
964 guint i, len;
965
966 g_return_if_fail (structure != NULL);
967 g_return_if_fail (fieldname != NULL);
968 g_return_if_fail (IS_MUTABLE (structure));
969
970 id = g_quark_from_string (fieldname);
971 len = GST_STRUCTURE_FIELDS (structure)->len;
972
973 for (i = 0; i < len; i++) {
974 field = GST_STRUCTURE_FIELD (structure, i);
975
976 if (field->name == id) {
977 if (G_IS_VALUE (&field->value)) {
978 g_value_unset (&field->value);
979 }
980 GST_STRUCTURE_FIELDS (structure) =
981 g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
982 return;
983 }
984 }
985 }
986
987 /**
988 * gst_structure_remove_fields:
989 * @structure: a #GstStructure
990 * @fieldname: the name of the field to remove
991 * @...: %NULL-terminated list of more fieldnames to remove
992 *
993 * Removes the fields with the given names. If a field does not exist, the
994 * argument is ignored.
995 */
996 void
gst_structure_remove_fields(GstStructure * structure,const gchar * fieldname,...)997 gst_structure_remove_fields (GstStructure * structure,
998 const gchar * fieldname, ...)
999 {
1000 va_list varargs;
1001
1002 g_return_if_fail (structure != NULL);
1003 g_return_if_fail (fieldname != NULL);
1004 /* mutability checked in remove_field */
1005
1006 va_start (varargs, fieldname);
1007 gst_structure_remove_fields_valist (structure, fieldname, varargs);
1008 va_end (varargs);
1009 }
1010
1011 /**
1012 * gst_structure_remove_fields_valist:
1013 * @structure: a #GstStructure
1014 * @fieldname: the name of the field to remove
1015 * @varargs: %NULL-terminated list of more fieldnames to remove
1016 *
1017 * va_list form of gst_structure_remove_fields().
1018 */
1019 void
gst_structure_remove_fields_valist(GstStructure * structure,const gchar * fieldname,va_list varargs)1020 gst_structure_remove_fields_valist (GstStructure * structure,
1021 const gchar * fieldname, va_list varargs)
1022 {
1023 gchar *field = (gchar *) fieldname;
1024
1025 g_return_if_fail (structure != NULL);
1026 g_return_if_fail (fieldname != NULL);
1027 /* mutability checked in remove_field */
1028
1029 while (field) {
1030 gst_structure_remove_field (structure, field);
1031 field = va_arg (varargs, char *);
1032 }
1033 }
1034
1035 /**
1036 * gst_structure_remove_all_fields:
1037 * @structure: a #GstStructure
1038 *
1039 * Removes all fields in a GstStructure.
1040 */
1041 void
gst_structure_remove_all_fields(GstStructure * structure)1042 gst_structure_remove_all_fields (GstStructure * structure)
1043 {
1044 GstStructureField *field;
1045 int i;
1046
1047 g_return_if_fail (structure != NULL);
1048 g_return_if_fail (IS_MUTABLE (structure));
1049
1050 for (i = GST_STRUCTURE_FIELDS (structure)->len - 1; i >= 0; i--) {
1051 field = GST_STRUCTURE_FIELD (structure, i);
1052
1053 if (G_IS_VALUE (&field->value)) {
1054 g_value_unset (&field->value);
1055 }
1056 GST_STRUCTURE_FIELDS (structure) =
1057 g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
1058 }
1059 }
1060
1061 /**
1062 * gst_structure_get_field_type:
1063 * @structure: a #GstStructure
1064 * @fieldname: the name of the field
1065 *
1066 * Finds the field with the given name, and returns the type of the
1067 * value it contains. If the field is not found, G_TYPE_INVALID is
1068 * returned.
1069 *
1070 * Returns: the #GValue of the field
1071 */
1072 GType
gst_structure_get_field_type(const GstStructure * structure,const gchar * fieldname)1073 gst_structure_get_field_type (const GstStructure * structure,
1074 const gchar * fieldname)
1075 {
1076 GstStructureField *field;
1077
1078 g_return_val_if_fail (structure != NULL, G_TYPE_INVALID);
1079 g_return_val_if_fail (fieldname != NULL, G_TYPE_INVALID);
1080
1081 field = gst_structure_get_field (structure, fieldname);
1082 if (field == NULL)
1083 return G_TYPE_INVALID;
1084
1085 return G_VALUE_TYPE (&field->value);
1086 }
1087
1088 /**
1089 * gst_structure_n_fields:
1090 * @structure: a #GstStructure
1091 *
1092 * Get the number of fields in the structure.
1093 *
1094 * Returns: the number of fields in the structure
1095 */
1096 gint
gst_structure_n_fields(const GstStructure * structure)1097 gst_structure_n_fields (const GstStructure * structure)
1098 {
1099 g_return_val_if_fail (structure != NULL, 0);
1100
1101 return GST_STRUCTURE_FIELDS (structure)->len;
1102 }
1103
1104 /**
1105 * gst_structure_nth_field_name:
1106 * @structure: a #GstStructure
1107 * @index: the index to get the name of
1108 *
1109 * Get the name of the given field number, counting from 0 onwards.
1110 *
1111 * Returns: the name of the given field number
1112 */
1113 const gchar *
gst_structure_nth_field_name(const GstStructure * structure,guint index)1114 gst_structure_nth_field_name (const GstStructure * structure, guint index)
1115 {
1116 GstStructureField *field;
1117
1118 g_return_val_if_fail (structure != NULL, NULL);
1119 g_return_val_if_fail (index < GST_STRUCTURE_FIELDS (structure)->len, NULL);
1120
1121 field = GST_STRUCTURE_FIELD (structure, index);
1122
1123 return g_quark_to_string (field->name);
1124 }
1125
1126 /**
1127 * gst_structure_foreach:
1128 * @structure: a #GstStructure
1129 * @func: (scope call): a function to call for each field
1130 * @user_data: (closure): private data
1131 *
1132 * Calls the provided function once for each field in the #GstStructure. The
1133 * function must not modify the fields. Also see gst_structure_map_in_place()
1134 * and gst_structure_filter_and_map_in_place().
1135 *
1136 * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
1137 * %FALSE otherwise.
1138 */
1139 gboolean
gst_structure_foreach(const GstStructure * structure,GstStructureForeachFunc func,gpointer user_data)1140 gst_structure_foreach (const GstStructure * structure,
1141 GstStructureForeachFunc func, gpointer user_data)
1142 {
1143 guint i, len;
1144 GstStructureField *field;
1145 gboolean ret;
1146
1147 g_return_val_if_fail (structure != NULL, FALSE);
1148 g_return_val_if_fail (func != NULL, FALSE);
1149
1150 len = GST_STRUCTURE_FIELDS (structure)->len;
1151
1152 for (i = 0; i < len; i++) {
1153 field = GST_STRUCTURE_FIELD (structure, i);
1154
1155 ret = func (field->name, &field->value, user_data);
1156 if (G_UNLIKELY (!ret))
1157 return FALSE;
1158 }
1159
1160 return TRUE;
1161 }
1162
1163 /**
1164 * gst_structure_map_in_place:
1165 * @structure: a #GstStructure
1166 * @func: (scope call): a function to call for each field
1167 * @user_data: (closure): private data
1168 *
1169 * Calls the provided function once for each field in the #GstStructure. In
1170 * contrast to gst_structure_foreach(), the function may modify but not delete the
1171 * fields. The structure must be mutable.
1172 *
1173 * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
1174 * %FALSE otherwise.
1175 */
1176 gboolean
gst_structure_map_in_place(GstStructure * structure,GstStructureMapFunc func,gpointer user_data)1177 gst_structure_map_in_place (GstStructure * structure,
1178 GstStructureMapFunc func, gpointer user_data)
1179 {
1180 guint i, len;
1181 GstStructureField *field;
1182 gboolean ret;
1183
1184 g_return_val_if_fail (structure != NULL, FALSE);
1185 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
1186 g_return_val_if_fail (func != NULL, FALSE);
1187 len = GST_STRUCTURE_FIELDS (structure)->len;
1188
1189 for (i = 0; i < len; i++) {
1190 field = GST_STRUCTURE_FIELD (structure, i);
1191
1192 ret = func (field->name, &field->value, user_data);
1193 if (!ret)
1194 return FALSE;
1195 }
1196
1197 return TRUE;
1198 }
1199
1200 /**
1201 * gst_structure_filter_and_map_in_place:
1202 * @structure: a #GstStructure
1203 * @func: (scope call): a function to call for each field
1204 * @user_data: (closure): private data
1205 *
1206 * Calls the provided function once for each field in the #GstStructure. In
1207 * contrast to gst_structure_foreach(), the function may modify the fields.
1208 * In contrast to gst_structure_map_in_place(), the field is removed from
1209 * the structure if %FALSE is returned from the function.
1210 * The structure must be mutable.
1211 *
1212 * Since: 1.6
1213 */
1214 void
gst_structure_filter_and_map_in_place(GstStructure * structure,GstStructureFilterMapFunc func,gpointer user_data)1215 gst_structure_filter_and_map_in_place (GstStructure * structure,
1216 GstStructureFilterMapFunc func, gpointer user_data)
1217 {
1218 guint i, len;
1219 GstStructureField *field;
1220 gboolean ret;
1221
1222 g_return_if_fail (structure != NULL);
1223 g_return_if_fail (IS_MUTABLE (structure));
1224 g_return_if_fail (func != NULL);
1225 len = GST_STRUCTURE_FIELDS (structure)->len;
1226
1227 for (i = 0; i < len;) {
1228 field = GST_STRUCTURE_FIELD (structure, i);
1229
1230 ret = func (field->name, &field->value, user_data);
1231
1232 if (!ret) {
1233 if (G_IS_VALUE (&field->value)) {
1234 g_value_unset (&field->value);
1235 }
1236 GST_STRUCTURE_FIELDS (structure) =
1237 g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
1238 len = GST_STRUCTURE_FIELDS (structure)->len;
1239 } else {
1240 i++;
1241 }
1242 }
1243 }
1244
1245 /**
1246 * gst_structure_id_has_field:
1247 * @structure: a #GstStructure
1248 * @field: #GQuark of the field name
1249 *
1250 * Check if @structure contains a field named @field.
1251 *
1252 * Returns: %TRUE if the structure contains a field with the given name
1253 */
1254 gboolean
gst_structure_id_has_field(const GstStructure * structure,GQuark field)1255 gst_structure_id_has_field (const GstStructure * structure, GQuark field)
1256 {
1257 GstStructureField *f;
1258
1259 g_return_val_if_fail (structure != NULL, FALSE);
1260 g_return_val_if_fail (field != 0, FALSE);
1261
1262 f = gst_structure_id_get_field (structure, field);
1263
1264 return (f != NULL);
1265 }
1266
1267 /**
1268 * gst_structure_has_field:
1269 * @structure: a #GstStructure
1270 * @fieldname: the name of a field
1271 *
1272 * Check if @structure contains a field named @fieldname.
1273 *
1274 * Returns: %TRUE if the structure contains a field with the given name
1275 */
1276 gboolean
gst_structure_has_field(const GstStructure * structure,const gchar * fieldname)1277 gst_structure_has_field (const GstStructure * structure,
1278 const gchar * fieldname)
1279 {
1280 g_return_val_if_fail (structure != NULL, FALSE);
1281 g_return_val_if_fail (fieldname != NULL, FALSE);
1282
1283 return gst_structure_id_has_field (structure,
1284 g_quark_from_string (fieldname));
1285 }
1286
1287 /**
1288 * gst_structure_id_has_field_typed:
1289 * @structure: a #GstStructure
1290 * @field: #GQuark of the field name
1291 * @type: the type of a value
1292 *
1293 * Check if @structure contains a field named @field and with GType @type.
1294 *
1295 * Returns: %TRUE if the structure contains a field with the given name and type
1296 */
1297 gboolean
gst_structure_id_has_field_typed(const GstStructure * structure,GQuark field,GType type)1298 gst_structure_id_has_field_typed (const GstStructure * structure,
1299 GQuark field, GType type)
1300 {
1301 GstStructureField *f;
1302
1303 g_return_val_if_fail (structure != NULL, FALSE);
1304 g_return_val_if_fail (field != 0, FALSE);
1305
1306 f = gst_structure_id_get_field (structure, field);
1307 if (f == NULL)
1308 return FALSE;
1309
1310 return (G_VALUE_TYPE (&f->value) == type);
1311 }
1312
1313 /**
1314 * gst_structure_has_field_typed:
1315 * @structure: a #GstStructure
1316 * @fieldname: the name of a field
1317 * @type: the type of a value
1318 *
1319 * Check if @structure contains a field named @fieldname and with GType @type.
1320 *
1321 * Returns: %TRUE if the structure contains a field with the given name and type
1322 */
1323 gboolean
gst_structure_has_field_typed(const GstStructure * structure,const gchar * fieldname,GType type)1324 gst_structure_has_field_typed (const GstStructure * structure,
1325 const gchar * fieldname, GType type)
1326 {
1327 g_return_val_if_fail (structure != NULL, FALSE);
1328 g_return_val_if_fail (fieldname != NULL, FALSE);
1329
1330 return gst_structure_id_has_field_typed (structure,
1331 g_quark_from_string (fieldname), type);
1332 }
1333
1334 /* utility functions */
1335
1336 /**
1337 * gst_structure_get_boolean:
1338 * @structure: a #GstStructure
1339 * @fieldname: the name of a field
1340 * @value: (out): a pointer to a #gboolean to set
1341 *
1342 * Sets the boolean pointed to by @value corresponding to the value of the
1343 * given field. Caller is responsible for making sure the field exists
1344 * and has the correct type.
1345 *
1346 * Returns: %TRUE if the value could be set correctly. If there was no field
1347 * with @fieldname or the existing field did not contain a boolean, this
1348 * function returns %FALSE.
1349 */
1350 gboolean
gst_structure_get_boolean(const GstStructure * structure,const gchar * fieldname,gboolean * value)1351 gst_structure_get_boolean (const GstStructure * structure,
1352 const gchar * fieldname, gboolean * value)
1353 {
1354 GstStructureField *field;
1355
1356 g_return_val_if_fail (structure != NULL, FALSE);
1357 g_return_val_if_fail (fieldname != NULL, FALSE);
1358
1359 field = gst_structure_get_field (structure, fieldname);
1360
1361 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_BOOLEAN)
1362 return FALSE;
1363
1364 *value = gst_g_value_get_boolean_unchecked (&field->value);
1365
1366 return TRUE;
1367 }
1368
1369 /**
1370 * gst_structure_get_int:
1371 * @structure: a #GstStructure
1372 * @fieldname: the name of a field
1373 * @value: (out): a pointer to an int to set
1374 *
1375 * Sets the int pointed to by @value corresponding to the value of the
1376 * given field. Caller is responsible for making sure the field exists
1377 * and has the correct type.
1378 *
1379 * Returns: %TRUE if the value could be set correctly. If there was no field
1380 * with @fieldname or the existing field did not contain an int, this function
1381 * returns %FALSE.
1382 */
1383 gboolean
gst_structure_get_int(const GstStructure * structure,const gchar * fieldname,gint * value)1384 gst_structure_get_int (const GstStructure * structure,
1385 const gchar * fieldname, gint * value)
1386 {
1387 GstStructureField *field;
1388
1389 g_return_val_if_fail (structure != NULL, FALSE);
1390 g_return_val_if_fail (fieldname != NULL, FALSE);
1391 g_return_val_if_fail (value != NULL, FALSE);
1392
1393 field = gst_structure_get_field (structure, fieldname);
1394
1395 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT)
1396 return FALSE;
1397
1398 *value = gst_g_value_get_int_unchecked (&field->value);
1399
1400 return TRUE;
1401 }
1402
1403 /**
1404 * gst_structure_get_uint:
1405 * @structure: a #GstStructure
1406 * @fieldname: the name of a field
1407 * @value: (out): a pointer to a uint to set
1408 *
1409 * Sets the uint pointed to by @value corresponding to the value of the
1410 * given field. Caller is responsible for making sure the field exists
1411 * and has the correct type.
1412 *
1413 * Returns: %TRUE if the value could be set correctly. If there was no field
1414 * with @fieldname or the existing field did not contain a uint, this function
1415 * returns %FALSE.
1416 */
1417 gboolean
gst_structure_get_uint(const GstStructure * structure,const gchar * fieldname,guint * value)1418 gst_structure_get_uint (const GstStructure * structure,
1419 const gchar * fieldname, guint * value)
1420 {
1421 GstStructureField *field;
1422
1423 g_return_val_if_fail (structure != NULL, FALSE);
1424 g_return_val_if_fail (fieldname != NULL, FALSE);
1425 g_return_val_if_fail (value != NULL, FALSE);
1426
1427 field = gst_structure_get_field (structure, fieldname);
1428
1429 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT)
1430 return FALSE;
1431
1432 *value = gst_g_value_get_uint_unchecked (&field->value);
1433
1434 return TRUE;
1435 }
1436
1437 /**
1438 * gst_structure_get_int64:
1439 * @structure: a #GstStructure
1440 * @fieldname: the name of a field
1441 * @value: (out): a pointer to a #gint64 to set
1442 *
1443 * Sets the #gint64 pointed to by @value corresponding to the value of the
1444 * given field. Caller is responsible for making sure the field exists
1445 * and has the correct type.
1446 *
1447 * Returns: %TRUE if the value could be set correctly. If there was no field
1448 * with @fieldname or the existing field did not contain a #gint64, this function
1449 * returns %FALSE.
1450 *
1451 * Since: 1.4
1452 */
1453 gboolean
gst_structure_get_int64(const GstStructure * structure,const gchar * fieldname,gint64 * value)1454 gst_structure_get_int64 (const GstStructure * structure,
1455 const gchar * fieldname, gint64 * value)
1456 {
1457 GstStructureField *field;
1458
1459 g_return_val_if_fail (structure != NULL, FALSE);
1460 g_return_val_if_fail (fieldname != NULL, FALSE);
1461 g_return_val_if_fail (value != NULL, FALSE);
1462
1463 field = gst_structure_get_field (structure, fieldname);
1464
1465 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_INT64)
1466 return FALSE;
1467
1468 *value = gst_g_value_get_int64_unchecked (&field->value);
1469
1470 return TRUE;
1471 }
1472
1473 /**
1474 * gst_structure_get_uint64:
1475 * @structure: a #GstStructure
1476 * @fieldname: the name of a field
1477 * @value: (out): a pointer to a #guint64 to set
1478 *
1479 * Sets the #guint64 pointed to by @value corresponding to the value of the
1480 * given field. Caller is responsible for making sure the field exists
1481 * and has the correct type.
1482 *
1483 * Returns: %TRUE if the value could be set correctly. If there was no field
1484 * with @fieldname or the existing field did not contain a #guint64, this function
1485 * returns %FALSE.
1486 *
1487 * Since: 1.4
1488 */
1489 gboolean
gst_structure_get_uint64(const GstStructure * structure,const gchar * fieldname,guint64 * value)1490 gst_structure_get_uint64 (const GstStructure * structure,
1491 const gchar * fieldname, guint64 * value)
1492 {
1493 GstStructureField *field;
1494
1495 g_return_val_if_fail (structure != NULL, FALSE);
1496 g_return_val_if_fail (fieldname != NULL, FALSE);
1497 g_return_val_if_fail (value != NULL, FALSE);
1498
1499 field = gst_structure_get_field (structure, fieldname);
1500
1501 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_UINT64)
1502 return FALSE;
1503
1504 *value = gst_g_value_get_uint64_unchecked (&field->value);
1505
1506 return TRUE;
1507 }
1508
1509 /**
1510 * gst_structure_get_date:
1511 * @structure: a #GstStructure
1512 * @fieldname: the name of a field
1513 * @value: (out callee-allocates): a pointer to a #GDate to set
1514 *
1515 * Sets the date pointed to by @value corresponding to the date of the
1516 * given field. Caller is responsible for making sure the field exists
1517 * and has the correct type.
1518 *
1519 * On success @value will point to a newly-allocated copy of the date which
1520 * should be freed with g_date_free() when no longer needed (note: this is
1521 * inconsistent with e.g. gst_structure_get_string() which doesn't return a
1522 * copy of the string).
1523 *
1524 * Returns: %TRUE if the value could be set correctly. If there was no field
1525 * with @fieldname or the existing field did not contain a data, this function
1526 * returns %FALSE.
1527 */
1528 gboolean
gst_structure_get_date(const GstStructure * structure,const gchar * fieldname,GDate ** value)1529 gst_structure_get_date (const GstStructure * structure, const gchar * fieldname,
1530 GDate ** value)
1531 {
1532 GstStructureField *field;
1533
1534 g_return_val_if_fail (structure != NULL, FALSE);
1535 g_return_val_if_fail (fieldname != NULL, FALSE);
1536 g_return_val_if_fail (value != NULL, FALSE);
1537
1538 field = gst_structure_get_field (structure, fieldname);
1539
1540 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DATE)
1541 return FALSE;
1542
1543 /* FIXME: 2.0 g_value_dup_boxed() -> g_value_get_boxed() */
1544 *value = g_value_dup_boxed (&field->value);
1545
1546 return TRUE;
1547 }
1548
1549 /**
1550 * gst_structure_get_date_time:
1551 * @structure: a #GstStructure
1552 * @fieldname: the name of a field
1553 * @value: (out callee-allocates): a pointer to a #GstDateTime to set
1554 *
1555 * Sets the datetime pointed to by @value corresponding to the datetime of the
1556 * given field. Caller is responsible for making sure the field exists
1557 * and has the correct type.
1558 *
1559 * On success @value will point to a reference of the datetime which
1560 * should be unreffed with gst_date_time_unref() when no longer needed
1561 * (note: this is inconsistent with e.g. gst_structure_get_string()
1562 * which doesn't return a copy of the string).
1563 *
1564 * Returns: %TRUE if the value could be set correctly. If there was no field
1565 * with @fieldname or the existing field did not contain a data, this function
1566 * returns %FALSE.
1567 */
1568 gboolean
gst_structure_get_date_time(const GstStructure * structure,const gchar * fieldname,GstDateTime ** value)1569 gst_structure_get_date_time (const GstStructure * structure,
1570 const gchar * fieldname, GstDateTime ** value)
1571 {
1572 GstStructureField *field;
1573
1574 g_return_val_if_fail (structure != NULL, FALSE);
1575 g_return_val_if_fail (fieldname != NULL, FALSE);
1576 g_return_val_if_fail (value != NULL, FALSE);
1577
1578 field = gst_structure_get_field (structure, fieldname);
1579
1580 if (field == NULL)
1581 return FALSE;
1582 if (!GST_VALUE_HOLDS_DATE_TIME (&field->value))
1583 return FALSE;
1584
1585 /* FIXME 2.0: g_value_dup_boxed() -> g_value_get_boxed() */
1586 *value = g_value_dup_boxed (&field->value);
1587
1588 return TRUE;
1589 }
1590
1591 /**
1592 * gst_structure_get_clock_time:
1593 * @structure: a #GstStructure
1594 * @fieldname: the name of a field
1595 * @value: (out): a pointer to a #GstClockTime to set
1596 *
1597 * Sets the clock time pointed to by @value corresponding to the clock time
1598 * of the given field. Caller is responsible for making sure the field exists
1599 * and has the correct type.
1600 *
1601 * Returns: %TRUE if the value could be set correctly. If there was no field
1602 * with @fieldname or the existing field did not contain a #GstClockTime, this
1603 * function returns %FALSE.
1604 */
1605 gboolean
gst_structure_get_clock_time(const GstStructure * structure,const gchar * fieldname,GstClockTime * value)1606 gst_structure_get_clock_time (const GstStructure * structure,
1607 const gchar * fieldname, GstClockTime * value)
1608 {
1609 return gst_structure_get_uint64 (structure, fieldname, value);
1610 }
1611
1612 /**
1613 * gst_structure_get_double:
1614 * @structure: a #GstStructure
1615 * @fieldname: the name of a field
1616 * @value: (out): a pointer to a gdouble to set
1617 *
1618 * Sets the double pointed to by @value corresponding to the value of the
1619 * given field. Caller is responsible for making sure the field exists
1620 * and has the correct type.
1621 *
1622 * Returns: %TRUE if the value could be set correctly. If there was no field
1623 * with @fieldname or the existing field did not contain a double, this
1624 * function returns %FALSE.
1625 */
1626 gboolean
gst_structure_get_double(const GstStructure * structure,const gchar * fieldname,gdouble * value)1627 gst_structure_get_double (const GstStructure * structure,
1628 const gchar * fieldname, gdouble * value)
1629 {
1630 GstStructureField *field;
1631
1632 g_return_val_if_fail (structure != NULL, FALSE);
1633 g_return_val_if_fail (fieldname != NULL, FALSE);
1634 g_return_val_if_fail (value != NULL, FALSE);
1635
1636 field = gst_structure_get_field (structure, fieldname);
1637
1638 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_DOUBLE)
1639 return FALSE;
1640
1641 *value = gst_g_value_get_double_unchecked (&field->value);
1642
1643 return TRUE;
1644 }
1645
1646 /**
1647 * gst_structure_get_string:
1648 * @structure: a #GstStructure
1649 * @fieldname: the name of a field
1650 *
1651 * Finds the field corresponding to @fieldname, and returns the string
1652 * contained in the field's value. Caller is responsible for making
1653 * sure the field exists and has the correct type.
1654 *
1655 * The string should not be modified, and remains valid until the next
1656 * call to a gst_structure_*() function with the given structure.
1657 *
1658 * Returns: (nullable): a pointer to the string or %NULL when the
1659 * field did not exist or did not contain a string.
1660 */
1661 const gchar *
gst_structure_get_string(const GstStructure * structure,const gchar * fieldname)1662 gst_structure_get_string (const GstStructure * structure,
1663 const gchar * fieldname)
1664 {
1665 GstStructureField *field;
1666
1667 g_return_val_if_fail (structure != NULL, NULL);
1668 g_return_val_if_fail (fieldname != NULL, NULL);
1669
1670 field = gst_structure_get_field (structure, fieldname);
1671
1672 if (field == NULL || G_VALUE_TYPE (&field->value) != G_TYPE_STRING)
1673 return NULL;
1674
1675 return gst_g_value_get_string_unchecked (&field->value);
1676 }
1677
1678 /**
1679 * gst_structure_get_enum:
1680 * @structure: a #GstStructure
1681 * @fieldname: the name of a field
1682 * @enumtype: the enum type of a field
1683 * @value: (out): a pointer to an int to set
1684 *
1685 * Sets the int pointed to by @value corresponding to the value of the
1686 * given field. Caller is responsible for making sure the field exists,
1687 * has the correct type and that the enumtype is correct.
1688 *
1689 * Returns: %TRUE if the value could be set correctly. If there was no field
1690 * with @fieldname or the existing field did not contain an enum of the given
1691 * type, this function returns %FALSE.
1692 */
1693 gboolean
gst_structure_get_enum(const GstStructure * structure,const gchar * fieldname,GType enumtype,gint * value)1694 gst_structure_get_enum (const GstStructure * structure,
1695 const gchar * fieldname, GType enumtype, gint * value)
1696 {
1697 GstStructureField *field;
1698
1699 g_return_val_if_fail (structure != NULL, FALSE);
1700 g_return_val_if_fail (fieldname != NULL, FALSE);
1701 g_return_val_if_fail (enumtype != G_TYPE_INVALID, FALSE);
1702 g_return_val_if_fail (value != NULL, FALSE);
1703
1704 field = gst_structure_get_field (structure, fieldname);
1705
1706 if (field == NULL)
1707 return FALSE;
1708 if (!G_TYPE_CHECK_VALUE_TYPE (&field->value, enumtype))
1709 return FALSE;
1710
1711 *value = g_value_get_enum (&field->value);
1712
1713 return TRUE;
1714 }
1715
1716 /**
1717 * gst_structure_get_fraction:
1718 * @structure: a #GstStructure
1719 * @fieldname: the name of a field
1720 * @value_numerator: (out): a pointer to an int to set
1721 * @value_denominator: (out): a pointer to an int to set
1722 *
1723 * Sets the integers pointed to by @value_numerator and @value_denominator
1724 * corresponding to the value of the given field. Caller is responsible
1725 * for making sure the field exists and has the correct type.
1726 *
1727 * Returns: %TRUE if the values could be set correctly. If there was no field
1728 * with @fieldname or the existing field did not contain a GstFraction, this
1729 * function returns %FALSE.
1730 */
1731 gboolean
gst_structure_get_fraction(const GstStructure * structure,const gchar * fieldname,gint * value_numerator,gint * value_denominator)1732 gst_structure_get_fraction (const GstStructure * structure,
1733 const gchar * fieldname, gint * value_numerator, gint * value_denominator)
1734 {
1735 GstStructureField *field;
1736
1737 g_return_val_if_fail (structure != NULL, FALSE);
1738 g_return_val_if_fail (fieldname != NULL, FALSE);
1739 g_return_val_if_fail (value_numerator != NULL, FALSE);
1740 g_return_val_if_fail (value_denominator != NULL, FALSE);
1741
1742 field = gst_structure_get_field (structure, fieldname);
1743
1744 if (field == NULL || G_VALUE_TYPE (&field->value) != GST_TYPE_FRACTION)
1745 return FALSE;
1746
1747 *value_numerator = gst_value_get_fraction_numerator (&field->value);
1748 *value_denominator = gst_value_get_fraction_denominator (&field->value);
1749
1750 return TRUE;
1751 }
1752
1753 /**
1754 * gst_structure_get_flagset:
1755 * @structure: a #GstStructure
1756 * @fieldname: the name of a field
1757 * @value_flags: (out) (allow-none): a pointer to a guint for the flags field
1758 * @value_mask: (out) (allow-none): a pointer to a guint for the mask field
1759 *
1760 * Read the GstFlagSet flags and mask out of the structure into the
1761 * provided pointers.
1762 *
1763 * Returns: %TRUE if the values could be set correctly. If there was no field
1764 * with @fieldname or the existing field did not contain a GstFlagSet, this
1765 * function returns %FALSE.
1766 *
1767 * Since: 1.6
1768 */
1769 gboolean
gst_structure_get_flagset(const GstStructure * structure,const gchar * fieldname,guint * value_flags,guint * value_mask)1770 gst_structure_get_flagset (const GstStructure * structure,
1771 const gchar * fieldname, guint * value_flags, guint * value_mask)
1772 {
1773 GstStructureField *field;
1774
1775 g_return_val_if_fail (structure != NULL, FALSE);
1776 g_return_val_if_fail (fieldname != NULL, FALSE);
1777
1778 field = gst_structure_get_field (structure, fieldname);
1779
1780 if (field == NULL || !GST_VALUE_HOLDS_FLAG_SET (&field->value))
1781 return FALSE;
1782
1783 if (value_flags)
1784 *value_flags = gst_value_get_flagset_flags (&field->value);
1785 if (value_mask)
1786 *value_mask = gst_value_get_flagset_mask (&field->value);
1787
1788 return TRUE;
1789 }
1790
1791 static GType
gst_structure_value_get_generic_type(const GValue * val)1792 gst_structure_value_get_generic_type (const GValue * val)
1793 {
1794 if (G_VALUE_TYPE (val) == GST_TYPE_LIST
1795 || G_VALUE_TYPE (val) == GST_TYPE_ARRAY) {
1796 GArray *array = g_value_peek_pointer (val);
1797
1798 if (array->len > 0) {
1799 GValue *value = &g_array_index (array, GValue, 0);
1800
1801 return gst_structure_value_get_generic_type (value);
1802 } else {
1803 return G_TYPE_INT;
1804 }
1805 } else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE) {
1806 return G_TYPE_INT;
1807 } else if (G_VALUE_TYPE (val) == GST_TYPE_INT64_RANGE) {
1808 return G_TYPE_INT64;
1809 } else if (G_VALUE_TYPE (val) == GST_TYPE_DOUBLE_RANGE) {
1810 return G_TYPE_DOUBLE;
1811 } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) {
1812 return GST_TYPE_FRACTION;
1813 }
1814 return G_VALUE_TYPE (val);
1815 }
1816
1817 gboolean
priv_gst_structure_append_to_gstring(const GstStructure * structure,GString * s)1818 priv_gst_structure_append_to_gstring (const GstStructure * structure,
1819 GString * s)
1820 {
1821 GstStructureField *field;
1822 guint i, len;
1823
1824 g_return_val_if_fail (s != NULL, FALSE);
1825
1826 len = GST_STRUCTURE_FIELDS (structure)->len;
1827 for (i = 0; i < len; i++) {
1828 char *t;
1829 GType type;
1830
1831 field = GST_STRUCTURE_FIELD (structure, i);
1832
1833 if (G_VALUE_TYPE (&field->value) == GST_TYPE_ARRAY) {
1834 t = _priv_gst_value_serialize_any_list (&field->value, "< ", " >", FALSE);
1835 } else if (G_VALUE_TYPE (&field->value) == GST_TYPE_LIST) {
1836 t = _priv_gst_value_serialize_any_list (&field->value, "{ ", " }", FALSE);
1837 } else {
1838 t = gst_value_serialize (&field->value);
1839 }
1840
1841 type = gst_structure_value_get_generic_type (&field->value);
1842
1843 g_string_append_len (s, ", ", 2);
1844 /* FIXME: do we need to escape fieldnames? */
1845 g_string_append (s, g_quark_to_string (field->name));
1846 g_string_append_len (s, "=(", 2);
1847 g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
1848 g_string_append_c (s, ')');
1849 if (t) {
1850 g_string_append (s, t);
1851 g_free (t);
1852 } else if (G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_POINTER)) {
1853 gpointer ptr = g_value_get_pointer (&field->value);
1854
1855 if (!ptr)
1856 g_string_append (s, "NULL");
1857 else
1858 g_string_append_printf (s, "%p", ptr);
1859 } else {
1860 if (!G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_STRING))
1861 GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
1862 g_quark_to_string (field->name),
1863 _priv_gst_value_gtype_to_abbr (type));
1864 /* TODO(ensonic): don't print NULL if field->value is not empty */
1865 g_string_append (s, "NULL");
1866 }
1867 }
1868
1869 g_string_append_c (s, ';');
1870 return TRUE;
1871 }
1872
1873 gboolean
priv__gst_structure_append_template_to_gstring(GQuark field_id,const GValue * value,gpointer user_data)1874 priv__gst_structure_append_template_to_gstring (GQuark field_id,
1875 const GValue * value, gpointer user_data)
1876 {
1877 GType type = gst_structure_value_get_generic_type (value);
1878 GString *s = (GString *) user_data;
1879
1880 g_string_append_len (s, ", ", 2);
1881 /* FIXME: do we need to escape fieldnames? */
1882 g_string_append (s, g_quark_to_string (field_id));
1883 g_string_append_len (s, "=(", 2);
1884 g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
1885 g_string_append_c (s, ')');
1886
1887 //TODO(ensonic): table like GstStructureAbbreviation (or extend it)
1888 if (type == G_TYPE_INT) {
1889 g_string_append_len (s, "%i", 2);
1890 } else if (type == G_TYPE_UINT) {
1891 g_string_append_len (s, "%u", 2);
1892 } else if (type == G_TYPE_FLOAT) {
1893 g_string_append_len (s, "%f", 2);
1894 } else if (type == G_TYPE_DOUBLE) {
1895 g_string_append_len (s, "%lf", 3);
1896 } else if (type == G_TYPE_STRING) {
1897 g_string_append_len (s, "%s", 2);
1898 } else if (type == G_TYPE_BOOLEAN) {
1899 /* we normally store this as a string, but can parse it also from an int */
1900 g_string_append_len (s, "%i", 2);
1901 } else if (type == G_TYPE_INT64) {
1902 g_string_append (s, "%" G_GINT64_FORMAT);
1903 } else if (type == G_TYPE_UINT64) {
1904 g_string_append (s, "%" G_GUINT64_FORMAT);
1905 } else if (type == GST_TYPE_STRUCTURE) {
1906 g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT);
1907 } else if (g_type_is_a (type, G_TYPE_ENUM)
1908 || g_type_is_a (type, G_TYPE_FLAGS)) {
1909 g_string_append_len (s, "%i", 2);
1910 } else if (type == G_TYPE_GTYPE) {
1911 g_string_append_len (s, "%s", 2);
1912 } else if (type == G_TYPE_POINTER) {
1913 g_string_append_len (s, "%p", 2);
1914 } else {
1915 GST_WARNING ("unhandled type: %s", g_type_name (type));
1916 g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT);
1917 }
1918
1919 return TRUE;
1920 }
1921
1922 /**
1923 * gst_structure_to_string:
1924 * @structure: a #GstStructure
1925 *
1926 * Converts @structure to a human-readable string representation.
1927 *
1928 * For debugging purposes its easier to do something like this:
1929 * |[<!-- language="C" -->
1930 * GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
1931 * ]|
1932 * This prints the structure in human readable form.
1933 *
1934 * The current implementation of serialization will lead to unexpected results
1935 * when there are nested #GstCaps / #GstStructure deeper than one level.
1936 *
1937 * Free-function: g_free
1938 *
1939 * Returns: (transfer full): a pointer to string allocated by g_malloc().
1940 * g_free() after usage.
1941 */
1942 gchar *
gst_structure_to_string(const GstStructure * structure)1943 gst_structure_to_string (const GstStructure * structure)
1944 {
1945 GString *s;
1946
1947 /* NOTE: This function is potentially called by the debug system,
1948 * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.)
1949 * should be careful to avoid recursion. This includes any functions
1950 * called by gst_structure_to_string. In particular, calls should
1951 * not use the GST_PTR_FORMAT extension. */
1952
1953 g_return_val_if_fail (structure != NULL, NULL);
1954
1955 /* we estimate a minimum size based on the number of fields in order to
1956 * avoid unnecessary reallocs within GString */
1957 s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
1958 g_string_append (s, g_quark_to_string (structure->name));
1959 priv_gst_structure_append_to_gstring (structure, s);
1960 return g_string_free (s, FALSE);
1961 }
1962
1963 static gboolean
gst_structure_parse_field(gchar * str,gchar ** after,GstStructureField * field)1964 gst_structure_parse_field (gchar * str,
1965 gchar ** after, GstStructureField * field)
1966 {
1967 gchar *name;
1968 gchar *name_end;
1969 gchar *s;
1970 gchar c;
1971
1972 s = str;
1973
1974 while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
1975 s++;
1976 name = s;
1977 if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &name_end))) {
1978 GST_WARNING ("failed to parse simple string, str=%s", str);
1979 return FALSE;
1980 }
1981
1982 s = name_end;
1983 while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
1984 s++;
1985
1986 if (G_UNLIKELY (*s != '=')) {
1987 GST_WARNING ("missing assignment operator in the field, str=%s", str);
1988 return FALSE;
1989 }
1990 s++;
1991
1992 c = *name_end;
1993 *name_end = '\0';
1994 field->name = g_quark_from_string (name);
1995 GST_DEBUG ("trying field name '%s'", name);
1996 *name_end = c;
1997
1998 if (G_UNLIKELY (!_priv_gst_value_parse_value (s, &s, &field->value,
1999 G_TYPE_INVALID))) {
2000 GST_WARNING ("failed to parse value %s", str);
2001 return FALSE;
2002 }
2003
2004 *after = s;
2005 return TRUE;
2006 }
2007
2008 gboolean
priv_gst_structure_parse_name(gchar * str,gchar ** start,gchar ** end,gchar ** next)2009 priv_gst_structure_parse_name (gchar * str, gchar ** start, gchar ** end,
2010 gchar ** next)
2011 {
2012 char *w;
2013 char *r;
2014
2015 r = str;
2016
2017 /* skip spaces (FIXME: _isspace treats tabs and newlines as space!) */
2018 while (*r && (g_ascii_isspace (*r) || (r[0] == '\\'
2019 && g_ascii_isspace (r[1]))))
2020 r++;
2021
2022 *start = r;
2023
2024 if (G_UNLIKELY (!_priv_gst_value_parse_string (r, &w, &r, TRUE))) {
2025 GST_WARNING ("Failed to parse structure string '%s'", str);
2026 return FALSE;
2027 }
2028
2029 *end = w;
2030 *next = r;
2031
2032 return TRUE;
2033 }
2034
2035 gboolean
priv_gst_structure_parse_fields(gchar * str,gchar ** end,GstStructure * structure)2036 priv_gst_structure_parse_fields (gchar * str, gchar ** end,
2037 GstStructure * structure)
2038 {
2039 gchar *r;
2040 GstStructureField field;
2041
2042 r = str;
2043
2044 do {
2045 while (*r && (g_ascii_isspace (*r) || (r[0] == '\\'
2046 && g_ascii_isspace (r[1]))))
2047 r++;
2048 if (*r == ';') {
2049 /* end of structure, get the next char and finish */
2050 r++;
2051 break;
2052 }
2053 if (*r == '\0') {
2054 /* accept \0 as end delimiter */
2055 break;
2056 }
2057 if (G_UNLIKELY (*r != ',')) {
2058 GST_WARNING ("Failed to find delimiter, r=%s", r);
2059 return FALSE;
2060 }
2061 r++;
2062 while (*r && (g_ascii_isspace (*r) || (r[0] == '\\'
2063 && g_ascii_isspace (r[1]))))
2064 r++;
2065
2066 memset (&field, 0, sizeof (field));
2067 if (G_UNLIKELY (!gst_structure_parse_field (r, &r, &field))) {
2068 GST_WARNING ("Failed to parse field, r=%s", r);
2069 return FALSE;
2070 }
2071 gst_structure_set_field (structure, &field);
2072 } while (TRUE);
2073
2074 *end = r;
2075
2076 return TRUE;
2077 }
2078
2079 /**
2080 * gst_structure_new_from_string:
2081 * @string: a string representation of a #GstStructure
2082 *
2083 * Creates a #GstStructure from a string representation.
2084 * If end is not %NULL, a pointer to the place inside the given string
2085 * where parsing ended will be returned.
2086 *
2087 * The current implementation of serialization will lead to unexpected results
2088 * when there are nested #GstCaps / #GstStructure deeper than one level.
2089 *
2090 * Free-function: gst_structure_free
2091 *
2092 * Returns: (transfer full) (nullable): a new #GstStructure or %NULL
2093 * when the string could not be parsed. Free with
2094 * gst_structure_free() after use.
2095 *
2096 * Since: 1.2
2097 */
2098 GstStructure *
gst_structure_new_from_string(const gchar * string)2099 gst_structure_new_from_string (const gchar * string)
2100 {
2101 return gst_structure_from_string (string, NULL);
2102 }
2103
2104 /**
2105 * gst_structure_from_string:
2106 * @string: a string representation of a #GstStructure.
2107 * @end: (out) (allow-none) (transfer none) (skip): pointer to store the end of the string in.
2108 *
2109 * Creates a #GstStructure from a string representation.
2110 * If end is not %NULL, a pointer to the place inside the given string
2111 * where parsing ended will be returned.
2112 *
2113 * Free-function: gst_structure_free
2114 *
2115 * Returns: (transfer full) (nullable): a new #GstStructure or %NULL
2116 * when the string could not be parsed. Free with
2117 * gst_structure_free() after use.
2118 */
2119 GstStructure *
gst_structure_from_string(const gchar * string,gchar ** end)2120 gst_structure_from_string (const gchar * string, gchar ** end)
2121 {
2122 char *name;
2123 char *copy;
2124 char *w;
2125 char *r;
2126 char save;
2127 GstStructure *structure = NULL;
2128
2129 g_return_val_if_fail (string != NULL, NULL);
2130
2131 copy = g_strdup (string);
2132 r = copy;
2133
2134 if (!priv_gst_structure_parse_name (r, &name, &w, &r))
2135 goto error;
2136
2137 save = *w;
2138 *w = '\0';
2139 structure = gst_structure_new_empty (name);
2140 *w = save;
2141
2142 if (G_UNLIKELY (structure == NULL))
2143 goto error;
2144
2145 if (!priv_gst_structure_parse_fields (r, &r, structure))
2146 goto error;
2147
2148 if (end)
2149 *end = (char *) string + (r - copy);
2150 else if (*r)
2151 g_warning ("gst_structure_from_string did not consume whole string,"
2152 " but caller did not provide end pointer (\"%s\")", string);
2153
2154 g_free (copy);
2155 return structure;
2156
2157 error:
2158 if (structure)
2159 gst_structure_free (structure);
2160 g_free (copy);
2161 return NULL;
2162 }
2163
2164 static void
gst_structure_transform_to_string(const GValue * src_value,GValue * dest_value)2165 gst_structure_transform_to_string (const GValue * src_value,
2166 GValue * dest_value)
2167 {
2168 g_return_if_fail (src_value != NULL);
2169 g_return_if_fail (dest_value != NULL);
2170
2171 dest_value->data[0].v_pointer =
2172 gst_structure_to_string (src_value->data[0].v_pointer);
2173 }
2174
2175 static GstStructure *
gst_structure_copy_conditional(const GstStructure * structure)2176 gst_structure_copy_conditional (const GstStructure * structure)
2177 {
2178 if (structure)
2179 return gst_structure_copy (structure);
2180 return NULL;
2181 }
2182
2183 /* fixate utility functions */
2184
2185 /**
2186 * gst_structure_fixate_field_nearest_int:
2187 * @structure: a #GstStructure
2188 * @field_name: a field in @structure
2189 * @target: the target value of the fixation
2190 *
2191 * Fixates a #GstStructure by changing the given field to the nearest
2192 * integer to @target that is a subset of the existing field.
2193 *
2194 * Returns: %TRUE if the structure could be fixated
2195 */
2196 gboolean
gst_structure_fixate_field_nearest_int(GstStructure * structure,const char * field_name,int target)2197 gst_structure_fixate_field_nearest_int (GstStructure * structure,
2198 const char *field_name, int target)
2199 {
2200 const GValue *value;
2201
2202 g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE);
2203 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2204
2205 value = gst_structure_get_value (structure, field_name);
2206
2207 if (G_VALUE_TYPE (value) == G_TYPE_INT) {
2208 /* already fixed */
2209 return FALSE;
2210 } else if (G_VALUE_TYPE (value) == GST_TYPE_INT_RANGE) {
2211 int min, max, step;
2212
2213 min = gst_value_get_int_range_min (value);
2214 max = gst_value_get_int_range_max (value);
2215 step = gst_value_get_int_range_step (value);
2216
2217 target = CLAMP (target, min, max);
2218 if (G_UNLIKELY (step != 1)) {
2219 gint rem = target % step;
2220 target -= rem;
2221 if (rem > step / 2)
2222 target += step;
2223 }
2224
2225 gst_structure_set (structure, field_name, G_TYPE_INT, target, NULL);
2226 return TRUE;
2227 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
2228 const GValue *list_value;
2229 int i, n;
2230 int best = 0;
2231 int best_index = -1;
2232
2233 n = gst_value_list_get_size (value);
2234 for (i = 0; i < n; i++) {
2235 list_value = gst_value_list_get_value (value, i);
2236 if (G_VALUE_TYPE (list_value) == G_TYPE_INT) {
2237 int x = gst_g_value_get_int_unchecked (list_value);
2238
2239 if (best_index == -1 || (ABS (target - x) < ABS (target - best))) {
2240 best_index = i;
2241 best = x;
2242 }
2243 }
2244 }
2245 if (best_index != -1) {
2246 gst_structure_set (structure, field_name, G_TYPE_INT, best, NULL);
2247 return TRUE;
2248 }
2249 return FALSE;
2250 }
2251
2252 return FALSE;
2253 }
2254
2255 /**
2256 * gst_structure_fixate_field_nearest_double:
2257 * @structure: a #GstStructure
2258 * @field_name: a field in @structure
2259 * @target: the target value of the fixation
2260 *
2261 * Fixates a #GstStructure by changing the given field to the nearest
2262 * double to @target that is a subset of the existing field.
2263 *
2264 * Returns: %TRUE if the structure could be fixated
2265 */
2266 gboolean
gst_structure_fixate_field_nearest_double(GstStructure * structure,const char * field_name,double target)2267 gst_structure_fixate_field_nearest_double (GstStructure * structure,
2268 const char *field_name, double target)
2269 {
2270 const GValue *value;
2271
2272 g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE);
2273 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2274
2275 value = gst_structure_get_value (structure, field_name);
2276
2277 if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) {
2278 /* already fixed */
2279 return FALSE;
2280 } else if (G_VALUE_TYPE (value) == GST_TYPE_DOUBLE_RANGE) {
2281 double x;
2282
2283 x = gst_value_get_double_range_min (value);
2284 if (target < x)
2285 target = x;
2286 x = gst_value_get_double_range_max (value);
2287 if (target > x)
2288 target = x;
2289 gst_structure_set (structure, field_name, G_TYPE_DOUBLE, target, NULL);
2290 return TRUE;
2291 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
2292 const GValue *list_value;
2293 int i, n;
2294 double best = 0;
2295 int best_index = -1;
2296
2297 n = gst_value_list_get_size (value);
2298 for (i = 0; i < n; i++) {
2299 list_value = gst_value_list_get_value (value, i);
2300 if (G_VALUE_TYPE (list_value) == G_TYPE_DOUBLE) {
2301 double x = gst_g_value_get_double_unchecked (list_value);
2302
2303 if (best_index == -1 || (ABS (target - x) < ABS (target - best))) {
2304 best_index = i;
2305 best = x;
2306 }
2307 }
2308 }
2309 if (best_index != -1) {
2310 gst_structure_set (structure, field_name, G_TYPE_DOUBLE, best, NULL);
2311 return TRUE;
2312 }
2313 return FALSE;
2314 }
2315
2316 return FALSE;
2317
2318 }
2319
2320 /**
2321 * gst_structure_fixate_field_boolean:
2322 * @structure: a #GstStructure
2323 * @field_name: a field in @structure
2324 * @target: the target value of the fixation
2325 *
2326 * Fixates a #GstStructure by changing the given @field_name field to the given
2327 * @target boolean if that field is not fixed yet.
2328 *
2329 * Returns: %TRUE if the structure could be fixated
2330 */
2331 gboolean
gst_structure_fixate_field_boolean(GstStructure * structure,const char * field_name,gboolean target)2332 gst_structure_fixate_field_boolean (GstStructure * structure,
2333 const char *field_name, gboolean target)
2334 {
2335 const GValue *value;
2336
2337 g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE);
2338 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2339
2340 value = gst_structure_get_value (structure, field_name);
2341
2342 if (G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
2343 /* already fixed */
2344 return FALSE;
2345 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
2346 const GValue *list_value;
2347 int i, n;
2348 int best = 0;
2349 int best_index = -1;
2350
2351 n = gst_value_list_get_size (value);
2352 for (i = 0; i < n; i++) {
2353 list_value = gst_value_list_get_value (value, i);
2354 if (G_VALUE_TYPE (list_value) == G_TYPE_BOOLEAN) {
2355 gboolean x = gst_g_value_get_boolean_unchecked (list_value);
2356
2357 if (best_index == -1 || x == target) {
2358 best_index = i;
2359 best = x;
2360 }
2361 }
2362 }
2363 if (best_index != -1) {
2364 gst_structure_set (structure, field_name, G_TYPE_BOOLEAN, best, NULL);
2365 return TRUE;
2366 }
2367 return FALSE;
2368 }
2369
2370 return FALSE;
2371 }
2372
2373 /**
2374 * gst_structure_fixate_field_string:
2375 * @structure: a #GstStructure
2376 * @field_name: a field in @structure
2377 * @target: the target value of the fixation
2378 *
2379 * Fixates a #GstStructure by changing the given @field_name field to the given
2380 * @target string if that field is not fixed yet.
2381 *
2382 * Returns: %TRUE if the structure could be fixated
2383 */
2384 gboolean
gst_structure_fixate_field_string(GstStructure * structure,const gchar * field_name,const gchar * target)2385 gst_structure_fixate_field_string (GstStructure * structure,
2386 const gchar * field_name, const gchar * target)
2387 {
2388 const GValue *value;
2389
2390 g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE);
2391 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2392
2393 value = gst_structure_get_value (structure, field_name);
2394
2395 if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
2396 /* already fixed */
2397 return FALSE;
2398 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
2399 const GValue *list_value;
2400 int i, n;
2401 const gchar *best = NULL;
2402 int best_index = -1;
2403
2404 n = gst_value_list_get_size (value);
2405 for (i = 0; i < n; i++) {
2406 list_value = gst_value_list_get_value (value, i);
2407 if (G_VALUE_TYPE (list_value) == G_TYPE_STRING) {
2408 const gchar *x = g_value_get_string (list_value);
2409
2410 if (best_index == -1 || g_str_equal (x, target)) {
2411 best_index = i;
2412 best = x;
2413 }
2414 }
2415 }
2416 if (best_index != -1) {
2417 gst_structure_set (structure, field_name, G_TYPE_STRING, best, NULL);
2418 return TRUE;
2419 }
2420 return FALSE;
2421 }
2422
2423 return FALSE;
2424 }
2425
2426 /**
2427 * gst_structure_fixate_field_nearest_fraction:
2428 * @structure: a #GstStructure
2429 * @field_name: a field in @structure
2430 * @target_numerator: The numerator of the target value of the fixation
2431 * @target_denominator: The denominator of the target value of the fixation
2432 *
2433 * Fixates a #GstStructure by changing the given field to the nearest
2434 * fraction to @target_numerator/@target_denominator that is a subset
2435 * of the existing field.
2436 *
2437 * Returns: %TRUE if the structure could be fixated
2438 */
2439 gboolean
gst_structure_fixate_field_nearest_fraction(GstStructure * structure,const char * field_name,const gint target_numerator,const gint target_denominator)2440 gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
2441 const char *field_name, const gint target_numerator,
2442 const gint target_denominator)
2443 {
2444 const GValue *value;
2445
2446 g_return_val_if_fail (gst_structure_has_field (structure, field_name), FALSE);
2447 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2448 g_return_val_if_fail (target_denominator != 0, FALSE);
2449
2450 value = gst_structure_get_value (structure, field_name);
2451
2452 if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION) {
2453 /* already fixed */
2454 return FALSE;
2455 } else if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION_RANGE) {
2456 const GValue *x, *new_value;
2457 GValue target = { 0 };
2458 g_value_init (&target, GST_TYPE_FRACTION);
2459 gst_value_set_fraction (&target, target_numerator, target_denominator);
2460
2461 new_value = ⌖
2462 x = gst_value_get_fraction_range_min (value);
2463 if (gst_value_compare (&target, x) == GST_VALUE_LESS_THAN)
2464 new_value = x;
2465 x = gst_value_get_fraction_range_max (value);
2466 if (gst_value_compare (&target, x) == GST_VALUE_GREATER_THAN)
2467 new_value = x;
2468
2469 gst_structure_set_value (structure, field_name, new_value);
2470 g_value_unset (&target);
2471 return TRUE;
2472 } else if (G_VALUE_TYPE (value) == GST_TYPE_LIST) {
2473 const GValue *list_value;
2474 int i, n;
2475 const GValue *best = NULL;
2476 gdouble target;
2477 gdouble cur_diff;
2478 gdouble best_diff = G_MAXDOUBLE;
2479
2480 target = (gdouble) target_numerator / (gdouble) target_denominator;
2481
2482 GST_DEBUG ("target %g, best %g", target, best_diff);
2483
2484 best = NULL;
2485
2486 n = gst_value_list_get_size (value);
2487 for (i = 0; i < n; i++) {
2488 list_value = gst_value_list_get_value (value, i);
2489 if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) {
2490 gint num, denom;
2491 gdouble list_double;
2492
2493 num = gst_value_get_fraction_numerator (list_value);
2494 denom = gst_value_get_fraction_denominator (list_value);
2495
2496 list_double = ((gdouble) num / (gdouble) denom);
2497 cur_diff = target - list_double;
2498
2499 GST_DEBUG ("curr diff %g, list %g", cur_diff, list_double);
2500
2501 if (cur_diff < 0)
2502 cur_diff = -cur_diff;
2503
2504 if (!best || cur_diff < best_diff) {
2505 GST_DEBUG ("new best %g", list_double);
2506 best = list_value;
2507 best_diff = cur_diff;
2508 }
2509 }
2510 }
2511 if (best != NULL) {
2512 gst_structure_set_value (structure, field_name, best);
2513 return TRUE;
2514 }
2515 }
2516
2517 return FALSE;
2518 }
2519
2520 static gboolean
default_fixate(GQuark field_id,const GValue * value,gpointer data)2521 default_fixate (GQuark field_id, const GValue * value, gpointer data)
2522 {
2523 GstStructure *s = data;
2524 GValue v = { 0 };
2525
2526 if (gst_value_fixate (&v, value)) {
2527 gst_structure_id_take_value (s, field_id, &v);
2528 }
2529 return TRUE;
2530 }
2531
2532 /**
2533 * gst_structure_fixate_field:
2534 * @structure: a #GstStructure
2535 * @field_name: a field in @structure
2536 *
2537 * Fixates a #GstStructure by changing the given field with its fixated value.
2538 *
2539 * Returns: %TRUE if the structure field could be fixated
2540 */
2541 gboolean
gst_structure_fixate_field(GstStructure * structure,const char * field_name)2542 gst_structure_fixate_field (GstStructure * structure, const char *field_name)
2543 {
2544 GstStructureField *field;
2545
2546 g_return_val_if_fail (structure != NULL, FALSE);
2547 g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
2548
2549 if (!(field = gst_structure_get_field (structure, field_name)))
2550 return FALSE;
2551
2552 return default_fixate (field->name, &field->value, structure);
2553 }
2554
2555 /* our very own version of G_VALUE_LCOPY that allows NULL return locations
2556 * (useful for message parsing functions where the return location is user
2557 * supplied and the user may pass %NULL if the value isn't of interest) */
2558 #define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname) \
2559 G_STMT_START { \
2560 const GValue *_value = (value); \
2561 guint _flags = (flags); \
2562 GType _value_type = G_VALUE_TYPE (_value); \
2563 GTypeValueTable *_vtable = g_type_value_table_peek (_value_type); \
2564 const gchar *_lcopy_format = _vtable->lcopy_format; \
2565 GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, }; \
2566 guint _n_values = 0; \
2567 \
2568 while (*_lcopy_format != '\0') { \
2569 g_assert (*_lcopy_format == G_VALUE_COLLECT_POINTER); \
2570 _cvalues[_n_values++].v_pointer = va_arg ((var_args), gpointer); \
2571 _lcopy_format++; \
2572 } \
2573 if (_n_values == 2 && !!_cvalues[0].v_pointer != !!_cvalues[1].v_pointer) { \
2574 *(__error) = g_strdup_printf ("either all or none of the return " \
2575 "locations for field '%s' need to be NULL", fieldname); \
2576 } else if (_cvalues[0].v_pointer != NULL) { \
2577 *(__error) = _vtable->lcopy_value (_value, _n_values, _cvalues, _flags); \
2578 } \
2579 } G_STMT_END
2580
2581 /**
2582 * gst_structure_get_valist:
2583 * @structure: a #GstStructure
2584 * @first_fieldname: the name of the first field to read
2585 * @args: variable arguments
2586 *
2587 * Parses the variable arguments and reads fields from @structure accordingly.
2588 * valist-variant of gst_structure_get(). Look at the documentation of
2589 * gst_structure_get() for more details.
2590 *
2591 * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields
2592 */
2593 gboolean
gst_structure_get_valist(const GstStructure * structure,const char * first_fieldname,va_list args)2594 gst_structure_get_valist (const GstStructure * structure,
2595 const char *first_fieldname, va_list args)
2596 {
2597 const char *field_name;
2598 GType expected_type = G_TYPE_INVALID;
2599
2600 g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
2601 g_return_val_if_fail (first_fieldname != NULL, FALSE);
2602
2603 field_name = first_fieldname;
2604 while (field_name) {
2605 const GValue *val = NULL;
2606 gchar *err = NULL;
2607
2608 expected_type = va_arg (args, GType);
2609
2610 val = gst_structure_get_value (structure, field_name);
2611
2612 if (val == NULL)
2613 goto no_such_field;
2614
2615 if (G_VALUE_TYPE (val) != expected_type)
2616 goto wrong_type;
2617
2618 GST_VALUE_LCOPY (val, args, 0, &err, field_name);
2619 if (err) {
2620 g_warning ("%s: %s", G_STRFUNC, err);
2621 g_free (err);
2622 return FALSE;
2623 }
2624
2625 field_name = va_arg (args, const gchar *);
2626 }
2627
2628 return TRUE;
2629
2630 /* ERRORS */
2631 no_such_field:
2632 {
2633 GST_INFO ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
2634 field_name, structure);
2635 return FALSE;
2636 }
2637 wrong_type:
2638 {
2639 GST_INFO ("Expected field '%s' in structure to be of type '%s', but "
2640 "field was of type '%s': %" GST_PTR_FORMAT, field_name,
2641 GST_STR_NULL (g_type_name (expected_type)),
2642 G_VALUE_TYPE_NAME (gst_structure_get_value (structure, field_name)),
2643 structure);
2644 return FALSE;
2645 }
2646 }
2647
2648 /**
2649 * gst_structure_id_get_valist:
2650 * @structure: a #GstStructure
2651 * @first_field_id: the quark of the first field to read
2652 * @args: variable arguments
2653 *
2654 * Parses the variable arguments and reads fields from @structure accordingly.
2655 * valist-variant of gst_structure_id_get(). Look at the documentation of
2656 * gst_structure_id_get() for more details.
2657 *
2658 * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields
2659 */
2660 gboolean
gst_structure_id_get_valist(const GstStructure * structure,GQuark first_field_id,va_list args)2661 gst_structure_id_get_valist (const GstStructure * structure,
2662 GQuark first_field_id, va_list args)
2663 {
2664 GQuark field_id;
2665 GType expected_type = G_TYPE_INVALID;
2666
2667 g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
2668 g_return_val_if_fail (first_field_id != 0, FALSE);
2669
2670 field_id = first_field_id;
2671 while (field_id) {
2672 const GValue *val = NULL;
2673 gchar *err = NULL;
2674
2675 expected_type = va_arg (args, GType);
2676
2677 val = gst_structure_id_get_value (structure, field_id);
2678
2679 if (val == NULL)
2680 goto no_such_field;
2681
2682 if (G_VALUE_TYPE (val) != expected_type)
2683 goto wrong_type;
2684
2685 GST_VALUE_LCOPY (val, args, 0, &err, g_quark_to_string (field_id));
2686 if (err) {
2687 g_warning ("%s: %s", G_STRFUNC, err);
2688 g_free (err);
2689 return FALSE;
2690 }
2691
2692 field_id = va_arg (args, GQuark);
2693 }
2694
2695 return TRUE;
2696
2697 /* ERRORS */
2698 no_such_field:
2699 {
2700 GST_DEBUG ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
2701 GST_STR_NULL (g_quark_to_string (field_id)), structure);
2702 return FALSE;
2703 }
2704 wrong_type:
2705 {
2706 GST_DEBUG ("Expected field '%s' in structure to be of type '%s', but "
2707 "field was of type '%s': %" GST_PTR_FORMAT,
2708 g_quark_to_string (field_id),
2709 GST_STR_NULL (g_type_name (expected_type)),
2710 G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)),
2711 structure);
2712 return FALSE;
2713 }
2714 }
2715
2716 /**
2717 * gst_structure_get:
2718 * @structure: a #GstStructure
2719 * @first_fieldname: the name of the first field to read
2720 * @...: variable arguments
2721 *
2722 * Parses the variable arguments and reads fields from @structure accordingly.
2723 * Variable arguments should be in the form field name, field type
2724 * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
2725 * The last variable argument should be %NULL.
2726 *
2727 * For refcounted (mini)objects you will receive a new reference which
2728 * you must release with a suitable _unref() when no longer needed. For
2729 * strings and boxed types you will receive a copy which you will need to
2730 * release with either g_free() or the suitable function for the boxed type.
2731 *
2732 * Returns: %FALSE if there was a problem reading any of the fields (e.g.
2733 * because the field requested did not exist, or was of a type other
2734 * than the type specified), otherwise %TRUE.
2735 */
2736 gboolean
gst_structure_get(const GstStructure * structure,const char * first_fieldname,...)2737 gst_structure_get (const GstStructure * structure, const char *first_fieldname,
2738 ...)
2739 {
2740 gboolean ret;
2741 va_list args;
2742
2743 g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
2744 g_return_val_if_fail (first_fieldname != NULL, FALSE);
2745
2746 va_start (args, first_fieldname);
2747 ret = gst_structure_get_valist (structure, first_fieldname, args);
2748 va_end (args);
2749
2750 return ret;
2751 }
2752
2753 /**
2754 * gst_structure_id_get:
2755 * @structure: a #GstStructure
2756 * @first_field_id: the quark of the first field to read
2757 * @...: variable arguments
2758 *
2759 * Parses the variable arguments and reads fields from @structure accordingly.
2760 * Variable arguments should be in the form field id quark, field type
2761 * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
2762 * The last variable argument should be %NULL (technically it should be a
2763 * 0 quark, but we require %NULL so compilers that support it can check for
2764 * the %NULL terminator and warn if it's not there).
2765 *
2766 * This function is just like gst_structure_get() only that it is slightly
2767 * more efficient since it saves the string-to-quark lookup in the global
2768 * quark hashtable.
2769 *
2770 * For refcounted (mini)objects you will receive a new reference which
2771 * you must release with a suitable _unref() when no longer needed. For
2772 * strings and boxed types you will receive a copy which you will need to
2773 * release with either g_free() or the suitable function for the boxed type.
2774 *
2775 * Returns: %FALSE if there was a problem reading any of the fields (e.g.
2776 * because the field requested did not exist, or was of a type other
2777 * than the type specified), otherwise %TRUE.
2778 */
2779 gboolean
gst_structure_id_get(const GstStructure * structure,GQuark first_field_id,...)2780 gst_structure_id_get (const GstStructure * structure, GQuark first_field_id,
2781 ...)
2782 {
2783 gboolean ret;
2784 va_list args;
2785
2786 g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
2787 g_return_val_if_fail (first_field_id != 0, FALSE);
2788
2789 va_start (args, first_field_id);
2790 ret = gst_structure_id_get_valist (structure, first_field_id, args);
2791 va_end (args);
2792
2793 return ret;
2794 }
2795
2796 static gboolean
gst_structure_is_equal_foreach(GQuark field_id,const GValue * val2,gpointer data)2797 gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
2798 gpointer data)
2799 {
2800 const GstStructure *struct1 = (const GstStructure *) data;
2801 const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
2802
2803 if (G_UNLIKELY (val1 == NULL))
2804 return FALSE;
2805 if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
2806 return TRUE;
2807 }
2808
2809 return FALSE;
2810 }
2811
2812 /**
2813 * gst_structure_is_equal:
2814 * @structure1: a #GstStructure.
2815 * @structure2: a #GstStructure.
2816 *
2817 * Tests if the two #GstStructure are equal.
2818 *
2819 * Returns: %TRUE if the two structures have the same name and field.
2820 **/
2821 gboolean
gst_structure_is_equal(const GstStructure * structure1,const GstStructure * structure2)2822 gst_structure_is_equal (const GstStructure * structure1,
2823 const GstStructure * structure2)
2824 {
2825 g_return_val_if_fail (GST_IS_STRUCTURE (structure1), FALSE);
2826 g_return_val_if_fail (GST_IS_STRUCTURE (structure2), FALSE);
2827
2828 if (G_UNLIKELY (structure1 == structure2))
2829 return TRUE;
2830
2831 if (structure1->name != structure2->name) {
2832 return FALSE;
2833 }
2834 if (GST_STRUCTURE_FIELDS (structure1)->len !=
2835 GST_STRUCTURE_FIELDS (structure2)->len) {
2836 return FALSE;
2837 }
2838
2839 return gst_structure_foreach (structure1, gst_structure_is_equal_foreach,
2840 (gpointer) structure2);
2841 }
2842
2843
2844 typedef struct
2845 {
2846 GstStructure *dest;
2847 const GstStructure *intersect;
2848 }
2849 IntersectData;
2850
2851 static gboolean
gst_structure_intersect_field1(GQuark id,const GValue * val1,gpointer data)2852 gst_structure_intersect_field1 (GQuark id, const GValue * val1, gpointer data)
2853 {
2854 IntersectData *idata = (IntersectData *) data;
2855 const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
2856
2857 if (G_UNLIKELY (val2 == NULL)) {
2858 gst_structure_id_set_value (idata->dest, id, val1);
2859 } else {
2860 GValue dest_value = { 0 };
2861 if (gst_value_intersect (&dest_value, val1, val2)) {
2862 gst_structure_id_take_value (idata->dest, id, &dest_value);
2863 } else {
2864 return FALSE;
2865 }
2866 }
2867 return TRUE;
2868 }
2869
2870 static gboolean
gst_structure_intersect_field2(GQuark id,const GValue * val1,gpointer data)2871 gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data)
2872 {
2873 IntersectData *idata = (IntersectData *) data;
2874 const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
2875
2876 if (G_UNLIKELY (val2 == NULL)) {
2877 gst_structure_id_set_value (idata->dest, id, val1);
2878 }
2879 return TRUE;
2880 }
2881
2882 /**
2883 * gst_structure_intersect:
2884 * @struct1: a #GstStructure
2885 * @struct2: a #GstStructure
2886 *
2887 * Intersects @struct1 and @struct2 and returns the intersection.
2888 *
2889 * Returns: (nullable): Intersection of @struct1 and @struct2
2890 */
2891 GstStructure *
gst_structure_intersect(const GstStructure * struct1,const GstStructure * struct2)2892 gst_structure_intersect (const GstStructure * struct1,
2893 const GstStructure * struct2)
2894 {
2895 IntersectData data;
2896
2897 g_assert (struct1 != NULL);
2898 g_assert (struct2 != NULL);
2899
2900 if (G_UNLIKELY (struct1->name != struct2->name))
2901 return NULL;
2902
2903 /* copy fields from struct1 which we have not in struct2 to target
2904 * intersect if we have the field in both */
2905 data.dest = gst_structure_new_id_empty (struct1->name);
2906 data.intersect = struct2;
2907 if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
2908 gst_structure_intersect_field1, &data)))
2909 goto error;
2910
2911 /* copy fields from struct2 which we have not in struct1 to target */
2912 data.intersect = struct1;
2913 if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
2914 gst_structure_intersect_field2, &data)))
2915 goto error;
2916
2917 return data.dest;
2918
2919 error:
2920 gst_structure_free (data.dest);
2921 return NULL;
2922 }
2923
2924 static gboolean
gst_caps_structure_can_intersect_field(GQuark id,const GValue * val1,gpointer data)2925 gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1,
2926 gpointer data)
2927 {
2928 GstStructure *other = (GstStructure *) data;
2929 const GValue *val2 = gst_structure_id_get_value (other, id);
2930
2931 if (G_LIKELY (val2)) {
2932 if (!gst_value_can_intersect (val1, val2)) {
2933 return FALSE;
2934 } else {
2935 gint eq = gst_value_compare (val1, val2);
2936
2937 if (eq == GST_VALUE_UNORDERED) {
2938 /* we need to try interseting */
2939 if (!gst_value_intersect (NULL, val1, val2)) {
2940 return FALSE;
2941 }
2942 } else if (eq != GST_VALUE_EQUAL) {
2943 return FALSE;
2944 }
2945 }
2946 }
2947 return TRUE;
2948 }
2949
2950 /**
2951 * gst_structure_can_intersect:
2952 * @struct1: a #GstStructure
2953 * @struct2: a #GstStructure
2954 *
2955 * Tries intersecting @struct1 and @struct2 and reports whether the result
2956 * would not be empty.
2957 *
2958 * Returns: %TRUE if intersection would not be empty
2959 */
2960 gboolean
gst_structure_can_intersect(const GstStructure * struct1,const GstStructure * struct2)2961 gst_structure_can_intersect (const GstStructure * struct1,
2962 const GstStructure * struct2)
2963 {
2964 g_return_val_if_fail (GST_IS_STRUCTURE (struct1), FALSE);
2965 g_return_val_if_fail (GST_IS_STRUCTURE (struct2), FALSE);
2966
2967 if (G_UNLIKELY (struct1->name != struct2->name))
2968 return FALSE;
2969
2970 /* tries to intersect if we have the field in both */
2971 return gst_structure_foreach ((GstStructure *) struct1,
2972 gst_caps_structure_can_intersect_field, (gpointer) struct2);
2973 }
2974
2975 static gboolean
gst_caps_structure_is_superset_field(GQuark field_id,const GValue * value,gpointer user_data)2976 gst_caps_structure_is_superset_field (GQuark field_id, const GValue * value,
2977 gpointer user_data)
2978 {
2979 GstStructure *subset = user_data;
2980 const GValue *other;
2981 int comparison;
2982
2983 if (!(other = gst_structure_id_get_value (subset, field_id)))
2984 /* field is missing in the subset => no subset */
2985 return FALSE;
2986
2987 comparison = gst_value_compare (value, other);
2988
2989 /* equal values are subset */
2990 if (comparison == GST_VALUE_EQUAL)
2991 return TRUE;
2992
2993 /* ordered, but unequal, values are not */
2994 if (comparison != GST_VALUE_UNORDERED)
2995 return FALSE;
2996
2997 return gst_value_is_subset (other, value);
2998 }
2999
3000 /**
3001 * gst_structure_is_subset:
3002 * @subset: a #GstStructure
3003 * @superset: a potentially greater #GstStructure
3004 *
3005 * Checks if @subset is a subset of @superset, i.e. has the same
3006 * structure name and for all fields that are existing in @superset,
3007 * @subset has a value that is a subset of the value in @superset.
3008 *
3009 * Returns: %TRUE if @subset is a subset of @superset
3010 */
3011 gboolean
gst_structure_is_subset(const GstStructure * subset,const GstStructure * superset)3012 gst_structure_is_subset (const GstStructure * subset,
3013 const GstStructure * superset)
3014 {
3015 if ((superset->name != subset->name) ||
3016 (gst_structure_n_fields (superset) > gst_structure_n_fields (subset)))
3017 return FALSE;
3018
3019 return gst_structure_foreach ((GstStructure *) superset,
3020 gst_caps_structure_is_superset_field, (gpointer) subset);
3021 }
3022
3023
3024 /**
3025 * gst_structure_fixate:
3026 * @structure: a #GstStructure
3027 *
3028 * Fixate all values in @structure using gst_value_fixate().
3029 * @structure will be modified in-place and should be writable.
3030 */
3031 void
gst_structure_fixate(GstStructure * structure)3032 gst_structure_fixate (GstStructure * structure)
3033 {
3034 g_return_if_fail (GST_IS_STRUCTURE (structure));
3035
3036 gst_structure_foreach (structure, default_fixate, structure);
3037 }
3038
3039 static gboolean
_gst_structure_get_any_list(GstStructure * structure,GType type,const gchar * fieldname,GValueArray ** array)3040 _gst_structure_get_any_list (GstStructure * structure, GType type,
3041 const gchar * fieldname, GValueArray ** array)
3042 {
3043 GstStructureField *field;
3044 GValue val = G_VALUE_INIT;
3045
3046 g_return_val_if_fail (structure != NULL, FALSE);
3047 g_return_val_if_fail (fieldname != NULL, FALSE);
3048 g_return_val_if_fail (array != NULL, FALSE);
3049
3050 field = gst_structure_get_field (structure, fieldname);
3051
3052 if (field == NULL || G_VALUE_TYPE (&field->value) != type)
3053 return FALSE;
3054
3055 g_value_init (&val, G_TYPE_VALUE_ARRAY);
3056
3057 if (g_value_transform (&field->value, &val)) {
3058 *array = g_value_get_boxed (&val);
3059 return TRUE;
3060 }
3061
3062 g_value_unset (&val);
3063 return FALSE;
3064 }
3065
3066 /**
3067 * gst_structure_get_array:
3068 * @structure: a #GstStructure
3069 * @fieldname: the name of a field
3070 * @array: (out): a pointer to a #GValueArray
3071 *
3072 * This is useful in language bindings where unknown #GValue types are not
3073 * supported. This function will convert the %GST_TYPE_ARRAY into a newly
3074 * allocated #GValueArray and return it through @array. Be aware that this is
3075 * slower then getting the #GValue directly.
3076 *
3077 * Returns: %TRUE if the value could be set correctly. If there was no field
3078 * with @fieldname or the existing field did not contain a %GST_TYPE_ARRAY,
3079 * this function returns %FALSE.
3080 */
3081 gboolean
gst_structure_get_array(GstStructure * structure,const gchar * fieldname,GValueArray ** array)3082 gst_structure_get_array (GstStructure * structure, const gchar * fieldname,
3083 GValueArray ** array)
3084 {
3085 return _gst_structure_get_any_list (structure, GST_TYPE_ARRAY, fieldname,
3086 array);
3087 }
3088
3089 /**
3090 * gst_structure_get_list:
3091 * @structure: a #GstStructure
3092 * @fieldname: the name of a field
3093 * @array: (out): a pointer to a #GValueArray
3094 *
3095 * This is useful in language bindings where unknown #GValue types are not
3096 * supported. This function will convert the %GST_TYPE_LIST into a newly
3097 * allocated GValueArray and return it through @array. Be aware that this is
3098 * slower then getting the #GValue directly.
3099 *
3100 * Returns: %TRUE if the value could be set correctly. If there was no field
3101 * with @fieldname or the existing field did not contain a %GST_TYPE_LIST, this
3102 * function returns %FALSE.
3103 *
3104 * Since: 1.12
3105 */
3106 gboolean
gst_structure_get_list(GstStructure * structure,const gchar * fieldname,GValueArray ** array)3107 gst_structure_get_list (GstStructure * structure, const gchar * fieldname,
3108 GValueArray ** array)
3109 {
3110 return _gst_structure_get_any_list (structure, GST_TYPE_LIST, fieldname,
3111 array);
3112 }
3113
3114 static void
_gst_structure_set_any_list(GstStructure * structure,GType type,const gchar * fieldname,const GValueArray * array)3115 _gst_structure_set_any_list (GstStructure * structure, GType type,
3116 const gchar * fieldname, const GValueArray * array)
3117 {
3118 GValue arval = G_VALUE_INIT;
3119 GValue value = G_VALUE_INIT;
3120
3121 g_return_if_fail (structure != NULL);
3122 g_return_if_fail (fieldname != NULL);
3123 g_return_if_fail (array != NULL);
3124 g_return_if_fail (IS_MUTABLE (structure));
3125
3126 g_value_init (&value, type);
3127 g_value_init (&arval, G_TYPE_VALUE_ARRAY);
3128 g_value_set_static_boxed (&arval, array);
3129
3130 if (g_value_transform (&arval, &value)) {
3131 gst_structure_id_set_value_internal (structure,
3132 g_quark_from_string (fieldname), &value);
3133 } else {
3134 g_warning ("Failed to convert a GValueArray");
3135 }
3136
3137 g_value_unset (&arval);
3138 g_value_unset (&value);
3139 }
3140
3141 /**
3142 * gst_structure_set_array:
3143 * @structure: a #GstStructure
3144 * @fieldname: the name of a field
3145 * @array: a pointer to a #GValueArray
3146 *
3147 * This is useful in language bindings where unknown GValue types are not
3148 * supported. This function will convert a @array to %GST_TYPE_ARRAY and set
3149 * the field specified by @fieldname. Be aware that this is slower then using
3150 * %GST_TYPE_ARRAY in a #GValue directly.
3151 *
3152 * Since: 1.12
3153 */
3154 void
gst_structure_set_array(GstStructure * structure,const gchar * fieldname,const GValueArray * array)3155 gst_structure_set_array (GstStructure * structure, const gchar * fieldname,
3156 const GValueArray * array)
3157 {
3158 _gst_structure_set_any_list (structure, GST_TYPE_ARRAY, fieldname, array);
3159 }
3160
3161 /**
3162 * gst_structure_set_list:
3163 * @structure: a #GstStructure
3164 * @fieldname: the name of a field
3165 * @array: a pointer to a #GValueArray
3166 *
3167 * This is useful in language bindings where unknown GValue types are not
3168 * supported. This function will convert a @array to %GST_TYPE_LIST and set
3169 * the field specified by @fieldname. Be aware that this is slower then using
3170 * %GST_TYPE_LIST in a #GValue directly.
3171 *
3172 * Since: 1.12
3173 */
3174 void
gst_structure_set_list(GstStructure * structure,const gchar * fieldname,const GValueArray * array)3175 gst_structure_set_list (GstStructure * structure, const gchar * fieldname,
3176 const GValueArray * array)
3177 {
3178 _gst_structure_set_any_list (structure, GST_TYPE_LIST, fieldname, array);
3179 }
3180