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.
21 * @short_description: GValue implementations specific to GStreamer
33 #include "gst_private.h"
35 #include <gobject/gvaluecollector.h>
37 typedef struct _GstValueUnionInfo GstValueUnionInfo;
38 struct _GstValueUnionInfo
42 GstValueUnionFunc func;
45 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
46 struct _GstValueIntersectInfo
50 GstValueIntersectFunc func;
53 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
54 struct _GstValueSubtractInfo
58 GstValueSubtractFunc func;
61 GType gst_type_fourcc;
62 GType gst_type_int_range;
63 GType gst_type_double_range;
66 GType gst_type_fraction;
68 static GArray *gst_value_table;
69 static GArray *gst_value_union_funcs;
70 static GArray *gst_value_intersect_funcs;
71 static GArray *gst_value_subtract_funcs;
77 /* two helper functions to serialize/stringify any type of list
78 * regular lists are done with { }, arrays with < >
81 gst_value_serialize_any_list (const GValue * value, const char *begin,
85 GArray *array = value->data[0].v_pointer;
90 s = g_string_new (begin);
91 for (i = 0; i < array->len; i++) {
92 v = &g_array_index (array, GValue, i);
93 s_val = gst_value_serialize (v);
94 g_string_append (s, s_val);
96 if (i < array->len - 1) {
97 g_string_append (s, ", ");
100 g_string_append (s, end);
101 return g_string_free (s, FALSE);
105 gst_value_transform_any_list_string (const GValue * src_value,
106 GValue * dest_value, const char *begin, const char *end)
114 array = src_value->data[0].v_pointer;
116 s = g_string_new (begin);
117 for (i = 0; i < array->len; i++) {
118 list_value = &g_array_index (array, GValue, i);
121 g_string_append (s, ", ");
123 list_s = g_strdup_value_contents (list_value);
124 g_string_append (s, list_s);
127 g_string_append (s, end);
129 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
133 * helper function to see if a type is fixed. Is used internally here and
134 * there. Do not export, since it doesn't work for types where the content
135 * decides the fixedness (e.g. GST_TYPE_ARRAY).
139 gst_type_is_fixed (GType type)
141 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
142 type == GST_TYPE_LIST) {
145 if (G_TYPE_FUNDAMENTAL (type) <=
146 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
149 if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC
150 || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) {
157 /* GValue functions usable for both regular lists and arrays */
159 gst_value_init_list (GValue * value)
161 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
165 gst_value_list_array_copy (const GArray * src)
170 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
171 g_array_set_size (dest, src->len);
172 for (i = 0; i < src->len; i++) {
173 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
174 &g_array_index (src, GValue, i));
181 gst_value_copy_list (const GValue * src_value, GValue * dest_value)
183 dest_value->data[0].v_pointer =
184 gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
188 gst_value_free_list (GValue * value)
191 GArray *src = (GArray *) value->data[0].v_pointer;
193 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
194 for (i = 0; i < src->len; i++) {
195 g_value_unset (&g_array_index (src, GValue, i));
197 g_array_free (src, TRUE);
202 gst_value_list_peek_pointer (const GValue * value)
204 return value->data[0].v_pointer;
208 gst_value_collect_list (GValue * value, guint n_collect_values,
209 GTypeCValue * collect_values, guint collect_flags)
211 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
212 value->data[0].v_pointer = collect_values[0].v_pointer;
213 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
215 value->data[0].v_pointer =
216 gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
222 gst_value_lcopy_list (const GValue * value, guint n_collect_values,
223 GTypeCValue * collect_values, guint collect_flags)
225 GArray **dest = collect_values[0].v_pointer;
228 return g_strdup_printf ("value location for `%s' passed as NULL",
229 G_VALUE_TYPE_NAME (value));
230 if (!value->data[0].v_pointer)
231 return g_strdup_printf ("invalid value given for `%s'",
232 G_VALUE_TYPE_NAME (value));
233 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
234 *dest = (GArray *) value->data[0].v_pointer;
236 *dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
242 * gst_value_list_prepend_value:
243 * @value: a GstValueList to prepend a value to
244 * @prepend_value: the value to prepend
246 * Prepends @prepend_value to the GstValueList in @value.
250 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
254 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)
255 || GST_VALUE_HOLDS_ARRAY (value));
257 gst_value_init_and_copy (&val, prepend_value);
258 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
262 * gst_value_list_append_value:
263 * @value: a GstValueList to append a value to
264 * @append_value: the value to append
266 * Appends @append_value to the GstValueList in @value.
269 gst_value_list_append_value (GValue * value, const GValue * append_value)
273 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)
274 || GST_VALUE_HOLDS_ARRAY (value));
276 gst_value_init_and_copy (&val, append_value);
277 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
281 * gst_value_list_get_size:
282 * @value: a #GValue of type #GST_LIST_TYPE or #GST_ARRAY_TYPE
284 * Gets the number of values contained in @value.
286 * Returns: the number of values
289 gst_value_list_get_size (const GValue * value)
291 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value)
292 || GST_VALUE_HOLDS_ARRAY (value), 0);
294 return ((GArray *) value->data[0].v_pointer)->len;
298 * gst_value_list_get_value:
299 * @value: a #GValue of type #GST_LIST_TYPE or #GST_ARRAY_TYPE
300 * @index: index of value to get from the list
302 * Gets the value that is a member of the list contained in @value and
303 * has the index @index.
305 * Returns: the value at the given index
308 gst_value_list_get_value (const GValue * value, guint index)
310 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value)
311 || GST_VALUE_HOLDS_ARRAY (value), NULL);
312 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
314 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
319 * gst_value_list_concat:
320 * @dest: an uninitialized #GValue to take the result
321 * @value1: first value to put into the union
322 * @value2: second value to put into the union
324 * Concatenates copies of value1 and value2 into a list. The value
325 * @dest is initialized to the type GST_TYPE_LIST.
328 gst_value_list_concat (GValue * dest, const GValue * value1,
329 const GValue * value2)
331 guint i, value1_length, value2_length;
334 g_return_if_fail (dest != NULL);
335 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
336 g_return_if_fail (G_IS_VALUE (value1));
337 g_return_if_fail (G_IS_VALUE (value2));
340 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
342 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
343 g_value_init (dest, GST_TYPE_LIST);
344 array = (GArray *) dest->data[0].v_pointer;
345 g_array_set_size (array, value1_length + value2_length);
347 if (GST_VALUE_HOLDS_LIST (value1)) {
348 for (i = 0; i < value1_length; i++) {
349 gst_value_init_and_copy (&g_array_index (array, GValue, i),
350 gst_value_list_get_value (value1, i));
353 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
356 if (GST_VALUE_HOLDS_LIST (value2)) {
357 for (i = 0; i < value2_length; i++) {
358 gst_value_init_and_copy (&g_array_index (array, GValue,
359 i + value1_length), gst_value_list_get_value (value2, i));
362 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
368 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
370 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
374 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
376 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
380 gst_value_compare_list (const GValue * value1, const GValue * value2)
383 GArray *array1 = value1->data[0].v_pointer;
384 GArray *array2 = value2->data[0].v_pointer;
388 if (array1->len != array2->len)
389 return GST_VALUE_UNORDERED;
391 for (i = 0; i < array1->len; i++) {
392 v1 = &g_array_index (array1, GValue, i);
393 for (j = 0; j < array1->len; j++) {
394 v2 = &g_array_index (array2, GValue, j);
395 if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
398 if (j == array1->len) {
399 return GST_VALUE_UNORDERED;
403 return GST_VALUE_EQUAL;
407 gst_value_serialize_list (const GValue * value)
409 return gst_value_serialize_any_list (value, "{ ", " }");
413 gst_value_deserialize_list (GValue * dest, const char *s)
415 g_warning ("unimplemented");
420 gst_value_serialize_array (const GValue * value)
422 return gst_value_serialize_any_list (value, "< ", " >");
426 gst_value_deserialize_array (GValue * dest, const char *s)
428 g_warning ("unimplemented");
437 gst_value_init_fourcc (GValue * value)
439 value->data[0].v_int = 0;
443 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
445 dest_value->data[0].v_int = src_value->data[0].v_int;
449 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
450 GTypeCValue * collect_values, guint collect_flags)
452 value->data[0].v_int = collect_values[0].v_int;
458 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
459 GTypeCValue * collect_values, guint collect_flags)
461 guint32 *fourcc_p = collect_values[0].v_pointer;
464 return g_strdup_printf ("value location for `%s' passed as NULL",
465 G_VALUE_TYPE_NAME (value));
467 *fourcc_p = value->data[0].v_int;
473 * gst_value_set_fourcc:
474 * @value: a GValue initialized to #GST_TYPE_FOURCC
475 * @fourcc: the #guint32 fourcc to set
477 * Sets @value to @fourcc.
480 gst_value_set_fourcc (GValue * value, guint32 fourcc)
482 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
484 value->data[0].v_int = fourcc;
488 * gst_value_get_fourcc:
489 * @value: a GValue initialized to #GST_TYPE_FOURCC
491 * Gets the #guint32 fourcc contained in @value.
493 * Returns: the #guint32 fourcc contained in @value.
496 gst_value_get_fourcc (const GValue * value)
498 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
500 return value->data[0].v_int;
504 gst_value_transform_fourcc_string (const GValue * src_value,
507 guint32 fourcc = src_value->data[0].v_int;
509 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
510 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
511 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
512 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
513 dest_value->data[0].v_pointer =
514 g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
516 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
521 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
523 if (value2->data[0].v_int == value1->data[0].v_int)
524 return GST_VALUE_EQUAL;
525 return GST_VALUE_UNORDERED;
529 gst_value_serialize_fourcc (const GValue * value)
531 guint32 fourcc = value->data[0].v_int;
533 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
534 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
535 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
536 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
537 return g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
539 return g_strdup_printf ("0x%08x", fourcc);
544 gst_value_deserialize_fourcc (GValue * dest, const char *s)
546 gboolean ret = FALSE;
550 if (strlen (s) == 4) {
551 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
553 } else if (g_ascii_isdigit (*s)) {
554 fourcc = strtoul (s, &end, 0);
559 gst_value_set_fourcc (dest, fourcc);
569 gst_value_init_int_range (GValue * value)
571 value->data[0].v_int = 0;
572 value->data[1].v_int = 0;
576 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
578 dest_value->data[0].v_int = src_value->data[0].v_int;
579 dest_value->data[1].v_int = src_value->data[1].v_int;
583 gst_value_collect_int_range (GValue * value, guint n_collect_values,
584 GTypeCValue * collect_values, guint collect_flags)
586 value->data[0].v_int = collect_values[0].v_int;
587 value->data[1].v_int = collect_values[1].v_int;
593 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
594 GTypeCValue * collect_values, guint collect_flags)
596 guint32 *int_range_start = collect_values[0].v_pointer;
597 guint32 *int_range_end = collect_values[1].v_pointer;
599 if (!int_range_start)
600 return g_strdup_printf ("start value location for `%s' passed as NULL",
601 G_VALUE_TYPE_NAME (value));
603 return g_strdup_printf ("end value location for `%s' passed as NULL",
604 G_VALUE_TYPE_NAME (value));
606 *int_range_start = value->data[0].v_int;
607 *int_range_end = value->data[1].v_int;
613 * gst_value_set_int_range:
614 * @value: a GValue initialized to GST_TYPE_INT_RANGE
615 * @start: the start of the range
616 * @end: the end of the range
618 * Sets @value to the range specified by @start and @end.
621 gst_value_set_int_range (GValue * value, int start, int end)
623 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
624 g_return_if_fail (start < end);
626 value->data[0].v_int = start;
627 value->data[1].v_int = end;
631 * gst_value_get_int_range_min:
632 * @value: a GValue initialized to GST_TYPE_INT_RANGE
634 * Gets the minimum of the range specified by @value.
636 * Returns: the minimum of the range
639 gst_value_get_int_range_min (const GValue * value)
641 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
643 return value->data[0].v_int;
647 * gst_value_get_int_range_max:
648 * @value: a GValue initialized to GST_TYPE_INT_RANGE
650 * Gets the maximum of the range specified by @value.
652 * Returns: the maxumum of the range
655 gst_value_get_int_range_max (const GValue * value)
657 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
659 return value->data[1].v_int;
663 gst_value_transform_int_range_string (const GValue * src_value,
666 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
667 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
671 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
673 if (value2->data[0].v_int == value1->data[0].v_int &&
674 value2->data[1].v_int == value1->data[1].v_int)
675 return GST_VALUE_EQUAL;
676 return GST_VALUE_UNORDERED;
680 gst_value_serialize_int_range (const GValue * value)
682 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
683 value->data[1].v_int);
687 gst_value_deserialize_int_range (GValue * dest, const char *s)
689 g_warning ("unimplemented");
698 gst_value_init_double_range (GValue * value)
700 value->data[0].v_double = 0;
701 value->data[1].v_double = 0;
705 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
707 dest_value->data[0].v_double = src_value->data[0].v_double;
708 dest_value->data[1].v_double = src_value->data[1].v_double;
712 gst_value_collect_double_range (GValue * value, guint n_collect_values,
713 GTypeCValue * collect_values, guint collect_flags)
715 value->data[0].v_double = collect_values[0].v_double;
716 value->data[1].v_double = collect_values[1].v_double;
722 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
723 GTypeCValue * collect_values, guint collect_flags)
725 gdouble *double_range_start = collect_values[0].v_pointer;
726 gdouble *double_range_end = collect_values[1].v_pointer;
728 if (!double_range_start)
729 return g_strdup_printf ("start value location for `%s' passed as NULL",
730 G_VALUE_TYPE_NAME (value));
731 if (!double_range_end)
732 return g_strdup_printf ("end value location for `%s' passed as NULL",
733 G_VALUE_TYPE_NAME (value));
735 *double_range_start = value->data[0].v_double;
736 *double_range_end = value->data[1].v_double;
742 * gst_value_set_double_range:
743 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
744 * @start: the start of the range
745 * @end: the end of the range
747 * Sets @value to the range specified by @start and @end.
750 gst_value_set_double_range (GValue * value, double start, double end)
752 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
754 value->data[0].v_double = start;
755 value->data[1].v_double = end;
759 * gst_value_get_double_range_min:
760 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
762 * Gets the minimum of the range specified by @value.
764 * Returns: the minumum of the range
767 gst_value_get_double_range_min (const GValue * value)
769 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
771 return value->data[0].v_double;
775 * gst_value_get_double_range_max:
776 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
778 * Gets the maximum of the range specified by @value.
780 * Returns: the maxumum of the range
783 gst_value_get_double_range_max (const GValue * value)
785 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
787 return value->data[1].v_double;
791 gst_value_transform_double_range_string (const GValue * src_value,
794 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
796 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
797 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
798 src_value->data[0].v_double),
799 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
800 src_value->data[1].v_double));
804 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
806 if (value2->data[0].v_double == value1->data[0].v_double &&
807 value2->data[0].v_double == value1->data[0].v_double)
808 return GST_VALUE_EQUAL;
809 return GST_VALUE_UNORDERED;
813 gst_value_serialize_double_range (const GValue * value)
815 char d1[G_ASCII_DTOSTR_BUF_SIZE];
816 char d2[G_ASCII_DTOSTR_BUF_SIZE];
818 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
819 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
820 return g_strdup_printf ("[ %s, %s ]", d1, d2);
824 gst_value_deserialize_double_range (GValue * dest, const char *s)
826 g_warning ("unimplemented");
835 * gst_value_set_caps:
836 * @value: a GValue initialized to GST_TYPE_CAPS
837 * @caps: the caps to set the value to
839 * Sets the contents of @value to coorespond to @caps. The actual
840 * #GstCaps structure is copied before it is used.
843 gst_value_set_caps (GValue * value, const GstCaps * caps)
845 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
847 g_value_set_boxed (value, caps);
851 * gst_value_get_caps:
852 * @value: a GValue initialized to GST_TYPE_CAPS
854 * Gets the contents of @value.
856 * Returns: the contents of @value
859 gst_value_get_caps (const GValue * value)
861 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
863 return (GstCaps *) g_value_get_boxed (value);
867 gst_value_serialize_caps (const GValue * value)
869 GstCaps *caps = g_value_get_boxed (value);
871 return gst_caps_to_string (caps);
875 gst_value_deserialize_caps (GValue * dest, const char *s)
879 caps = gst_caps_from_string (s);
882 g_value_set_boxed (dest, caps);
894 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
896 GstBuffer *buf1 = GST_BUFFER (gst_value_get_mini_object (value1));
897 GstBuffer *buf2 = GST_BUFFER (gst_value_get_mini_object (value2));
899 if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2))
900 return GST_VALUE_UNORDERED;
901 if (GST_BUFFER_SIZE (buf1) == 0)
902 return GST_VALUE_EQUAL;
903 g_assert (GST_BUFFER_DATA (buf1));
904 g_assert (GST_BUFFER_DATA (buf2));
905 if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2),
906 GST_BUFFER_SIZE (buf1)) == 0)
907 return GST_VALUE_EQUAL;
909 return GST_VALUE_UNORDERED;
913 gst_value_serialize_buffer (const GValue * value)
919 GstBuffer *buffer = GST_BUFFER (gst_value_get_mini_object (value));
921 data = GST_BUFFER_DATA (buffer);
922 size = GST_BUFFER_SIZE (buffer);
924 string = g_malloc (size * 2 + 1);
925 for (i = 0; i < size; i++) {
926 sprintf (string + i * 2, "%02x", data[i]);
928 string[size * 2] = 0;
934 gst_value_deserialize_buffer (GValue * dest, const char *s)
946 buffer = gst_buffer_new_and_alloc (len / 2);
947 data = GST_BUFFER_DATA (buffer);
948 for (i = 0; i < len / 2; i++) {
949 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1])) {
953 ts[0] = s[i * 2 + 0];
954 ts[1] = s[i * 2 + 1];
957 data[i] = strtoul (ts, NULL, 16);
961 gst_value_take_mini_object (dest, GST_MINI_OBJECT (buffer));
964 gst_buffer_unref (buffer);
975 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
977 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
978 return GST_VALUE_EQUAL;
979 return GST_VALUE_UNORDERED;
983 gst_value_serialize_boolean (const GValue * value)
985 if (value->data[0].v_int) {
986 return g_strdup ("true");
988 return g_strdup ("false");
992 gst_value_deserialize_boolean (GValue * dest, const char *s)
994 gboolean ret = FALSE;
996 if (g_ascii_strcasecmp (s, "true") == 0 ||
997 g_ascii_strcasecmp (s, "yes") == 0 ||
998 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
999 g_value_set_boolean (dest, TRUE);
1001 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
1002 g_ascii_strcasecmp (s, "no") == 0 ||
1003 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
1004 g_value_set_boolean (dest, FALSE);
1011 #define CREATE_SERIALIZATION_START(_type,_macro) \
1013 gst_value_compare_ ## _type \
1014 (const GValue * value1, const GValue * value2) \
1016 g ## _type val1 = g_value_get_ ## _type (value1); \
1017 g ## _type val2 = g_value_get_ ## _type (value2); \
1019 return GST_VALUE_GREATER_THAN; \
1021 return GST_VALUE_LESS_THAN; \
1022 return GST_VALUE_EQUAL; \
1026 gst_value_serialize_ ## _type (const GValue * value) \
1028 GValue val = { 0, }; \
1029 g_value_init (&val, G_TYPE_STRING); \
1030 if (!g_value_transform (value, &val)) \
1031 g_assert_not_reached (); \
1032 /* NO_COPY_MADNESS!!! */ \
1033 return (char *) g_value_get_string (&val); \
1036 /* deserialize the given s into to as a long long.
1037 * check if the result is actually storeable in the given size number of
1041 gst_value_deserialize_int_helper (long long *to, const char *s,
1042 long long min, long long max, int size)
1044 gboolean ret = FALSE;
1046 long long mask = -1;
1049 *to = g_ascii_strtoull (s, &end, 0);
1050 /* a range error is a definitive no-no */
1051 if (errno == ERANGE) {
1058 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
1059 *to = G_LITTLE_ENDIAN;
1061 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
1064 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
1067 } else if (g_ascii_strcasecmp (s, "min") == 0) {
1070 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1076 /* by definition, a long long fits into a long long; so ignore those */
1077 if (size != sizeof (mask)) {
1079 /* for positive numbers, we create a mask of 1's outside of the range
1080 * and 0's inside the range. An and will thus keep only 1 bits
1081 * outside of the range */
1082 mask <<= (size * 8);
1083 if ((mask & *to) != 0) {
1087 /* for negative numbers, we do a 2's complement version */
1088 mask <<= ((size * 8) - 1);
1089 if ((mask & *to) != mask) {
1098 #define CREATE_SERIALIZATION(_type,_macro) \
1099 CREATE_SERIALIZATION_START(_type,_macro) \
1102 gst_value_deserialize_ ## _type (GValue * dest, const char *s) \
1106 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
1107 G_MAX ## _macro, sizeof (g ## _type))) { \
1108 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
1115 #define CREATE_USERIALIZATION(_type,_macro) \
1116 CREATE_SERIALIZATION_START(_type,_macro) \
1119 gst_value_deserialize_ ## _type (GValue * dest, const char *s) \
1123 gboolean ret = FALSE; \
1126 x = g_ascii_strtoull (s, &end, 0); \
1127 /* a range error is a definitive no-no */ \
1128 if (errno == ERANGE) { \
1131 /* the cast ensures the range check later on makes sense */ \
1132 x = (g ## _type) x; \
1136 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
1137 x = G_LITTLE_ENDIAN; \
1139 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
1142 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
1145 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
1148 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
1149 x = G_MAX ## _macro; \
1154 if (x > G_MAX ## _macro) { \
1157 g_value_set_ ## _type (dest, x); \
1163 #define REGISTER_SERIALIZATION(_gtype, _type) \
1165 static const GstValueTable gst_value = { \
1167 gst_value_compare_ ## _type, \
1168 gst_value_serialize_ ## _type, \
1169 gst_value_deserialize_ ## _type, \
1172 gst_value_register (&gst_value); \
1175 CREATE_SERIALIZATION (int, INT)
1176 CREATE_SERIALIZATION (int64, INT64)
1177 CREATE_SERIALIZATION (long, LONG)
1178 CREATE_USERIALIZATION (uint, UINT)
1179 CREATE_USERIALIZATION (uint64, UINT64)
1180 CREATE_USERIALIZATION (ulong, ULONG)
1186 gst_value_compare_double (const GValue * value1, const GValue * value2)
1188 if (value1->data[0].v_double > value2->data[0].v_double)
1189 return GST_VALUE_GREATER_THAN;
1190 if (value1->data[0].v_double < value2->data[0].v_double)
1191 return GST_VALUE_LESS_THAN;
1192 if (value1->data[0].v_double == value2->data[0].v_double)
1193 return GST_VALUE_EQUAL;
1194 return GST_VALUE_UNORDERED;
1198 gst_value_serialize_double (const GValue * value)
1200 char d[G_ASCII_DTOSTR_BUF_SIZE];
1202 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1203 return g_strdup (d);
1207 gst_value_deserialize_double (GValue * dest, const char *s)
1210 gboolean ret = FALSE;
1213 x = g_ascii_strtod (s, &end);
1217 if (g_ascii_strcasecmp (s, "min") == 0) {
1220 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1226 g_value_set_double (dest, x);
1236 gst_value_compare_float (const GValue * value1, const GValue * value2)
1238 if (value1->data[0].v_float > value2->data[0].v_float)
1239 return GST_VALUE_GREATER_THAN;
1240 if (value1->data[0].v_float < value2->data[0].v_float)
1241 return GST_VALUE_LESS_THAN;
1242 if (value1->data[0].v_float == value2->data[0].v_float)
1243 return GST_VALUE_EQUAL;
1244 return GST_VALUE_UNORDERED;
1248 gst_value_serialize_float (const GValue * value)
1250 char d[G_ASCII_DTOSTR_BUF_SIZE];
1252 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
1253 return g_strdup (d);
1257 gst_value_deserialize_float (GValue * dest, const char *s)
1260 gboolean ret = FALSE;
1263 x = g_ascii_strtod (s, &end);
1267 if (g_ascii_strcasecmp (s, "min") == 0) {
1270 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1275 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
1278 g_value_set_float (dest, x);
1288 gst_value_compare_string (const GValue * value1, const GValue * value2)
1290 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
1293 return GST_VALUE_LESS_THAN;
1295 return GST_VALUE_GREATER_THAN;
1296 return GST_VALUE_EQUAL;
1299 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
1300 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
1304 gst_string_wrap (const char *s)
1309 gboolean wrap = FALSE;
1314 return g_strdup ("");
1316 if (GST_ASCII_IS_STRING (*t)) {
1318 } else if (*t < 0x20 || *t >= 0x7f) {
1329 return g_strdup (s);
1331 e = d = g_malloc (len + 3);
1336 if (GST_ASCII_IS_STRING (*t)) {
1338 } else if (*t < 0x20 || *t >= 0x7f) {
1340 *e++ = '0' + ((*(guchar *) t) >> 6);
1341 *e++ = '0' + (((*t) >> 3) & 0x7);
1342 *e++ = '0' + ((*t++) & 0x7);
1355 * This function takes a string delimited with double quotes (")
1356 * and unescapes any \xxx octal numbers.
1358 * If sequences of \y are found where y is not in the range of
1359 * 0->3, y is copied unescaped.
1361 * If \xyy is found where x is an octal number but y is not, an
1362 * error is encountered and NULL is returned.
1364 * the input string must be \0 terminated.
1367 gst_string_unwrap (const gchar * s)
1370 gchar *read, *write;
1372 /* NULL string returns NULL */
1376 /* strings not starting with " are invalid */
1380 /* make copy of original string to hold the result. This
1381 * string will always be smaller than the original */
1386 /* need to move to the next position as we parsed the " */
1390 if (GST_ASCII_IS_STRING (*read)) {
1391 /* normal chars are just copied */
1393 } else if (*read == '"') {
1394 /* quote marks end of string */
1396 } else if (*read == '\\') {
1397 /* got an escape char, move to next position to read a tripplet
1398 * of octal numbers */
1400 /* is the next char a possible first octal number? */
1401 if (*read >= '0' && *read <= '3') {
1402 /* parse other 2 numbers, if one of them is not in the range of
1403 * an octal number, we error. We also catch the case where a zero
1404 * byte is found here. */
1405 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
1408 /* now convert the octal number to a byte again. */
1409 *write++ = ((read[0] - '0') << 6) +
1410 ((read[1] - '0') << 3) + (read[2] - '0');
1414 /* if we run into a \0 here, we definately won't get a quote later */
1418 /* else copy \X sequence */
1422 /* weird character, error */
1426 /* if the string is not ending in " and zero terminated, we error */
1427 if (*read != '"' || read[1] != '\0')
1430 /* null terminate result string and return */
1440 gst_value_serialize_string (const GValue * value)
1442 return gst_string_wrap (value->data[0].v_pointer);
1446 gst_value_deserialize_string (GValue * dest, const char *s)
1449 if (!g_utf8_validate (s, -1, NULL))
1451 g_value_set_string (dest, s);
1454 gchar *str = gst_string_unwrap (s);
1458 g_value_take_string (dest, str);
1469 gst_value_compare_enum (const GValue * value1, const GValue * value2)
1471 GEnumValue *en1, *en2;
1472 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
1473 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
1475 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
1476 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
1477 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
1478 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
1479 g_type_class_unref (klass1);
1480 g_type_class_unref (klass2);
1481 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
1482 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
1483 if (en1->value < en2->value)
1484 return GST_VALUE_LESS_THAN;
1485 if (en1->value > en2->value)
1486 return GST_VALUE_GREATER_THAN;
1488 return GST_VALUE_EQUAL;
1492 gst_value_serialize_enum (const GValue * value)
1495 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
1497 g_return_val_if_fail (klass, NULL);
1498 en = g_enum_get_value (klass, g_value_get_enum (value));
1499 g_type_class_unref (klass);
1500 g_return_val_if_fail (en, NULL);
1501 return g_strdup (en->value_name);
1505 gst_value_deserialize_enum (GValue * dest, const char *s)
1508 gchar *endptr = NULL;
1509 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
1511 g_return_val_if_fail (klass, FALSE);
1512 if (!(en = g_enum_get_value_by_name (klass, s))) {
1513 if (!(en = g_enum_get_value_by_nick (klass, s))) {
1514 gint i = strtol (s, &endptr, 0);
1516 if (endptr && *endptr == '\0') {
1517 en = g_enum_get_value (klass, i);
1521 g_type_class_unref (klass);
1522 g_return_val_if_fail (en, FALSE);
1523 g_value_set_enum (dest, en->value);
1531 /* we just compare the value here */
1533 gst_value_compare_flags (const GValue * value1, const GValue * value2)
1536 GFlagsClass *klass1 =
1537 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
1538 GFlagsClass *klass2 =
1539 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
1541 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
1542 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
1543 fl1 = g_value_get_flags (value1);
1544 fl2 = g_value_get_flags (value2);
1545 g_type_class_unref (klass1);
1546 g_type_class_unref (klass2);
1548 return GST_VALUE_LESS_THAN;
1550 return GST_VALUE_GREATER_THAN;
1552 return GST_VALUE_EQUAL;
1555 /* the different flags are serialized separated with a + */
1557 gst_value_serialize_flags (const GValue * value)
1561 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
1562 gchar *result, *tmp;
1563 gboolean first = TRUE;
1565 g_return_val_if_fail (klass, NULL);
1567 result = g_strdup ("");
1568 flags = g_value_get_flags (value);
1570 fl = g_flags_get_first_value (klass, flags);
1572 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
1578 flags &= ~fl->value;
1580 g_type_class_unref (klass);
1586 gst_value_deserialize_flags (GValue * dest, const char *s)
1589 gchar *endptr = NULL;
1590 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
1595 g_return_val_if_fail (klass, FALSE);
1597 /* split into parts delimited with + */
1598 split = g_strsplit (s, "+", 0);
1602 /* loop over each part */
1604 if (!(fl = g_flags_get_value_by_name (klass, split[i]))) {
1605 if (!(fl = g_flags_get_value_by_nick (klass, split[i]))) {
1606 gint val = strtol (split[i], &endptr, 0);
1608 /* just or numeric value */
1609 if (endptr && *endptr == '\0') {
1620 g_type_class_unref (klass);
1621 g_value_set_flags (dest, flags);
1631 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
1632 const GValue * src2)
1634 if (src2->data[0].v_int <= src1->data[0].v_int &&
1635 src2->data[1].v_int >= src1->data[0].v_int) {
1636 gst_value_init_and_copy (dest, src2);
1643 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
1644 const GValue * src2)
1649 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1650 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1653 g_value_init (dest, GST_TYPE_INT_RANGE);
1654 gst_value_set_int_range (dest,
1655 MIN (src1->data[0].v_int, src2->data[0].v_int),
1656 MAX (src1->data[1].v_int, src2->data[1].v_int));
1668 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
1669 const GValue * src2)
1671 if (src2->data[0].v_int <= src1->data[0].v_int &&
1672 src2->data[1].v_int >= src1->data[0].v_int) {
1673 gst_value_init_and_copy (dest, src1);
1681 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
1682 const GValue * src2)
1687 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1688 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1691 g_value_init (dest, GST_TYPE_INT_RANGE);
1692 gst_value_set_int_range (dest, min, max);
1696 g_value_init (dest, G_TYPE_INT);
1697 g_value_set_int (dest, min);
1705 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
1706 const GValue * src2)
1708 if (src2->data[0].v_double <= src1->data[0].v_double &&
1709 src2->data[1].v_double >= src1->data[0].v_double) {
1710 gst_value_init_and_copy (dest, src1);
1718 gst_value_intersect_double_range_double_range (GValue * dest,
1719 const GValue * src1, const GValue * src2)
1724 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
1725 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
1728 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
1729 gst_value_set_double_range (dest, min, max);
1733 g_value_init (dest, G_TYPE_DOUBLE);
1734 g_value_set_int (dest, min);
1742 gst_value_intersect_list (GValue * dest, const GValue * value1,
1743 const GValue * value2)
1746 GValue intersection = { 0, };
1747 gboolean ret = FALSE;
1749 size = gst_value_list_get_size (value1);
1750 for (i = 0; i < size; i++) {
1751 const GValue *cur = gst_value_list_get_value (value1, i);
1753 if (gst_value_intersect (&intersection, cur, value2)) {
1756 gst_value_init_and_copy (dest, &intersection);
1758 } else if (GST_VALUE_HOLDS_LIST (dest)) {
1759 gst_value_list_append_value (dest, &intersection);
1761 GValue temp = { 0, };
1763 gst_value_init_and_copy (&temp, dest);
1764 g_value_unset (dest);
1765 gst_value_list_concat (dest, &temp, &intersection);
1766 g_value_unset (&temp);
1768 g_value_unset (&intersection);
1776 gst_value_intersect_array (GValue * dest, const GValue * src1,
1777 const GValue * src2)
1782 /* only works on similar-sized arrays */
1783 size = gst_value_list_get_size (src1);
1784 if (size != gst_value_list_get_size (src2))
1786 g_value_init (dest, GST_TYPE_ARRAY);
1788 for (n = 0; n < size; n++) {
1789 if (!gst_value_intersect (&val, gst_value_list_get_value (src1, n),
1790 gst_value_list_get_value (src2, n))) {
1791 g_value_unset (dest);
1794 gst_value_list_append_value (dest, &val);
1795 g_value_unset (&val);
1806 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
1807 const GValue * subtrahend)
1809 int min = gst_value_get_int_range_min (subtrahend);
1810 int max = gst_value_get_int_range_max (subtrahend);
1811 int val = g_value_get_int (minuend);
1813 /* subtracting a range from an int only works if the int is not in the
1815 if (val < min || val > max) {
1816 /* and the result is the int */
1817 gst_value_init_and_copy (dest, minuend);
1823 /* creates a new int range based on input values.
1826 gst_value_create_new_range (GValue * dest, int min1, int max1, int min2,
1831 GValue *pv1, *pv2; /* yeah, hungarian! */
1833 if (min1 <= max1 && min2 <= max2) {
1836 } else if (min1 <= max1) {
1839 } else if (min2 <= max2) {
1847 g_value_init (pv1, GST_TYPE_INT_RANGE);
1848 gst_value_set_int_range (pv1, min1, max1);
1849 } else if (min1 == max1) {
1850 g_value_init (pv1, G_TYPE_INT);
1851 g_value_set_int (pv1, min1);
1854 g_value_init (pv2, GST_TYPE_INT_RANGE);
1855 gst_value_set_int_range (pv2, min2, max2);
1856 } else if (min2 == max2) {
1857 g_value_init (pv2, G_TYPE_INT);
1858 g_value_set_int (pv2, min2);
1861 if (min1 <= max1 && min2 <= max2) {
1862 gst_value_list_concat (dest, pv1, pv2);
1863 g_value_unset (pv1);
1864 g_value_unset (pv2);
1870 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
1871 const GValue * subtrahend)
1873 int min = gst_value_get_int_range_min (minuend);
1874 int max = gst_value_get_int_range_max (minuend);
1875 int val = g_value_get_int (subtrahend);
1877 g_return_val_if_fail (min < max, FALSE);
1879 /* value is outside of the range, return range unchanged */
1880 if (val < min || val > max) {
1881 gst_value_init_and_copy (dest, minuend);
1884 /* max must be MAXINT too as val <= max */
1885 if (val == G_MAXINT) {
1889 /* min must be MININT too as val >= max */
1890 if (val == G_MININT) {
1894 gst_value_create_new_range (dest, min, val - 1, val + 1, max);
1900 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
1901 const GValue * subtrahend)
1903 int min1 = gst_value_get_int_range_min (minuend);
1904 int max1 = gst_value_get_int_range_max (minuend);
1905 int min2 = gst_value_get_int_range_min (subtrahend);
1906 int max2 = gst_value_get_int_range_max (subtrahend);
1908 if (max2 == G_MAXINT && min2 == G_MININT) {
1910 } else if (max2 == G_MAXINT) {
1911 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0);
1912 } else if (min2 == G_MININT) {
1913 return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0);
1915 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
1916 MAX (max2 + 1, min1), max1);
1921 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
1922 const GValue * subtrahend)
1924 double min = gst_value_get_double_range_min (subtrahend);
1925 double max = gst_value_get_double_range_max (subtrahend);
1926 double val = g_value_get_double (minuend);
1928 if (val < min || val > max) {
1929 gst_value_init_and_copy (dest, minuend);
1936 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
1937 const GValue * subtrahend)
1939 /* since we don't have open ranges, we cannot create a hole in
1940 * a double range. We return the original range */
1941 gst_value_init_and_copy (dest, minuend);
1946 gst_value_subtract_double_range_double_range (GValue * dest,
1947 const GValue * minuend, const GValue * subtrahend)
1949 /* since we don't have open ranges, we have to approximate */
1950 /* done like with ints */
1951 double min1 = gst_value_get_double_range_min (minuend);
1952 double max2 = gst_value_get_double_range_max (minuend);
1953 double max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
1954 double min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
1957 GValue *pv1, *pv2; /* yeah, hungarian! */
1959 if (min1 < max1 && min2 < max2) {
1962 } else if (min1 < max1) {
1965 } else if (min2 < max2) {
1973 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
1974 gst_value_set_double_range (pv1, min1, max1);
1977 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
1978 gst_value_set_double_range (pv2, min2, max2);
1981 if (min1 < max1 && min2 < max2) {
1982 gst_value_list_concat (dest, pv1, pv2);
1983 g_value_unset (pv1);
1984 g_value_unset (pv2);
1990 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
1991 const GValue * subtrahend)
1994 GValue subtraction = { 0, };
1995 gboolean ret = FALSE;
1997 size = gst_value_list_get_size (minuend);
1998 for (i = 0; i < size; i++) {
1999 const GValue *cur = gst_value_list_get_value (minuend, i);
2001 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
2003 gst_value_init_and_copy (dest, &subtraction);
2005 } else if (GST_VALUE_HOLDS_LIST (dest)
2006 && GST_VALUE_HOLDS_LIST (&subtraction)) {
2008 GValue unroll = { 0, };
2010 gst_value_init_and_copy (&unroll, dest);
2011 g_value_unset (dest);
2012 gst_value_list_concat (dest, &unroll, &subtraction);
2013 } else if (GST_VALUE_HOLDS_LIST (dest)) {
2014 gst_value_list_append_value (dest, &subtraction);
2016 GValue temp = { 0, };
2018 gst_value_init_and_copy (&temp, dest);
2019 g_value_unset (dest);
2020 gst_value_list_concat (dest, &temp, &subtraction);
2021 g_value_unset (&temp);
2023 g_value_unset (&subtraction);
2030 gst_value_subtract_list (GValue * dest, const GValue * minuend,
2031 const GValue * subtrahend)
2034 GValue data[2] = { {0,}, {0,} };
2035 GValue *subtraction = &data[0], *result = &data[1];
2037 gst_value_init_and_copy (result, minuend);
2038 size = gst_value_list_get_size (subtrahend);
2039 for (i = 0; i < size; i++) {
2040 const GValue *cur = gst_value_list_get_value (subtrahend, i);
2042 if (gst_value_subtract (subtraction, result, cur)) {
2043 GValue *temp = result;
2045 result = subtraction;
2047 g_value_unset (subtraction);
2049 g_value_unset (result);
2053 gst_value_init_and_copy (dest, result);
2054 g_value_unset (result);
2064 * gst_value_can_compare:
2065 * @value1: a value to compare
2066 * @value2: another value to compare
2068 * Determines if @value1 and @value2 can be compared.
2070 * Returns: TRUE if the values can be compared
2073 gst_value_can_compare (const GValue * value1, const GValue * value2)
2075 GstValueTable *table;
2078 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2081 for (i = 0; i < gst_value_table->len; i++) {
2082 table = &g_array_index (gst_value_table, GstValueTable, i);
2083 if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare)
2091 * gst_value_compare:
2092 * @value1: a value to compare
2093 * @value2: another value to compare
2095 * Compares @value1 and @value2. If @value1 and @value2 cannot be
2096 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
2097 * if @value1 is greater than @value2, GST_VALUE_GREATER is returned.
2098 * If @value1 is less than @value2, GST_VALUE_LESSER is returned.
2099 * If the values are equal, GST_VALUE_EQUAL is returned.
2101 * Returns: A GstValueCompareType value
2104 gst_value_compare (const GValue * value1, const GValue * value2)
2106 GstValueTable *table, *best = NULL;
2109 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
2110 return GST_VALUE_UNORDERED;
2112 for (i = 0; i < gst_value_table->len; i++) {
2113 table = &g_array_index (gst_value_table, GstValueTable, i);
2114 if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) {
2118 if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) {
2119 if (!best || g_type_is_a (table->type, best->type))
2124 return best->compare (value1, value2);
2127 g_critical ("unable to compare values of type %s\n",
2128 g_type_name (G_VALUE_TYPE (value1)));
2129 return GST_VALUE_UNORDERED;
2135 * gst_value_can_union:
2136 * @value1: a value to union
2137 * @value2: another value to union
2139 * Determines if @value1 and @value2 can be non-trivially unioned.
2140 * Any two values can be trivially unioned by adding both of them
2141 * to a GstValueList. However, certain types have the possibility
2142 * to be unioned in a simpler way. For example, an integer range
2143 * and an integer can be unioned if the integer is a subset of the
2144 * integer range. If there is the possibility that two values can
2145 * be unioned, this function returns TRUE.
2147 * Returns: TRUE if there is a function allowing the two values to
2151 gst_value_can_union (const GValue * value1, const GValue * value2)
2153 GstValueUnionInfo *union_info;
2156 for (i = 0; i < gst_value_union_funcs->len; i++) {
2157 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
2158 if (union_info->type1 == G_VALUE_TYPE (value1) &&
2159 union_info->type2 == G_VALUE_TYPE (value2))
2161 if (union_info->type1 == G_VALUE_TYPE (value2) &&
2162 union_info->type2 == G_VALUE_TYPE (value1))
2171 * @dest: the destination value
2172 * @value1: a value to union
2173 * @value2: another value to union
2175 * Creates a GValue cooresponding to the union of @value1 and @value2.
2177 * Returns: TRUE if the values could be unioned
2180 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
2182 GstValueUnionInfo *union_info;
2185 for (i = 0; i < gst_value_union_funcs->len; i++) {
2186 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
2187 if (union_info->type1 == G_VALUE_TYPE (value1) &&
2188 union_info->type2 == G_VALUE_TYPE (value2)) {
2189 if (union_info->func (dest, value1, value2)) {
2193 if (union_info->type1 == G_VALUE_TYPE (value2) &&
2194 union_info->type2 == G_VALUE_TYPE (value1)) {
2195 if (union_info->func (dest, value2, value1)) {
2201 gst_value_list_concat (dest, value1, value2);
2206 * gst_value_register_union_func:
2207 * @type1: a type to union
2208 * @type2: another type to union
2209 * @func: a function that implments creating a union between the two types
2211 * Registers a union function that can create a union between GValues
2212 * of the type @type1 and @type2.
2216 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
2218 GstValueUnionInfo union_info;
2220 union_info.type1 = type1;
2221 union_info.type2 = type2;
2222 union_info.func = func;
2224 g_array_append_val (gst_value_union_funcs, union_info);
2230 * gst_value_can_intersect:
2231 * @value1: a value to intersect
2232 * @value2: another value to intersect
2234 * Determines if intersecting two values will produce a valid result.
2235 * Two values will produce a valid intersection if they have the same
2236 * type, or if there is a method (registered by
2237 * #gst_value_register_intersection_func) to calculate the intersection.
2239 * Returns: TRUE if the values can intersect
2242 gst_value_can_intersect (const GValue * value1, const GValue * value2)
2244 GstValueIntersectInfo *intersect_info;
2248 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
2251 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
2252 intersect_info = &g_array_index (gst_value_intersect_funcs,
2253 GstValueIntersectInfo, i);
2254 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
2255 intersect_info->type2 == G_VALUE_TYPE (value2))
2256 if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
2257 intersect_info->type1 == G_VALUE_TYPE (value2))
2261 return gst_value_can_compare (value1, value2);
2265 * gst_value_intersect:
2266 * @dest: a uninitialized #GValue that will hold the calculated
2267 * intersection value
2268 * @value1: a value to intersect
2269 * @value2: another value to intersect
2271 * Calculates the intersection of two values. If the values have
2272 * a non-empty intersection, the value representing the intersection
2273 * is placed in @dest. If the intersection is non-empty, @dest is
2276 * Returns: TRUE if the intersection is non-empty
2279 gst_value_intersect (GValue * dest, const GValue * value1,
2280 const GValue * value2)
2282 GstValueIntersectInfo *intersect_info;
2286 /* special cases first */
2287 if (GST_VALUE_HOLDS_LIST (value1))
2288 return gst_value_intersect_list (dest, value1, value2);
2289 if (GST_VALUE_HOLDS_LIST (value2))
2290 return gst_value_intersect_list (dest, value2, value1);
2292 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
2293 intersect_info = &g_array_index (gst_value_intersect_funcs,
2294 GstValueIntersectInfo, i);
2295 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
2296 intersect_info->type2 == G_VALUE_TYPE (value2)) {
2297 ret = intersect_info->func (dest, value1, value2);
2300 if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
2301 intersect_info->type2 == G_VALUE_TYPE (value1)) {
2302 ret = intersect_info->func (dest, value2, value1);
2307 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
2308 gst_value_init_and_copy (dest, value1);
2316 * gst_value_register_intersection_func:
2317 * @type1: the first type to intersect
2318 * @type2: the second type to intersect
2319 * @func: the intersection function
2321 * Registers a function that is called to calculate the intersection
2322 * of the values having the types @type1 and @type2.
2325 * GstValueIntersectFunc:
2326 * @dest: a uninitialized #GValue that will hold the calculated
2327 * intersection value
2328 * @value1: a value to intersect
2329 * @value2: another value to intersect
2331 * Functions having this type calculate the intersection of @value1
2332 * and @value2. If the intersection is non-empty, the result is
2333 * placed in @dest and TRUE is returned. If the intersection is
2334 * empty, @dest is unmodified and FALSE is returned.
2336 * Returns: TRUE if the intersection is non-empty, FALSE otherwise
2339 gst_value_register_intersect_func (GType type1, GType type2,
2340 GstValueIntersectFunc func)
2342 GstValueIntersectInfo intersect_info;
2344 intersect_info.type1 = type1;
2345 intersect_info.type2 = type2;
2346 intersect_info.func = func;
2348 g_array_append_val (gst_value_intersect_funcs, intersect_info);
2355 * gst_value_subtract:
2356 * @dest: the destination value for the result if the subtraction is not empty
2357 * @minuend: the value to subtract from
2358 * @subtrahend: the value to subtract
2360 * Subtracts @subtrahend from @minuend and stores the result in @dest.
2361 * Note that this means subtraction as in sets, not as in mathematics.
2363 * Returns: TRUE if the subtraction is not empty
2366 gst_value_subtract (GValue * dest, const GValue * minuend,
2367 const GValue * subtrahend)
2369 GstValueSubtractInfo *info;
2372 /* special cases first */
2373 if (GST_VALUE_HOLDS_LIST (minuend))
2374 return gst_value_subtract_from_list (dest, minuend, subtrahend);
2375 if (GST_VALUE_HOLDS_LIST (subtrahend))
2376 return gst_value_subtract_list (dest, minuend, subtrahend);
2378 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
2379 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
2380 if (info->minuend == G_VALUE_TYPE (minuend) &&
2381 info->subtrahend == G_VALUE_TYPE (subtrahend)) {
2382 return info->func (dest, minuend, subtrahend);
2386 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
2387 gst_value_init_and_copy (dest, minuend);
2396 gst_value_subtract (GValue * dest, const GValue * minuend,
2397 const GValue * subtrahend)
2399 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
2401 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
2402 gst_value_serialize (subtrahend),
2403 ret ? gst_value_serialize (dest) : "---");
2409 * gst_value_can_subtract:
2410 * @minuend: the value to subtract from
2411 * @subtrahend: the value to subtract
2413 * Checks if it's possible to subtract @subtrahend from @minuend.
2415 * Returns: TRUE if a subtraction is possible
2418 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
2420 GstValueSubtractInfo *info;
2424 if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
2427 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
2428 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
2429 if (info->minuend == G_VALUE_TYPE (minuend) &&
2430 info->subtrahend == G_VALUE_TYPE (subtrahend))
2434 return gst_value_can_compare (minuend, subtrahend);
2438 * gst_value_register_subtract_func:
2439 * @minuend_type: type of the minuend
2440 * @subtrahend_type: type of the subtrahend
2441 * @func: function to use
2443 * Registers @func as a function capable of subtracting the values of
2444 * @subtrahend_type from values of @minuend_type.
2447 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
2448 GstValueSubtractFunc func)
2450 GstValueSubtractInfo info;
2452 /* one type must be unfixed, other subtractions can be done as comparisons */
2453 g_return_if_fail (!gst_type_is_fixed (minuend_type)
2454 || !gst_type_is_fixed (subtrahend_type));
2456 info.minuend = minuend_type;
2457 info.subtrahend = subtrahend_type;
2460 g_array_append_val (gst_value_subtract_funcs, info);
2464 * gst_value_register:
2465 * @table: structure containing functions to register
2467 * Registers functions to perform calculations on #GValues of a given
2472 * @type: GType that the functions operate on.
2473 * @compare: A function that compares two values of this type.
2474 * @serialize: A function that transforms a value of this type to a
2475 * string. Strings created by this function must be unique and should
2476 * be human readable.
2477 * @deserialize: A function that transforms a string to a value of
2478 * this type. This function must transform strings created by the
2479 * serialize function back to the original value. This function may
2480 * optionally transform other strings into values.
2483 gst_value_register (const GstValueTable * table)
2485 g_array_append_val (gst_value_table, *table);
2489 * gst_value_init_and_copy:
2490 * @dest: the target value
2491 * @src: the source value
2493 * Initialises the target value to be of the same type as source and then copies
2494 * the contents from source to target.
2497 gst_value_init_and_copy (GValue * dest, const GValue * src)
2499 g_value_init (dest, G_VALUE_TYPE (src));
2500 g_value_copy (src, dest);
2504 * gst_value_serialize:
2505 * @value: a #GValue to serialize
2507 * tries to transform the given @value into a string representation that allows
2508 * getting back this string later on using gst_value_deserialize().
2510 * Returns: the serialization for @value or NULL if none exists
2513 gst_value_serialize (const GValue * value)
2516 GValue s_val = { 0 };
2517 GstValueTable *table, *best = NULL;
2520 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2522 for (i = 0; i < gst_value_table->len; i++) {
2523 table = &g_array_index (gst_value_table, GstValueTable, i);
2524 if (table->serialize == NULL)
2526 if (table->type == G_VALUE_TYPE (value)) {
2530 if (g_type_is_a (G_VALUE_TYPE (value), table->type)) {
2531 if (!best || g_type_is_a (table->type, best->type))
2536 return best->serialize (value);
2538 g_value_init (&s_val, G_TYPE_STRING);
2539 if (g_value_transform (value, &s_val)) {
2540 s = gst_string_wrap (g_value_get_string (&s_val));
2544 g_value_unset (&s_val);
2550 * gst_value_deserialize:
2551 * @dest: #GValue to fill with contents of deserialization
2552 * @src: string to deserialize
2554 * Tries to deserialize a string into the type specified by the given GValue.
2555 * If the operation succeeds, TRUE is returned, FALSE otherwise.
2557 * Returns: TRUE on success
2560 gst_value_deserialize (GValue * dest, const gchar * src)
2562 GstValueTable *table, *best = NULL;
2565 g_return_val_if_fail (src != NULL, FALSE);
2566 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
2568 for (i = 0; i < gst_value_table->len; i++) {
2569 table = &g_array_index (gst_value_table, GstValueTable, i);
2570 if (table->serialize == NULL)
2573 if (table->type == G_VALUE_TYPE (dest)) {
2578 if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) {
2579 if (!best || g_type_is_a (table->type, best->type))
2584 return best->deserialize (dest, src);
2591 * gst_value_is_fixed:
2592 * @value: the #GValue to check
2594 * Tests if the given GValue, if available in a GstStructure (or any other
2595 * container) contains a "fixed" (which means: one value) or an "unfixed"
2596 * (which means: multiple possible values, such as data lists or data
2599 * Returns: true if the value is "fixed".
2603 gst_value_is_fixed (const GValue * value)
2605 GType type = G_VALUE_TYPE (value);
2607 if (type == GST_TYPE_ARRAY) {
2608 gboolean fixed = TRUE;
2612 /* check recursively */
2613 size = gst_value_list_get_size (value);
2614 for (n = 0; n < size; n++) {
2615 kid = gst_value_list_get_value (value, n);
2616 fixed &= gst_value_is_fixed (kid);
2622 return gst_type_is_fixed (type);
2629 /* helper functions */
2631 /* Finds the greatest common divisor.
2632 * Returns 1 if none other found.
2633 * This is Euclid's algorithm. */
2635 gst_greatest_common_divisor (gint a, gint b)
2648 gst_value_init_fraction (GValue * value)
2650 value->data[0].v_int = 0;
2651 value->data[1].v_int = 1;
2655 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
2657 dest_value->data[0].v_int = src_value->data[0].v_int;
2658 dest_value->data[1].v_int = src_value->data[1].v_int;
2662 gst_value_collect_fraction (GValue * value, guint n_collect_values,
2663 GTypeCValue * collect_values, guint collect_flags)
2665 value->data[0].v_int = collect_values[0].v_int;
2666 value->data[1].v_int = collect_values[1].v_int;
2672 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
2673 GTypeCValue * collect_values, guint collect_flags)
2675 gint *numerator = collect_values[0].v_pointer;
2676 gint *denominator = collect_values[1].v_pointer;
2679 return g_strdup_printf ("numerator for `%s' passed as NULL",
2680 G_VALUE_TYPE_NAME (value));
2682 return g_strdup_printf ("denominator for `%s' passed as NULL",
2683 G_VALUE_TYPE_NAME (value));
2685 *numerator = value->data[0].v_int;
2686 *denominator = value->data[1].v_int;
2692 * gst_value_set_fraction:
2693 * @value: a GValue initialized to #GST_TYPE_FRACTION
2694 * @numerator: the numerator of the fraction
2695 * @denominator: the denominator of the fraction
2697 * Sets @value to the fraction specified by @numerator over @denominator.
2698 * The fraction gets reduced to the smallest numerator and denominator,
2699 * and if necessary the sign is moved to the numerator.
2702 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
2706 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
2707 g_return_if_fail (denominator != 0);
2708 g_return_if_fail (denominator >= -G_MAXINT);
2709 g_return_if_fail (numerator >= -G_MAXINT);
2711 /* normalize sign */
2712 if (denominator < 0) {
2713 numerator = -numerator;
2714 denominator = -denominator;
2717 /* check for reduction */
2718 gcd = gst_greatest_common_divisor (numerator, denominator);
2723 value->data[0].v_int = numerator;
2724 value->data[1].v_int = denominator;
2728 * gst_value_get_fraction_numerator:
2729 * @value: a GValue initialized to #GST_TYPE_FRACTION
2731 * Gets the numerator of the fraction specified by @value.
2733 * Returns: the numerator of the fraction.
2736 gst_value_get_fraction_numerator (const GValue * value)
2738 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
2740 return value->data[0].v_int;
2744 * gst_value_get_fraction_denominator:
2745 * @value: a GValue initialized to #GST_TYPE_FRACTION
2747 * Gets the denominator of the fraction specified by @value.
2749 * Returns: the denominator of the fraction.
2752 gst_value_get_fraction_denominator (const GValue * value)
2754 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
2756 return value->data[1].v_int;
2760 * gst_value_fraction_multiply:
2761 * @product: a GValue initialized to #GST_TYPE_FRACTION
2762 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
2763 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
2765 * Multiplies the two GValues containing a GstFraction and sets @product
2766 * to the product of the two fractions.
2768 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
2771 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
2772 const GValue * factor2)
2774 gint gcd, n1, n2, d1, d2;
2776 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
2777 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
2779 n1 = factor1->data[0].v_int;
2780 n2 = factor2->data[0].v_int;
2781 d1 = factor1->data[1].v_int;
2782 d2 = factor2->data[1].v_int;
2784 gcd = gst_greatest_common_divisor (n1, d2);
2787 gcd = gst_greatest_common_divisor (n2, d1);
2791 g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (n2), FALSE);
2792 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE);
2794 gst_value_set_fraction (product, n1 * n2, d1 * d2);
2800 gst_value_serialize_fraction (const GValue * value)
2802 gint32 numerator = value->data[0].v_int;
2803 gint32 denominator = value->data[1].v_int;
2804 gboolean positive = TRUE;
2806 /* get the sign and make components absolute */
2807 if (numerator < 0) {
2808 numerator = -numerator;
2809 positive = !positive;
2811 if (denominator < 0) {
2812 denominator = -denominator;
2813 positive = !positive;
2816 return g_strdup_printf ("%s%d/%d",
2817 positive ? "" : "-", numerator, denominator);
2821 gst_value_deserialize_fraction (GValue * dest, const char *s)
2827 div = strstr (s, "/");
2830 tmp = g_strndup (s, (size_t) (div - s));
2833 den = atoi (div + 1);
2835 gst_value_set_fraction (dest, num, den);
2841 gst_value_transform_fraction_string (const GValue * src_value,
2842 GValue * dest_value)
2844 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
2848 gst_value_transform_string_fraction (const GValue * src_value,
2849 GValue * dest_value)
2851 gst_value_deserialize_fraction (dest_value, src_value->data[0].v_pointer);
2854 #define MAX_TERMS 30
2855 #define MIN_DIVISOR 1.0e-10
2856 #define MAX_ERROR 1.0e-20
2858 /* use continued fractions to transform a double into a fraction,
2859 * see http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac.
2860 * This algorithm takes care of overflows.
2863 gst_value_transform_double_fraction (const GValue * src_value,
2864 GValue * dest_value)
2866 gdouble V, F; /* double being converted */
2867 gint N, D; /* will contain the result */
2868 gint A; /* current term in continued fraction */
2869 gint64 N1, D1; /* numerator, denominator of last approx */
2870 gint64 N2, D2; /* numerator, denominator of previous approx */
2872 gboolean negative = FALSE;
2874 /* initialize fraction being converted */
2875 F = src_value->data[0].v_double;
2882 /* initialize fractions with 1/0, 0/1 */
2890 for (i = 0; i < MAX_TERMS; i++) {
2893 /* get new divisor */
2896 /* calculate new fraction in temp */
2900 /* guard against overflow */
2901 if (N2 > G_MAXINT || D2 > G_MAXINT) {
2908 /* save last two fractions */
2914 /* quit if dividing by zero or close enough to target */
2915 if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) {
2919 /* Take reciprocal */
2922 /* fix for overflow */
2927 /* fix for negative */
2931 /* will also simplify */
2932 gst_value_set_fraction (dest_value, N, D);
2936 gst_value_transform_fraction_double (const GValue * src_value,
2937 GValue * dest_value)
2939 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
2940 ((double) src_value->data[1].v_int);
2944 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
2952 n1 = value1->data[0].v_int;
2953 n2 = value2->data[0].v_int;
2954 d1 = value1->data[1].v_int;
2955 d2 = value2->data[1].v_int;
2957 /* fractions are reduced when set, so we can quickly see if they're equal */
2958 if (n1 == n2 && d1 == d2)
2959 return GST_VALUE_EQUAL;
2961 /* extend to 64 bits */
2962 new_num_1 = ((gint64) n1) * d2;
2963 new_num_2 = ((gint64) n2) * d1;
2964 if (new_num_1 < new_num_2)
2965 return GST_VALUE_LESS_THAN;
2966 if (new_num_1 > new_num_2)
2967 return GST_VALUE_GREATER_THAN;
2969 g_assert_not_reached ();
2970 return GST_VALUE_UNORDERED;
2974 _gst_value_initialize (void)
2988 GTypeFundamentalInfo finfo = {
2992 //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
2994 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
2995 gst_value_union_funcs = g_array_new (FALSE, FALSE,
2996 sizeof (GstValueUnionInfo));
2997 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
2998 sizeof (GstValueIntersectInfo));
2999 gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
3000 sizeof (GstValueSubtractInfo));
3003 static const GTypeValueTable value_table = {
3004 gst_value_init_fourcc,
3006 gst_value_copy_fourcc,
3009 gst_value_collect_fourcc,
3011 gst_value_lcopy_fourcc
3013 static GstValueTable gst_value = {
3015 gst_value_compare_fourcc,
3016 gst_value_serialize_fourcc,
3017 gst_value_deserialize_fourcc,
3020 info.value_table = &value_table;
3021 gst_type_fourcc = g_type_register_fundamental (g_type_fundamental_next (),
3022 "GstFourcc", &info, &finfo, 0);
3023 gst_value.type = gst_type_fourcc;
3024 gst_value_register (&gst_value);
3028 static const GTypeValueTable value_table = {
3029 gst_value_init_int_range,
3031 gst_value_copy_int_range,
3034 gst_value_collect_int_range,
3036 gst_value_lcopy_int_range
3038 static GstValueTable gst_value = {
3040 gst_value_compare_int_range,
3041 gst_value_serialize_int_range,
3042 gst_value_deserialize_int_range,
3045 info.value_table = &value_table;
3046 gst_type_int_range =
3047 g_type_register_fundamental (g_type_fundamental_next (), "GstIntRange",
3049 gst_value.type = gst_type_int_range;
3050 gst_value_register (&gst_value);
3054 static const GTypeValueTable value_table = {
3055 gst_value_init_double_range,
3057 gst_value_copy_double_range,
3060 gst_value_collect_double_range,
3062 gst_value_lcopy_double_range
3064 static GstValueTable gst_value = {
3066 gst_value_compare_double_range,
3067 gst_value_serialize_double_range,
3068 gst_value_deserialize_double_range,
3071 info.value_table = &value_table;
3072 gst_type_double_range =
3073 g_type_register_fundamental (g_type_fundamental_next (),
3074 "GstDoubleRange", &info, &finfo, 0);
3075 gst_value.type = gst_type_double_range;
3076 gst_value_register (&gst_value);
3080 static const GTypeValueTable value_table = {
3081 gst_value_init_list,
3082 gst_value_free_list,
3083 gst_value_copy_list,
3084 gst_value_list_peek_pointer,
3086 gst_value_collect_list,
3088 gst_value_lcopy_list
3090 static GstValueTable gst_value = {
3092 gst_value_compare_list,
3093 gst_value_serialize_list,
3094 gst_value_deserialize_list,
3097 info.value_table = &value_table;
3098 gst_type_list = g_type_register_fundamental (g_type_fundamental_next (),
3099 "GstValueList", &info, &finfo, 0);
3100 gst_value.type = gst_type_list;
3101 gst_value_register (&gst_value);
3105 static const GTypeValueTable value_table = {
3106 gst_value_init_list,
3107 gst_value_free_list,
3108 gst_value_copy_list,
3109 gst_value_list_peek_pointer,
3111 gst_value_collect_list,
3113 gst_value_lcopy_list
3115 static GstValueTable gst_value = {
3117 gst_value_compare_list,
3118 gst_value_serialize_array,
3119 gst_value_deserialize_array,
3122 info.value_table = &value_table;
3124 g_type_register_fundamental (g_type_fundamental_next (),
3125 "GstValueArray", &info, &finfo, 0);
3126 gst_value.type = gst_type_array;
3127 gst_value_register (&gst_value);
3132 static const GTypeValueTable value_table = {
3133 gst_value_init_buffer,
3135 gst_value_copy_buffer,
3138 NULL, /*gst_value_collect_buffer, */
3140 NULL /*gst_value_lcopy_buffer */
3143 static GstValueTable gst_value = {
3145 gst_value_compare_buffer,
3146 gst_value_serialize_buffer,
3147 gst_value_deserialize_buffer,
3150 gst_value.type = GST_TYPE_BUFFER;
3151 gst_value_register (&gst_value);
3154 static const GTypeValueTable value_table = {
3155 gst_value_init_fraction,
3157 gst_value_copy_fraction,
3160 gst_value_collect_fraction,
3162 gst_value_lcopy_fraction
3164 static GstValueTable gst_value = {
3166 gst_value_compare_fraction,
3167 gst_value_serialize_fraction,
3168 gst_value_deserialize_fraction,
3171 info.value_table = &value_table;
3173 g_type_register_fundamental (g_type_fundamental_next (), "GstFraction",
3175 gst_value.type = gst_type_fraction;
3176 gst_value_register (&gst_value);
3179 static GstValueTable gst_value = {
3182 gst_value_serialize_caps,
3183 gst_value_deserialize_caps,
3186 gst_value.type = GST_TYPE_CAPS;
3187 gst_value_register (&gst_value);
3191 REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
3192 REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
3194 REGISTER_SERIALIZATION (G_TYPE_STRING, string);
3195 REGISTER_SERIALIZATION (G_TYPE_BOOLEAN, boolean);
3196 REGISTER_SERIALIZATION (G_TYPE_ENUM, enum);
3198 REGISTER_SERIALIZATION (G_TYPE_FLAGS, flags);
3200 REGISTER_SERIALIZATION (G_TYPE_INT, int);
3202 REGISTER_SERIALIZATION (G_TYPE_INT64, int64);
3203 REGISTER_SERIALIZATION (G_TYPE_LONG, long);
3205 REGISTER_SERIALIZATION (G_TYPE_UINT, uint);
3206 REGISTER_SERIALIZATION (G_TYPE_UINT64, uint64);
3207 REGISTER_SERIALIZATION (G_TYPE_ULONG, ulong);
3209 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
3210 gst_value_transform_fourcc_string);
3211 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
3212 gst_value_transform_int_range_string);
3213 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
3214 gst_value_transform_double_range_string);
3215 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
3216 gst_value_transform_list_string);
3217 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
3218 gst_value_transform_array_string);
3219 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
3220 gst_value_transform_fraction_string);
3221 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
3222 gst_value_transform_string_fraction);
3223 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
3224 gst_value_transform_fraction_double);
3225 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
3226 gst_value_transform_double_fraction);
3228 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
3229 gst_value_intersect_int_int_range);
3230 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
3231 gst_value_intersect_int_range_int_range);
3232 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
3233 gst_value_intersect_double_double_range);
3234 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
3235 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
3236 gst_value_register_intersect_func (GST_TYPE_ARRAY,
3237 GST_TYPE_ARRAY, gst_value_intersect_array);
3239 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
3240 gst_value_subtract_int_int_range);
3241 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
3242 gst_value_subtract_int_range_int);
3243 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
3244 gst_value_subtract_int_range_int_range);
3245 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
3246 gst_value_subtract_double_double_range);
3247 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
3248 gst_value_subtract_double_range_double);
3249 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
3250 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
3252 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
3253 gst_value_union_int_int_range);
3254 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
3255 gst_value_union_int_range_int_range);