2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 * @short_description: GValue implementations specific
25 * GValue implementations specific to GStreamer.
27 * Note that operations on the same GstValue (or GValue) from multiple
28 * threads may lead to undefined behaviour.
30 * Last reviewed on 2008-03-11 (0.10.18)
42 #include "gst_private.h"
43 #include "glib-compat-private.h"
45 #include <gobject/gvaluecollector.h>
48 typedef struct _GstValueUnionInfo GstValueUnionInfo;
49 struct _GstValueUnionInfo
53 GstValueUnionFunc func;
56 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
57 struct _GstValueIntersectInfo
61 GstValueIntersectFunc func;
64 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
65 struct _GstValueSubtractInfo
69 GstValueSubtractFunc func;
72 #define FUNDAMENTAL_TYPE_ID_MAX \
73 (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
74 #define FUNDAMENTAL_TYPE_ID(type) \
75 ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
77 static GArray *gst_value_table;
78 static GHashTable *gst_value_hash;
79 static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1];
80 static GArray *gst_value_union_funcs;
81 static GArray *gst_value_intersect_funcs;
82 static GArray *gst_value_subtract_funcs;
84 /* Forward declarations */
85 static gchar *gst_value_serialize_fraction (const GValue * value);
87 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
88 static gint gst_value_compare_with_func (const GValue * value1,
89 const GValue * value2, GstValueCompareFunc compare);
91 static gchar *gst_string_wrap (const gchar * s);
92 static gchar *gst_string_take_and_wrap (gchar * s);
93 static gchar *gst_string_unwrap (const gchar * s);
95 static inline GstValueTable *
96 gst_value_hash_lookup_type (GType type)
98 if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type)))
99 return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)];
101 return g_hash_table_lookup (gst_value_hash, (gpointer) type);
105 gst_value_hash_add_type (GType type, const GstValueTable * table)
107 if (G_TYPE_IS_FUNDAMENTAL (type))
108 gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table;
110 g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table);
117 /* two helper functions to serialize/stringify any type of list
118 * regular lists are done with { }, arrays with < >
121 gst_value_serialize_any_list (const GValue * value, const gchar * begin,
125 GArray *array = value->data[0].v_pointer;
129 guint alen = array->len;
131 /* estimate minimum string length to minimise re-allocs in GString */
132 s = g_string_sized_new (2 + (6 * alen) + 2);
133 g_string_append (s, begin);
134 for (i = 0; i < alen; i++) {
135 v = &g_array_index (array, GValue, i);
136 s_val = gst_value_serialize (v);
137 g_string_append (s, s_val);
140 g_string_append_len (s, ", ", 2);
143 g_string_append (s, end);
144 return g_string_free (s, FALSE);
148 gst_value_transform_any_list_string (const GValue * src_value,
149 GValue * dest_value, const gchar * begin, const gchar * end)
158 array = src_value->data[0].v_pointer;
161 /* estimate minimum string length to minimise re-allocs in GString */
162 s = g_string_sized_new (2 + (10 * alen) + 2);
163 g_string_append (s, begin);
164 for (i = 0; i < alen; i++) {
165 list_value = &g_array_index (array, GValue, i);
168 g_string_append_len (s, ", ", 2);
170 list_s = g_strdup_value_contents (list_value);
171 g_string_append (s, list_s);
174 g_string_append (s, end);
176 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
180 * helper function to see if a type is fixed. Is used internally here and
181 * there. Do not export, since it doesn't work for types where the content
182 * decides the fixedness (e.g. GST_TYPE_ARRAY).
185 gst_type_is_fixed (GType type)
187 /* the basic int, string, double types */
188 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
191 /* our fundamental types that are certainly not fixed */
192 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
193 type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE) {
196 /* other (boxed) types that are fixed */
197 if (type == GST_TYPE_BUFFER) {
201 if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
202 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
209 /* GValue functions usable for both regular lists and arrays */
211 gst_value_init_list_or_array (GValue * value)
213 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
217 copy_garray_of_gstvalue (const GArray * src)
223 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
224 g_array_set_size (dest, len);
225 for (i = 0; i < len; i++) {
226 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
227 &g_array_index (src, GValue, i));
234 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
236 dest_value->data[0].v_pointer =
237 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
241 gst_value_free_list_or_array (GValue * value)
244 GArray *src = (GArray *) value->data[0].v_pointer;
247 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
248 for (i = 0; i < len; i++) {
249 g_value_unset (&g_array_index (src, GValue, i));
251 g_array_free (src, TRUE);
256 gst_value_list_or_array_peek_pointer (const GValue * value)
258 return value->data[0].v_pointer;
262 gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
263 GTypeCValue * collect_values, guint collect_flags)
265 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
266 value->data[0].v_pointer = collect_values[0].v_pointer;
267 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
269 value->data[0].v_pointer =
270 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
276 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
277 GTypeCValue * collect_values, guint collect_flags)
279 GArray **dest = collect_values[0].v_pointer;
282 return g_strdup_printf ("value location for `%s' passed as NULL",
283 G_VALUE_TYPE_NAME (value));
284 if (!value->data[0].v_pointer)
285 return g_strdup_printf ("invalid value given for `%s'",
286 G_VALUE_TYPE_NAME (value));
287 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
288 *dest = (GArray *) value->data[0].v_pointer;
290 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
296 * gst_value_list_append_value:
297 * @value: a #GValue of type #GST_TYPE_LIST
298 * @append_value: the value to append
300 * Appends @append_value to the GstValueList in @value.
303 gst_value_list_append_value (GValue * value, const GValue * append_value)
307 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
309 gst_value_init_and_copy (&val, append_value);
310 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
314 * gst_value_list_prepend_value:
315 * @value: a #GValue of type #GST_TYPE_LIST
316 * @prepend_value: the value to prepend
318 * Prepends @prepend_value to the GstValueList in @value.
321 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
325 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
327 gst_value_init_and_copy (&val, prepend_value);
328 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
332 * gst_value_list_concat:
333 * @dest: an uninitialized #GValue to take the result
337 * Concatenates copies of @value1 and @value2 into a list. Values that are not
338 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
339 * @dest will be initialized to the type #GST_TYPE_LIST.
342 gst_value_list_concat (GValue * dest, const GValue * value1,
343 const GValue * value2)
345 guint i, value1_length, value2_length;
348 g_return_if_fail (dest != NULL);
349 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
350 g_return_if_fail (G_IS_VALUE (value1));
351 g_return_if_fail (G_IS_VALUE (value2));
354 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
356 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
357 g_value_init (dest, GST_TYPE_LIST);
358 array = (GArray *) dest->data[0].v_pointer;
359 g_array_set_size (array, value1_length + value2_length);
361 if (GST_VALUE_HOLDS_LIST (value1)) {
362 for (i = 0; i < value1_length; i++) {
363 gst_value_init_and_copy (&g_array_index (array, GValue, i),
364 gst_value_list_get_value (value1, i));
367 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
370 if (GST_VALUE_HOLDS_LIST (value2)) {
371 for (i = 0; i < value2_length; i++) {
372 gst_value_init_and_copy (&g_array_index (array, GValue,
373 i + value1_length), gst_value_list_get_value (value2, i));
376 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
382 * gst_value_list_get_size:
383 * @value: a #GValue of type #GST_TYPE_LIST
385 * Gets the number of values contained in @value.
387 * Returns: the number of values
390 gst_value_list_get_size (const GValue * value)
392 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
394 return ((GArray *) value->data[0].v_pointer)->len;
398 * gst_value_list_get_value:
399 * @value: a #GValue of type #GST_TYPE_LIST
400 * @index: index of value to get from the list
402 * Gets the value that is a member of the list contained in @value and
403 * has the index @index.
405 * Returns: the value at the given index
408 gst_value_list_get_value (const GValue * value, guint index)
410 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
411 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
413 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
418 * gst_value_array_append_value:
419 * @value: a #GValue of type #GST_TYPE_ARRAY
420 * @append_value: the value to append
422 * Appends @append_value to the GstValueArray in @value.
425 gst_value_array_append_value (GValue * value, const GValue * append_value)
429 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
431 gst_value_init_and_copy (&val, append_value);
432 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
436 * gst_value_array_prepend_value:
437 * @value: a #GValue of type #GST_TYPE_ARRAY
438 * @prepend_value: the value to prepend
440 * Prepends @prepend_value to the GstValueArray in @value.
443 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
447 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
449 gst_value_init_and_copy (&val, prepend_value);
450 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
454 * gst_value_array_get_size:
455 * @value: a #GValue of type #GST_TYPE_ARRAY
457 * Gets the number of values contained in @value.
459 * Returns: the number of values
462 gst_value_array_get_size (const GValue * value)
464 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
466 return ((GArray *) value->data[0].v_pointer)->len;
470 * gst_value_array_get_value:
471 * @value: a #GValue of type #GST_TYPE_ARRAY
472 * @index: index of value to get from the array
474 * Gets the value that is a member of the array contained in @value and
475 * has the index @index.
477 * Returns: the value at the given index
480 gst_value_array_get_value (const GValue * value, guint index)
482 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
483 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
485 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
490 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
492 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
496 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
498 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
501 /* Do an unordered compare of the contents of a list */
503 gst_value_compare_list (const GValue * value1, const GValue * value2)
506 GArray *array1 = value1->data[0].v_pointer;
507 GArray *array2 = value2->data[0].v_pointer;
512 GstValueCompareFunc compare;
514 /* get length and do initial length check. */
516 if (len != array2->len)
517 return GST_VALUE_UNORDERED;
519 /* place to mark removed value indices of array2 */
520 removed = g_newa (guint8, len);
521 memset (removed, 0, len);
524 /* loop over array1, all items should be in array2. When we find an
525 * item in array2, remove it from array2 by marking it as removed */
526 for (i = 0; i < len; i++) {
527 v1 = &g_array_index (array1, GValue, i);
528 if ((compare = gst_value_get_compare_func (v1))) {
529 for (j = 0; j < len; j++) {
530 /* item is removed, we can skip it */
533 v2 = &g_array_index (array2, GValue, j);
534 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
535 /* mark item as removed now that we found it in array2 and
536 * decrement the number of remaining items in array2. */
542 /* item in array1 and not in array2, UNORDERED */
544 return GST_VALUE_UNORDERED;
546 return GST_VALUE_UNORDERED;
548 /* if not all items were removed, array2 contained something not in array1 */
550 return GST_VALUE_UNORDERED;
552 /* arrays are equal */
553 return GST_VALUE_EQUAL;
556 /* Perform an ordered comparison of the contents of an array */
558 gst_value_compare_array (const GValue * value1, const GValue * value2)
561 GArray *array1 = value1->data[0].v_pointer;
562 GArray *array2 = value2->data[0].v_pointer;
563 guint len = array1->len;
567 if (len != array2->len)
568 return GST_VALUE_UNORDERED;
570 for (i = 0; i < len; i++) {
571 v1 = &g_array_index (array1, GValue, i);
572 v2 = &g_array_index (array2, GValue, i);
573 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
574 return GST_VALUE_UNORDERED;
577 return GST_VALUE_EQUAL;
581 gst_value_serialize_list (const GValue * value)
583 return gst_value_serialize_any_list (value, "{ ", " }");
587 gst_value_deserialize_list (GValue * dest, const gchar * s)
589 g_warning ("gst_value_deserialize_list: unimplemented");
594 gst_value_serialize_array (const GValue * value)
596 return gst_value_serialize_any_list (value, "< ", " >");
600 gst_value_deserialize_array (GValue * dest, const gchar * s)
602 g_warning ("gst_value_deserialize_array: unimplemented");
611 gst_value_init_fourcc (GValue * value)
613 value->data[0].v_int = 0;
617 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
619 dest_value->data[0].v_int = src_value->data[0].v_int;
623 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
624 GTypeCValue * collect_values, guint collect_flags)
626 value->data[0].v_int = collect_values[0].v_int;
632 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
633 GTypeCValue * collect_values, guint collect_flags)
635 guint32 *fourcc_p = collect_values[0].v_pointer;
638 return g_strdup_printf ("value location for `%s' passed as NULL",
639 G_VALUE_TYPE_NAME (value));
641 *fourcc_p = value->data[0].v_int;
647 * gst_value_set_fourcc:
648 * @value: a GValue initialized to #GST_TYPE_FOURCC
649 * @fourcc: the #guint32 fourcc to set
651 * Sets @value to @fourcc.
654 gst_value_set_fourcc (GValue * value, guint32 fourcc)
656 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
658 value->data[0].v_int = fourcc;
662 * gst_value_get_fourcc:
663 * @value: a GValue initialized to #GST_TYPE_FOURCC
665 * Gets the #guint32 fourcc contained in @value.
667 * Returns: the #guint32 fourcc contained in @value.
670 gst_value_get_fourcc (const GValue * value)
672 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
674 return value->data[0].v_int;
678 gst_value_transform_fourcc_string (const GValue * src_value,
681 guint32 fourcc = src_value->data[0].v_int;
683 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
684 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
685 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
686 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
687 dest_value->data[0].v_pointer =
688 g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
690 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
695 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
697 if (value2->data[0].v_int == value1->data[0].v_int)
698 return GST_VALUE_EQUAL;
699 return GST_VALUE_UNORDERED;
703 gst_value_serialize_fourcc (const GValue * value)
705 guint32 fourcc = value->data[0].v_int;
707 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
708 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
709 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
710 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
711 return g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
713 return g_strdup_printf ("0x%08x", fourcc);
718 gst_value_deserialize_fourcc (GValue * dest, const char *s)
720 gboolean ret = FALSE;
724 if (strlen (s) == 4) {
725 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
727 } else if (g_ascii_isdigit (*s)) {
728 fourcc = strtoul (s, &end, 0);
733 gst_value_set_fourcc (dest, fourcc);
743 gst_value_init_int_range (GValue * value)
745 value->data[0].v_int = 0;
746 value->data[1].v_int = 0;
750 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
752 dest_value->data[0].v_int = src_value->data[0].v_int;
753 dest_value->data[1].v_int = src_value->data[1].v_int;
757 gst_value_collect_int_range (GValue * value, guint n_collect_values,
758 GTypeCValue * collect_values, guint collect_flags)
760 value->data[0].v_int = collect_values[0].v_int;
761 value->data[1].v_int = collect_values[1].v_int;
767 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
768 GTypeCValue * collect_values, guint collect_flags)
770 guint32 *int_range_start = collect_values[0].v_pointer;
771 guint32 *int_range_end = collect_values[1].v_pointer;
773 if (!int_range_start)
774 return g_strdup_printf ("start value location for `%s' passed as NULL",
775 G_VALUE_TYPE_NAME (value));
777 return g_strdup_printf ("end value location for `%s' passed as NULL",
778 G_VALUE_TYPE_NAME (value));
780 *int_range_start = value->data[0].v_int;
781 *int_range_end = value->data[1].v_int;
787 * gst_value_set_int_range:
788 * @value: a GValue initialized to GST_TYPE_INT_RANGE
789 * @start: the start of the range
790 * @end: the end of the range
792 * Sets @value to the range specified by @start and @end.
795 gst_value_set_int_range (GValue * value, gint start, gint end)
797 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
798 g_return_if_fail (start < end);
800 value->data[0].v_int = start;
801 value->data[1].v_int = end;
805 * gst_value_get_int_range_min:
806 * @value: a GValue initialized to GST_TYPE_INT_RANGE
808 * Gets the minimum of the range specified by @value.
810 * Returns: the minimum of the range
813 gst_value_get_int_range_min (const GValue * value)
815 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
817 return value->data[0].v_int;
821 * gst_value_get_int_range_max:
822 * @value: a GValue initialized to GST_TYPE_INT_RANGE
824 * Gets the maximum of the range specified by @value.
826 * Returns: the maxumum of the range
829 gst_value_get_int_range_max (const GValue * value)
831 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
833 return value->data[1].v_int;
837 gst_value_transform_int_range_string (const GValue * src_value,
840 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
841 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
845 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
847 if (value2->data[0].v_int == value1->data[0].v_int &&
848 value2->data[1].v_int == value1->data[1].v_int)
849 return GST_VALUE_EQUAL;
850 return GST_VALUE_UNORDERED;
854 gst_value_serialize_int_range (const GValue * value)
856 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
857 value->data[1].v_int);
861 gst_value_deserialize_int_range (GValue * dest, const gchar * s)
863 g_warning ("unimplemented");
872 gst_value_init_double_range (GValue * value)
874 value->data[0].v_double = 0;
875 value->data[1].v_double = 0;
879 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
881 dest_value->data[0].v_double = src_value->data[0].v_double;
882 dest_value->data[1].v_double = src_value->data[1].v_double;
886 gst_value_collect_double_range (GValue * value, guint n_collect_values,
887 GTypeCValue * collect_values, guint collect_flags)
889 value->data[0].v_double = collect_values[0].v_double;
890 value->data[1].v_double = collect_values[1].v_double;
896 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
897 GTypeCValue * collect_values, guint collect_flags)
899 gdouble *double_range_start = collect_values[0].v_pointer;
900 gdouble *double_range_end = collect_values[1].v_pointer;
902 if (!double_range_start)
903 return g_strdup_printf ("start value location for `%s' passed as NULL",
904 G_VALUE_TYPE_NAME (value));
905 if (!double_range_end)
906 return g_strdup_printf ("end value location for `%s' passed as NULL",
907 G_VALUE_TYPE_NAME (value));
909 *double_range_start = value->data[0].v_double;
910 *double_range_end = value->data[1].v_double;
916 * gst_value_set_double_range:
917 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
918 * @start: the start of the range
919 * @end: the end of the range
921 * Sets @value to the range specified by @start and @end.
924 gst_value_set_double_range (GValue * value, gdouble start, gdouble end)
926 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
928 value->data[0].v_double = start;
929 value->data[1].v_double = end;
933 * gst_value_get_double_range_min:
934 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
936 * Gets the minimum of the range specified by @value.
938 * Returns: the minimum of the range
941 gst_value_get_double_range_min (const GValue * value)
943 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
945 return value->data[0].v_double;
949 * gst_value_get_double_range_max:
950 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
952 * Gets the maximum of the range specified by @value.
954 * Returns: the maxumum of the range
957 gst_value_get_double_range_max (const GValue * value)
959 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
961 return value->data[1].v_double;
965 gst_value_transform_double_range_string (const GValue * src_value,
968 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
970 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
971 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
972 src_value->data[0].v_double),
973 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
974 src_value->data[1].v_double));
978 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
980 if (value2->data[0].v_double == value1->data[0].v_double &&
981 value2->data[0].v_double == value1->data[0].v_double)
982 return GST_VALUE_EQUAL;
983 return GST_VALUE_UNORDERED;
987 gst_value_serialize_double_range (const GValue * value)
989 char d1[G_ASCII_DTOSTR_BUF_SIZE];
990 char d2[G_ASCII_DTOSTR_BUF_SIZE];
992 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
993 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
994 return g_strdup_printf ("[ %s, %s ]", d1, d2);
998 gst_value_deserialize_double_range (GValue * dest, const gchar * s)
1000 g_warning ("unimplemented");
1009 gst_value_init_fraction_range (GValue * value)
1014 ftype = GST_TYPE_FRACTION;
1016 value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
1017 g_value_init (&vals[0], ftype);
1018 g_value_init (&vals[1], ftype);
1022 gst_value_free_fraction_range (GValue * value)
1024 GValue *vals = (GValue *) value->data[0].v_pointer;
1027 g_value_unset (&vals[0]);
1028 g_value_unset (&vals[1]);
1029 g_slice_free1 (2 * sizeof (GValue), vals);
1030 value->data[0].v_pointer = NULL;
1035 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value)
1037 GValue *vals = (GValue *) dest_value->data[0].v_pointer;
1038 GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
1041 gst_value_init_fraction_range (dest_value);
1042 vals = dest_value->data[0].v_pointer;
1044 if (src_vals != NULL) {
1045 g_value_copy (&src_vals[0], &vals[0]);
1046 g_value_copy (&src_vals[1], &vals[1]);
1051 gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
1052 GTypeCValue * collect_values, guint collect_flags)
1054 GValue *vals = (GValue *) value->data[0].v_pointer;
1056 if (n_collect_values != 4)
1057 return g_strdup_printf ("not enough value locations for `%s' passed",
1058 G_VALUE_TYPE_NAME (value));
1060 gst_value_init_fraction_range (value);
1061 vals = value->data[0].v_pointer;
1064 gst_value_set_fraction (&vals[0], collect_values[0].v_int,
1065 collect_values[1].v_int);
1066 gst_value_set_fraction (&vals[1], collect_values[2].v_int,
1067 collect_values[3].v_int);
1073 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
1074 GTypeCValue * collect_values, guint collect_flags)
1077 int *dest_values[4];
1078 GValue *vals = (GValue *) value->data[0].v_pointer;
1080 if (G_UNLIKELY (n_collect_values != 4))
1081 return g_strdup_printf ("not enough value locations for `%s' passed",
1082 G_VALUE_TYPE_NAME (value));
1084 for (i = 0; i < 4; i++) {
1085 if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
1086 return g_strdup_printf ("value location for `%s' passed as NULL",
1087 G_VALUE_TYPE_NAME (value));
1089 dest_values[i] = collect_values[i].v_pointer;
1092 if (G_UNLIKELY (vals == NULL)) {
1093 return g_strdup_printf ("Uninitialised `%s' passed",
1094 G_VALUE_TYPE_NAME (value));
1097 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
1098 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
1099 dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
1100 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
1105 * gst_value_set_fraction_range:
1106 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1107 * @start: the start of the range (a GST_TYPE_FRACTION GValue)
1108 * @end: the end of the range (a GST_TYPE_FRACTION GValue)
1110 * Sets @value to the range specified by @start and @end.
1113 gst_value_set_fraction_range (GValue * value, const GValue * start,
1118 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
1120 vals = (GValue *) value->data[0].v_pointer;
1122 gst_value_init_fraction_range (value);
1123 vals = value->data[0].v_pointer;
1125 g_value_copy (start, &vals[0]);
1126 g_value_copy (end, &vals[1]);
1130 * gst_value_set_fraction_range_full:
1131 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1132 * @numerator_start: the numerator start of the range
1133 * @denominator_start: the denominator start of the range
1134 * @numerator_end: the numerator end of the range
1135 * @denominator_end: the denominator end of the range
1137 * Sets @value to the range specified by @numerator_start/@denominator_start
1138 * and @numerator_end/@denominator_end.
1141 gst_value_set_fraction_range_full (GValue * value,
1142 gint numerator_start, gint denominator_start,
1143 gint numerator_end, gint denominator_end)
1145 GValue start = { 0 };
1148 g_value_init (&start, GST_TYPE_FRACTION);
1149 g_value_init (&end, GST_TYPE_FRACTION);
1151 gst_value_set_fraction (&start, numerator_start, denominator_start);
1152 gst_value_set_fraction (&end, numerator_end, denominator_end);
1153 gst_value_set_fraction_range (value, &start, &end);
1155 g_value_unset (&start);
1156 g_value_unset (&end);
1160 * gst_value_get_fraction_range_min:
1161 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1163 * Gets the minimum of the range specified by @value.
1165 * Returns: the minimum of the range
1168 gst_value_get_fraction_range_min (const GValue * value)
1172 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE);
1174 vals = (GValue *) value->data[0].v_pointer;
1183 * gst_value_get_fraction_range_max:
1184 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1186 * Gets the maximum of the range specified by @value.
1188 * Returns: the maximum of the range
1191 gst_value_get_fraction_range_max (const GValue * value)
1195 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE);
1197 vals = (GValue *) value->data[0].v_pointer;
1206 gst_value_serialize_fraction_range (const GValue * value)
1208 GValue *vals = (GValue *) value->data[0].v_pointer;
1212 retval = g_strdup ("[ 0/1, 0/1 ]");
1216 start = gst_value_serialize_fraction (&vals[0]);
1217 end = gst_value_serialize_fraction (&vals[1]);
1219 retval = g_strdup_printf ("[ %s, %s ]", start, end);
1228 gst_value_transform_fraction_range_string (const GValue * src_value,
1229 GValue * dest_value)
1231 dest_value->data[0].v_pointer =
1232 gst_value_serialize_fraction_range (src_value);
1236 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
1238 GValue *vals1, *vals2;
1239 GstValueCompareFunc compare;
1241 if (value2->data[0].v_pointer == value1->data[0].v_pointer)
1242 return GST_VALUE_EQUAL; /* Only possible if both are NULL */
1244 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL)
1245 return GST_VALUE_UNORDERED;
1247 vals1 = (GValue *) value1->data[0].v_pointer;
1248 vals2 = (GValue *) value2->data[0].v_pointer;
1249 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
1250 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
1252 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
1254 return GST_VALUE_EQUAL;
1256 return GST_VALUE_UNORDERED;
1260 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s)
1262 g_warning ("unimplemented");
1271 * gst_value_set_caps:
1272 * @value: a GValue initialized to GST_TYPE_CAPS
1273 * @caps: the caps to set the value to
1275 * Sets the contents of @value to @caps. The actual
1276 * #GstCaps structure is copied before it is used.
1279 gst_value_set_caps (GValue * value, const GstCaps * caps)
1281 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
1283 g_value_set_boxed (value, caps);
1287 * gst_value_get_caps:
1288 * @value: a GValue initialized to GST_TYPE_CAPS
1290 * Gets the contents of @value.
1292 * Returns: the contents of @value
1295 gst_value_get_caps (const GValue * value)
1297 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
1299 return (GstCaps *) g_value_get_boxed (value);
1303 gst_value_serialize_caps (const GValue * value)
1305 GstCaps *caps = g_value_get_boxed (value);
1307 return gst_caps_to_string (caps);
1311 gst_value_deserialize_caps (GValue * dest, const gchar * s)
1315 caps = gst_caps_from_string (s);
1318 g_value_take_boxed (dest, caps);
1329 * gst_value_set_structure:
1330 * @value: a GValue initialized to GST_TYPE_STRUCTURE
1331 * @structure: the structure to set the value to
1333 * Sets the contents of @value to @structure. The actual
1338 gst_value_set_structure (GValue * value, const GstStructure * structure)
1340 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE);
1342 g_value_set_boxed (value, structure);
1346 * gst_value_get_structure:
1347 * @value: a GValue initialized to GST_TYPE_STRUCTURE
1349 * Gets the contents of @value.
1351 * Returns: the contents of @value
1355 const GstStructure *
1356 gst_value_get_structure (const GValue * value)
1358 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL);
1360 return (GstStructure *) g_value_get_boxed (value);
1364 gst_value_serialize_structure (const GValue * value)
1366 GstStructure *structure = g_value_get_boxed (value);
1368 return gst_string_take_and_wrap (gst_structure_to_string (structure));
1372 gst_value_deserialize_structure (GValue * dest, const gchar * s)
1374 GstStructure *structure;
1377 structure = gst_structure_from_string (s, NULL);
1379 gchar *str = gst_string_unwrap (s);
1381 if (G_UNLIKELY (!str))
1384 structure = gst_structure_from_string (str, NULL);
1388 if (G_LIKELY (structure)) {
1389 g_value_take_boxed (dest, structure);
1400 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
1402 GstBuffer *buf1 = GST_BUFFER (gst_value_get_mini_object (value1));
1403 GstBuffer *buf2 = GST_BUFFER (gst_value_get_mini_object (value2));
1405 if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2))
1406 return GST_VALUE_UNORDERED;
1407 if (GST_BUFFER_SIZE (buf1) == 0)
1408 return GST_VALUE_EQUAL;
1409 g_assert (GST_BUFFER_DATA (buf1));
1410 g_assert (GST_BUFFER_DATA (buf2));
1411 if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2),
1412 GST_BUFFER_SIZE (buf1)) == 0)
1413 return GST_VALUE_EQUAL;
1415 return GST_VALUE_UNORDERED;
1419 gst_value_serialize_buffer (const GValue * value)
1427 buffer = gst_value_get_buffer (value);
1431 data = GST_BUFFER_DATA (buffer);
1432 size = GST_BUFFER_SIZE (buffer);
1434 string = g_malloc (size * 2 + 1);
1435 for (i = 0; i < size; i++) {
1436 sprintf (string + i * 2, "%02x", data[i]);
1438 string[size * 2] = 0;
1444 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
1456 buffer = gst_buffer_new_and_alloc (len / 2);
1457 data = GST_BUFFER_DATA (buffer);
1458 for (i = 0; i < len / 2; i++) {
1459 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
1462 ts[0] = s[i * 2 + 0];
1463 ts[1] = s[i * 2 + 1];
1466 data[i] = (guint8) strtoul (ts, NULL, 16);
1469 gst_value_take_buffer (dest, buffer);
1480 gst_buffer_unref (buffer);
1491 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
1493 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
1494 return GST_VALUE_EQUAL;
1495 return GST_VALUE_UNORDERED;
1499 gst_value_serialize_boolean (const GValue * value)
1501 if (value->data[0].v_int) {
1502 return g_strdup ("true");
1504 return g_strdup ("false");
1508 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
1510 gboolean ret = FALSE;
1512 if (g_ascii_strcasecmp (s, "true") == 0 ||
1513 g_ascii_strcasecmp (s, "yes") == 0 ||
1514 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
1515 g_value_set_boolean (dest, TRUE);
1517 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
1518 g_ascii_strcasecmp (s, "no") == 0 ||
1519 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
1520 g_value_set_boolean (dest, FALSE);
1527 #define CREATE_SERIALIZATION_START(_type,_macro) \
1529 gst_value_compare_ ## _type \
1530 (const GValue * value1, const GValue * value2) \
1532 g ## _type val1 = g_value_get_ ## _type (value1); \
1533 g ## _type val2 = g_value_get_ ## _type (value2); \
1535 return GST_VALUE_GREATER_THAN; \
1537 return GST_VALUE_LESS_THAN; \
1538 return GST_VALUE_EQUAL; \
1542 gst_value_serialize_ ## _type (const GValue * value) \
1544 GValue val = { 0, }; \
1545 g_value_init (&val, G_TYPE_STRING); \
1546 if (!g_value_transform (value, &val)) \
1547 g_assert_not_reached (); \
1548 /* NO_COPY_MADNESS!!! */ \
1549 return (char *) g_value_get_string (&val); \
1552 /* deserialize the given s into to as a gint64.
1553 * check if the result is actually storeable in the given size number of
1557 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
1558 gint64 min, gint64 max, gint size)
1560 gboolean ret = FALSE;
1565 *to = g_ascii_strtoull (s, &end, 0);
1566 /* a range error is a definitive no-no */
1567 if (errno == ERANGE) {
1574 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
1575 *to = G_LITTLE_ENDIAN;
1577 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
1580 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
1583 } else if (g_ascii_strcasecmp (s, "min") == 0) {
1586 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1592 /* by definition, a gint64 fits into a gint64; so ignore those */
1593 if (size != sizeof (mask)) {
1595 /* for positive numbers, we create a mask of 1's outside of the range
1596 * and 0's inside the range. An and will thus keep only 1 bits
1597 * outside of the range */
1598 mask <<= (size * 8);
1599 if ((mask & *to) != 0) {
1603 /* for negative numbers, we do a 2's complement version */
1604 mask <<= ((size * 8) - 1);
1605 if ((mask & *to) != mask) {
1614 #define CREATE_SERIALIZATION(_type,_macro) \
1615 CREATE_SERIALIZATION_START(_type,_macro) \
1618 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
1622 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
1623 G_MAX ## _macro, sizeof (g ## _type))) { \
1624 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
1631 #define CREATE_USERIALIZATION(_type,_macro) \
1632 CREATE_SERIALIZATION_START(_type,_macro) \
1635 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
1639 gboolean ret = FALSE; \
1642 x = g_ascii_strtoull (s, &end, 0); \
1643 /* a range error is a definitive no-no */ \
1644 if (errno == ERANGE) { \
1647 /* the cast ensures the range check later on makes sense */ \
1648 x = (g ## _type) x; \
1652 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
1653 x = G_LITTLE_ENDIAN; \
1655 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
1658 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
1661 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
1664 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
1665 x = G_MAX ## _macro; \
1670 if (x > G_MAX ## _macro) { \
1673 g_value_set_ ## _type (dest, x); \
1679 #define REGISTER_SERIALIZATION(_gtype, _type) \
1681 static const GstValueTable gst_value = { \
1683 gst_value_compare_ ## _type, \
1684 gst_value_serialize_ ## _type, \
1685 gst_value_deserialize_ ## _type, \
1688 gst_value_register (&gst_value); \
1691 CREATE_SERIALIZATION (int, INT);
1692 CREATE_SERIALIZATION (int64, INT64);
1693 CREATE_SERIALIZATION (long, LONG);
1695 CREATE_USERIALIZATION (uint, UINT);
1696 CREATE_USERIALIZATION (uint64, UINT64);
1697 CREATE_USERIALIZATION (ulong, ULONG);
1703 gst_value_compare_double (const GValue * value1, const GValue * value2)
1705 if (value1->data[0].v_double > value2->data[0].v_double)
1706 return GST_VALUE_GREATER_THAN;
1707 if (value1->data[0].v_double < value2->data[0].v_double)
1708 return GST_VALUE_LESS_THAN;
1709 if (value1->data[0].v_double == value2->data[0].v_double)
1710 return GST_VALUE_EQUAL;
1711 return GST_VALUE_UNORDERED;
1715 gst_value_serialize_double (const GValue * value)
1717 char d[G_ASCII_DTOSTR_BUF_SIZE];
1719 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1720 return g_strdup (d);
1724 gst_value_deserialize_double (GValue * dest, const gchar * s)
1727 gboolean ret = FALSE;
1730 x = g_ascii_strtod (s, &end);
1734 if (g_ascii_strcasecmp (s, "min") == 0) {
1737 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1743 g_value_set_double (dest, x);
1753 gst_value_compare_float (const GValue * value1, const GValue * value2)
1755 if (value1->data[0].v_float > value2->data[0].v_float)
1756 return GST_VALUE_GREATER_THAN;
1757 if (value1->data[0].v_float < value2->data[0].v_float)
1758 return GST_VALUE_LESS_THAN;
1759 if (value1->data[0].v_float == value2->data[0].v_float)
1760 return GST_VALUE_EQUAL;
1761 return GST_VALUE_UNORDERED;
1765 gst_value_serialize_float (const GValue * value)
1767 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
1769 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
1770 return g_strdup (d);
1774 gst_value_deserialize_float (GValue * dest, const gchar * s)
1777 gboolean ret = FALSE;
1780 x = g_ascii_strtod (s, &end);
1784 if (g_ascii_strcasecmp (s, "min") == 0) {
1787 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1792 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
1795 g_value_set_float (dest, (float) x);
1805 gst_value_compare_string (const GValue * value1, const GValue * value2)
1807 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
1808 /* if only one is NULL, no match - otherwise both NULL == EQUAL */
1809 if (value1->data[0].v_pointer != value2->data[0].v_pointer)
1810 return GST_VALUE_UNORDERED;
1812 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
1815 return GST_VALUE_LESS_THAN;
1817 return GST_VALUE_GREATER_THAN;
1820 return GST_VALUE_EQUAL;
1824 gst_string_measure_wrapping (const gchar * s)
1827 gboolean wrap = FALSE;
1829 if (G_UNLIKELY (s == NULL))
1832 /* Special case: the actual string NULL needs wrapping */
1833 if (G_UNLIKELY (strcmp (s, "NULL") == 0))
1838 if (GST_ASCII_IS_STRING (*s)) {
1840 } else if (*s < 0x20 || *s >= 0x7f) {
1850 /* Wrap the string if we found something that needs
1851 * wrapping, or the empty string (len == 0) */
1852 return (wrap || len == 0) ? len : -1;
1856 gst_string_wrap_inner (const gchar * s, int len)
1860 e = d = g_malloc (len + 3);
1864 if (GST_ASCII_IS_STRING (*s)) {
1866 } else if (*s < 0x20 || *s >= 0x7f) {
1868 *e++ = '0' + ((*(guchar *) s) >> 6);
1869 *e++ = '0' + (((*s) >> 3) & 0x7);
1870 *e++ = '0' + ((*s++) & 0x7);
1879 g_assert (e - d <= len + 3);
1883 /* Do string wrapping/escaping */
1885 gst_string_wrap (const gchar * s)
1887 int len = gst_string_measure_wrapping (s);
1889 if (G_LIKELY (len < 0))
1890 return g_strdup (s);
1892 return gst_string_wrap_inner (s, len);
1895 /* Same as above, but take ownership of the string */
1897 gst_string_take_and_wrap (gchar * s)
1900 int len = gst_string_measure_wrapping (s);
1902 if (G_LIKELY (len < 0))
1905 out = gst_string_wrap_inner (s, len);
1912 * This function takes a string delimited with double quotes (")
1913 * and unescapes any \xxx octal numbers.
1915 * If sequences of \y are found where y is not in the range of
1916 * 0->3, y is copied unescaped.
1918 * If \xyy is found where x is an octal number but y is not, an
1919 * error is encountered and NULL is returned.
1921 * the input string must be \0 terminated.
1924 gst_string_unwrap (const gchar * s)
1927 gchar *read, *write;
1929 /* NULL string returns NULL */
1933 /* strings not starting with " are invalid */
1937 /* make copy of original string to hold the result. This
1938 * string will always be smaller than the original */
1943 /* need to move to the next position as we parsed the " */
1947 if (GST_ASCII_IS_STRING (*read)) {
1948 /* normal chars are just copied */
1950 } else if (*read == '"') {
1951 /* quote marks end of string */
1953 } else if (*read == '\\') {
1954 /* got an escape char, move to next position to read a tripplet
1955 * of octal numbers */
1957 /* is the next char a possible first octal number? */
1958 if (*read >= '0' && *read <= '3') {
1959 /* parse other 2 numbers, if one of them is not in the range of
1960 * an octal number, we error. We also catch the case where a zero
1961 * byte is found here. */
1962 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
1965 /* now convert the octal number to a byte again. */
1966 *write++ = ((read[0] - '0') << 6) +
1967 ((read[1] - '0') << 3) + (read[2] - '0');
1971 /* if we run into a \0 here, we definately won't get a quote later */
1975 /* else copy \X sequence */
1979 /* weird character, error */
1983 /* if the string is not ending in " and zero terminated, we error */
1984 if (*read != '"' || read[1] != '\0')
1987 /* null terminate result string and return */
1997 gst_value_serialize_string (const GValue * value)
1999 return gst_string_wrap (value->data[0].v_pointer);
2003 gst_value_deserialize_string (GValue * dest, const gchar * s)
2005 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
2006 g_value_set_string (dest, NULL);
2008 } else if (G_LIKELY (*s != '"')) {
2009 if (!g_utf8_validate (s, -1, NULL))
2011 g_value_set_string (dest, s);
2014 gchar *str = gst_string_unwrap (s);
2015 if (G_UNLIKELY (!str))
2017 g_value_take_string (dest, str);
2028 gst_value_compare_enum (const GValue * value1, const GValue * value2)
2030 GEnumValue *en1, *en2;
2031 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
2032 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
2034 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
2035 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
2036 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
2037 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
2038 g_type_class_unref (klass1);
2039 g_type_class_unref (klass2);
2040 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
2041 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
2042 if (en1->value < en2->value)
2043 return GST_VALUE_LESS_THAN;
2044 if (en1->value > en2->value)
2045 return GST_VALUE_GREATER_THAN;
2047 return GST_VALUE_EQUAL;
2051 gst_value_serialize_enum (const GValue * value)
2054 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
2056 g_return_val_if_fail (klass, NULL);
2057 en = g_enum_get_value (klass, g_value_get_enum (value));
2058 g_type_class_unref (klass);
2060 /* might be one of the custom formats registered later */
2061 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) {
2062 const GstFormatDefinition *format_def;
2064 format_def = gst_format_get_details (g_value_get_enum (value));
2065 g_return_val_if_fail (format_def != NULL, NULL);
2066 return g_strdup (format_def->description);
2069 g_return_val_if_fail (en, NULL);
2070 return g_strdup (en->value_name);
2074 gst_value_deserialize_enum_iter_cmp (const GstFormatDefinition * format_def,
2077 if (g_ascii_strcasecmp (s, format_def->nick) == 0)
2080 return g_ascii_strcasecmp (s, format_def->description);
2084 gst_value_deserialize_enum (GValue * dest, const gchar * s)
2087 gchar *endptr = NULL;
2088 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
2090 g_return_val_if_fail (klass, FALSE);
2091 if (!(en = g_enum_get_value_by_name (klass, s))) {
2092 if (!(en = g_enum_get_value_by_nick (klass, s))) {
2093 gint i = strtol (s, &endptr, 0);
2095 if (endptr && *endptr == '\0') {
2096 en = g_enum_get_value (klass, i);
2100 g_type_class_unref (klass);
2102 /* might be one of the custom formats registered later */
2103 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
2104 const GstFormatDefinition *format_def;
2107 iter = gst_format_iterate_definitions ();
2109 format_def = gst_iterator_find_custom (iter,
2110 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, (gpointer) s);
2112 g_return_val_if_fail (format_def != NULL, FALSE);
2113 g_value_set_enum (dest, (gint) format_def->value);
2114 gst_iterator_free (iter);
2118 g_return_val_if_fail (en, FALSE);
2119 g_value_set_enum (dest, en->value);
2127 /* we just compare the value here */
2129 gst_value_compare_flags (const GValue * value1, const GValue * value2)
2132 GFlagsClass *klass1 =
2133 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
2134 GFlagsClass *klass2 =
2135 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
2137 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
2138 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
2139 fl1 = g_value_get_flags (value1);
2140 fl2 = g_value_get_flags (value2);
2141 g_type_class_unref (klass1);
2142 g_type_class_unref (klass2);
2144 return GST_VALUE_LESS_THAN;
2146 return GST_VALUE_GREATER_THAN;
2148 return GST_VALUE_EQUAL;
2151 /* the different flags are serialized separated with a + */
2153 gst_value_serialize_flags (const GValue * value)
2157 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
2158 gchar *result, *tmp;
2159 gboolean first = TRUE;
2161 g_return_val_if_fail (klass, NULL);
2163 flags = g_value_get_flags (value);
2165 /* if no flags are set, try to serialize to the _NONE string */
2167 fl = g_flags_get_first_value (klass, flags);
2168 return g_strdup (fl->value_name);
2171 /* some flags are set, so serialize one by one */
2172 result = g_strdup ("");
2174 fl = g_flags_get_first_value (klass, flags);
2176 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
2182 flags &= ~fl->value;
2185 g_type_class_unref (klass);
2191 gst_value_deserialize_flags (GValue * dest, const gchar * s)
2194 gchar *endptr = NULL;
2195 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
2200 g_return_val_if_fail (klass, FALSE);
2202 /* split into parts delimited with + */
2203 split = g_strsplit (s, "+", 0);
2207 /* loop over each part */
2209 if (!(fl = g_flags_get_value_by_name (klass, split[i]))) {
2210 if (!(fl = g_flags_get_value_by_nick (klass, split[i]))) {
2211 gint val = strtol (split[i], &endptr, 0);
2213 /* just or numeric value */
2214 if (endptr && *endptr == '\0') {
2225 g_type_class_unref (klass);
2226 g_value_set_flags (dest, flags);
2236 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
2237 const GValue * src2)
2239 if (src2->data[0].v_int <= src1->data[0].v_int &&
2240 src2->data[1].v_int >= src1->data[0].v_int) {
2241 gst_value_init_and_copy (dest, src2);
2248 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
2249 const GValue * src2)
2254 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
2255 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
2258 g_value_init (dest, GST_TYPE_INT_RANGE);
2259 gst_value_set_int_range (dest,
2260 MIN (src1->data[0].v_int, src2->data[0].v_int),
2261 MAX (src1->data[1].v_int, src2->data[1].v_int));
2273 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
2274 const GValue * src2)
2276 if (src2->data[0].v_int <= src1->data[0].v_int &&
2277 src2->data[1].v_int >= src1->data[0].v_int) {
2278 gst_value_init_and_copy (dest, src1);
2286 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
2287 const GValue * src2)
2292 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
2293 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
2296 g_value_init (dest, GST_TYPE_INT_RANGE);
2297 gst_value_set_int_range (dest, min, max);
2301 g_value_init (dest, G_TYPE_INT);
2302 g_value_set_int (dest, min);
2310 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
2311 const GValue * src2)
2313 if (src2->data[0].v_double <= src1->data[0].v_double &&
2314 src2->data[1].v_double >= src1->data[0].v_double) {
2315 gst_value_init_and_copy (dest, src1);
2323 gst_value_intersect_double_range_double_range (GValue * dest,
2324 const GValue * src1, const GValue * src2)
2329 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
2330 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
2333 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
2334 gst_value_set_double_range (dest, min, max);
2338 g_value_init (dest, G_TYPE_DOUBLE);
2339 g_value_set_int (dest, (int) min);
2347 gst_value_intersect_list (GValue * dest, const GValue * value1,
2348 const GValue * value2)
2351 GValue intersection = { 0, };
2352 gboolean ret = FALSE;
2354 size = gst_value_list_get_size (value1);
2355 for (i = 0; i < size; i++) {
2356 const GValue *cur = gst_value_list_get_value (value1, i);
2358 if (gst_value_intersect (&intersection, cur, value2)) {
2361 gst_value_init_and_copy (dest, &intersection);
2363 } else if (GST_VALUE_HOLDS_LIST (dest)) {
2364 gst_value_list_append_value (dest, &intersection);
2366 GValue temp = { 0, };
2368 gst_value_init_and_copy (&temp, dest);
2369 g_value_unset (dest);
2370 gst_value_list_concat (dest, &temp, &intersection);
2371 g_value_unset (&temp);
2373 g_value_unset (&intersection);
2381 gst_value_intersect_array (GValue * dest, const GValue * src1,
2382 const GValue * src2)
2388 /* only works on similar-sized arrays */
2389 size = gst_value_array_get_size (src1);
2390 if (size != gst_value_array_get_size (src2))
2392 g_value_init (dest, GST_TYPE_ARRAY);
2394 for (n = 0; n < size; n++) {
2395 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
2396 gst_value_array_get_value (src2, n))) {
2397 g_value_unset (dest);
2400 gst_value_array_append_value (dest, &val);
2401 g_value_unset (&val);
2408 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
2409 const GValue * src2)
2413 GstValueCompareFunc compare;
2415 vals = src2->data[0].v_pointer;
2420 if ((compare = gst_value_get_compare_func (src1))) {
2421 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
2422 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
2424 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
2425 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
2426 gst_value_init_and_copy (dest, src1);
2435 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
2436 const GValue * src1, const GValue * src2)
2441 GValue *vals1, *vals2;
2442 GstValueCompareFunc compare;
2444 vals1 = src1->data[0].v_pointer;
2445 vals2 = src2->data[0].v_pointer;
2446 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
2448 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
2449 /* min = MAX (src1.start, src2.start) */
2450 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
2451 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2452 if (res == GST_VALUE_LESS_THAN)
2453 min = &vals2[0]; /* Take the max of the 2 */
2457 /* max = MIN (src1.end, src2.end) */
2458 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
2459 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2460 if (res == GST_VALUE_GREATER_THAN)
2461 max = &vals2[1]; /* Take the min of the 2 */
2465 res = gst_value_compare_with_func (min, max, compare);
2466 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2467 if (res == GST_VALUE_LESS_THAN) {
2468 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
2469 vals1 = dest->data[0].v_pointer;
2470 g_value_copy (min, &vals1[0]);
2471 g_value_copy (max, &vals1[1]);
2474 if (res == GST_VALUE_EQUAL) {
2475 gst_value_init_and_copy (dest, min);
2488 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
2489 const GValue * subtrahend)
2491 int min = gst_value_get_int_range_min (subtrahend);
2492 int max = gst_value_get_int_range_max (subtrahend);
2493 int val = g_value_get_int (minuend);
2495 /* subtracting a range from an int only works if the int is not in the
2497 if (val < min || val > max) {
2498 /* and the result is the int */
2499 gst_value_init_and_copy (dest, minuend);
2505 /* creates a new int range based on input values.
2508 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
2513 GValue *pv1, *pv2; /* yeah, hungarian! */
2515 if (min1 <= max1 && min2 <= max2) {
2518 } else if (min1 <= max1) {
2521 } else if (min2 <= max2) {
2529 g_value_init (pv1, GST_TYPE_INT_RANGE);
2530 gst_value_set_int_range (pv1, min1, max1);
2531 } else if (min1 == max1) {
2532 g_value_init (pv1, G_TYPE_INT);
2533 g_value_set_int (pv1, min1);
2536 g_value_init (pv2, GST_TYPE_INT_RANGE);
2537 gst_value_set_int_range (pv2, min2, max2);
2538 } else if (min2 == max2) {
2539 g_value_init (pv2, G_TYPE_INT);
2540 g_value_set_int (pv2, min2);
2543 if (min1 <= max1 && min2 <= max2) {
2544 gst_value_list_concat (dest, pv1, pv2);
2545 g_value_unset (pv1);
2546 g_value_unset (pv2);
2552 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
2553 const GValue * subtrahend)
2555 gint min = gst_value_get_int_range_min (minuend);
2556 gint max = gst_value_get_int_range_max (minuend);
2557 gint val = g_value_get_int (subtrahend);
2559 g_return_val_if_fail (min < max, FALSE);
2561 /* value is outside of the range, return range unchanged */
2562 if (val < min || val > max) {
2563 gst_value_init_and_copy (dest, minuend);
2566 /* max must be MAXINT too as val <= max */
2567 if (val == G_MAXINT) {
2571 /* min must be MININT too as val >= max */
2572 if (val == G_MININT) {
2576 gst_value_create_new_range (dest, min, val - 1, val + 1, max);
2582 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
2583 const GValue * subtrahend)
2585 gint min1 = gst_value_get_int_range_min (minuend);
2586 gint max1 = gst_value_get_int_range_max (minuend);
2587 gint min2 = gst_value_get_int_range_min (subtrahend);
2588 gint max2 = gst_value_get_int_range_max (subtrahend);
2590 if (max2 == G_MAXINT && min2 == G_MININT) {
2592 } else if (max2 == G_MAXINT) {
2593 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0);
2594 } else if (min2 == G_MININT) {
2595 return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0);
2597 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
2598 MAX (max2 + 1, min1), max1);
2603 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
2604 const GValue * subtrahend)
2606 gdouble min = gst_value_get_double_range_min (subtrahend);
2607 gdouble max = gst_value_get_double_range_max (subtrahend);
2608 gdouble val = g_value_get_double (minuend);
2610 if (val < min || val > max) {
2611 gst_value_init_and_copy (dest, minuend);
2618 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
2619 const GValue * subtrahend)
2621 /* since we don't have open ranges, we cannot create a hole in
2622 * a double range. We return the original range */
2623 gst_value_init_and_copy (dest, minuend);
2628 gst_value_subtract_double_range_double_range (GValue * dest,
2629 const GValue * minuend, const GValue * subtrahend)
2631 /* since we don't have open ranges, we have to approximate */
2632 /* done like with ints */
2633 gdouble min1 = gst_value_get_double_range_min (minuend);
2634 gdouble max2 = gst_value_get_double_range_max (minuend);
2635 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
2636 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
2639 GValue *pv1, *pv2; /* yeah, hungarian! */
2641 if (min1 < max1 && min2 < max2) {
2644 } else if (min1 < max1) {
2647 } else if (min2 < max2) {
2655 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
2656 gst_value_set_double_range (pv1, min1, max1);
2659 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
2660 gst_value_set_double_range (pv2, min2, max2);
2663 if (min1 < max1 && min2 < max2) {
2664 gst_value_list_concat (dest, pv1, pv2);
2665 g_value_unset (pv1);
2666 g_value_unset (pv2);
2672 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
2673 const GValue * subtrahend)
2676 GValue subtraction = { 0, };
2677 gboolean ret = FALSE;
2680 ltype = gst_value_list_get_type ();
2682 size = gst_value_list_get_size (minuend);
2683 for (i = 0; i < size; i++) {
2684 const GValue *cur = gst_value_list_get_value (minuend, i);
2686 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
2688 gst_value_init_and_copy (dest, &subtraction);
2690 } else if (G_VALUE_HOLDS (dest, ltype)
2691 && !G_VALUE_HOLDS (&subtraction, ltype)) {
2692 gst_value_list_append_value (dest, &subtraction);
2694 GValue temp = { 0, };
2696 gst_value_init_and_copy (&temp, dest);
2697 g_value_unset (dest);
2698 gst_value_list_concat (dest, &temp, &subtraction);
2699 g_value_unset (&temp);
2701 g_value_unset (&subtraction);
2708 gst_value_subtract_list (GValue * dest, const GValue * minuend,
2709 const GValue * subtrahend)
2712 GValue data[2] = { {0,}, {0,} };
2713 GValue *subtraction = &data[0], *result = &data[1];
2715 gst_value_init_and_copy (result, minuend);
2716 size = gst_value_list_get_size (subtrahend);
2717 for (i = 0; i < size; i++) {
2718 const GValue *cur = gst_value_list_get_value (subtrahend, i);
2720 if (gst_value_subtract (subtraction, result, cur)) {
2721 GValue *temp = result;
2723 result = subtraction;
2725 g_value_unset (subtraction);
2727 g_value_unset (result);
2731 gst_value_init_and_copy (dest, result);
2732 g_value_unset (result);
2737 gst_value_subtract_fraction_fraction_range (GValue * dest,
2738 const GValue * minuend, const GValue * subtrahend)
2740 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
2741 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
2742 GstValueCompareFunc compare;
2744 if ((compare = gst_value_get_compare_func (minuend))) {
2745 /* subtracting a range from an fraction only works if the fraction
2746 * is not in the range */
2747 if (gst_value_compare_with_func (minuend, min, compare) ==
2748 GST_VALUE_LESS_THAN ||
2749 gst_value_compare_with_func (minuend, max, compare) ==
2750 GST_VALUE_GREATER_THAN) {
2751 /* and the result is the value */
2752 gst_value_init_and_copy (dest, minuend);
2760 gst_value_subtract_fraction_range_fraction (GValue * dest,
2761 const GValue * minuend, const GValue * subtrahend)
2763 /* since we don't have open ranges, we cannot create a hole in
2764 * a range. We return the original range */
2765 gst_value_init_and_copy (dest, minuend);
2770 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
2771 const GValue * minuend, const GValue * subtrahend)
2773 /* since we don't have open ranges, we have to approximate */
2774 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
2775 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
2776 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
2777 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
2778 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
2782 GValue *pv1, *pv2; /* yeah, hungarian! */
2783 GstValueCompareFunc compare;
2785 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
2786 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
2788 compare = gst_value_get_compare_func (min1);
2789 g_return_val_if_fail (compare, FALSE);
2791 cmp1 = gst_value_compare_with_func (max2, max1, compare);
2792 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
2793 if (cmp1 == GST_VALUE_LESS_THAN)
2795 cmp1 = gst_value_compare_with_func (min1, min2, compare);
2796 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
2797 if (cmp1 == GST_VALUE_GREATER_THAN)
2800 cmp1 = gst_value_compare_with_func (min1, max1, compare);
2801 cmp2 = gst_value_compare_with_func (min2, max2, compare);
2803 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
2806 } else if (cmp1 == GST_VALUE_LESS_THAN) {
2809 } else if (cmp2 == GST_VALUE_LESS_THAN) {
2816 if (cmp1 == GST_VALUE_LESS_THAN) {
2817 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
2818 gst_value_set_fraction_range (pv1, min1, max1);
2820 if (cmp2 == GST_VALUE_LESS_THAN) {
2821 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
2822 gst_value_set_fraction_range (pv2, min2, max2);
2825 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
2826 gst_value_list_concat (dest, pv1, pv2);
2827 g_value_unset (pv1);
2828 g_value_unset (pv2);
2839 * gst_value_get_compare_func:
2840 * @value1: a value to get the compare function for
2842 * Determines the compare function to be used with values of the same type as
2843 * @value1. The function can be given to gst_value_compare_with_func().
2845 * Returns: A #GstValueCompareFunc value
2847 static GstValueCompareFunc
2848 gst_value_get_compare_func (const GValue * value1)
2850 GstValueTable *table, *best = NULL;
2854 type1 = G_VALUE_TYPE (value1);
2856 /* this is a fast check */
2857 best = gst_value_hash_lookup_type (type1);
2860 if (G_UNLIKELY (!best || !best->compare)) {
2861 guint len = gst_value_table->len;
2864 for (i = 0; i < len; i++) {
2865 table = &g_array_index (gst_value_table, GstValueTable, i);
2866 if (table->compare && g_type_is_a (type1, table->type)) {
2867 if (!best || g_type_is_a (table->type, best->type))
2872 if (G_LIKELY (best))
2873 return best->compare;
2879 * gst_value_can_compare:
2880 * @value1: a value to compare
2881 * @value2: another value to compare
2883 * Determines if @value1 and @value2 can be compared.
2885 * Returns: TRUE if the values can be compared
2888 gst_value_can_compare (const GValue * value1, const GValue * value2)
2890 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2893 return gst_value_get_compare_func (value1) != NULL;
2897 * gst_value_compare:
2898 * @value1: a value to compare
2899 * @value2: another value to compare
2901 * Compares @value1 and @value2. If @value1 and @value2 cannot be
2902 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
2903 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned.
2904 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned.
2905 * If the values are equal, GST_VALUE_EQUAL is returned.
2907 * Returns: A #GstValueCompareType value
2910 gst_value_compare (const GValue * value1, const GValue * value2)
2912 GstValueCompareFunc compare;
2914 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2915 return GST_VALUE_UNORDERED;
2917 compare = gst_value_get_compare_func (value1);
2919 return compare (value1, value2);
2922 g_critical ("unable to compare values of type %s\n",
2923 g_type_name (G_VALUE_TYPE (value1)));
2924 return GST_VALUE_UNORDERED;
2928 * gst_value_compare_with_func:
2929 * @value1: a value to compare
2930 * @value2: another value to compare
2931 * @compare: compare function
2933 * Compares @value1 and @value2 using the @compare function. Works like
2934 * gst_value_compare() but allows to save time determining the compare function
2937 * Returns: A #GstValueCompareType value
2940 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
2941 GstValueCompareFunc compare)
2945 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2946 return GST_VALUE_UNORDERED;
2948 return compare (value1, value2);
2954 * gst_value_can_union:
2955 * @value1: a value to union
2956 * @value2: another value to union
2958 * Determines if @value1 and @value2 can be non-trivially unioned.
2959 * Any two values can be trivially unioned by adding both of them
2960 * to a GstValueList. However, certain types have the possibility
2961 * to be unioned in a simpler way. For example, an integer range
2962 * and an integer can be unioned if the integer is a subset of the
2963 * integer range. If there is the possibility that two values can
2964 * be unioned, this function returns TRUE.
2966 * Returns: TRUE if there is a function allowing the two values to
2970 gst_value_can_union (const GValue * value1, const GValue * value2)
2972 GstValueUnionInfo *union_info;
2975 len = gst_value_union_funcs->len;
2977 for (i = 0; i < len; i++) {
2978 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
2979 if (union_info->type1 == G_VALUE_TYPE (value1) &&
2980 union_info->type2 == G_VALUE_TYPE (value2))
2982 if (union_info->type1 == G_VALUE_TYPE (value2) &&
2983 union_info->type2 == G_VALUE_TYPE (value1))
2992 * @dest: the destination value
2993 * @value1: a value to union
2994 * @value2: another value to union
2996 * Creates a GValue corresponding to the union of @value1 and @value2.
2998 * Returns: always returns %TRUE
3000 /* FIXME: change return type to 'void'? */
3002 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
3004 GstValueUnionInfo *union_info;
3007 len = gst_value_union_funcs->len;
3009 for (i = 0; i < len; i++) {
3010 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
3011 if (union_info->type1 == G_VALUE_TYPE (value1) &&
3012 union_info->type2 == G_VALUE_TYPE (value2)) {
3013 if (union_info->func (dest, value1, value2)) {
3017 if (union_info->type1 == G_VALUE_TYPE (value2) &&
3018 union_info->type2 == G_VALUE_TYPE (value1)) {
3019 if (union_info->func (dest, value2, value1)) {
3025 gst_value_list_concat (dest, value1, value2);
3030 * gst_value_register_union_func:
3031 * @type1: a type to union
3032 * @type2: another type to union
3033 * @func: a function that implments creating a union between the two types
3035 * Registers a union function that can create a union between GValues
3036 * of the type @type1 and @type2.
3038 * Union functions should be registered at startup before any pipelines are
3039 * started, as gst_value_register_union_func() is not thread-safe and cannot
3040 * be used at the same time as gst_value_union() or gst_value_can_union().
3043 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
3045 GstValueUnionInfo union_info;
3047 union_info.type1 = type1;
3048 union_info.type2 = type2;
3049 union_info.func = func;
3051 g_array_append_val (gst_value_union_funcs, union_info);
3057 * gst_value_can_intersect:
3058 * @value1: a value to intersect
3059 * @value2: another value to intersect
3061 * Determines if intersecting two values will produce a valid result.
3062 * Two values will produce a valid intersection if they have the same
3063 * type, or if there is a method (registered by
3064 * gst_value_register_intersection_func()) to calculate the intersection.
3066 * Returns: TRUE if the values can intersect
3069 gst_value_can_intersect (const GValue * value1, const GValue * value2)
3071 GstValueIntersectInfo *intersect_info;
3073 GType ltype, type1, type2;
3075 ltype = gst_value_list_get_type ();
3078 if (G_VALUE_HOLDS (value1, ltype) || G_VALUE_HOLDS (value2, ltype))
3081 type1 = G_VALUE_TYPE (value1);
3082 type2 = G_VALUE_TYPE (value2);
3084 /* practically all GstValue types have a compare function (_can_compare=TRUE)
3085 * GstStructure and GstCaps have npot, but are intersectable */
3089 /* check registered intersect functions */
3090 len = gst_value_intersect_funcs->len;
3091 for (i = 0; i < len; i++) {
3092 intersect_info = &g_array_index (gst_value_intersect_funcs,
3093 GstValueIntersectInfo, i);
3094 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
3095 (intersect_info->type1 == type2 && intersect_info->type2 == type1))
3099 return gst_value_can_compare (value1, value2);
3103 * gst_value_intersect:
3104 * @dest: a uninitialized #GValue that will hold the calculated
3105 * intersection value
3106 * @value1: a value to intersect
3107 * @value2: another value to intersect
3109 * Calculates the intersection of two values. If the values have
3110 * a non-empty intersection, the value representing the intersection
3111 * is placed in @dest. If the intersection is non-empty, @dest is
3114 * Returns: TRUE if the intersection is non-empty
3117 gst_value_intersect (GValue * dest, const GValue * value1,
3118 const GValue * value2)
3120 GstValueIntersectInfo *intersect_info;
3122 GType ltype, type1, type2;
3124 ltype = gst_value_list_get_type ();
3126 /* special cases first */
3127 if (G_VALUE_HOLDS (value1, ltype))
3128 return gst_value_intersect_list (dest, value1, value2);
3129 if (G_VALUE_HOLDS (value2, ltype))
3130 return gst_value_intersect_list (dest, value2, value1);
3132 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
3133 gst_value_init_and_copy (dest, value1);
3137 type1 = G_VALUE_TYPE (value1);
3138 type2 = G_VALUE_TYPE (value2);
3140 len = gst_value_intersect_funcs->len;
3141 for (i = 0; i < len; i++) {
3142 intersect_info = &g_array_index (gst_value_intersect_funcs,
3143 GstValueIntersectInfo, i);
3144 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
3145 return intersect_info->func (dest, value1, value2);
3147 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
3148 return intersect_info->func (dest, value2, value1);
3155 * gst_value_register_intersect_func:
3156 * @type1: the first type to intersect
3157 * @type2: the second type to intersect
3158 * @func: the intersection function
3160 * Registers a function that is called to calculate the intersection
3161 * of the values having the types @type1 and @type2.
3163 * Intersect functions should be registered at startup before any pipelines are
3164 * started, as gst_value_register_intersect_func() is not thread-safe and
3165 * cannot be used at the same time as gst_value_intersect() or
3166 * gst_value_can_intersect().
3169 gst_value_register_intersect_func (GType type1, GType type2,
3170 GstValueIntersectFunc func)
3172 GstValueIntersectInfo intersect_info;
3174 intersect_info.type1 = type1;
3175 intersect_info.type2 = type2;
3176 intersect_info.func = func;
3178 g_array_append_val (gst_value_intersect_funcs, intersect_info);
3185 * gst_value_subtract:
3186 * @dest: the destination value for the result if the subtraction is not empty
3187 * @minuend: the value to subtract from
3188 * @subtrahend: the value to subtract
3190 * Subtracts @subtrahend from @minuend and stores the result in @dest.
3191 * Note that this means subtraction as in sets, not as in mathematics.
3193 * Returns: %TRUE if the subtraction is not empty
3196 gst_value_subtract (GValue * dest, const GValue * minuend,
3197 const GValue * subtrahend)
3199 GstValueSubtractInfo *info;
3201 GType ltype, mtype, stype;
3203 ltype = gst_value_list_get_type ();
3205 /* special cases first */
3206 if (G_VALUE_HOLDS (minuend, ltype))
3207 return gst_value_subtract_from_list (dest, minuend, subtrahend);
3208 if (G_VALUE_HOLDS (subtrahend, ltype))
3209 return gst_value_subtract_list (dest, minuend, subtrahend);
3211 mtype = G_VALUE_TYPE (minuend);
3212 stype = G_VALUE_TYPE (subtrahend);
3214 len = gst_value_subtract_funcs->len;
3215 for (i = 0; i < len; i++) {
3216 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
3217 if (info->minuend == mtype && info->subtrahend == stype) {
3218 return info->func (dest, minuend, subtrahend);
3222 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
3223 gst_value_init_and_copy (dest, minuend);
3232 gst_value_subtract (GValue * dest, const GValue * minuend,
3233 const GValue * subtrahend)
3235 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
3237 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
3238 gst_value_serialize (subtrahend),
3239 ret ? gst_value_serialize (dest) : "---");
3245 * gst_value_can_subtract:
3246 * @minuend: the value to subtract from
3247 * @subtrahend: the value to subtract
3249 * Checks if it's possible to subtract @subtrahend from @minuend.
3251 * Returns: TRUE if a subtraction is possible
3254 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
3256 GstValueSubtractInfo *info;
3258 GType ltype, mtype, stype;
3260 ltype = gst_value_list_get_type ();
3263 if (G_VALUE_HOLDS (minuend, ltype) || G_VALUE_HOLDS (subtrahend, ltype))
3266 mtype = G_VALUE_TYPE (minuend);
3267 stype = G_VALUE_TYPE (subtrahend);
3269 len = gst_value_subtract_funcs->len;
3270 for (i = 0; i < len; i++) {
3271 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
3272 if (info->minuend == mtype && info->subtrahend == stype)
3276 return gst_value_can_compare (minuend, subtrahend);
3280 * gst_value_register_subtract_func:
3281 * @minuend_type: type of the minuend
3282 * @subtrahend_type: type of the subtrahend
3283 * @func: function to use
3285 * Registers @func as a function capable of subtracting the values of
3286 * @subtrahend_type from values of @minuend_type.
3288 * Subtract functions should be registered at startup before any pipelines are
3289 * started, as gst_value_register_subtract_func() is not thread-safe and
3290 * cannot be used at the same time as gst_value_subtract().
3293 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
3294 GstValueSubtractFunc func)
3296 GstValueSubtractInfo info;
3298 /* one type must be unfixed, other subtractions can be done as comparisons */
3299 g_return_if_fail (!gst_type_is_fixed (minuend_type)
3300 || !gst_type_is_fixed (subtrahend_type));
3302 info.minuend = minuend_type;
3303 info.subtrahend = subtrahend_type;
3306 g_array_append_val (gst_value_subtract_funcs, info);
3310 * gst_value_register:
3311 * @table: structure containing functions to register
3313 * Registers functions to perform calculations on #GValues of a given
3314 * type. Each type can only be added once.
3317 gst_value_register (const GstValueTable * table)
3319 GstValueTable *found;
3321 g_array_append_val (gst_value_table, *table);
3323 found = gst_value_hash_lookup_type (table->type);
3325 g_warning ("adding type %s multiple times", g_type_name (table->type));
3327 /* FIXME: we're not really doing the const justice, we assume the table is
3329 gst_value_hash_add_type (table->type, table);
3333 * gst_value_init_and_copy:
3334 * @dest: the target value
3335 * @src: the source value
3337 * Initialises the target value to be of the same type as source and then copies
3338 * the contents from source to target.
3341 gst_value_init_and_copy (GValue * dest, const GValue * src)
3343 g_value_init (dest, G_VALUE_TYPE (src));
3344 g_value_copy (src, dest);
3348 * gst_value_serialize:
3349 * @value: a #GValue to serialize
3351 * tries to transform the given @value into a string representation that allows
3352 * getting back this string later on using gst_value_deserialize().
3354 * Returns: the serialization for @value or NULL if none exists
3357 gst_value_serialize (const GValue * value)
3360 GValue s_val = { 0 };
3361 GstValueTable *table, *best;
3365 g_return_val_if_fail (G_IS_VALUE (value), NULL);
3367 type = G_VALUE_TYPE (value);
3369 best = gst_value_hash_lookup_type (type);
3371 if (G_UNLIKELY (!best || !best->serialize)) {
3372 len = gst_value_table->len;
3374 for (i = 0; i < len; i++) {
3375 table = &g_array_index (gst_value_table, GstValueTable, i);
3376 if (table->serialize && g_type_is_a (type, table->type)) {
3377 if (!best || g_type_is_a (table->type, best->type))
3382 if (G_LIKELY (best))
3383 return best->serialize (value);
3385 g_value_init (&s_val, G_TYPE_STRING);
3386 if (g_value_transform (value, &s_val)) {
3387 s = gst_string_wrap (g_value_get_string (&s_val));
3391 g_value_unset (&s_val);
3397 * gst_value_deserialize:
3398 * @dest: #GValue to fill with contents of deserialization
3399 * @src: string to deserialize
3401 * Tries to deserialize a string into the type specified by the given GValue.
3402 * If the operation succeeds, TRUE is returned, FALSE otherwise.
3404 * Returns: TRUE on success
3407 gst_value_deserialize (GValue * dest, const gchar * src)
3409 GstValueTable *table, *best;
3413 g_return_val_if_fail (src != NULL, FALSE);
3414 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
3416 type = G_VALUE_TYPE (dest);
3418 best = gst_value_hash_lookup_type (type);
3419 if (G_UNLIKELY (!best || !best->deserialize)) {
3420 len = gst_value_table->len;
3422 for (i = 0; i < len; i++) {
3423 table = &g_array_index (gst_value_table, GstValueTable, i);
3424 if (table->deserialize && g_type_is_a (type, table->type)) {
3425 if (!best || g_type_is_a (table->type, best->type))
3430 if (G_LIKELY (best))
3431 return best->deserialize (dest, src);
3437 * gst_value_is_fixed:
3438 * @value: the #GValue to check
3440 * Tests if the given GValue, if available in a GstStructure (or any other
3441 * container) contains a "fixed" (which means: one value) or an "unfixed"
3442 * (which means: multiple possible values, such as data lists or data
3445 * Returns: true if the value is "fixed".
3449 gst_value_is_fixed (const GValue * value)
3451 GType type = G_VALUE_TYPE (value);
3453 /* the most common types are just basic plain glib types */
3454 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
3458 if (type == GST_TYPE_ARRAY) {
3462 /* check recursively */
3463 size = gst_value_array_get_size (value);
3464 for (n = 0; n < size; n++) {
3465 kid = gst_value_array_get_value (value, n);
3466 if (!gst_value_is_fixed (kid))
3471 return gst_type_is_fixed (type);
3478 /* helper functions */
3480 gst_value_init_fraction (GValue * value)
3482 value->data[0].v_int = 0;
3483 value->data[1].v_int = 1;
3487 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
3489 dest_value->data[0].v_int = src_value->data[0].v_int;
3490 dest_value->data[1].v_int = src_value->data[1].v_int;
3494 gst_value_collect_fraction (GValue * value, guint n_collect_values,
3495 GTypeCValue * collect_values, guint collect_flags)
3497 gst_value_set_fraction (value,
3498 collect_values[0].v_int, collect_values[1].v_int);
3504 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
3505 GTypeCValue * collect_values, guint collect_flags)
3507 gint *numerator = collect_values[0].v_pointer;
3508 gint *denominator = collect_values[1].v_pointer;
3511 return g_strdup_printf ("numerator for `%s' passed as NULL",
3512 G_VALUE_TYPE_NAME (value));
3514 return g_strdup_printf ("denominator for `%s' passed as NULL",
3515 G_VALUE_TYPE_NAME (value));
3517 *numerator = value->data[0].v_int;
3518 *denominator = value->data[1].v_int;
3524 * gst_value_set_fraction:
3525 * @value: a GValue initialized to #GST_TYPE_FRACTION
3526 * @numerator: the numerator of the fraction
3527 * @denominator: the denominator of the fraction
3529 * Sets @value to the fraction specified by @numerator over @denominator.
3530 * The fraction gets reduced to the smallest numerator and denominator,
3531 * and if necessary the sign is moved to the numerator.
3534 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
3538 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
3539 g_return_if_fail (denominator != 0);
3540 g_return_if_fail (denominator >= -G_MAXINT);
3541 g_return_if_fail (numerator >= -G_MAXINT);
3543 /* normalize sign */
3544 if (denominator < 0) {
3545 numerator = -numerator;
3546 denominator = -denominator;
3549 /* check for reduction */
3550 gcd = gst_util_greatest_common_divisor (numerator, denominator);
3556 g_assert (denominator > 0);
3558 value->data[0].v_int = numerator;
3559 value->data[1].v_int = denominator;
3563 * gst_value_get_fraction_numerator:
3564 * @value: a GValue initialized to #GST_TYPE_FRACTION
3566 * Gets the numerator of the fraction specified by @value.
3568 * Returns: the numerator of the fraction.
3571 gst_value_get_fraction_numerator (const GValue * value)
3573 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
3575 return value->data[0].v_int;
3579 * gst_value_get_fraction_denominator:
3580 * @value: a GValue initialized to #GST_TYPE_FRACTION
3582 * Gets the denominator of the fraction specified by @value.
3584 * Returns: the denominator of the fraction.
3587 gst_value_get_fraction_denominator (const GValue * value)
3589 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
3591 return value->data[1].v_int;
3595 * gst_value_fraction_multiply:
3596 * @product: a GValue initialized to #GST_TYPE_FRACTION
3597 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
3598 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
3600 * Multiplies the two GValues containing a GstFraction and sets @product
3601 * to the product of the two fractions.
3603 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
3606 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
3607 const GValue * factor2)
3609 gint n1, n2, d1, d2;
3612 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
3613 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
3615 n1 = factor1->data[0].v_int;
3616 n2 = factor2->data[0].v_int;
3617 d1 = factor1->data[1].v_int;
3618 d2 = factor2->data[1].v_int;
3620 if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
3623 gst_value_set_fraction (product, res_n, res_d);
3629 * gst_value_fraction_subtract:
3630 * @dest: a GValue initialized to #GST_TYPE_FRACTION
3631 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
3632 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
3634 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
3636 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
3639 gst_value_fraction_subtract (GValue * dest,
3640 const GValue * minuend, const GValue * subtrahend)
3642 gint n1, n2, d1, d2;
3645 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
3646 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
3648 n1 = minuend->data[0].v_int;
3649 n2 = subtrahend->data[0].v_int;
3650 d1 = minuend->data[1].v_int;
3651 d2 = subtrahend->data[1].v_int;
3653 if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d))
3655 gst_value_set_fraction (dest, res_n, res_d);
3661 gst_value_serialize_fraction (const GValue * value)
3663 gint32 numerator = value->data[0].v_int;
3664 gint32 denominator = value->data[1].v_int;
3665 gboolean positive = TRUE;
3667 /* get the sign and make components absolute */
3668 if (numerator < 0) {
3669 numerator = -numerator;
3670 positive = !positive;
3672 if (denominator < 0) {
3673 denominator = -denominator;
3674 positive = !positive;
3677 return g_strdup_printf ("%s%d/%d",
3678 positive ? "" : "-", numerator, denominator);
3682 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
3686 if (G_UNLIKELY (s == NULL))
3689 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
3692 if (sscanf (s, "%d/%d", &num, &den) == 2) {
3693 gst_value_set_fraction (dest, num, den);
3696 if (sscanf (s, "%d", &num) == 1) {
3697 gst_value_set_fraction (dest, num, 1);
3700 if (g_ascii_strcasecmp (s, "min") == 0) {
3701 gst_value_set_fraction (dest, -G_MAXINT, 1);
3703 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3704 gst_value_set_fraction (dest, G_MAXINT, 1);
3712 gst_value_transform_fraction_string (const GValue * src_value,
3713 GValue * dest_value)
3715 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
3719 gst_value_transform_string_fraction (const GValue * src_value,
3720 GValue * dest_value)
3722 if (!gst_value_deserialize_fraction (dest_value,
3723 src_value->data[0].v_pointer))
3724 /* If the deserialize fails, ensure we leave the fraction in a
3725 * valid, if incorrect, state */
3726 gst_value_set_fraction (dest_value, 0, 1);
3730 gst_value_transform_double_fraction (const GValue * src_value,
3731 GValue * dest_value)
3733 gdouble src = g_value_get_double (src_value);
3736 gst_util_double_to_fraction (src, &n, &d);
3737 gst_value_set_fraction (dest_value, n, d);
3741 gst_value_transform_float_fraction (const GValue * src_value,
3742 GValue * dest_value)
3744 gfloat src = g_value_get_float (src_value);
3747 gst_util_double_to_fraction (src, &n, &d);
3748 gst_value_set_fraction (dest_value, n, d);
3752 gst_value_transform_fraction_double (const GValue * src_value,
3753 GValue * dest_value)
3755 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
3756 ((double) src_value->data[1].v_int);
3760 gst_value_transform_fraction_float (const GValue * src_value,
3761 GValue * dest_value)
3763 dest_value->data[0].v_float = ((float) src_value->data[0].v_int) /
3764 ((float) src_value->data[1].v_int);
3768 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
3776 n1 = value1->data[0].v_int;
3777 n2 = value2->data[0].v_int;
3778 d1 = value1->data[1].v_int;
3779 d2 = value2->data[1].v_int;
3781 /* fractions are reduced when set, so we can quickly see if they're equal */
3782 if (n1 == n2 && d1 == d2)
3783 return GST_VALUE_EQUAL;
3785 /* extend to 64 bits */
3786 new_num_1 = ((gint64) n1) * d2;
3787 new_num_2 = ((gint64) n2) * d1;
3788 if (new_num_1 < new_num_2)
3789 return GST_VALUE_LESS_THAN;
3790 if (new_num_1 > new_num_2)
3791 return GST_VALUE_GREATER_THAN;
3793 /* new_num_1 == new_num_2 implies that both denominators must have
3794 * been 0, beause otherwise simplification would have caught the
3796 return GST_VALUE_UNORDERED;
3804 * gst_value_set_date:
3805 * @value: a GValue initialized to GST_TYPE_DATE
3806 * @date: the date to set the value to
3808 * Sets the contents of @value to coorespond to @date. The actual
3809 * #GDate structure is copied before it is used.
3812 gst_value_set_date (GValue * value, const GDate * date)
3814 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE);
3815 g_return_if_fail (g_date_valid (date));
3817 g_value_set_boxed (value, date);
3821 * gst_value_get_date:
3822 * @value: a GValue initialized to GST_TYPE_DATE
3824 * Gets the contents of @value.
3826 * Returns: the contents of @value
3829 gst_value_get_date (const GValue * value)
3831 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE, NULL);
3833 return (const GDate *) g_value_get_boxed (value);
3837 gst_date_copy (gpointer boxed)
3839 const GDate *date = (const GDate *) boxed;
3841 if (!g_date_valid (date)) {
3842 GST_WARNING ("invalid GDate");
3846 return g_date_new_julian (g_date_get_julian (date));
3850 gst_value_compare_date (const GValue * value1, const GValue * value2)
3852 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
3853 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
3857 return GST_VALUE_EQUAL;
3859 if ((date1 == NULL || !g_date_valid (date1))
3860 && (date2 != NULL && g_date_valid (date2))) {
3861 return GST_VALUE_LESS_THAN;
3864 if ((date2 == NULL || !g_date_valid (date2))
3865 && (date1 != NULL && g_date_valid (date1))) {
3866 return GST_VALUE_GREATER_THAN;
3869 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
3870 || !g_date_valid (date2)) {
3871 return GST_VALUE_UNORDERED;
3874 j1 = g_date_get_julian (date1);
3875 j2 = g_date_get_julian (date2);
3878 return GST_VALUE_EQUAL;
3880 return GST_VALUE_LESS_THAN;
3882 return GST_VALUE_GREATER_THAN;
3886 gst_value_serialize_date (const GValue * val)
3888 const GDate *date = (const GDate *) g_value_get_boxed (val);
3890 if (date == NULL || !g_date_valid (date))
3891 return g_strdup ("9999-99-99");
3893 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
3894 g_date_get_month (date), g_date_get_day (date));
3898 gst_value_deserialize_date (GValue * dest, const char *s)
3900 guint year, month, day;
3902 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
3905 if (!g_date_valid_dmy (day, month, year))
3908 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
3913 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
3915 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
3919 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
3921 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
3925 gst_value_transform_object_string (const GValue * src_value,
3926 GValue * dest_value)
3931 obj = g_value_get_object (src_value);
3934 g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
3935 GST_OBJECT_NAME (obj));
3937 str = g_strdup ("NULL");
3940 dest_value->data[0].v_pointer = str;
3943 static GTypeInfo _info = {
3956 static GTypeFundamentalInfo _finfo = {
3960 #define FUNC_VALUE_GET_TYPE(type, name) \
3961 GType gst_ ## type ## _get_type (void) \
3963 static GType gst_ ## type ## _type = 0; \
3965 if (G_UNLIKELY (gst_ ## type ## _type == 0)) { \
3966 _info.value_table = & _gst_ ## type ## _value_table; \
3967 gst_ ## type ## _type = g_type_register_fundamental ( \
3968 g_type_fundamental_next (), \
3969 name, &_info, &_finfo, 0); \
3972 return gst_ ## type ## _type; \
3975 static const GTypeValueTable _gst_fourcc_value_table = {
3976 gst_value_init_fourcc,
3978 gst_value_copy_fourcc,
3981 gst_value_collect_fourcc,
3983 gst_value_lcopy_fourcc
3986 FUNC_VALUE_GET_TYPE (fourcc, "GstFourcc");
3988 static const GTypeValueTable _gst_int_range_value_table = {
3989 gst_value_init_int_range,
3991 gst_value_copy_int_range,
3994 gst_value_collect_int_range,
3996 gst_value_lcopy_int_range
3999 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
4001 static const GTypeValueTable _gst_double_range_value_table = {
4002 gst_value_init_double_range,
4004 gst_value_copy_double_range,
4007 gst_value_collect_double_range,
4009 gst_value_lcopy_double_range
4012 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
4014 static const GTypeValueTable _gst_fraction_range_value_table = {
4015 gst_value_init_fraction_range,
4016 gst_value_free_fraction_range,
4017 gst_value_copy_fraction_range,
4020 gst_value_collect_fraction_range,
4022 gst_value_lcopy_fraction_range
4025 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
4027 static const GTypeValueTable _gst_value_list_value_table = {
4028 gst_value_init_list_or_array,
4029 gst_value_free_list_or_array,
4030 gst_value_copy_list_or_array,
4031 gst_value_list_or_array_peek_pointer,
4033 gst_value_collect_list_or_array,
4035 gst_value_lcopy_list_or_array
4038 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
4040 static const GTypeValueTable _gst_value_array_value_table = {
4041 gst_value_init_list_or_array,
4042 gst_value_free_list_or_array,
4043 gst_value_copy_list_or_array,
4044 gst_value_list_or_array_peek_pointer,
4046 gst_value_collect_list_or_array,
4048 gst_value_lcopy_list_or_array
4051 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
4053 static const GTypeValueTable _gst_fraction_value_table = {
4054 gst_value_init_fraction,
4056 gst_value_copy_fraction,
4059 gst_value_collect_fraction,
4061 gst_value_lcopy_fraction
4064 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
4068 gst_date_get_type (void)
4070 static GType gst_date_type = 0;
4072 if (G_UNLIKELY (gst_date_type == 0)) {
4073 /* FIXME 0.11: we require GLib 2.8 already
4074 * Not using G_TYPE_DATE here on purpose, even if we could
4075 * if GLIB_CHECK_VERSION(2,8,0) was true: we don't want the
4076 * serialised strings to have different type strings depending
4077 * on what version is used, so FIXME when we require GLib-2.8 */
4078 gst_date_type = g_boxed_type_register_static ("GstDate",
4079 (GBoxedCopyFunc) gst_date_copy, (GBoxedFreeFunc) g_date_free);
4082 return gst_date_type;
4086 _gst_value_initialize (void)
4088 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
4089 gst_value_hash = g_hash_table_new (NULL, NULL);
4090 gst_value_union_funcs = g_array_new (FALSE, FALSE,
4091 sizeof (GstValueUnionInfo));
4092 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
4093 sizeof (GstValueIntersectInfo));
4094 gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
4095 sizeof (GstValueSubtractInfo));
4098 static GstValueTable gst_value = {
4100 gst_value_compare_fourcc,
4101 gst_value_serialize_fourcc,
4102 gst_value_deserialize_fourcc,
4105 gst_value.type = gst_fourcc_get_type ();
4106 gst_value_register (&gst_value);
4110 static GstValueTable gst_value = {
4112 gst_value_compare_int_range,
4113 gst_value_serialize_int_range,
4114 gst_value_deserialize_int_range,
4117 gst_value.type = gst_int_range_get_type ();
4118 gst_value_register (&gst_value);
4122 static GstValueTable gst_value = {
4124 gst_value_compare_double_range,
4125 gst_value_serialize_double_range,
4126 gst_value_deserialize_double_range,
4129 gst_value.type = gst_double_range_get_type ();
4130 gst_value_register (&gst_value);
4134 static GstValueTable gst_value = {
4136 gst_value_compare_fraction_range,
4137 gst_value_serialize_fraction_range,
4138 gst_value_deserialize_fraction_range,
4141 gst_value.type = gst_fraction_range_get_type ();
4142 gst_value_register (&gst_value);
4146 static GstValueTable gst_value = {
4148 gst_value_compare_list,
4149 gst_value_serialize_list,
4150 gst_value_deserialize_list,
4153 gst_value.type = gst_value_list_get_type ();
4154 gst_value_register (&gst_value);
4158 static GstValueTable gst_value = {
4160 gst_value_compare_array,
4161 gst_value_serialize_array,
4162 gst_value_deserialize_array,
4165 gst_value.type = gst_value_array_get_type ();
4166 gst_value_register (&gst_value);
4171 static const GTypeValueTable value_table = {
4172 gst_value_init_buffer,
4174 gst_value_copy_buffer,
4177 NULL, /*gst_value_collect_buffer, */
4179 NULL /*gst_value_lcopy_buffer */
4182 static GstValueTable gst_value = {
4184 gst_value_compare_buffer,
4185 gst_value_serialize_buffer,
4186 gst_value_deserialize_buffer,
4189 gst_value.type = GST_TYPE_BUFFER;
4190 gst_value_register (&gst_value);
4193 static GstValueTable gst_value = {
4195 gst_value_compare_fraction,
4196 gst_value_serialize_fraction,
4197 gst_value_deserialize_fraction,
4200 gst_value.type = gst_fraction_get_type ();
4201 gst_value_register (&gst_value);
4204 static GstValueTable gst_value = {
4207 gst_value_serialize_caps,
4208 gst_value_deserialize_caps,
4211 gst_value.type = GST_TYPE_CAPS;
4212 gst_value_register (&gst_value);
4215 static GstValueTable gst_value = {
4218 gst_value_serialize_structure,
4219 gst_value_deserialize_structure,
4222 gst_value.type = GST_TYPE_STRUCTURE;
4223 gst_value_register (&gst_value);
4226 static GstValueTable gst_value = {
4228 gst_value_compare_date,
4229 gst_value_serialize_date,
4230 gst_value_deserialize_date,
4233 gst_value.type = gst_date_get_type ();
4234 gst_value_register (&gst_value);
4237 REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
4238 REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
4240 REGISTER_SERIALIZATION (G_TYPE_STRING, string);
4241 REGISTER_SERIALIZATION (G_TYPE_BOOLEAN, boolean);
4242 REGISTER_SERIALIZATION (G_TYPE_ENUM, enum);
4244 REGISTER_SERIALIZATION (G_TYPE_FLAGS, flags);
4246 REGISTER_SERIALIZATION (G_TYPE_INT, int);
4248 REGISTER_SERIALIZATION (G_TYPE_INT64, int64);
4249 REGISTER_SERIALIZATION (G_TYPE_LONG, long);
4251 REGISTER_SERIALIZATION (G_TYPE_UINT, uint);
4252 REGISTER_SERIALIZATION (G_TYPE_UINT64, uint64);
4253 REGISTER_SERIALIZATION (G_TYPE_ULONG, ulong);
4255 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
4256 gst_value_transform_fourcc_string);
4257 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
4258 gst_value_transform_int_range_string);
4259 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
4260 gst_value_transform_double_range_string);
4261 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
4262 gst_value_transform_fraction_range_string);
4263 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
4264 gst_value_transform_list_string);
4265 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
4266 gst_value_transform_array_string);
4267 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
4268 gst_value_transform_fraction_string);
4269 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
4270 gst_value_transform_string_fraction);
4271 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
4272 gst_value_transform_fraction_double);
4273 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT,
4274 gst_value_transform_fraction_float);
4275 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
4276 gst_value_transform_double_fraction);
4277 g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
4278 gst_value_transform_float_fraction);
4279 g_value_register_transform_func (GST_TYPE_DATE, G_TYPE_STRING,
4280 gst_value_transform_date_string);
4281 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_DATE,
4282 gst_value_transform_string_date);
4283 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
4284 gst_value_transform_object_string);
4286 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4287 gst_value_intersect_int_int_range);
4288 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4289 gst_value_intersect_int_range_int_range);
4290 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
4291 gst_value_intersect_double_double_range);
4292 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
4293 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
4294 gst_value_register_intersect_func (GST_TYPE_ARRAY,
4295 GST_TYPE_ARRAY, gst_value_intersect_array);
4296 gst_value_register_intersect_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4297 gst_value_intersect_fraction_fraction_range);
4298 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
4299 GST_TYPE_FRACTION_RANGE,
4300 gst_value_intersect_fraction_range_fraction_range);
4302 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4303 gst_value_subtract_int_int_range);
4304 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
4305 gst_value_subtract_int_range_int);
4306 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4307 gst_value_subtract_int_range_int_range);
4308 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
4309 gst_value_subtract_double_double_range);
4310 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
4311 gst_value_subtract_double_range_double);
4312 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
4313 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
4315 gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4316 gst_value_subtract_fraction_fraction_range);
4317 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION,
4318 gst_value_subtract_fraction_range_fraction);
4319 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
4320 GST_TYPE_FRACTION_RANGE,
4321 gst_value_subtract_fraction_range_fraction_range);
4323 /* see bug #317246, #64994, #65041 */
4325 volatile GType date_type = G_TYPE_DATE;
4327 g_type_name (date_type);
4330 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4331 gst_value_union_int_int_range);
4332 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4333 gst_value_union_int_range_int_range);
4336 /* Implement these if needed */
4337 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4338 gst_value_union_fraction_fraction_range);
4339 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
4340 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);