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 to GStreamer
24 * GValue implementations specific to GStreamer.
26 * Note that operations on the same GstValue (or GValue) from multiple
27 * threads may lead to undefined behaviour.
29 * Last reviewed on 2006-03-07 (0.10.4)
40 #include "gst_private.h"
41 #include "glib-compat-private.h"
43 #include <gobject/gvaluecollector.h>
45 typedef struct _GstValueUnionInfo GstValueUnionInfo;
46 struct _GstValueUnionInfo
50 GstValueUnionFunc func;
53 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
54 struct _GstValueIntersectInfo
58 GstValueIntersectFunc func;
61 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
62 struct _GstValueSubtractInfo
66 GstValueSubtractFunc func;
69 GType gst_type_double_range;
70 GType gst_type_fraction_range;
73 GType gst_type_fraction;
76 static GArray *gst_value_table;
77 static GArray *gst_value_union_funcs;
78 static GArray *gst_value_intersect_funcs;
79 static GArray *gst_value_subtract_funcs;
81 /* Forward declarations */
82 static gint gst_greatest_common_divisor (gint a, gint b);
83 static gchar *gst_value_serialize_fraction (const GValue * value);
89 /* two helper functions to serialize/stringify any type of list
90 * regular lists are done with { }, arrays with < >
93 gst_value_serialize_any_list (const GValue * value, const gchar * begin,
97 GArray *array = value->data[0].v_pointer;
102 s = g_string_new (begin);
103 for (i = 0; i < array->len; i++) {
104 v = &g_array_index (array, GValue, i);
105 s_val = gst_value_serialize (v);
106 g_string_append (s, s_val);
108 if (i < array->len - 1) {
109 g_string_append (s, ", ");
112 g_string_append (s, end);
113 return g_string_free (s, FALSE);
117 gst_value_transform_any_list_string (const GValue * src_value,
118 GValue * dest_value, const gchar * begin, const gchar * end)
126 array = src_value->data[0].v_pointer;
128 s = g_string_new (begin);
129 for (i = 0; i < array->len; i++) {
130 list_value = &g_array_index (array, GValue, i);
133 g_string_append (s, ", ");
135 list_s = g_strdup_value_contents (list_value);
136 g_string_append (s, list_s);
139 g_string_append (s, end);
141 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
145 * helper function to see if a type is fixed. Is used internally here and
146 * there. Do not export, since it doesn't work for types where the content
147 * decides the fixedness (e.g. GST_TYPE_ARRAY).
151 gst_type_is_fixed (GType type)
153 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
154 type == GST_TYPE_LIST) {
157 if (G_TYPE_FUNDAMENTAL (type) <=
158 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
161 if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC
162 || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) {
169 /* GValue functions usable for both regular lists and arrays */
171 gst_value_init_list_or_array (GValue * value)
173 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
177 copy_garray_of_gstvalue (const GArray * src)
182 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
183 g_array_set_size (dest, src->len);
184 for (i = 0; i < src->len; i++) {
185 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
186 &g_array_index (src, GValue, i));
193 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
195 dest_value->data[0].v_pointer =
196 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
200 gst_value_free_list_or_array (GValue * value)
203 GArray *src = (GArray *) value->data[0].v_pointer;
205 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
206 for (i = 0; i < src->len; i++) {
207 g_value_unset (&g_array_index (src, GValue, i));
209 g_array_free (src, TRUE);
214 gst_value_list_or_array_peek_pointer (const GValue * value)
216 return value->data[0].v_pointer;
220 gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
221 GTypeCValue * collect_values, guint collect_flags)
223 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
224 value->data[0].v_pointer = collect_values[0].v_pointer;
225 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
227 value->data[0].v_pointer =
228 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
234 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
235 GTypeCValue * collect_values, guint collect_flags)
237 GArray **dest = collect_values[0].v_pointer;
240 return g_strdup_printf ("value location for `%s' passed as NULL",
241 G_VALUE_TYPE_NAME (value));
242 if (!value->data[0].v_pointer)
243 return g_strdup_printf ("invalid value given for `%s'",
244 G_VALUE_TYPE_NAME (value));
245 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
246 *dest = (GArray *) value->data[0].v_pointer;
248 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
254 * gst_value_list_append_value:
255 * @value: a #GValue of type #GST_TYPE_LIST
256 * @append_value: the value to append
258 * Appends @append_value to the GstValueList in @value.
261 gst_value_list_append_value (GValue * value, const GValue * append_value)
265 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
267 gst_value_init_and_copy (&val, append_value);
268 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
272 * gst_value_list_prepend_value:
273 * @value: a #GValue of type #GST_TYPE_LIST
274 * @prepend_value: the value to prepend
276 * Prepends @prepend_value to the GstValueList in @value.
279 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
283 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
285 gst_value_init_and_copy (&val, prepend_value);
286 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
290 * gst_value_list_concat:
291 * @dest: an uninitialized #GValue to take the result
295 * Concatenates copies of @value1 and @value2 into a list. Values that are not
296 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
297 * @dest will be initialized to the type #GST_TYPE_LIST.
300 gst_value_list_concat (GValue * dest, const GValue * value1,
301 const GValue * value2)
303 guint i, value1_length, value2_length;
306 g_return_if_fail (dest != NULL);
307 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
308 g_return_if_fail (G_IS_VALUE (value1));
309 g_return_if_fail (G_IS_VALUE (value2));
312 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
314 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
315 g_value_init (dest, GST_TYPE_LIST);
316 array = (GArray *) dest->data[0].v_pointer;
317 g_array_set_size (array, value1_length + value2_length);
319 if (GST_VALUE_HOLDS_LIST (value1)) {
320 for (i = 0; i < value1_length; i++) {
321 gst_value_init_and_copy (&g_array_index (array, GValue, i),
322 gst_value_list_get_value (value1, i));
325 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
328 if (GST_VALUE_HOLDS_LIST (value2)) {
329 for (i = 0; i < value2_length; i++) {
330 gst_value_init_and_copy (&g_array_index (array, GValue,
331 i + value1_length), gst_value_list_get_value (value2, i));
334 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
340 * gst_value_list_get_size:
341 * @value: a #GValue of type #GST_TYPE_LIST
343 * Gets the number of values contained in @value.
345 * Returns: the number of values
348 gst_value_list_get_size (const GValue * value)
350 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
352 return ((GArray *) value->data[0].v_pointer)->len;
356 * gst_value_list_get_value:
357 * @value: a #GValue of type #GST_TYPE_LIST
358 * @index: index of value to get from the list
360 * Gets the value that is a member of the list contained in @value and
361 * has the index @index.
363 * Returns: the value at the given index
366 gst_value_list_get_value (const GValue * value, guint index)
368 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
369 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
371 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
376 * gst_value_array_append_value:
377 * @value: a #GValue of type #GST_TYPE_ARRAY
378 * @append_value: the value to append
380 * Appends @append_value to the GstValueArray in @value.
383 gst_value_array_append_value (GValue * value, const GValue * append_value)
387 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
389 gst_value_init_and_copy (&val, append_value);
390 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
394 * gst_value_array_prepend_value:
395 * @value: a #GValue of type #GST_TYPE_ARRAY
396 * @prepend_value: the value to prepend
398 * Prepends @prepend_value to the GstValueArray in @value.
401 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
405 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
407 gst_value_init_and_copy (&val, prepend_value);
408 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
412 * gst_value_array_get_size:
413 * @value: a #GValue of type #GST_TYPE_ARRAY
415 * Gets the number of values contained in @value.
417 * Returns: the number of values
420 gst_value_array_get_size (const GValue * value)
422 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
424 return ((GArray *) value->data[0].v_pointer)->len;
428 * gst_value_array_get_value:
429 * @value: a #GValue of type #GST_TYPE_ARRAY
430 * @index: index of value to get from the array
432 * Gets the value that is a member of the array contained in @value and
433 * has the index @index.
435 * Returns: the value at the given index
438 gst_value_array_get_value (const GValue * value, guint index)
440 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
441 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
443 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
448 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
450 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
454 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
456 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
459 /* Do an unordered compare of the contents of a list */
461 gst_value_compare_list (const GValue * value1, const GValue * value2)
464 GArray *array1 = value1->data[0].v_pointer;
465 GArray *array2 = value2->data[0].v_pointer;
470 GstValueCompareFunc compare;
472 /* get length and do initial length check. */
474 if (len != array2->len)
475 return GST_VALUE_UNORDERED;
477 /* place to mark removed value indices of array2 */
478 removed = g_newa (guint8, len);
479 memset (removed, 0, len);
482 /* loop over array1, all items should be in array2. When we find an
483 * item in array2, remove it from array2 by marking it as removed */
484 for (i = 0; i < len; i++) {
485 v1 = &g_array_index (array1, GValue, i);
486 if ((compare = gst_value_get_compare_func (v1))) {
487 for (j = 0; j < len; j++) {
488 /* item is removed, we can skip it */
491 v2 = &g_array_index (array2, GValue, j);
492 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
493 /* mark item as removed now that we found it in array2 and
494 * decrement the number of remaining items in array2. */
500 /* item in array1 and not in array2, UNORDERED */
502 return GST_VALUE_UNORDERED;
504 return GST_VALUE_UNORDERED;
506 /* if not all items were removed, array2 contained something not in array1 */
508 return GST_VALUE_UNORDERED;
510 /* arrays are equal */
511 return GST_VALUE_EQUAL;
514 /* Perform an ordered comparison of the contents of an array */
516 gst_value_compare_array (const GValue * value1, const GValue * value2)
519 GArray *array1 = value1->data[0].v_pointer;
520 GArray *array2 = value2->data[0].v_pointer;
524 if (array1->len != array2->len)
525 return GST_VALUE_UNORDERED;
527 for (i = 0; i < array1->len; i++) {
528 v1 = &g_array_index (array1, GValue, i);
529 v2 = &g_array_index (array2, GValue, i);
530 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
531 return GST_VALUE_UNORDERED;
534 return GST_VALUE_EQUAL;
538 gst_value_serialize_list (const GValue * value)
540 return gst_value_serialize_any_list (value, "{ ", " }");
544 gst_value_deserialize_list (GValue * dest, const gchar * s)
546 g_warning ("unimplemented");
551 gst_value_serialize_array (const GValue * value)
553 return gst_value_serialize_any_list (value, "< ", " >");
557 gst_value_deserialize_array (GValue * dest, const gchar * s)
559 g_warning ("unimplemented");
568 gst_value_init_fourcc (GValue * value)
570 value->data[0].v_int = 0;
574 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
576 dest_value->data[0].v_int = src_value->data[0].v_int;
580 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
581 GTypeCValue * collect_values, guint collect_flags)
583 value->data[0].v_int = collect_values[0].v_int;
589 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
590 GTypeCValue * collect_values, guint collect_flags)
592 guint32 *fourcc_p = collect_values[0].v_pointer;
595 return g_strdup_printf ("value location for `%s' passed as NULL",
596 G_VALUE_TYPE_NAME (value));
598 *fourcc_p = value->data[0].v_int;
604 * gst_value_set_fourcc:
605 * @value: a GValue initialized to #GST_TYPE_FOURCC
606 * @fourcc: the #guint32 fourcc to set
608 * Sets @value to @fourcc.
611 gst_value_set_fourcc (GValue * value, guint32 fourcc)
613 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
615 value->data[0].v_int = fourcc;
619 * gst_value_get_fourcc:
620 * @value: a GValue initialized to #GST_TYPE_FOURCC
622 * Gets the #guint32 fourcc contained in @value.
624 * Returns: the #guint32 fourcc contained in @value.
627 gst_value_get_fourcc (const GValue * value)
629 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
631 return value->data[0].v_int;
635 gst_value_transform_fourcc_string (const GValue * src_value,
638 guint32 fourcc = src_value->data[0].v_int;
640 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
641 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
642 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
643 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
644 dest_value->data[0].v_pointer =
645 g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
647 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
652 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
654 if (value2->data[0].v_int == value1->data[0].v_int)
655 return GST_VALUE_EQUAL;
656 return GST_VALUE_UNORDERED;
660 gst_value_serialize_fourcc (const GValue * value)
662 guint32 fourcc = value->data[0].v_int;
664 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
665 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
666 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
667 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
668 return g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
670 return g_strdup_printf ("0x%08x", fourcc);
675 gst_value_deserialize_fourcc (GValue * dest, const char *s)
677 gboolean ret = FALSE;
681 if (strlen (s) == 4) {
682 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
684 } else if (g_ascii_isdigit (*s)) {
685 fourcc = strtoul (s, &end, 0);
690 gst_value_set_fourcc (dest, fourcc);
700 gst_value_init_int_range (GValue * value)
702 value->data[0].v_int = 0;
703 value->data[1].v_int = 0;
707 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
709 dest_value->data[0].v_int = src_value->data[0].v_int;
710 dest_value->data[1].v_int = src_value->data[1].v_int;
714 gst_value_collect_int_range (GValue * value, guint n_collect_values,
715 GTypeCValue * collect_values, guint collect_flags)
717 value->data[0].v_int = collect_values[0].v_int;
718 value->data[1].v_int = collect_values[1].v_int;
724 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
725 GTypeCValue * collect_values, guint collect_flags)
727 guint32 *int_range_start = collect_values[0].v_pointer;
728 guint32 *int_range_end = collect_values[1].v_pointer;
730 if (!int_range_start)
731 return g_strdup_printf ("start value location for `%s' passed as NULL",
732 G_VALUE_TYPE_NAME (value));
734 return g_strdup_printf ("end value location for `%s' passed as NULL",
735 G_VALUE_TYPE_NAME (value));
737 *int_range_start = value->data[0].v_int;
738 *int_range_end = value->data[1].v_int;
744 * gst_value_set_int_range:
745 * @value: a GValue initialized to GST_TYPE_INT_RANGE
746 * @start: the start of the range
747 * @end: the end of the range
749 * Sets @value to the range specified by @start and @end.
752 gst_value_set_int_range (GValue * value, gint start, gint end)
754 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
755 g_return_if_fail (start < end);
757 value->data[0].v_int = start;
758 value->data[1].v_int = end;
762 * gst_value_get_int_range_min:
763 * @value: a GValue initialized to GST_TYPE_INT_RANGE
765 * Gets the minimum of the range specified by @value.
767 * Returns: the minimum of the range
770 gst_value_get_int_range_min (const GValue * value)
772 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
774 return value->data[0].v_int;
778 * gst_value_get_int_range_max:
779 * @value: a GValue initialized to GST_TYPE_INT_RANGE
781 * Gets the maximum of the range specified by @value.
783 * Returns: the maxumum of the range
786 gst_value_get_int_range_max (const GValue * value)
788 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
790 return value->data[1].v_int;
794 gst_value_transform_int_range_string (const GValue * src_value,
797 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
798 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
802 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
804 if (value2->data[0].v_int == value1->data[0].v_int &&
805 value2->data[1].v_int == value1->data[1].v_int)
806 return GST_VALUE_EQUAL;
807 return GST_VALUE_UNORDERED;
811 gst_value_serialize_int_range (const GValue * value)
813 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
814 value->data[1].v_int);
818 gst_value_deserialize_int_range (GValue * dest, const gchar * s)
820 g_warning ("unimplemented");
829 gst_value_init_double_range (GValue * value)
831 value->data[0].v_double = 0;
832 value->data[1].v_double = 0;
836 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
838 dest_value->data[0].v_double = src_value->data[0].v_double;
839 dest_value->data[1].v_double = src_value->data[1].v_double;
843 gst_value_collect_double_range (GValue * value, guint n_collect_values,
844 GTypeCValue * collect_values, guint collect_flags)
846 value->data[0].v_double = collect_values[0].v_double;
847 value->data[1].v_double = collect_values[1].v_double;
853 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
854 GTypeCValue * collect_values, guint collect_flags)
856 gdouble *double_range_start = collect_values[0].v_pointer;
857 gdouble *double_range_end = collect_values[1].v_pointer;
859 if (!double_range_start)
860 return g_strdup_printf ("start value location for `%s' passed as NULL",
861 G_VALUE_TYPE_NAME (value));
862 if (!double_range_end)
863 return g_strdup_printf ("end value location for `%s' passed as NULL",
864 G_VALUE_TYPE_NAME (value));
866 *double_range_start = value->data[0].v_double;
867 *double_range_end = value->data[1].v_double;
873 * gst_value_set_double_range:
874 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
875 * @start: the start of the range
876 * @end: the end of the range
878 * Sets @value to the range specified by @start and @end.
881 gst_value_set_double_range (GValue * value, gdouble start, gdouble end)
883 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
885 value->data[0].v_double = start;
886 value->data[1].v_double = end;
890 * gst_value_get_double_range_min:
891 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
893 * Gets the minimum of the range specified by @value.
895 * Returns: the minumum of the range
898 gst_value_get_double_range_min (const GValue * value)
900 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
902 return value->data[0].v_double;
906 * gst_value_get_double_range_max:
907 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
909 * Gets the maximum of the range specified by @value.
911 * Returns: the maxumum of the range
914 gst_value_get_double_range_max (const GValue * value)
916 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
918 return value->data[1].v_double;
922 gst_value_transform_double_range_string (const GValue * src_value,
925 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
927 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
928 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
929 src_value->data[0].v_double),
930 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
931 src_value->data[1].v_double));
935 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
937 if (value2->data[0].v_double == value1->data[0].v_double &&
938 value2->data[0].v_double == value1->data[0].v_double)
939 return GST_VALUE_EQUAL;
940 return GST_VALUE_UNORDERED;
944 gst_value_serialize_double_range (const GValue * value)
946 char d1[G_ASCII_DTOSTR_BUF_SIZE];
947 char d2[G_ASCII_DTOSTR_BUF_SIZE];
949 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
950 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
951 return g_strdup_printf ("[ %s, %s ]", d1, d2);
955 gst_value_deserialize_double_range (GValue * dest, const gchar * s)
957 g_warning ("unimplemented");
966 gst_value_init_fraction_range (GValue * value)
970 value->data[0].v_pointer = vals = g_new0 (GValue, 2);
971 g_value_init (&vals[0], GST_TYPE_FRACTION);
972 g_value_init (&vals[1], GST_TYPE_FRACTION);
976 gst_value_free_fraction_range (GValue * value)
978 GValue *vals = (GValue *) value->data[0].v_pointer;
981 g_value_unset (&vals[0]);
982 g_value_unset (&vals[1]);
984 value->data[0].v_pointer = NULL;
989 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value)
991 GValue *vals = (GValue *) dest_value->data[0].v_pointer;
992 GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
995 dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2);
996 g_return_if_fail (vals != NULL);
997 g_value_init (&vals[0], GST_TYPE_FRACTION);
998 g_value_init (&vals[1], GST_TYPE_FRACTION);
1001 if (src_vals != NULL) {
1002 g_value_copy (&src_vals[0], &vals[0]);
1003 g_value_copy (&src_vals[1], &vals[1]);
1008 gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
1009 GTypeCValue * collect_values, guint collect_flags)
1011 GValue *vals = (GValue *) value->data[0].v_pointer;
1013 if (n_collect_values != 4)
1014 return g_strdup_printf ("not enough value locations for `%s' passed",
1015 G_VALUE_TYPE_NAME (value));
1017 value->data[0].v_pointer = vals = g_new0 (GValue, 2);
1019 return g_strdup_printf ("Could not initialise`%s' during collect",
1020 G_VALUE_TYPE_NAME (value));
1021 g_value_init (&vals[0], GST_TYPE_FRACTION);
1022 g_value_init (&vals[1], GST_TYPE_FRACTION);
1025 gst_value_set_fraction (&vals[0], collect_values[0].v_int,
1026 collect_values[1].v_int);
1027 gst_value_set_fraction (&vals[1], collect_values[2].v_int,
1028 collect_values[3].v_int);
1034 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
1035 GTypeCValue * collect_values, guint collect_flags)
1038 int *dest_values[4];
1039 GValue *vals = (GValue *) value->data[0].v_pointer;
1041 if (n_collect_values != 4)
1042 return g_strdup_printf ("not enough value locations for `%s' passed",
1043 G_VALUE_TYPE_NAME (value));
1045 for (i = 0; i < 4; i++) {
1046 if (collect_values[i].v_pointer == NULL) {
1047 return g_strdup_printf ("value location for `%s' passed as NULL",
1048 G_VALUE_TYPE_NAME (value));
1050 dest_values[i] = collect_values[i].v_pointer;
1054 return g_strdup_printf ("Uninitialised `%s' passed",
1055 G_VALUE_TYPE_NAME (value));
1058 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
1059 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
1060 dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]);
1061 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
1066 * gst_value_set_fraction_range:
1067 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1068 * @start: the start of the range (a GST_TYPE_FRACTION GValue)
1069 * @end: the end of the range (a GST_TYPE_FRACTION GValue)
1071 * Sets @value to the range specified by @start and @end.
1074 gst_value_set_fraction_range (GValue * value, const GValue * start,
1079 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
1081 vals = (GValue *) value->data[0].v_pointer;
1083 value->data[0].v_pointer = vals = g_new0 (GValue, 2);
1084 g_value_init (&vals[0], GST_TYPE_FRACTION);
1085 g_value_init (&vals[1], GST_TYPE_FRACTION);
1088 g_value_copy (start, &vals[0]);
1089 g_value_copy (end, &vals[1]);
1093 * gst_value_set_fraction_range_full:
1094 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1095 * @numerator_start: the numerator start of the range
1096 * @denominator_start: the denominator start of the range
1097 * @numerator_end: the numerator end of the range
1098 * @denominator_end: the denominator end of the range
1100 * Sets @value to the range specified by @numerator_start/@denominator_start
1101 * and @numerator_end/@denominator_end.
1104 gst_value_set_fraction_range_full (GValue * value,
1105 gint numerator_start, gint denominator_start,
1106 gint numerator_end, gint denominator_end)
1108 GValue start = { 0 };
1111 g_value_init (&start, GST_TYPE_FRACTION);
1112 g_value_init (&end, GST_TYPE_FRACTION);
1114 gst_value_set_fraction (&start, numerator_start, denominator_start);
1115 gst_value_set_fraction (&end, numerator_end, denominator_end);
1116 gst_value_set_fraction_range (value, &start, &end);
1118 g_value_unset (&start);
1119 g_value_unset (&end);
1123 * gst_value_get_fraction_range_min:
1124 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1126 * Gets the minimum of the range specified by @value.
1128 * Returns: the minumum of the range
1131 gst_value_get_fraction_range_min (const GValue * value)
1135 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE);
1137 vals = (GValue *) value->data[0].v_pointer;
1146 * gst_value_get_fraction_range_max:
1147 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1149 * Gets the maximum of the range specified by @value.
1151 * Returns: the maximum of the range
1154 gst_value_get_fraction_range_max (const GValue * value)
1158 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE);
1160 vals = (GValue *) value->data[0].v_pointer;
1169 gst_value_serialize_fraction_range (const GValue * value)
1171 GValue *vals = (GValue *) value->data[0].v_pointer;
1175 retval = g_strdup ("[ 0/1, 0/1 ]");
1179 start = gst_value_serialize_fraction (&vals[0]);
1180 end = gst_value_serialize_fraction (&vals[1]);
1182 retval = g_strdup_printf ("[ %s, %s ]", start, end);
1191 gst_value_transform_fraction_range_string (const GValue * src_value,
1192 GValue * dest_value)
1194 dest_value->data[0].v_pointer =
1195 gst_value_serialize_fraction_range (src_value);
1199 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
1201 GValue *vals1, *vals2;
1202 GstValueCompareFunc compare;
1204 if (value2->data[0].v_pointer == value1->data[0].v_pointer)
1205 return GST_VALUE_EQUAL; /* Only possible if both are NULL */
1207 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL)
1208 return GST_VALUE_UNORDERED;
1210 vals1 = (GValue *) value1->data[0].v_pointer;
1211 vals2 = (GValue *) value2->data[0].v_pointer;
1212 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
1213 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
1215 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
1217 return GST_VALUE_EQUAL;
1219 return GST_VALUE_UNORDERED;
1223 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s)
1225 g_warning ("unimplemented");
1234 * gst_value_set_caps:
1235 * @value: a GValue initialized to GST_TYPE_CAPS
1236 * @caps: the caps to set the value to
1238 * Sets the contents of @value to coorespond to @caps. The actual
1239 * #GstCaps structure is copied before it is used.
1242 gst_value_set_caps (GValue * value, const GstCaps * caps)
1244 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
1246 g_value_set_boxed (value, caps);
1250 * gst_value_get_caps:
1251 * @value: a GValue initialized to GST_TYPE_CAPS
1253 * Gets the contents of @value.
1255 * Returns: the contents of @value
1258 gst_value_get_caps (const GValue * value)
1260 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
1262 return (GstCaps *) g_value_get_boxed (value);
1266 gst_value_serialize_caps (const GValue * value)
1268 GstCaps *caps = g_value_get_boxed (value);
1270 return gst_caps_to_string (caps);
1274 gst_value_deserialize_caps (GValue * dest, const gchar * s)
1278 caps = gst_caps_from_string (s);
1281 g_value_set_boxed (dest, caps);
1293 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
1295 GstBuffer *buf1 = GST_BUFFER (gst_value_get_mini_object (value1));
1296 GstBuffer *buf2 = GST_BUFFER (gst_value_get_mini_object (value2));
1298 if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2))
1299 return GST_VALUE_UNORDERED;
1300 if (GST_BUFFER_SIZE (buf1) == 0)
1301 return GST_VALUE_EQUAL;
1302 g_assert (GST_BUFFER_DATA (buf1));
1303 g_assert (GST_BUFFER_DATA (buf2));
1304 if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2),
1305 GST_BUFFER_SIZE (buf1)) == 0)
1306 return GST_VALUE_EQUAL;
1308 return GST_VALUE_UNORDERED;
1312 gst_value_serialize_buffer (const GValue * value)
1320 buffer = gst_value_get_buffer (value);
1324 data = GST_BUFFER_DATA (buffer);
1325 size = GST_BUFFER_SIZE (buffer);
1327 string = g_malloc (size * 2 + 1);
1328 for (i = 0; i < size; i++) {
1329 sprintf (string + i * 2, "%02x", data[i]);
1331 string[size * 2] = 0;
1337 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
1349 buffer = gst_buffer_new_and_alloc (len / 2);
1350 data = GST_BUFFER_DATA (buffer);
1351 for (i = 0; i < len / 2; i++) {
1352 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
1355 ts[0] = s[i * 2 + 0];
1356 ts[1] = s[i * 2 + 1];
1359 data[i] = (guint8) strtoul (ts, NULL, 16);
1362 gst_value_take_buffer (dest, buffer);
1373 gst_buffer_unref (buffer);
1384 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
1386 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
1387 return GST_VALUE_EQUAL;
1388 return GST_VALUE_UNORDERED;
1392 gst_value_serialize_boolean (const GValue * value)
1394 if (value->data[0].v_int) {
1395 return g_strdup ("true");
1397 return g_strdup ("false");
1401 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
1403 gboolean ret = FALSE;
1405 if (g_ascii_strcasecmp (s, "true") == 0 ||
1406 g_ascii_strcasecmp (s, "yes") == 0 ||
1407 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
1408 g_value_set_boolean (dest, TRUE);
1410 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
1411 g_ascii_strcasecmp (s, "no") == 0 ||
1412 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
1413 g_value_set_boolean (dest, FALSE);
1420 #define CREATE_SERIALIZATION_START(_type,_macro) \
1422 gst_value_compare_ ## _type \
1423 (const GValue * value1, const GValue * value2) \
1425 g ## _type val1 = g_value_get_ ## _type (value1); \
1426 g ## _type val2 = g_value_get_ ## _type (value2); \
1428 return GST_VALUE_GREATER_THAN; \
1430 return GST_VALUE_LESS_THAN; \
1431 return GST_VALUE_EQUAL; \
1435 gst_value_serialize_ ## _type (const GValue * value) \
1437 GValue val = { 0, }; \
1438 g_value_init (&val, G_TYPE_STRING); \
1439 if (!g_value_transform (value, &val)) \
1440 g_assert_not_reached (); \
1441 /* NO_COPY_MADNESS!!! */ \
1442 return (char *) g_value_get_string (&val); \
1445 /* deserialize the given s into to as a gint64.
1446 * check if the result is actually storeable in the given size number of
1450 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
1451 gint64 min, gint64 max, gint size)
1453 gboolean ret = FALSE;
1458 *to = g_ascii_strtoull (s, &end, 0);
1459 /* a range error is a definitive no-no */
1460 if (errno == ERANGE) {
1467 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
1468 *to = G_LITTLE_ENDIAN;
1470 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
1473 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
1476 } else if (g_ascii_strcasecmp (s, "min") == 0) {
1479 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1485 /* by definition, a gint64 fits into a gint64; so ignore those */
1486 if (size != sizeof (mask)) {
1488 /* for positive numbers, we create a mask of 1's outside of the range
1489 * and 0's inside the range. An and will thus keep only 1 bits
1490 * outside of the range */
1491 mask <<= (size * 8);
1492 if ((mask & *to) != 0) {
1496 /* for negative numbers, we do a 2's complement version */
1497 mask <<= ((size * 8) - 1);
1498 if ((mask & *to) != mask) {
1507 #define CREATE_SERIALIZATION(_type,_macro) \
1508 CREATE_SERIALIZATION_START(_type,_macro) \
1511 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
1515 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
1516 G_MAX ## _macro, sizeof (g ## _type))) { \
1517 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
1524 #define CREATE_USERIALIZATION(_type,_macro) \
1525 CREATE_SERIALIZATION_START(_type,_macro) \
1528 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
1532 gboolean ret = FALSE; \
1535 x = g_ascii_strtoull (s, &end, 0); \
1536 /* a range error is a definitive no-no */ \
1537 if (errno == ERANGE) { \
1540 /* the cast ensures the range check later on makes sense */ \
1541 x = (g ## _type) x; \
1545 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
1546 x = G_LITTLE_ENDIAN; \
1548 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
1551 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
1554 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
1557 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
1558 x = G_MAX ## _macro; \
1563 if (x > G_MAX ## _macro) { \
1566 g_value_set_ ## _type (dest, x); \
1572 #define REGISTER_SERIALIZATION(_gtype, _type) \
1574 static const GstValueTable gst_value = { \
1576 gst_value_compare_ ## _type, \
1577 gst_value_serialize_ ## _type, \
1578 gst_value_deserialize_ ## _type, \
1581 gst_value_register (&gst_value); \
1584 CREATE_SERIALIZATION (int, INT);
1585 CREATE_SERIALIZATION (int64, INT64);
1586 CREATE_SERIALIZATION (long, LONG);
1588 CREATE_USERIALIZATION (uint, UINT);
1589 CREATE_USERIALIZATION (uint64, UINT64);
1590 CREATE_USERIALIZATION (ulong, ULONG);
1596 gst_value_compare_double (const GValue * value1, const GValue * value2)
1598 if (value1->data[0].v_double > value2->data[0].v_double)
1599 return GST_VALUE_GREATER_THAN;
1600 if (value1->data[0].v_double < value2->data[0].v_double)
1601 return GST_VALUE_LESS_THAN;
1602 if (value1->data[0].v_double == value2->data[0].v_double)
1603 return GST_VALUE_EQUAL;
1604 return GST_VALUE_UNORDERED;
1608 gst_value_serialize_double (const GValue * value)
1610 char d[G_ASCII_DTOSTR_BUF_SIZE];
1612 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1613 return g_strdup (d);
1617 gst_value_deserialize_double (GValue * dest, const gchar * s)
1620 gboolean ret = FALSE;
1623 x = g_ascii_strtod (s, &end);
1627 if (g_ascii_strcasecmp (s, "min") == 0) {
1630 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1636 g_value_set_double (dest, x);
1646 gst_value_compare_float (const GValue * value1, const GValue * value2)
1648 if (value1->data[0].v_float > value2->data[0].v_float)
1649 return GST_VALUE_GREATER_THAN;
1650 if (value1->data[0].v_float < value2->data[0].v_float)
1651 return GST_VALUE_LESS_THAN;
1652 if (value1->data[0].v_float == value2->data[0].v_float)
1653 return GST_VALUE_EQUAL;
1654 return GST_VALUE_UNORDERED;
1658 gst_value_serialize_float (const GValue * value)
1660 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
1662 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
1663 return g_strdup (d);
1667 gst_value_deserialize_float (GValue * dest, const gchar * s)
1670 gboolean ret = FALSE;
1673 x = g_ascii_strtod (s, &end);
1677 if (g_ascii_strcasecmp (s, "min") == 0) {
1680 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1685 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
1688 g_value_set_float (dest, (float) x);
1698 gst_value_compare_string (const GValue * value1, const GValue * value2)
1700 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
1703 return GST_VALUE_LESS_THAN;
1705 return GST_VALUE_GREATER_THAN;
1706 return GST_VALUE_EQUAL;
1709 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
1710 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
1714 gst_string_wrap (const gchar * s)
1719 gboolean wrap = FALSE;
1726 if (GST_ASCII_IS_STRING (*t)) {
1728 } else if (*t < 0x20 || *t >= 0x7f) {
1739 return g_strdup (s);
1741 e = d = g_malloc (len + 3);
1746 if (GST_ASCII_IS_STRING (*t)) {
1748 } else if (*t < 0x20 || *t >= 0x7f) {
1750 *e++ = '0' + ((*(guchar *) t) >> 6);
1751 *e++ = '0' + (((*t) >> 3) & 0x7);
1752 *e++ = '0' + ((*t++) & 0x7);
1765 * This function takes a string delimited with double quotes (")
1766 * and unescapes any \xxx octal numbers.
1768 * If sequences of \y are found where y is not in the range of
1769 * 0->3, y is copied unescaped.
1771 * If \xyy is found where x is an octal number but y is not, an
1772 * error is encountered and NULL is returned.
1774 * the input string must be \0 terminated.
1777 gst_string_unwrap (const gchar * s)
1780 gchar *read, *write;
1782 /* NULL string returns NULL */
1786 /* strings not starting with " are invalid */
1790 /* make copy of original string to hold the result. This
1791 * string will always be smaller than the original */
1796 /* need to move to the next position as we parsed the " */
1800 if (GST_ASCII_IS_STRING (*read)) {
1801 /* normal chars are just copied */
1803 } else if (*read == '"') {
1804 /* quote marks end of string */
1806 } else if (*read == '\\') {
1807 /* got an escape char, move to next position to read a tripplet
1808 * of octal numbers */
1810 /* is the next char a possible first octal number? */
1811 if (*read >= '0' && *read <= '3') {
1812 /* parse other 2 numbers, if one of them is not in the range of
1813 * an octal number, we error. We also catch the case where a zero
1814 * byte is found here. */
1815 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
1818 /* now convert the octal number to a byte again. */
1819 *write++ = ((read[0] - '0') << 6) +
1820 ((read[1] - '0') << 3) + (read[2] - '0');
1824 /* if we run into a \0 here, we definately won't get a quote later */
1828 /* else copy \X sequence */
1832 /* weird character, error */
1836 /* if the string is not ending in " and zero terminated, we error */
1837 if (*read != '"' || read[1] != '\0')
1840 /* null terminate result string and return */
1850 gst_value_serialize_string (const GValue * value)
1852 return gst_string_wrap (value->data[0].v_pointer);
1856 gst_value_deserialize_string (GValue * dest, const gchar * s)
1859 if (!g_utf8_validate (s, -1, NULL))
1861 g_value_set_string (dest, s);
1864 gchar *str = gst_string_unwrap (s);
1868 g_value_take_string (dest, str);
1879 gst_value_compare_enum (const GValue * value1, const GValue * value2)
1881 GEnumValue *en1, *en2;
1882 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
1883 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
1885 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
1886 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
1887 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
1888 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
1889 g_type_class_unref (klass1);
1890 g_type_class_unref (klass2);
1891 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
1892 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
1893 if (en1->value < en2->value)
1894 return GST_VALUE_LESS_THAN;
1895 if (en1->value > en2->value)
1896 return GST_VALUE_GREATER_THAN;
1898 return GST_VALUE_EQUAL;
1902 gst_value_serialize_enum (const GValue * value)
1905 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
1907 g_return_val_if_fail (klass, NULL);
1908 en = g_enum_get_value (klass, g_value_get_enum (value));
1909 g_type_class_unref (klass);
1910 g_return_val_if_fail (en, NULL);
1911 return g_strdup (en->value_name);
1915 gst_value_deserialize_enum (GValue * dest, const gchar * s)
1918 gchar *endptr = NULL;
1919 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
1921 g_return_val_if_fail (klass, FALSE);
1922 if (!(en = g_enum_get_value_by_name (klass, s))) {
1923 if (!(en = g_enum_get_value_by_nick (klass, s))) {
1924 gint i = strtol (s, &endptr, 0);
1926 if (endptr && *endptr == '\0') {
1927 en = g_enum_get_value (klass, i);
1931 g_type_class_unref (klass);
1932 g_return_val_if_fail (en, FALSE);
1933 g_value_set_enum (dest, en->value);
1941 /* we just compare the value here */
1943 gst_value_compare_flags (const GValue * value1, const GValue * value2)
1946 GFlagsClass *klass1 =
1947 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
1948 GFlagsClass *klass2 =
1949 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
1951 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
1952 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
1953 fl1 = g_value_get_flags (value1);
1954 fl2 = g_value_get_flags (value2);
1955 g_type_class_unref (klass1);
1956 g_type_class_unref (klass2);
1958 return GST_VALUE_LESS_THAN;
1960 return GST_VALUE_GREATER_THAN;
1962 return GST_VALUE_EQUAL;
1965 /* the different flags are serialized separated with a + */
1967 gst_value_serialize_flags (const GValue * value)
1971 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
1972 gchar *result, *tmp;
1973 gboolean first = TRUE;
1975 g_return_val_if_fail (klass, NULL);
1977 flags = g_value_get_flags (value);
1979 /* if no flags are set, try to serialize to the _NONE string */
1981 fl = g_flags_get_first_value (klass, flags);
1982 return g_strdup (fl->value_name);
1985 /* some flags are set, so serialize one by one */
1986 result = g_strdup ("");
1988 fl = g_flags_get_first_value (klass, flags);
1990 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
1996 flags &= ~fl->value;
1999 g_type_class_unref (klass);
2005 gst_value_deserialize_flags (GValue * dest, const gchar * s)
2008 gchar *endptr = NULL;
2009 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
2014 g_return_val_if_fail (klass, FALSE);
2016 /* split into parts delimited with + */
2017 split = g_strsplit (s, "+", 0);
2021 /* loop over each part */
2023 if (!(fl = g_flags_get_value_by_name (klass, split[i]))) {
2024 if (!(fl = g_flags_get_value_by_nick (klass, split[i]))) {
2025 gint val = strtol (split[i], &endptr, 0);
2027 /* just or numeric value */
2028 if (endptr && *endptr == '\0') {
2039 g_type_class_unref (klass);
2040 g_value_set_flags (dest, flags);
2050 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
2051 const GValue * src2)
2053 if (src2->data[0].v_int <= src1->data[0].v_int &&
2054 src2->data[1].v_int >= src1->data[0].v_int) {
2055 gst_value_init_and_copy (dest, src2);
2062 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
2063 const GValue * src2)
2068 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
2069 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
2072 g_value_init (dest, GST_TYPE_INT_RANGE);
2073 gst_value_set_int_range (dest,
2074 MIN (src1->data[0].v_int, src2->data[0].v_int),
2075 MAX (src1->data[1].v_int, src2->data[1].v_int));
2087 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
2088 const GValue * src2)
2090 if (src2->data[0].v_int <= src1->data[0].v_int &&
2091 src2->data[1].v_int >= src1->data[0].v_int) {
2092 gst_value_init_and_copy (dest, src1);
2100 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
2101 const GValue * src2)
2106 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
2107 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
2110 g_value_init (dest, GST_TYPE_INT_RANGE);
2111 gst_value_set_int_range (dest, min, max);
2115 g_value_init (dest, G_TYPE_INT);
2116 g_value_set_int (dest, min);
2124 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
2125 const GValue * src2)
2127 if (src2->data[0].v_double <= src1->data[0].v_double &&
2128 src2->data[1].v_double >= src1->data[0].v_double) {
2129 gst_value_init_and_copy (dest, src1);
2137 gst_value_intersect_double_range_double_range (GValue * dest,
2138 const GValue * src1, const GValue * src2)
2143 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
2144 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
2147 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
2148 gst_value_set_double_range (dest, min, max);
2152 g_value_init (dest, G_TYPE_DOUBLE);
2153 g_value_set_int (dest, (int) min);
2161 gst_value_intersect_list (GValue * dest, const GValue * value1,
2162 const GValue * value2)
2165 GValue intersection = { 0, };
2166 gboolean ret = FALSE;
2168 size = gst_value_list_get_size (value1);
2169 for (i = 0; i < size; i++) {
2170 const GValue *cur = gst_value_list_get_value (value1, i);
2172 if (gst_value_intersect (&intersection, cur, value2)) {
2175 gst_value_init_and_copy (dest, &intersection);
2177 } else if (GST_VALUE_HOLDS_LIST (dest)) {
2178 gst_value_list_append_value (dest, &intersection);
2180 GValue temp = { 0, };
2182 gst_value_init_and_copy (&temp, dest);
2183 g_value_unset (dest);
2184 gst_value_list_concat (dest, &temp, &intersection);
2185 g_value_unset (&temp);
2187 g_value_unset (&intersection);
2195 gst_value_intersect_array (GValue * dest, const GValue * src1,
2196 const GValue * src2)
2202 /* only works on similar-sized arrays */
2203 size = gst_value_array_get_size (src1);
2204 if (size != gst_value_array_get_size (src2))
2206 g_value_init (dest, GST_TYPE_ARRAY);
2208 for (n = 0; n < size; n++) {
2209 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
2210 gst_value_array_get_value (src2, n))) {
2211 g_value_unset (dest);
2214 gst_value_array_append_value (dest, &val);
2215 g_value_unset (&val);
2222 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
2223 const GValue * src2)
2227 GstValueCompareFunc compare;
2229 vals = src2->data[0].v_pointer;
2234 if ((compare = gst_value_get_compare_func (src1))) {
2235 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
2236 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
2238 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
2239 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
2240 gst_value_init_and_copy (dest, src1);
2249 gst_value_intersect_fraction_range_fraction_range
2250 (GValue * dest, const GValue * src1, const GValue * src2)
2255 GValue *vals1, *vals2;
2256 GstValueCompareFunc compare;
2258 vals1 = src1->data[0].v_pointer;
2259 vals2 = src2->data[0].v_pointer;
2260 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
2262 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
2263 /* min = MAX (src1.start, src2.start) */
2264 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
2265 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2266 if (res == GST_VALUE_LESS_THAN)
2267 min = &vals2[0]; /* Take the max of the 2 */
2271 /* max = MIN (src1.end, src2.end) */
2272 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
2273 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2274 if (res == GST_VALUE_GREATER_THAN)
2275 max = &vals2[1]; /* Take the min of the 2 */
2279 res = gst_value_compare_with_func (min, max, compare);
2280 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
2281 if (res == GST_VALUE_LESS_THAN) {
2282 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
2283 vals1 = dest->data[0].v_pointer;
2284 g_value_copy (min, &vals1[0]);
2285 g_value_copy (max, &vals1[1]);
2288 if (res == GST_VALUE_EQUAL) {
2289 gst_value_init_and_copy (dest, min);
2302 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
2303 const GValue * subtrahend)
2305 int min = gst_value_get_int_range_min (subtrahend);
2306 int max = gst_value_get_int_range_max (subtrahend);
2307 int val = g_value_get_int (minuend);
2309 /* subtracting a range from an int only works if the int is not in the
2311 if (val < min || val > max) {
2312 /* and the result is the int */
2313 gst_value_init_and_copy (dest, minuend);
2319 /* creates a new int range based on input values.
2322 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
2327 GValue *pv1, *pv2; /* yeah, hungarian! */
2329 if (min1 <= max1 && min2 <= max2) {
2332 } else if (min1 <= max1) {
2335 } else if (min2 <= max2) {
2343 g_value_init (pv1, GST_TYPE_INT_RANGE);
2344 gst_value_set_int_range (pv1, min1, max1);
2345 } else if (min1 == max1) {
2346 g_value_init (pv1, G_TYPE_INT);
2347 g_value_set_int (pv1, min1);
2350 g_value_init (pv2, GST_TYPE_INT_RANGE);
2351 gst_value_set_int_range (pv2, min2, max2);
2352 } else if (min2 == max2) {
2353 g_value_init (pv2, G_TYPE_INT);
2354 g_value_set_int (pv2, min2);
2357 if (min1 <= max1 && min2 <= max2) {
2358 gst_value_list_concat (dest, pv1, pv2);
2359 g_value_unset (pv1);
2360 g_value_unset (pv2);
2366 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
2367 const GValue * subtrahend)
2369 gint min = gst_value_get_int_range_min (minuend);
2370 gint max = gst_value_get_int_range_max (minuend);
2371 gint val = g_value_get_int (subtrahend);
2373 g_return_val_if_fail (min < max, FALSE);
2375 /* value is outside of the range, return range unchanged */
2376 if (val < min || val > max) {
2377 gst_value_init_and_copy (dest, minuend);
2380 /* max must be MAXINT too as val <= max */
2381 if (val == G_MAXINT) {
2385 /* min must be MININT too as val >= max */
2386 if (val == G_MININT) {
2390 gst_value_create_new_range (dest, min, val - 1, val + 1, max);
2396 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
2397 const GValue * subtrahend)
2399 gint min1 = gst_value_get_int_range_min (minuend);
2400 gint max1 = gst_value_get_int_range_max (minuend);
2401 gint min2 = gst_value_get_int_range_min (subtrahend);
2402 gint max2 = gst_value_get_int_range_max (subtrahend);
2404 if (max2 == G_MAXINT && min2 == G_MININT) {
2406 } else if (max2 == G_MAXINT) {
2407 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0);
2408 } else if (min2 == G_MININT) {
2409 return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0);
2411 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
2412 MAX (max2 + 1, min1), max1);
2417 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
2418 const GValue * subtrahend)
2420 gdouble min = gst_value_get_double_range_min (subtrahend);
2421 gdouble max = gst_value_get_double_range_max (subtrahend);
2422 gdouble val = g_value_get_double (minuend);
2424 if (val < min || val > max) {
2425 gst_value_init_and_copy (dest, minuend);
2432 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
2433 const GValue * subtrahend)
2435 /* since we don't have open ranges, we cannot create a hole in
2436 * a double range. We return the original range */
2437 gst_value_init_and_copy (dest, minuend);
2442 gst_value_subtract_double_range_double_range (GValue * dest,
2443 const GValue * minuend, const GValue * subtrahend)
2445 /* since we don't have open ranges, we have to approximate */
2446 /* done like with ints */
2447 gdouble min1 = gst_value_get_double_range_min (minuend);
2448 gdouble max2 = gst_value_get_double_range_max (minuend);
2449 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
2450 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
2453 GValue *pv1, *pv2; /* yeah, hungarian! */
2455 if (min1 < max1 && min2 < max2) {
2458 } else if (min1 < max1) {
2461 } else if (min2 < max2) {
2469 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
2470 gst_value_set_double_range (pv1, min1, max1);
2473 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
2474 gst_value_set_double_range (pv2, min2, max2);
2477 if (min1 < max1 && min2 < max2) {
2478 gst_value_list_concat (dest, pv1, pv2);
2479 g_value_unset (pv1);
2480 g_value_unset (pv2);
2486 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
2487 const GValue * subtrahend)
2490 GValue subtraction = { 0, };
2491 gboolean ret = FALSE;
2493 size = gst_value_list_get_size (minuend);
2494 for (i = 0; i < size; i++) {
2495 const GValue *cur = gst_value_list_get_value (minuend, i);
2497 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
2499 gst_value_init_and_copy (dest, &subtraction);
2501 } else if (GST_VALUE_HOLDS_LIST (dest)
2502 && GST_VALUE_HOLDS_LIST (&subtraction)) {
2504 GValue unroll = { 0, };
2506 gst_value_init_and_copy (&unroll, dest);
2507 g_value_unset (dest);
2508 gst_value_list_concat (dest, &unroll, &subtraction);
2509 } else if (GST_VALUE_HOLDS_LIST (dest)) {
2510 gst_value_list_append_value (dest, &subtraction);
2512 GValue temp = { 0, };
2514 gst_value_init_and_copy (&temp, dest);
2515 g_value_unset (dest);
2516 gst_value_list_concat (dest, &temp, &subtraction);
2517 g_value_unset (&temp);
2519 g_value_unset (&subtraction);
2526 gst_value_subtract_list (GValue * dest, const GValue * minuend,
2527 const GValue * subtrahend)
2530 GValue data[2] = { {0,}, {0,} };
2531 GValue *subtraction = &data[0], *result = &data[1];
2533 gst_value_init_and_copy (result, minuend);
2534 size = gst_value_list_get_size (subtrahend);
2535 for (i = 0; i < size; i++) {
2536 const GValue *cur = gst_value_list_get_value (subtrahend, i);
2538 if (gst_value_subtract (subtraction, result, cur)) {
2539 GValue *temp = result;
2541 result = subtraction;
2543 g_value_unset (subtraction);
2545 g_value_unset (result);
2549 gst_value_init_and_copy (dest, result);
2550 g_value_unset (result);
2555 gst_value_subtract_fraction_fraction_range (GValue * dest,
2556 const GValue * minuend, const GValue * subtrahend)
2558 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
2559 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
2560 GstValueCompareFunc compare;
2562 if ((compare = gst_value_get_compare_func (minuend))) {
2563 /* subtracting a range from an fraction only works if the fraction
2564 * is not in the range */
2565 if (gst_value_compare_with_func (minuend, min, compare) ==
2566 GST_VALUE_LESS_THAN ||
2567 gst_value_compare_with_func (minuend, max, compare) ==
2568 GST_VALUE_GREATER_THAN) {
2569 /* and the result is the value */
2570 gst_value_init_and_copy (dest, minuend);
2578 gst_value_subtract_fraction_range_fraction (GValue * dest,
2579 const GValue * minuend, const GValue * subtrahend)
2581 /* since we don't have open ranges, we cannot create a hole in
2582 * a range. We return the original range */
2583 gst_value_init_and_copy (dest, minuend);
2588 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
2589 const GValue * minuend, const GValue * subtrahend)
2591 /* since we don't have open ranges, we have to approximate */
2592 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
2593 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
2594 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
2595 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
2596 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
2600 GValue *pv1, *pv2; /* yeah, hungarian! */
2601 GstValueCompareFunc compare;
2603 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
2604 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
2606 compare = gst_value_get_compare_func (min1);
2607 g_return_val_if_fail (compare, FALSE);
2609 cmp1 = gst_value_compare_with_func (max2, max1, compare);
2610 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
2611 if (cmp1 == GST_VALUE_LESS_THAN)
2613 cmp1 = gst_value_compare_with_func (min1, min2, compare);
2614 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
2615 if (cmp1 == GST_VALUE_GREATER_THAN)
2618 cmp1 = gst_value_compare_with_func (min1, max1, compare);
2619 cmp2 = gst_value_compare_with_func (min2, max2, compare);
2621 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
2624 } else if (cmp1 == GST_VALUE_LESS_THAN) {
2627 } else if (cmp2 == GST_VALUE_LESS_THAN) {
2634 if (cmp1 == GST_VALUE_LESS_THAN) {
2635 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
2636 gst_value_set_fraction_range (pv1, min1, max1);
2638 if (cmp2 == GST_VALUE_LESS_THAN) {
2639 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
2640 gst_value_set_fraction_range (pv2, min2, max2);
2643 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
2644 gst_value_list_concat (dest, pv1, pv2);
2645 g_value_unset (pv1);
2646 g_value_unset (pv2);
2657 * gst_value_can_compare:
2658 * @value1: a value to compare
2659 * @value2: another value to compare
2661 * Determines if @value1 and @value2 can be compared.
2663 * Returns: TRUE if the values can be compared
2666 gst_value_can_compare (const GValue * value1, const GValue * value2)
2668 GstValueTable *table;
2671 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2674 for (i = 0; i < gst_value_table->len; i++) {
2675 table = &g_array_index (gst_value_table, GstValueTable, i);
2676 if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare)
2684 * gst_value_get_compare_func:
2685 * @value1: a value to get the compare function for
2687 * Determines the compare function to be used with values of the same type as
2688 * @value1. The function can be given to gst_value_compare_with_func().
2690 * Returns: A #GstValueCompareFunc value
2693 gst_value_get_compare_func (const GValue * value1)
2695 GstValueTable *table, *best = NULL;
2698 for (i = 0; i < gst_value_table->len; i++) {
2699 table = &g_array_index (gst_value_table, GstValueTable, i);
2700 if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) {
2704 if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) {
2705 if (!best || g_type_is_a (table->type, best->type))
2710 return best->compare;
2716 * gst_value_compare:
2717 * @value1: a value to compare
2718 * @value2: another value to compare
2720 * Compares @value1 and @value2. If @value1 and @value2 cannot be
2721 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
2722 * if @value1 is greater than @value2, GST_VALUE_GREATER is returned.
2723 * If @value1 is less than @value2, GST_VALUE_LESSER is returned.
2724 * If the values are equal, GST_VALUE_EQUAL is returned.
2726 * Returns: A #GstValueCompareType value
2729 gst_value_compare (const GValue * value1, const GValue * value2)
2731 GstValueCompareFunc compare;
2733 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2734 return GST_VALUE_UNORDERED;
2736 compare = gst_value_get_compare_func (value1);
2738 return compare (value1, value2);
2741 g_critical ("unable to compare values of type %s\n",
2742 g_type_name (G_VALUE_TYPE (value1)));
2743 return GST_VALUE_UNORDERED;
2747 * gst_value_compare_with_func:
2748 * @value1: a value to compare
2749 * @value2: another value to compare
2750 * @compare: compare function
2752 * Compares @value1 and @value2 using the @compare function. Works like
2753 * gst_value_compare() but allows to save time determining the compare function
2756 * Returns: A #GstValueCompareType value
2759 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
2760 GstValueCompareFunc compare)
2764 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2765 return GST_VALUE_UNORDERED;
2767 return compare (value1, value2);
2773 * gst_value_can_union:
2774 * @value1: a value to union
2775 * @value2: another value to union
2777 * Determines if @value1 and @value2 can be non-trivially unioned.
2778 * Any two values can be trivially unioned by adding both of them
2779 * to a GstValueList. However, certain types have the possibility
2780 * to be unioned in a simpler way. For example, an integer range
2781 * and an integer can be unioned if the integer is a subset of the
2782 * integer range. If there is the possibility that two values can
2783 * be unioned, this function returns TRUE.
2785 * Returns: TRUE if there is a function allowing the two values to
2789 gst_value_can_union (const GValue * value1, const GValue * value2)
2791 GstValueUnionInfo *union_info;
2794 for (i = 0; i < gst_value_union_funcs->len; i++) {
2795 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
2796 if (union_info->type1 == G_VALUE_TYPE (value1) &&
2797 union_info->type2 == G_VALUE_TYPE (value2))
2799 if (union_info->type1 == G_VALUE_TYPE (value2) &&
2800 union_info->type2 == G_VALUE_TYPE (value1))
2809 * @dest: the destination value
2810 * @value1: a value to union
2811 * @value2: another value to union
2813 * Creates a GValue cooresponding to the union of @value1 and @value2.
2815 * Returns: always returns %TRUE
2817 /* FIXME: change return type to 'void'? */
2819 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
2821 GstValueUnionInfo *union_info;
2824 for (i = 0; i < gst_value_union_funcs->len; i++) {
2825 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
2826 if (union_info->type1 == G_VALUE_TYPE (value1) &&
2827 union_info->type2 == G_VALUE_TYPE (value2)) {
2828 if (union_info->func (dest, value1, value2)) {
2832 if (union_info->type1 == G_VALUE_TYPE (value2) &&
2833 union_info->type2 == G_VALUE_TYPE (value1)) {
2834 if (union_info->func (dest, value2, value1)) {
2840 gst_value_list_concat (dest, value1, value2);
2845 * gst_value_register_union_func:
2846 * @type1: a type to union
2847 * @type2: another type to union
2848 * @func: a function that implments creating a union between the two types
2850 * Registers a union function that can create a union between GValues
2851 * of the type @type1 and @type2.
2853 * Union functions should be registered at startup before any pipelines are
2854 * started, as gst_value_register_union_func() is not thread-safe and cannot
2855 * be used at the same time as gst_value_union() or gst_value_can_union().
2858 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
2860 GstValueUnionInfo union_info;
2862 union_info.type1 = type1;
2863 union_info.type2 = type2;
2864 union_info.func = func;
2866 g_array_append_val (gst_value_union_funcs, union_info);
2872 * gst_value_can_intersect:
2873 * @value1: a value to intersect
2874 * @value2: another value to intersect
2876 * Determines if intersecting two values will produce a valid result.
2877 * Two values will produce a valid intersection if they have the same
2878 * type, or if there is a method (registered by
2879 * gst_value_register_intersection_func()) to calculate the intersection.
2881 * Returns: TRUE if the values can intersect
2884 gst_value_can_intersect (const GValue * value1, const GValue * value2)
2886 GstValueIntersectInfo *intersect_info;
2890 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
2893 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
2894 intersect_info = &g_array_index (gst_value_intersect_funcs,
2895 GstValueIntersectInfo, i);
2896 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
2897 intersect_info->type2 == G_VALUE_TYPE (value2))
2898 if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
2899 intersect_info->type1 == G_VALUE_TYPE (value2))
2903 return gst_value_can_compare (value1, value2);
2907 * gst_value_intersect:
2908 * @dest: a uninitialized #GValue that will hold the calculated
2909 * intersection value
2910 * @value1: a value to intersect
2911 * @value2: another value to intersect
2913 * Calculates the intersection of two values. If the values have
2914 * a non-empty intersection, the value representing the intersection
2915 * is placed in @dest. If the intersection is non-empty, @dest is
2918 * Returns: TRUE if the intersection is non-empty
2921 gst_value_intersect (GValue * dest, const GValue * value1,
2922 const GValue * value2)
2924 GstValueIntersectInfo *intersect_info;
2926 gboolean ret = FALSE;
2928 /* special cases first */
2929 if (GST_VALUE_HOLDS_LIST (value1))
2930 return gst_value_intersect_list (dest, value1, value2);
2931 if (GST_VALUE_HOLDS_LIST (value2))
2932 return gst_value_intersect_list (dest, value2, value1);
2934 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
2935 intersect_info = &g_array_index (gst_value_intersect_funcs,
2936 GstValueIntersectInfo, i);
2937 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
2938 intersect_info->type2 == G_VALUE_TYPE (value2)) {
2939 ret = intersect_info->func (dest, value1, value2);
2942 if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
2943 intersect_info->type2 == G_VALUE_TYPE (value1)) {
2944 ret = intersect_info->func (dest, value2, value1);
2949 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
2950 gst_value_init_and_copy (dest, value1);
2958 * gst_value_register_intersect_func:
2959 * @type1: the first type to intersect
2960 * @type2: the second type to intersect
2961 * @func: the intersection function
2963 * Registers a function that is called to calculate the intersection
2964 * of the values having the types @type1 and @type2.
2966 * Intersect functions should be registered at startup before any pipelines are
2967 * started, as gst_value_register_intersect_func() is not thread-safe and
2968 * cannot be used at the same time as gst_value_intersect() or
2969 * gst_value_can_intersect().
2972 gst_value_register_intersect_func (GType type1, GType type2,
2973 GstValueIntersectFunc func)
2975 GstValueIntersectInfo intersect_info;
2977 intersect_info.type1 = type1;
2978 intersect_info.type2 = type2;
2979 intersect_info.func = func;
2981 g_array_append_val (gst_value_intersect_funcs, intersect_info);
2988 * gst_value_subtract:
2989 * @dest: the destination value for the result if the subtraction is not empty
2990 * @minuend: the value to subtract from
2991 * @subtrahend: the value to subtract
2993 * Subtracts @subtrahend from @minuend and stores the result in @dest.
2994 * Note that this means subtraction as in sets, not as in mathematics.
2996 * Returns: %TRUE if the subtraction is not empty
2999 gst_value_subtract (GValue * dest, const GValue * minuend,
3000 const GValue * subtrahend)
3002 GstValueSubtractInfo *info;
3005 /* special cases first */
3006 if (GST_VALUE_HOLDS_LIST (minuend))
3007 return gst_value_subtract_from_list (dest, minuend, subtrahend);
3008 if (GST_VALUE_HOLDS_LIST (subtrahend))
3009 return gst_value_subtract_list (dest, minuend, subtrahend);
3011 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
3012 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
3013 if (info->minuend == G_VALUE_TYPE (minuend) &&
3014 info->subtrahend == G_VALUE_TYPE (subtrahend)) {
3015 return info->func (dest, minuend, subtrahend);
3019 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
3020 gst_value_init_and_copy (dest, minuend);
3029 gst_value_subtract (GValue * dest, const GValue * minuend,
3030 const GValue * subtrahend)
3032 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
3034 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
3035 gst_value_serialize (subtrahend),
3036 ret ? gst_value_serialize (dest) : "---");
3042 * gst_value_can_subtract:
3043 * @minuend: the value to subtract from
3044 * @subtrahend: the value to subtract
3046 * Checks if it's possible to subtract @subtrahend from @minuend.
3048 * Returns: TRUE if a subtraction is possible
3051 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
3053 GstValueSubtractInfo *info;
3057 if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
3060 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
3061 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
3062 if (info->minuend == G_VALUE_TYPE (minuend) &&
3063 info->subtrahend == G_VALUE_TYPE (subtrahend))
3067 return gst_value_can_compare (minuend, subtrahend);
3071 * gst_value_register_subtract_func:
3072 * @minuend_type: type of the minuend
3073 * @subtrahend_type: type of the subtrahend
3074 * @func: function to use
3076 * Registers @func as a function capable of subtracting the values of
3077 * @subtrahend_type from values of @minuend_type.
3079 * Subtract functions should be registered at startup before any pipelines are
3080 * started, as gst_value_register_subtract_func() is not thread-safe and
3081 * cannot be used at the same time as gst_value_subtract().
3084 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
3085 GstValueSubtractFunc func)
3087 GstValueSubtractInfo info;
3089 /* one type must be unfixed, other subtractions can be done as comparisons */
3090 g_return_if_fail (!gst_type_is_fixed (minuend_type)
3091 || !gst_type_is_fixed (subtrahend_type));
3093 info.minuend = minuend_type;
3094 info.subtrahend = subtrahend_type;
3097 g_array_append_val (gst_value_subtract_funcs, info);
3101 * gst_value_register:
3102 * @table: structure containing functions to register
3104 * Registers functions to perform calculations on #GValues of a given
3109 * @type: GType that the functions operate on.
3110 * @compare: A function that compares two values of this type.
3111 * @serialize: A function that transforms a value of this type to a
3112 * string. Strings created by this function must be unique and should
3113 * be human readable.
3114 * @deserialize: A function that transforms a string to a value of
3115 * this type. This function must transform strings created by the
3116 * serialize function back to the original value. This function may
3117 * optionally transform other strings into values.
3120 gst_value_register (const GstValueTable * table)
3122 g_array_append_val (gst_value_table, *table);
3126 * gst_value_init_and_copy:
3127 * @dest: the target value
3128 * @src: the source value
3130 * Initialises the target value to be of the same type as source and then copies
3131 * the contents from source to target.
3134 gst_value_init_and_copy (GValue * dest, const GValue * src)
3136 g_value_init (dest, G_VALUE_TYPE (src));
3137 g_value_copy (src, dest);
3141 * gst_value_serialize:
3142 * @value: a #GValue to serialize
3144 * tries to transform the given @value into a string representation that allows
3145 * getting back this string later on using gst_value_deserialize().
3147 * Returns: the serialization for @value or NULL if none exists
3150 gst_value_serialize (const GValue * value)
3153 GValue s_val = { 0 };
3154 GstValueTable *table, *best = NULL;
3157 g_return_val_if_fail (G_IS_VALUE (value), NULL);
3159 for (i = 0; i < gst_value_table->len; i++) {
3160 table = &g_array_index (gst_value_table, GstValueTable, i);
3161 if (table->serialize == NULL)
3163 if (table->type == G_VALUE_TYPE (value)) {
3167 if (g_type_is_a (G_VALUE_TYPE (value), table->type)) {
3168 if (!best || g_type_is_a (table->type, best->type))
3173 return best->serialize (value);
3175 g_value_init (&s_val, G_TYPE_STRING);
3176 if (g_value_transform (value, &s_val)) {
3177 s = gst_string_wrap (g_value_get_string (&s_val));
3181 g_value_unset (&s_val);
3187 * gst_value_deserialize:
3188 * @dest: #GValue to fill with contents of deserialization
3189 * @src: string to deserialize
3191 * Tries to deserialize a string into the type specified by the given GValue.
3192 * If the operation succeeds, TRUE is returned, FALSE otherwise.
3194 * Returns: TRUE on success
3197 gst_value_deserialize (GValue * dest, const gchar * src)
3199 GstValueTable *table, *best = NULL;
3202 g_return_val_if_fail (src != NULL, FALSE);
3203 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
3205 for (i = 0; i < gst_value_table->len; i++) {
3206 table = &g_array_index (gst_value_table, GstValueTable, i);
3207 if (table->serialize == NULL)
3210 if (table->type == G_VALUE_TYPE (dest)) {
3215 if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) {
3216 if (!best || g_type_is_a (table->type, best->type))
3221 return best->deserialize (dest, src);
3228 * gst_value_is_fixed:
3229 * @value: the #GValue to check
3231 * Tests if the given GValue, if available in a GstStructure (or any other
3232 * container) contains a "fixed" (which means: one value) or an "unfixed"
3233 * (which means: multiple possible values, such as data lists or data
3236 * Returns: true if the value is "fixed".
3240 gst_value_is_fixed (const GValue * value)
3242 GType type = G_VALUE_TYPE (value);
3244 if (type == GST_TYPE_ARRAY) {
3245 gboolean fixed = TRUE;
3249 /* check recursively */
3250 size = gst_value_array_get_size (value);
3251 for (n = 0; n < size; n++) {
3252 kid = gst_value_array_get_value (value, n);
3253 fixed &= gst_value_is_fixed (kid);
3259 return gst_type_is_fixed (type);
3266 /* helper functions */
3268 /* Finds the greatest common divisor.
3269 * Returns 1 if none other found.
3270 * This is Euclid's algorithm. */
3272 gst_greatest_common_divisor (gint a, gint b)
3285 gst_value_init_fraction (GValue * value)
3287 value->data[0].v_int = 0;
3288 value->data[1].v_int = 1;
3292 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
3294 dest_value->data[0].v_int = src_value->data[0].v_int;
3295 dest_value->data[1].v_int = src_value->data[1].v_int;
3299 gst_value_collect_fraction (GValue * value, guint n_collect_values,
3300 GTypeCValue * collect_values, guint collect_flags)
3302 gst_value_set_fraction (value,
3303 collect_values[0].v_int, collect_values[1].v_int);
3309 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
3310 GTypeCValue * collect_values, guint collect_flags)
3312 gint *numerator = collect_values[0].v_pointer;
3313 gint *denominator = collect_values[1].v_pointer;
3316 return g_strdup_printf ("numerator for `%s' passed as NULL",
3317 G_VALUE_TYPE_NAME (value));
3319 return g_strdup_printf ("denominator for `%s' passed as NULL",
3320 G_VALUE_TYPE_NAME (value));
3322 *numerator = value->data[0].v_int;
3323 *denominator = value->data[1].v_int;
3329 * gst_value_set_fraction:
3330 * @value: a GValue initialized to #GST_TYPE_FRACTION
3331 * @numerator: the numerator of the fraction
3332 * @denominator: the denominator of the fraction
3334 * Sets @value to the fraction specified by @numerator over @denominator.
3335 * The fraction gets reduced to the smallest numerator and denominator,
3336 * and if necessary the sign is moved to the numerator.
3339 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
3343 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
3344 g_return_if_fail (denominator != 0);
3345 g_return_if_fail (denominator >= -G_MAXINT);
3346 g_return_if_fail (numerator >= -G_MAXINT);
3348 /* normalize sign */
3349 if (denominator < 0) {
3350 numerator = -numerator;
3351 denominator = -denominator;
3354 /* check for reduction */
3355 gcd = gst_greatest_common_divisor (numerator, denominator);
3361 g_assert (denominator > 0);
3363 value->data[0].v_int = numerator;
3364 value->data[1].v_int = denominator;
3368 * gst_value_get_fraction_numerator:
3369 * @value: a GValue initialized to #GST_TYPE_FRACTION
3371 * Gets the numerator of the fraction specified by @value.
3373 * Returns: the numerator of the fraction.
3376 gst_value_get_fraction_numerator (const GValue * value)
3378 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
3380 return value->data[0].v_int;
3384 * gst_value_get_fraction_denominator:
3385 * @value: a GValue initialized to #GST_TYPE_FRACTION
3387 * Gets the denominator of the fraction specified by @value.
3389 * Returns: the denominator of the fraction.
3392 gst_value_get_fraction_denominator (const GValue * value)
3394 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
3396 return value->data[1].v_int;
3400 * gst_value_fraction_multiply:
3401 * @product: a GValue initialized to #GST_TYPE_FRACTION
3402 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
3403 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
3405 * Multiplies the two GValues containing a GstFraction and sets @product
3406 * to the product of the two fractions.
3408 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
3411 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
3412 const GValue * factor2)
3414 gint gcd, n1, n2, d1, d2;
3416 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
3417 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
3419 n1 = factor1->data[0].v_int;
3420 n2 = factor2->data[0].v_int;
3421 d1 = factor1->data[1].v_int;
3422 d2 = factor2->data[1].v_int;
3424 gcd = gst_greatest_common_divisor (n1, d2);
3427 gcd = gst_greatest_common_divisor (n2, d1);
3431 g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (n2), FALSE);
3432 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE);
3434 gst_value_set_fraction (product, n1 * n2, d1 * d2);
3440 * gst_value_fraction_subtract:
3441 * @dest: a GValue initialized to #GST_TYPE_FRACTION
3442 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
3443 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
3445 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
3447 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
3450 gst_value_fraction_subtract (GValue * dest,
3451 const GValue * minuend, const GValue * subtrahend)
3453 gint n1, n2, d1, d2;
3455 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
3456 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
3458 n1 = minuend->data[0].v_int;
3459 n2 = subtrahend->data[0].v_int;
3460 d1 = minuend->data[1].v_int;
3461 d2 = subtrahend->data[1].v_int;
3464 gst_value_set_fraction (dest, -n2, d2);
3468 gst_value_set_fraction (dest, n1, d1);
3472 g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (d2), FALSE);
3473 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (n2), FALSE);
3474 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE);
3476 gst_value_set_fraction (dest, (n1 * d2) - (n2 * d1), d1 * d2);
3482 gst_value_serialize_fraction (const GValue * value)
3484 gint32 numerator = value->data[0].v_int;
3485 gint32 denominator = value->data[1].v_int;
3486 gboolean positive = TRUE;
3488 /* get the sign and make components absolute */
3489 if (numerator < 0) {
3490 numerator = -numerator;
3491 positive = !positive;
3493 if (denominator < 0) {
3494 denominator = -denominator;
3495 positive = !positive;
3498 return g_strdup_printf ("%s%d/%d",
3499 positive ? "" : "-", numerator, denominator);
3503 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
3507 if (G_UNLIKELY (s == NULL))
3510 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
3513 if (sscanf (s, "%d/%d", &num, &den) == 2) {
3514 gst_value_set_fraction (dest, num, den);
3517 if (sscanf (s, "%d", &num) == 1) {
3518 gst_value_set_fraction (dest, num, 1);
3521 if (g_ascii_strcasecmp (s, "min") == 0) {
3522 gst_value_set_fraction (dest, -G_MAXINT, 1);
3524 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3525 gst_value_set_fraction (dest, G_MAXINT, 1);
3533 gst_value_transform_fraction_string (const GValue * src_value,
3534 GValue * dest_value)
3536 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
3540 gst_value_transform_string_fraction (const GValue * src_value,
3541 GValue * dest_value)
3543 if (!gst_value_deserialize_fraction (dest_value,
3544 src_value->data[0].v_pointer))
3545 /* If the deserialize fails, ensure we leave the fraction in a
3546 * valid, if incorrect, state */
3547 gst_value_set_fraction (dest_value, 0, 1);
3550 #define MAX_TERMS 30
3551 #define MIN_DIVISOR 1.0e-10
3552 #define MAX_ERROR 1.0e-20
3554 /* use continued fractions to transform a double into a fraction,
3555 * see http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac.
3556 * This algorithm takes care of overflows.
3559 gst_value_transform_double_fraction (const GValue * src_value,
3560 GValue * dest_value)
3562 gdouble V, F; /* double being converted */
3563 gint N, D; /* will contain the result */
3564 gint A; /* current term in continued fraction */
3565 gint64 N1, D1; /* numerator, denominator of last approx */
3566 gint64 N2, D2; /* numerator, denominator of previous approx */
3568 gboolean negative = FALSE;
3570 /* initialize fraction being converted */
3571 F = src_value->data[0].v_double;
3578 /* initialize fractions with 1/0, 0/1 */
3586 for (i = 0; i < MAX_TERMS; i++) {
3588 A = (gint) F; /* no floor() needed, F is always >= 0 */
3589 /* get new divisor */
3592 /* calculate new fraction in temp */
3596 /* guard against overflow */
3597 if (N2 > G_MAXINT || D2 > G_MAXINT) {
3604 /* save last two fractions */
3610 /* quit if dividing by zero or close enough to target */
3611 if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) {
3615 /* Take reciprocal */
3618 /* fix for overflow */
3623 /* fix for negative */
3627 /* will also simplify */
3628 gst_value_set_fraction (dest_value, N, D);
3632 gst_value_transform_fraction_double (const GValue * src_value,
3633 GValue * dest_value)
3635 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
3636 ((double) src_value->data[1].v_int);
3640 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
3648 n1 = value1->data[0].v_int;
3649 n2 = value2->data[0].v_int;
3650 d1 = value1->data[1].v_int;
3651 d2 = value2->data[1].v_int;
3653 /* fractions are reduced when set, so we can quickly see if they're equal */
3654 if (n1 == n2 && d1 == d2)
3655 return GST_VALUE_EQUAL;
3657 /* extend to 64 bits */
3658 new_num_1 = ((gint64) n1) * d2;
3659 new_num_2 = ((gint64) n2) * d1;
3660 if (new_num_1 < new_num_2)
3661 return GST_VALUE_LESS_THAN;
3662 if (new_num_1 > new_num_2)
3663 return GST_VALUE_GREATER_THAN;
3665 /* new_num_1 == new_num_2 implies that both denominators must have
3666 * been 0, beause otherwise simplification would have caught the
3668 g_assert_not_reached ();
3669 return GST_VALUE_UNORDERED;
3677 * gst_value_set_date:
3678 * @value: a GValue initialized to GST_TYPE_DATE
3679 * @date: the date to set the value to
3681 * Sets the contents of @value to coorespond to @date. The actual
3682 * #GDate structure is copied before it is used.
3685 gst_value_set_date (GValue * value, const GDate * date)
3687 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE);
3689 g_value_set_boxed (value, date);
3693 * gst_value_get_date:
3694 * @value: a GValue initialized to GST_TYPE_DATE
3696 * Gets the contents of @value.
3698 * Returns: the contents of @value
3701 gst_value_get_date (const GValue * value)
3703 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE, NULL);
3705 return (const GDate *) g_value_get_boxed (value);
3709 gst_date_copy (gpointer boxed)
3711 const GDate *date = (const GDate *) boxed;
3713 return g_date_new_julian (g_date_get_julian (date));
3717 gst_value_compare_date (const GValue * value1, const GValue * value2)
3719 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
3720 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
3724 return GST_VALUE_EQUAL;
3726 if ((date1 == NULL || !g_date_valid (date1))
3727 && (date2 != NULL && g_date_valid (date2))) {
3728 return GST_VALUE_LESS_THAN;
3731 if ((date2 == NULL || !g_date_valid (date2))
3732 && (date1 != NULL && g_date_valid (date1))) {
3733 return GST_VALUE_GREATER_THAN;
3736 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
3737 || !g_date_valid (date2)) {
3738 return GST_VALUE_UNORDERED;
3741 j1 = g_date_get_julian (date1);
3742 j2 = g_date_get_julian (date2);
3745 return GST_VALUE_EQUAL;
3747 return GST_VALUE_LESS_THAN;
3749 return GST_VALUE_GREATER_THAN;
3753 gst_value_serialize_date (const GValue * val)
3755 const GDate *date = (const GDate *) g_value_get_boxed (val);
3757 if (date == NULL || !g_date_valid (date))
3758 return g_strdup ("9999-99-99");
3760 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
3761 g_date_get_month (date), g_date_get_day (date));
3765 gst_value_deserialize_date (GValue * dest, const char *s)
3767 guint year, month, day;
3769 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
3772 if (!g_date_valid_dmy (day, month, year))
3775 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
3780 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
3782 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
3786 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
3788 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
3791 static GTypeInfo _info = {
3804 static GTypeFundamentalInfo _finfo = {
3808 #define FUNC_VALUE_GET_TYPE(type, name) \
3809 GType gst_ ## type ## _get_type (void) \
3811 static GType gst_ ## type ## _type = 0; \
3813 if (G_UNLIKELY (gst_ ## type ## _type == 0)) { \
3814 _info.value_table = & _gst_ ## type ## _value_table; \
3815 gst_ ## type ## _type = g_type_register_fundamental ( \
3816 g_type_fundamental_next (), \
3817 name, &_info, &_finfo, 0); \
3820 return gst_ ## type ## _type; \
3823 static const GTypeValueTable _gst_fourcc_value_table = {
3824 gst_value_init_fourcc,
3826 gst_value_copy_fourcc,
3829 gst_value_collect_fourcc,
3831 gst_value_lcopy_fourcc
3834 FUNC_VALUE_GET_TYPE (fourcc, "GstFourcc");
3836 static const GTypeValueTable _gst_int_range_value_table = {
3837 gst_value_init_int_range,
3839 gst_value_copy_int_range,
3842 gst_value_collect_int_range,
3844 gst_value_lcopy_int_range
3847 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
3849 static const GTypeValueTable _gst_double_range_value_table = {
3850 gst_value_init_double_range,
3852 gst_value_copy_double_range,
3855 gst_value_collect_double_range,
3857 gst_value_lcopy_double_range
3860 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
3862 static const GTypeValueTable _gst_fraction_range_value_table = {
3863 gst_value_init_fraction_range,
3864 gst_value_free_fraction_range,
3865 gst_value_copy_fraction_range,
3868 gst_value_collect_fraction_range,
3870 gst_value_lcopy_fraction_range
3873 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
3875 static const GTypeValueTable _gst_value_list_value_table = {
3876 gst_value_init_list_or_array,
3877 gst_value_free_list_or_array,
3878 gst_value_copy_list_or_array,
3879 gst_value_list_or_array_peek_pointer,
3881 gst_value_collect_list_or_array,
3883 gst_value_lcopy_list_or_array
3886 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
3888 static const GTypeValueTable _gst_value_array_value_table = {
3889 gst_value_init_list_or_array,
3890 gst_value_free_list_or_array,
3891 gst_value_copy_list_or_array,
3892 gst_value_list_or_array_peek_pointer,
3894 gst_value_collect_list_or_array,
3896 gst_value_lcopy_list_or_array
3899 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
3901 static const GTypeValueTable _gst_fraction_value_table = {
3902 gst_value_init_fraction,
3904 gst_value_copy_fraction,
3907 gst_value_collect_fraction,
3909 gst_value_lcopy_fraction
3912 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
3916 gst_date_get_type (void)
3918 static GType gst_date_type = 0;
3920 if (G_UNLIKELY (gst_date_type == 0)) {
3921 /* Not using G_TYPE_DATE here on purpose, even if we could
3922 * if GLIB_CHECK_VERSION(2,8,0) was true: we don't want the
3923 * serialised strings to have different type strings depending
3924 * on what version is used, so FIXME when we
3925 * require GLib-2.8 */
3926 gst_date_type = g_boxed_type_register_static ("GstDate",
3927 (GBoxedCopyFunc) gst_date_copy, (GBoxedFreeFunc) g_date_free);
3930 return gst_date_type;
3934 _gst_value_initialize (void)
3936 //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
3938 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
3939 gst_value_union_funcs = g_array_new (FALSE, FALSE,
3940 sizeof (GstValueUnionInfo));
3941 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
3942 sizeof (GstValueIntersectInfo));
3943 gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
3944 sizeof (GstValueSubtractInfo));
3947 static GstValueTable gst_value = {
3949 gst_value_compare_fourcc,
3950 gst_value_serialize_fourcc,
3951 gst_value_deserialize_fourcc,
3954 gst_value.type = gst_fourcc_get_type ();
3955 gst_value_register (&gst_value);
3959 static GstValueTable gst_value = {
3961 gst_value_compare_int_range,
3962 gst_value_serialize_int_range,
3963 gst_value_deserialize_int_range,
3966 gst_value.type = gst_int_range_get_type ();
3967 gst_value_register (&gst_value);
3971 static GstValueTable gst_value = {
3973 gst_value_compare_double_range,
3974 gst_value_serialize_double_range,
3975 gst_value_deserialize_double_range,
3978 gst_value.type = gst_double_range_get_type ();
3979 gst_value_register (&gst_value);
3983 static GstValueTable gst_value = {
3985 gst_value_compare_fraction_range,
3986 gst_value_serialize_fraction_range,
3987 gst_value_deserialize_fraction_range,
3990 gst_value.type = gst_fraction_range_get_type ();
3991 gst_value_register (&gst_value);
3995 static GstValueTable gst_value = {
3997 gst_value_compare_list,
3998 gst_value_serialize_list,
3999 gst_value_deserialize_list,
4002 gst_value.type = gst_value_list_get_type ();
4003 gst_value_register (&gst_value);
4007 static GstValueTable gst_value = {
4009 gst_value_compare_array,
4010 gst_value_serialize_array,
4011 gst_value_deserialize_array,
4014 gst_value.type = gst_value_array_get_type ();;
4015 gst_value_register (&gst_value);
4020 static const GTypeValueTable value_table = {
4021 gst_value_init_buffer,
4023 gst_value_copy_buffer,
4026 NULL, /*gst_value_collect_buffer, */
4028 NULL /*gst_value_lcopy_buffer */
4031 static GstValueTable gst_value = {
4033 gst_value_compare_buffer,
4034 gst_value_serialize_buffer,
4035 gst_value_deserialize_buffer,
4038 gst_value.type = GST_TYPE_BUFFER;
4039 gst_value_register (&gst_value);
4042 static GstValueTable gst_value = {
4044 gst_value_compare_fraction,
4045 gst_value_serialize_fraction,
4046 gst_value_deserialize_fraction,
4049 gst_value.type = gst_fraction_get_type ();
4050 gst_value_register (&gst_value);
4053 static GstValueTable gst_value = {
4056 gst_value_serialize_caps,
4057 gst_value_deserialize_caps,
4060 gst_value.type = GST_TYPE_CAPS;
4061 gst_value_register (&gst_value);
4064 static GstValueTable gst_value = {
4066 gst_value_compare_date,
4067 gst_value_serialize_date,
4068 gst_value_deserialize_date,
4071 gst_value.type = gst_date_get_type ();
4072 gst_value_register (&gst_value);
4075 REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
4076 REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
4078 REGISTER_SERIALIZATION (G_TYPE_STRING, string);
4079 REGISTER_SERIALIZATION (G_TYPE_BOOLEAN, boolean);
4080 REGISTER_SERIALIZATION (G_TYPE_ENUM, enum);
4082 REGISTER_SERIALIZATION (G_TYPE_FLAGS, flags);
4084 REGISTER_SERIALIZATION (G_TYPE_INT, int);
4086 REGISTER_SERIALIZATION (G_TYPE_INT64, int64);
4087 REGISTER_SERIALIZATION (G_TYPE_LONG, long);
4089 REGISTER_SERIALIZATION (G_TYPE_UINT, uint);
4090 REGISTER_SERIALIZATION (G_TYPE_UINT64, uint64);
4091 REGISTER_SERIALIZATION (G_TYPE_ULONG, ulong);
4093 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
4094 gst_value_transform_fourcc_string);
4095 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
4096 gst_value_transform_int_range_string);
4097 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
4098 gst_value_transform_double_range_string);
4099 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
4100 gst_value_transform_fraction_range_string);
4101 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
4102 gst_value_transform_list_string);
4103 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
4104 gst_value_transform_array_string);
4105 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
4106 gst_value_transform_fraction_string);
4107 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
4108 gst_value_transform_string_fraction);
4109 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
4110 gst_value_transform_fraction_double);
4111 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
4112 gst_value_transform_double_fraction);
4113 g_value_register_transform_func (GST_TYPE_DATE, G_TYPE_STRING,
4114 gst_value_transform_date_string);
4115 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_DATE,
4116 gst_value_transform_string_date);
4118 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4119 gst_value_intersect_int_int_range);
4120 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4121 gst_value_intersect_int_range_int_range);
4122 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
4123 gst_value_intersect_double_double_range);
4124 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
4125 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
4126 gst_value_register_intersect_func (GST_TYPE_ARRAY,
4127 GST_TYPE_ARRAY, gst_value_intersect_array);
4128 gst_value_register_intersect_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4129 gst_value_intersect_fraction_fraction_range);
4130 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
4131 GST_TYPE_FRACTION_RANGE,
4132 gst_value_intersect_fraction_range_fraction_range);
4134 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4135 gst_value_subtract_int_int_range);
4136 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
4137 gst_value_subtract_int_range_int);
4138 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4139 gst_value_subtract_int_range_int_range);
4140 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
4141 gst_value_subtract_double_double_range);
4142 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
4143 gst_value_subtract_double_range_double);
4144 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
4145 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
4147 gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4148 gst_value_subtract_fraction_fraction_range);
4149 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION,
4150 gst_value_subtract_fraction_range_fraction);
4151 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
4152 GST_TYPE_FRACTION_RANGE,
4153 gst_value_subtract_fraction_range_fraction_range);
4155 /* see bug #317246, #64994, #65041 */
4157 volatile GType date_type = G_TYPE_DATE;
4159 g_type_name (date_type);
4162 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
4163 gst_value_union_int_int_range);
4164 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
4165 gst_value_union_int_range_int_range);
4168 /* Implement these if needed */
4169 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
4170 gst_value_union_fraction_fraction_range);
4171 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
4172 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);