|
1 /* GStreamer |
|
2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org> |
|
3 * |
|
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. |
|
8 * |
|
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. |
|
13 * |
|
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. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:gstvalue |
|
22 * @short_description: GValue and GParamSpec implementations specific |
|
23 * to GStreamer |
|
24 * |
|
25 * GValue and GParamSpec implementations specific to GStreamer. |
|
26 * |
|
27 * Note that operations on the same GstValue (or GValue) from multiple |
|
28 * threads may lead to undefined behaviour. |
|
29 * |
|
30 * Last reviewed on 2006-03-07 (0.10.4) |
|
31 */ |
|
32 |
|
33 #ifdef HAVE_CONFIG_H |
|
34 #include "config.h" |
|
35 #endif |
|
36 #include <math.h> |
|
37 #include <stdlib.h> |
|
38 #include <string.h> |
|
39 #include <ctype.h> |
|
40 |
|
41 #include "gst_private.h" |
|
42 #include "glib-compat-private.h" |
|
43 #include <gst/gst.h> |
|
44 #include <gobject/gvaluecollector.h> |
|
45 |
|
46 #ifdef __SYMBIAN32__ |
|
47 #include <glib_global.h> |
|
48 #endif |
|
49 |
|
50 typedef struct _GstValueUnionInfo GstValueUnionInfo; |
|
51 struct _GstValueUnionInfo |
|
52 { |
|
53 GType type1; |
|
54 GType type2; |
|
55 GstValueUnionFunc func; |
|
56 }; |
|
57 |
|
58 typedef struct _GstValueIntersectInfo GstValueIntersectInfo; |
|
59 struct _GstValueIntersectInfo |
|
60 { |
|
61 GType type1; |
|
62 GType type2; |
|
63 GstValueIntersectFunc func; |
|
64 }; |
|
65 |
|
66 typedef struct _GstValueSubtractInfo GstValueSubtractInfo; |
|
67 struct _GstValueSubtractInfo |
|
68 { |
|
69 GType minuend; |
|
70 GType subtrahend; |
|
71 GstValueSubtractFunc func; |
|
72 }; |
|
73 |
|
74 static GArray *gst_value_table; |
|
75 static GArray *gst_value_union_funcs; |
|
76 static GArray *gst_value_intersect_funcs; |
|
77 static GArray *gst_value_subtract_funcs; |
|
78 |
|
79 /* Forward declarations */ |
|
80 static gint gst_greatest_common_divisor (gint a, gint b); |
|
81 static gchar *gst_value_serialize_fraction (const GValue * value); |
|
82 |
|
83 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1); |
|
84 static gint gst_value_compare_with_func (const GValue * value1, |
|
85 const GValue * value2, GstValueCompareFunc compare); |
|
86 |
|
87 /******** |
|
88 * list * |
|
89 ********/ |
|
90 |
|
91 /* two helper functions to serialize/stringify any type of list |
|
92 * regular lists are done with { }, arrays with < > |
|
93 */ |
|
94 static gchar * |
|
95 gst_value_serialize_any_list (const GValue * value, const gchar * begin, |
|
96 const gchar * end) |
|
97 { |
|
98 guint i; |
|
99 GArray *array = value->data[0].v_pointer; |
|
100 GString *s; |
|
101 GValue *v; |
|
102 gchar *s_val; |
|
103 |
|
104 /* estimate minimum string length to minimise re-allocs in GString */ |
|
105 s = g_string_sized_new (2 + (6 * array->len) + 2); |
|
106 g_string_append (s, begin); |
|
107 for (i = 0; i < array->len; i++) { |
|
108 v = &g_array_index (array, GValue, i); |
|
109 s_val = gst_value_serialize (v); |
|
110 g_string_append (s, s_val); |
|
111 g_free (s_val); |
|
112 if (i < array->len - 1) { |
|
113 g_string_append_len (s, ", ", 2); |
|
114 } |
|
115 } |
|
116 g_string_append (s, end); |
|
117 return g_string_free (s, FALSE); |
|
118 } |
|
119 |
|
120 static void |
|
121 gst_value_transform_any_list_string (const GValue * src_value, |
|
122 GValue * dest_value, const gchar * begin, const gchar * end) |
|
123 { |
|
124 GValue *list_value; |
|
125 GArray *array; |
|
126 GString *s; |
|
127 guint i; |
|
128 gchar *list_s; |
|
129 |
|
130 array = src_value->data[0].v_pointer; |
|
131 |
|
132 /* estimate minimum string length to minimise re-allocs in GString */ |
|
133 s = g_string_sized_new (2 + (10 * array->len) + 2); |
|
134 g_string_append (s, begin); |
|
135 for (i = 0; i < array->len; i++) { |
|
136 list_value = &g_array_index (array, GValue, i); |
|
137 |
|
138 if (i != 0) { |
|
139 g_string_append_len (s, ", ", 2); |
|
140 } |
|
141 list_s = g_strdup_value_contents (list_value); |
|
142 g_string_append (s, list_s); |
|
143 g_free (list_s); |
|
144 } |
|
145 g_string_append (s, end); |
|
146 |
|
147 dest_value->data[0].v_pointer = g_string_free (s, FALSE); |
|
148 } |
|
149 |
|
150 /* |
|
151 * helper function to see if a type is fixed. Is used internally here and |
|
152 * there. Do not export, since it doesn't work for types where the content |
|
153 * decides the fixedness (e.g. GST_TYPE_ARRAY). |
|
154 */ |
|
155 |
|
156 static gboolean |
|
157 gst_type_is_fixed (GType type) |
|
158 { |
|
159 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE || |
|
160 type == GST_TYPE_LIST) { |
|
161 return FALSE; |
|
162 } |
|
163 if (G_TYPE_FUNDAMENTAL (type) <= |
|
164 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { |
|
165 return TRUE; |
|
166 } |
|
167 if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC |
|
168 || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) { |
|
169 return TRUE; |
|
170 } |
|
171 |
|
172 return FALSE; |
|
173 } |
|
174 |
|
175 /* GValue functions usable for both regular lists and arrays */ |
|
176 static void |
|
177 gst_value_init_list_or_array (GValue * value) |
|
178 { |
|
179 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue)); |
|
180 } |
|
181 |
|
182 static GArray * |
|
183 copy_garray_of_gstvalue (const GArray * src) |
|
184 { |
|
185 GArray *dest; |
|
186 guint i; |
|
187 |
|
188 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len); |
|
189 g_array_set_size (dest, src->len); |
|
190 for (i = 0; i < src->len; i++) { |
|
191 gst_value_init_and_copy (&g_array_index (dest, GValue, i), |
|
192 &g_array_index (src, GValue, i)); |
|
193 } |
|
194 |
|
195 return dest; |
|
196 } |
|
197 |
|
198 static void |
|
199 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value) |
|
200 { |
|
201 dest_value->data[0].v_pointer = |
|
202 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer); |
|
203 } |
|
204 |
|
205 static void |
|
206 gst_value_free_list_or_array (GValue * value) |
|
207 { |
|
208 guint i; |
|
209 GArray *src = (GArray *) value->data[0].v_pointer; |
|
210 |
|
211 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) { |
|
212 for (i = 0; i < src->len; i++) { |
|
213 g_value_unset (&g_array_index (src, GValue, i)); |
|
214 } |
|
215 g_array_free (src, TRUE); |
|
216 } |
|
217 } |
|
218 |
|
219 static gpointer |
|
220 gst_value_list_or_array_peek_pointer (const GValue * value) |
|
221 { |
|
222 return value->data[0].v_pointer; |
|
223 } |
|
224 |
|
225 static gchar * |
|
226 gst_value_collect_list_or_array (GValue * value, guint n_collect_values, |
|
227 GTypeCValue * collect_values, guint collect_flags) |
|
228 { |
|
229 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { |
|
230 value->data[0].v_pointer = collect_values[0].v_pointer; |
|
231 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS; |
|
232 } else { |
|
233 value->data[0].v_pointer = |
|
234 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer); |
|
235 } |
|
236 return NULL; |
|
237 } |
|
238 |
|
239 static gchar * |
|
240 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values, |
|
241 GTypeCValue * collect_values, guint collect_flags) |
|
242 { |
|
243 GArray **dest = collect_values[0].v_pointer; |
|
244 |
|
245 if (!dest) |
|
246 return g_strdup_printf ("value location for `%s' passed as NULL", |
|
247 G_VALUE_TYPE_NAME (value)); |
|
248 if (!value->data[0].v_pointer) |
|
249 return g_strdup_printf ("invalid value given for `%s'", |
|
250 G_VALUE_TYPE_NAME (value)); |
|
251 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { |
|
252 *dest = (GArray *) value->data[0].v_pointer; |
|
253 } else { |
|
254 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer); |
|
255 } |
|
256 return NULL; |
|
257 } |
|
258 |
|
259 /** |
|
260 * gst_value_list_append_value: |
|
261 * @value: a #GValue of type #GST_TYPE_LIST |
|
262 * @append_value: the value to append |
|
263 * |
|
264 * Appends @append_value to the GstValueList in @value. |
|
265 */ |
|
266 #ifdef __SYMBIAN32__ |
|
267 EXPORT_C |
|
268 #endif |
|
269 |
|
270 void |
|
271 gst_value_list_append_value (GValue * value, const GValue * append_value) |
|
272 { |
|
273 GValue val = { 0, }; |
|
274 |
|
275 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)); |
|
276 |
|
277 gst_value_init_and_copy (&val, append_value); |
|
278 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1); |
|
279 } |
|
280 |
|
281 /** |
|
282 * gst_value_list_prepend_value: |
|
283 * @value: a #GValue of type #GST_TYPE_LIST |
|
284 * @prepend_value: the value to prepend |
|
285 * |
|
286 * Prepends @prepend_value to the GstValueList in @value. |
|
287 */ |
|
288 #ifdef __SYMBIAN32__ |
|
289 EXPORT_C |
|
290 #endif |
|
291 |
|
292 void |
|
293 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value) |
|
294 { |
|
295 GValue val = { 0, }; |
|
296 |
|
297 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)); |
|
298 |
|
299 gst_value_init_and_copy (&val, prepend_value); |
|
300 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1); |
|
301 } |
|
302 |
|
303 /** |
|
304 * gst_value_list_concat: |
|
305 * @dest: an uninitialized #GValue to take the result |
|
306 * @value1: a #GValue |
|
307 * @value2: a #GValue |
|
308 * |
|
309 * Concatenates copies of @value1 and @value2 into a list. Values that are not |
|
310 * of type #GST_TYPE_LIST are treated as if they were lists of length 1. |
|
311 * @dest will be initialized to the type #GST_TYPE_LIST. |
|
312 */ |
|
313 #ifdef __SYMBIAN32__ |
|
314 EXPORT_C |
|
315 #endif |
|
316 |
|
317 void |
|
318 gst_value_list_concat (GValue * dest, const GValue * value1, |
|
319 const GValue * value2) |
|
320 { |
|
321 guint i, value1_length, value2_length; |
|
322 GArray *array; |
|
323 |
|
324 g_return_if_fail (dest != NULL); |
|
325 g_return_if_fail (G_VALUE_TYPE (dest) == 0); |
|
326 g_return_if_fail (G_IS_VALUE (value1)); |
|
327 g_return_if_fail (G_IS_VALUE (value2)); |
|
328 |
|
329 value1_length = |
|
330 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1); |
|
331 value2_length = |
|
332 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1); |
|
333 g_value_init (dest, GST_TYPE_LIST); |
|
334 array = (GArray *) dest->data[0].v_pointer; |
|
335 g_array_set_size (array, value1_length + value2_length); |
|
336 |
|
337 if (GST_VALUE_HOLDS_LIST (value1)) { |
|
338 for (i = 0; i < value1_length; i++) { |
|
339 gst_value_init_and_copy (&g_array_index (array, GValue, i), |
|
340 gst_value_list_get_value (value1, i)); |
|
341 } |
|
342 } else { |
|
343 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1); |
|
344 } |
|
345 |
|
346 if (GST_VALUE_HOLDS_LIST (value2)) { |
|
347 for (i = 0; i < value2_length; i++) { |
|
348 gst_value_init_and_copy (&g_array_index (array, GValue, |
|
349 i + value1_length), gst_value_list_get_value (value2, i)); |
|
350 } |
|
351 } else { |
|
352 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length), |
|
353 value2); |
|
354 } |
|
355 } |
|
356 |
|
357 /** |
|
358 * gst_value_list_get_size: |
|
359 * @value: a #GValue of type #GST_TYPE_LIST |
|
360 * |
|
361 * Gets the number of values contained in @value. |
|
362 * |
|
363 * Returns: the number of values |
|
364 */ |
|
365 #ifdef __SYMBIAN32__ |
|
366 EXPORT_C |
|
367 #endif |
|
368 |
|
369 guint |
|
370 gst_value_list_get_size (const GValue * value) |
|
371 { |
|
372 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0); |
|
373 |
|
374 return ((GArray *) value->data[0].v_pointer)->len; |
|
375 } |
|
376 |
|
377 /** |
|
378 * gst_value_list_get_value: |
|
379 * @value: a #GValue of type #GST_TYPE_LIST |
|
380 * @index: index of value to get from the list |
|
381 * |
|
382 * Gets the value that is a member of the list contained in @value and |
|
383 * has the index @index. |
|
384 * |
|
385 * Returns: the value at the given index |
|
386 */ |
|
387 #ifdef __SYMBIAN32__ |
|
388 EXPORT_C |
|
389 #endif |
|
390 |
|
391 const GValue * |
|
392 gst_value_list_get_value (const GValue * value, guint index) |
|
393 { |
|
394 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL); |
|
395 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL); |
|
396 |
|
397 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, |
|
398 GValue, index); |
|
399 } |
|
400 |
|
401 /** |
|
402 * gst_value_array_append_value: |
|
403 * @value: a #GValue of type #GST_TYPE_ARRAY |
|
404 * @append_value: the value to append |
|
405 * |
|
406 * Appends @append_value to the GstValueArray in @value. |
|
407 */ |
|
408 #ifdef __SYMBIAN32__ |
|
409 EXPORT_C |
|
410 #endif |
|
411 |
|
412 void |
|
413 gst_value_array_append_value (GValue * value, const GValue * append_value) |
|
414 { |
|
415 GValue val = { 0, }; |
|
416 |
|
417 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value)); |
|
418 |
|
419 gst_value_init_and_copy (&val, append_value); |
|
420 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1); |
|
421 } |
|
422 |
|
423 /** |
|
424 * gst_value_array_prepend_value: |
|
425 * @value: a #GValue of type #GST_TYPE_ARRAY |
|
426 * @prepend_value: the value to prepend |
|
427 * |
|
428 * Prepends @prepend_value to the GstValueArray in @value. |
|
429 */ |
|
430 #ifdef __SYMBIAN32__ |
|
431 EXPORT_C |
|
432 #endif |
|
433 |
|
434 void |
|
435 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value) |
|
436 { |
|
437 GValue val = { 0, }; |
|
438 |
|
439 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value)); |
|
440 |
|
441 gst_value_init_and_copy (&val, prepend_value); |
|
442 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1); |
|
443 } |
|
444 |
|
445 /** |
|
446 * gst_value_array_get_size: |
|
447 * @value: a #GValue of type #GST_TYPE_ARRAY |
|
448 * |
|
449 * Gets the number of values contained in @value. |
|
450 * |
|
451 * Returns: the number of values |
|
452 */ |
|
453 #ifdef __SYMBIAN32__ |
|
454 EXPORT_C |
|
455 #endif |
|
456 |
|
457 guint |
|
458 gst_value_array_get_size (const GValue * value) |
|
459 { |
|
460 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0); |
|
461 |
|
462 return ((GArray *) value->data[0].v_pointer)->len; |
|
463 } |
|
464 |
|
465 /** |
|
466 * gst_value_array_get_value: |
|
467 * @value: a #GValue of type #GST_TYPE_ARRAY |
|
468 * @index: index of value to get from the array |
|
469 * |
|
470 * Gets the value that is a member of the array contained in @value and |
|
471 * has the index @index. |
|
472 * |
|
473 * Returns: the value at the given index |
|
474 */ |
|
475 #ifdef __SYMBIAN32__ |
|
476 EXPORT_C |
|
477 #endif |
|
478 |
|
479 const GValue * |
|
480 gst_value_array_get_value (const GValue * value, guint index) |
|
481 { |
|
482 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL); |
|
483 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL); |
|
484 |
|
485 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, |
|
486 GValue, index); |
|
487 } |
|
488 |
|
489 static void |
|
490 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value) |
|
491 { |
|
492 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }"); |
|
493 } |
|
494 |
|
495 static void |
|
496 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value) |
|
497 { |
|
498 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >"); |
|
499 } |
|
500 |
|
501 /* Do an unordered compare of the contents of a list */ |
|
502 static int |
|
503 gst_value_compare_list (const GValue * value1, const GValue * value2) |
|
504 { |
|
505 guint i, j; |
|
506 GArray *array1 = value1->data[0].v_pointer; |
|
507 GArray *array2 = value2->data[0].v_pointer; |
|
508 GValue *v1; |
|
509 GValue *v2; |
|
510 gint len, to_remove; |
|
511 guint8 *removed; |
|
512 GstValueCompareFunc compare; |
|
513 |
|
514 /* get length and do initial length check. */ |
|
515 len = array1->len; |
|
516 if (len != array2->len) |
|
517 return GST_VALUE_UNORDERED; |
|
518 |
|
519 /* place to mark removed value indices of array2 */ |
|
520 removed = g_newa (guint8, len); |
|
521 memset (removed, 0, len); |
|
522 to_remove = len; |
|
523 |
|
524 /* loop over array1, all items should be in array2. When we find an |
|
525 * item in array2, remove it from array2 by marking it as removed */ |
|
526 for (i = 0; i < len; i++) { |
|
527 v1 = &g_array_index (array1, GValue, i); |
|
528 if ((compare = gst_value_get_compare_func (v1))) { |
|
529 for (j = 0; j < len; j++) { |
|
530 /* item is removed, we can skip it */ |
|
531 if (removed[j]) |
|
532 continue; |
|
533 v2 = &g_array_index (array2, GValue, j); |
|
534 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) { |
|
535 /* mark item as removed now that we found it in array2 and |
|
536 * decrement the number of remaining items in array2. */ |
|
537 removed[j] = 1; |
|
538 to_remove--; |
|
539 break; |
|
540 } |
|
541 } |
|
542 /* item in array1 and not in array2, UNORDERED */ |
|
543 if (j == len) |
|
544 return GST_VALUE_UNORDERED; |
|
545 } else |
|
546 return GST_VALUE_UNORDERED; |
|
547 } |
|
548 /* if not all items were removed, array2 contained something not in array1 */ |
|
549 if (to_remove != 0) |
|
550 return GST_VALUE_UNORDERED; |
|
551 |
|
552 /* arrays are equal */ |
|
553 return GST_VALUE_EQUAL; |
|
554 } |
|
555 |
|
556 /* Perform an ordered comparison of the contents of an array */ |
|
557 static int |
|
558 gst_value_compare_array (const GValue * value1, const GValue * value2) |
|
559 { |
|
560 guint i; |
|
561 GArray *array1 = value1->data[0].v_pointer; |
|
562 GArray *array2 = value2->data[0].v_pointer; |
|
563 GValue *v1; |
|
564 GValue *v2; |
|
565 |
|
566 if (array1->len != array2->len) |
|
567 return GST_VALUE_UNORDERED; |
|
568 |
|
569 for (i = 0; i < array1->len; i++) { |
|
570 v1 = &g_array_index (array1, GValue, i); |
|
571 v2 = &g_array_index (array2, GValue, i); |
|
572 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL) |
|
573 return GST_VALUE_UNORDERED; |
|
574 } |
|
575 |
|
576 return GST_VALUE_EQUAL; |
|
577 } |
|
578 |
|
579 static gchar * |
|
580 gst_value_serialize_list (const GValue * value) |
|
581 { |
|
582 return gst_value_serialize_any_list (value, "{ ", " }"); |
|
583 } |
|
584 |
|
585 static gboolean |
|
586 gst_value_deserialize_list (GValue * dest, const gchar * s) |
|
587 { |
|
588 g_warning ("gst_value_deserialize_list: unimplemented"); |
|
589 return FALSE; |
|
590 } |
|
591 |
|
592 static gchar * |
|
593 gst_value_serialize_array (const GValue * value) |
|
594 { |
|
595 return gst_value_serialize_any_list (value, "< ", " >"); |
|
596 } |
|
597 |
|
598 static gboolean |
|
599 gst_value_deserialize_array (GValue * dest, const gchar * s) |
|
600 { |
|
601 g_warning ("gst_value_deserialize_array: unimplemented"); |
|
602 return FALSE; |
|
603 } |
|
604 |
|
605 /********** |
|
606 * fourcc * |
|
607 **********/ |
|
608 |
|
609 static void |
|
610 gst_value_init_fourcc (GValue * value) |
|
611 { |
|
612 value->data[0].v_int = 0; |
|
613 } |
|
614 |
|
615 static void |
|
616 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value) |
|
617 { |
|
618 dest_value->data[0].v_int = src_value->data[0].v_int; |
|
619 } |
|
620 |
|
621 static gchar * |
|
622 gst_value_collect_fourcc (GValue * value, guint n_collect_values, |
|
623 GTypeCValue * collect_values, guint collect_flags) |
|
624 { |
|
625 value->data[0].v_int = collect_values[0].v_int; |
|
626 |
|
627 return NULL; |
|
628 } |
|
629 |
|
630 static gchar * |
|
631 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values, |
|
632 GTypeCValue * collect_values, guint collect_flags) |
|
633 { |
|
634 guint32 *fourcc_p = collect_values[0].v_pointer; |
|
635 |
|
636 if (!fourcc_p) |
|
637 return g_strdup_printf ("value location for `%s' passed as NULL", |
|
638 G_VALUE_TYPE_NAME (value)); |
|
639 |
|
640 *fourcc_p = value->data[0].v_int; |
|
641 |
|
642 return NULL; |
|
643 } |
|
644 |
|
645 /** |
|
646 * gst_value_set_fourcc: |
|
647 * @value: a GValue initialized to #GST_TYPE_FOURCC |
|
648 * @fourcc: the #guint32 fourcc to set |
|
649 * |
|
650 * Sets @value to @fourcc. |
|
651 */ |
|
652 #ifdef __SYMBIAN32__ |
|
653 EXPORT_C |
|
654 #endif |
|
655 |
|
656 void |
|
657 gst_value_set_fourcc (GValue * value, guint32 fourcc) |
|
658 { |
|
659 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value)); |
|
660 |
|
661 value->data[0].v_int = fourcc; |
|
662 } |
|
663 |
|
664 /** |
|
665 * gst_value_get_fourcc: |
|
666 * @value: a GValue initialized to #GST_TYPE_FOURCC |
|
667 * |
|
668 * Gets the #guint32 fourcc contained in @value. |
|
669 * |
|
670 * Returns: the #guint32 fourcc contained in @value. |
|
671 */ |
|
672 #ifdef __SYMBIAN32__ |
|
673 EXPORT_C |
|
674 #endif |
|
675 |
|
676 guint32 |
|
677 gst_value_get_fourcc (const GValue * value) |
|
678 { |
|
679 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0); |
|
680 |
|
681 return value->data[0].v_int; |
|
682 } |
|
683 |
|
684 static void |
|
685 gst_value_transform_fourcc_string (const GValue * src_value, |
|
686 GValue * dest_value) |
|
687 { |
|
688 guint32 fourcc = src_value->data[0].v_int; |
|
689 |
|
690 if (g_ascii_isprint ((fourcc >> 0) & 0xff) && |
|
691 g_ascii_isprint ((fourcc >> 8) & 0xff) && |
|
692 g_ascii_isprint ((fourcc >> 16) & 0xff) && |
|
693 g_ascii_isprint ((fourcc >> 24) & 0xff)) { |
|
694 dest_value->data[0].v_pointer = |
|
695 g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); |
|
696 } else { |
|
697 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc); |
|
698 } |
|
699 } |
|
700 |
|
701 static gint |
|
702 gst_value_compare_fourcc (const GValue * value1, const GValue * value2) |
|
703 { |
|
704 if (value2->data[0].v_int == value1->data[0].v_int) |
|
705 return GST_VALUE_EQUAL; |
|
706 return GST_VALUE_UNORDERED; |
|
707 } |
|
708 |
|
709 static gchar * |
|
710 gst_value_serialize_fourcc (const GValue * value) |
|
711 { |
|
712 guint32 fourcc = value->data[0].v_int; |
|
713 |
|
714 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) && |
|
715 g_ascii_isalnum ((fourcc >> 8) & 0xff) && |
|
716 g_ascii_isalnum ((fourcc >> 16) & 0xff) && |
|
717 g_ascii_isalnum ((fourcc >> 24) & 0xff)) { |
|
718 return g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); |
|
719 } else { |
|
720 return g_strdup_printf ("0x%08x", fourcc); |
|
721 } |
|
722 } |
|
723 |
|
724 static gboolean |
|
725 gst_value_deserialize_fourcc (GValue * dest, const char *s) |
|
726 { |
|
727 gboolean ret = FALSE; |
|
728 guint32 fourcc = 0; |
|
729 char *end; |
|
730 |
|
731 if (strlen (s) == 4) { |
|
732 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]); |
|
733 ret = TRUE; |
|
734 } else if (g_ascii_isdigit (*s)) { |
|
735 fourcc = strtoul (s, &end, 0); |
|
736 if (*end == 0) { |
|
737 ret = TRUE; |
|
738 } |
|
739 } |
|
740 gst_value_set_fourcc (dest, fourcc); |
|
741 |
|
742 return ret; |
|
743 } |
|
744 |
|
745 /************* |
|
746 * int range * |
|
747 *************/ |
|
748 |
|
749 static void |
|
750 gst_value_init_int_range (GValue * value) |
|
751 { |
|
752 value->data[0].v_int = 0; |
|
753 value->data[1].v_int = 0; |
|
754 } |
|
755 |
|
756 static void |
|
757 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value) |
|
758 { |
|
759 dest_value->data[0].v_int = src_value->data[0].v_int; |
|
760 dest_value->data[1].v_int = src_value->data[1].v_int; |
|
761 } |
|
762 |
|
763 static gchar * |
|
764 gst_value_collect_int_range (GValue * value, guint n_collect_values, |
|
765 GTypeCValue * collect_values, guint collect_flags) |
|
766 { |
|
767 value->data[0].v_int = collect_values[0].v_int; |
|
768 value->data[1].v_int = collect_values[1].v_int; |
|
769 |
|
770 return NULL; |
|
771 } |
|
772 |
|
773 static gchar * |
|
774 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values, |
|
775 GTypeCValue * collect_values, guint collect_flags) |
|
776 { |
|
777 guint32 *int_range_start = collect_values[0].v_pointer; |
|
778 guint32 *int_range_end = collect_values[1].v_pointer; |
|
779 |
|
780 if (!int_range_start) |
|
781 return g_strdup_printf ("start value location for `%s' passed as NULL", |
|
782 G_VALUE_TYPE_NAME (value)); |
|
783 if (!int_range_end) |
|
784 return g_strdup_printf ("end value location for `%s' passed as NULL", |
|
785 G_VALUE_TYPE_NAME (value)); |
|
786 |
|
787 *int_range_start = value->data[0].v_int; |
|
788 *int_range_end = value->data[1].v_int; |
|
789 |
|
790 return NULL; |
|
791 } |
|
792 |
|
793 /** |
|
794 * gst_value_set_int_range: |
|
795 * @value: a GValue initialized to GST_TYPE_INT_RANGE |
|
796 * @start: the start of the range |
|
797 * @end: the end of the range |
|
798 * |
|
799 * Sets @value to the range specified by @start and @end. |
|
800 */ |
|
801 #ifdef __SYMBIAN32__ |
|
802 EXPORT_C |
|
803 #endif |
|
804 |
|
805 void |
|
806 gst_value_set_int_range (GValue * value, gint start, gint end) |
|
807 { |
|
808 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value)); |
|
809 g_return_if_fail (start < end); |
|
810 |
|
811 value->data[0].v_int = start; |
|
812 value->data[1].v_int = end; |
|
813 } |
|
814 |
|
815 /** |
|
816 * gst_value_get_int_range_min: |
|
817 * @value: a GValue initialized to GST_TYPE_INT_RANGE |
|
818 * |
|
819 * Gets the minimum of the range specified by @value. |
|
820 * |
|
821 * Returns: the minimum of the range |
|
822 */ |
|
823 #ifdef __SYMBIAN32__ |
|
824 EXPORT_C |
|
825 #endif |
|
826 |
|
827 gint |
|
828 gst_value_get_int_range_min (const GValue * value) |
|
829 { |
|
830 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); |
|
831 |
|
832 return value->data[0].v_int; |
|
833 } |
|
834 |
|
835 /** |
|
836 * gst_value_get_int_range_max: |
|
837 * @value: a GValue initialized to GST_TYPE_INT_RANGE |
|
838 * |
|
839 * Gets the maximum of the range specified by @value. |
|
840 * |
|
841 * Returns: the maxumum of the range |
|
842 */ |
|
843 #ifdef __SYMBIAN32__ |
|
844 EXPORT_C |
|
845 #endif |
|
846 |
|
847 gint |
|
848 gst_value_get_int_range_max (const GValue * value) |
|
849 { |
|
850 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0); |
|
851 |
|
852 return value->data[1].v_int; |
|
853 } |
|
854 |
|
855 static void |
|
856 gst_value_transform_int_range_string (const GValue * src_value, |
|
857 GValue * dest_value) |
|
858 { |
|
859 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]", |
|
860 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int); |
|
861 } |
|
862 |
|
863 static gint |
|
864 gst_value_compare_int_range (const GValue * value1, const GValue * value2) |
|
865 { |
|
866 if (value2->data[0].v_int == value1->data[0].v_int && |
|
867 value2->data[1].v_int == value1->data[1].v_int) |
|
868 return GST_VALUE_EQUAL; |
|
869 return GST_VALUE_UNORDERED; |
|
870 } |
|
871 |
|
872 static gchar * |
|
873 gst_value_serialize_int_range (const GValue * value) |
|
874 { |
|
875 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int, |
|
876 value->data[1].v_int); |
|
877 } |
|
878 |
|
879 static gboolean |
|
880 gst_value_deserialize_int_range (GValue * dest, const gchar * s) |
|
881 { |
|
882 g_warning ("unimplemented"); |
|
883 return FALSE; |
|
884 } |
|
885 |
|
886 /**************** |
|
887 * double range * |
|
888 ****************/ |
|
889 |
|
890 static void |
|
891 gst_value_init_double_range (GValue * value) |
|
892 { |
|
893 value->data[0].v_double = 0; |
|
894 value->data[1].v_double = 0; |
|
895 } |
|
896 |
|
897 static void |
|
898 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value) |
|
899 { |
|
900 dest_value->data[0].v_double = src_value->data[0].v_double; |
|
901 dest_value->data[1].v_double = src_value->data[1].v_double; |
|
902 } |
|
903 |
|
904 static gchar * |
|
905 gst_value_collect_double_range (GValue * value, guint n_collect_values, |
|
906 GTypeCValue * collect_values, guint collect_flags) |
|
907 { |
|
908 value->data[0].v_double = collect_values[0].v_double; |
|
909 value->data[1].v_double = collect_values[1].v_double; |
|
910 |
|
911 return NULL; |
|
912 } |
|
913 |
|
914 static gchar * |
|
915 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values, |
|
916 GTypeCValue * collect_values, guint collect_flags) |
|
917 { |
|
918 gdouble *double_range_start = collect_values[0].v_pointer; |
|
919 gdouble *double_range_end = collect_values[1].v_pointer; |
|
920 |
|
921 if (!double_range_start) |
|
922 return g_strdup_printf ("start value location for `%s' passed as NULL", |
|
923 G_VALUE_TYPE_NAME (value)); |
|
924 if (!double_range_end) |
|
925 return g_strdup_printf ("end value location for `%s' passed as NULL", |
|
926 G_VALUE_TYPE_NAME (value)); |
|
927 |
|
928 *double_range_start = value->data[0].v_double; |
|
929 *double_range_end = value->data[1].v_double; |
|
930 |
|
931 return NULL; |
|
932 } |
|
933 |
|
934 /** |
|
935 * gst_value_set_double_range: |
|
936 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE |
|
937 * @start: the start of the range |
|
938 * @end: the end of the range |
|
939 * |
|
940 * Sets @value to the range specified by @start and @end. |
|
941 */ |
|
942 #ifdef __SYMBIAN32__ |
|
943 EXPORT_C |
|
944 #endif |
|
945 |
|
946 void |
|
947 gst_value_set_double_range (GValue * value, gdouble start, gdouble end) |
|
948 { |
|
949 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value)); |
|
950 |
|
951 value->data[0].v_double = start; |
|
952 value->data[1].v_double = end; |
|
953 } |
|
954 |
|
955 /** |
|
956 * gst_value_get_double_range_min: |
|
957 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE |
|
958 * |
|
959 * Gets the minimum of the range specified by @value. |
|
960 * |
|
961 * Returns: the minumum of the range |
|
962 */ |
|
963 #ifdef __SYMBIAN32__ |
|
964 EXPORT_C |
|
965 #endif |
|
966 |
|
967 gdouble |
|
968 gst_value_get_double_range_min (const GValue * value) |
|
969 { |
|
970 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0); |
|
971 |
|
972 return value->data[0].v_double; |
|
973 } |
|
974 |
|
975 /** |
|
976 * gst_value_get_double_range_max: |
|
977 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE |
|
978 * |
|
979 * Gets the maximum of the range specified by @value. |
|
980 * |
|
981 * Returns: the maxumum of the range |
|
982 */ |
|
983 #ifdef __SYMBIAN32__ |
|
984 EXPORT_C |
|
985 #endif |
|
986 |
|
987 gdouble |
|
988 gst_value_get_double_range_max (const GValue * value) |
|
989 { |
|
990 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0); |
|
991 |
|
992 return value->data[1].v_double; |
|
993 } |
|
994 |
|
995 static void |
|
996 gst_value_transform_double_range_string (const GValue * src_value, |
|
997 GValue * dest_value) |
|
998 { |
|
999 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE]; |
|
1000 |
|
1001 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]", |
|
1002 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE, |
|
1003 src_value->data[0].v_double), |
|
1004 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE, |
|
1005 src_value->data[1].v_double)); |
|
1006 } |
|
1007 |
|
1008 static gint |
|
1009 gst_value_compare_double_range (const GValue * value1, const GValue * value2) |
|
1010 { |
|
1011 if (value2->data[0].v_double == value1->data[0].v_double && |
|
1012 value2->data[0].v_double == value1->data[0].v_double) |
|
1013 return GST_VALUE_EQUAL; |
|
1014 return GST_VALUE_UNORDERED; |
|
1015 } |
|
1016 |
|
1017 static gchar * |
|
1018 gst_value_serialize_double_range (const GValue * value) |
|
1019 { |
|
1020 char d1[G_ASCII_DTOSTR_BUF_SIZE]; |
|
1021 char d2[G_ASCII_DTOSTR_BUF_SIZE]; |
|
1022 |
|
1023 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double); |
|
1024 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double); |
|
1025 return g_strdup_printf ("[ %s, %s ]", d1, d2); |
|
1026 } |
|
1027 |
|
1028 static gboolean |
|
1029 gst_value_deserialize_double_range (GValue * dest, const gchar * s) |
|
1030 { |
|
1031 g_warning ("unimplemented"); |
|
1032 return FALSE; |
|
1033 } |
|
1034 |
|
1035 /**************** |
|
1036 * fraction range * |
|
1037 ****************/ |
|
1038 |
|
1039 static void |
|
1040 gst_value_init_fraction_range (GValue * value) |
|
1041 { |
|
1042 GValue *vals; |
|
1043 |
|
1044 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
|
1045 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1046 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1047 } |
|
1048 |
|
1049 static void |
|
1050 gst_value_free_fraction_range (GValue * value) |
|
1051 { |
|
1052 GValue *vals = (GValue *) value->data[0].v_pointer; |
|
1053 |
|
1054 if (vals != NULL) { |
|
1055 g_value_unset (&vals[0]); |
|
1056 g_value_unset (&vals[1]); |
|
1057 g_free (vals); |
|
1058 value->data[0].v_pointer = NULL; |
|
1059 } |
|
1060 } |
|
1061 |
|
1062 static void |
|
1063 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value) |
|
1064 { |
|
1065 GValue *vals = (GValue *) dest_value->data[0].v_pointer; |
|
1066 GValue *src_vals = (GValue *) src_value->data[0].v_pointer; |
|
1067 |
|
1068 if (vals == NULL) { |
|
1069 dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
|
1070 g_return_if_fail (vals != NULL); |
|
1071 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1072 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1073 } |
|
1074 |
|
1075 if (src_vals != NULL) { |
|
1076 g_value_copy (&src_vals[0], &vals[0]); |
|
1077 g_value_copy (&src_vals[1], &vals[1]); |
|
1078 } |
|
1079 } |
|
1080 |
|
1081 static gchar * |
|
1082 gst_value_collect_fraction_range (GValue * value, guint n_collect_values, |
|
1083 GTypeCValue * collect_values, guint collect_flags) |
|
1084 { |
|
1085 GValue *vals = (GValue *) value->data[0].v_pointer; |
|
1086 |
|
1087 if (n_collect_values != 4) |
|
1088 return g_strdup_printf ("not enough value locations for `%s' passed", |
|
1089 G_VALUE_TYPE_NAME (value)); |
|
1090 if (vals == NULL) { |
|
1091 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
|
1092 if (vals == NULL) |
|
1093 return g_strdup_printf ("Could not initialise`%s' during collect", |
|
1094 G_VALUE_TYPE_NAME (value)); |
|
1095 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1096 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1097 } |
|
1098 |
|
1099 gst_value_set_fraction (&vals[0], collect_values[0].v_int, |
|
1100 collect_values[1].v_int); |
|
1101 gst_value_set_fraction (&vals[1], collect_values[2].v_int, |
|
1102 collect_values[3].v_int); |
|
1103 |
|
1104 return NULL; |
|
1105 } |
|
1106 |
|
1107 static gchar * |
|
1108 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values, |
|
1109 GTypeCValue * collect_values, guint collect_flags) |
|
1110 { |
|
1111 int i; |
|
1112 int *dest_values[4]; |
|
1113 GValue *vals = (GValue *) value->data[0].v_pointer; |
|
1114 |
|
1115 if (n_collect_values != 4) |
|
1116 return g_strdup_printf ("not enough value locations for `%s' passed", |
|
1117 G_VALUE_TYPE_NAME (value)); |
|
1118 |
|
1119 for (i = 0; i < 4; i++) { |
|
1120 if (collect_values[i].v_pointer == NULL) { |
|
1121 return g_strdup_printf ("value location for `%s' passed as NULL", |
|
1122 G_VALUE_TYPE_NAME (value)); |
|
1123 } |
|
1124 dest_values[i] = collect_values[i].v_pointer; |
|
1125 } |
|
1126 |
|
1127 if (vals == NULL) { |
|
1128 return g_strdup_printf ("Uninitialised `%s' passed", |
|
1129 G_VALUE_TYPE_NAME (value)); |
|
1130 } |
|
1131 |
|
1132 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]); |
|
1133 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]); |
|
1134 dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]); |
|
1135 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]); |
|
1136 return NULL; |
|
1137 } |
|
1138 |
|
1139 /** |
|
1140 * gst_value_set_fraction_range: |
|
1141 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE |
|
1142 * @start: the start of the range (a GST_TYPE_FRACTION GValue) |
|
1143 * @end: the end of the range (a GST_TYPE_FRACTION GValue) |
|
1144 * |
|
1145 * Sets @value to the range specified by @start and @end. |
|
1146 */ |
|
1147 #ifdef __SYMBIAN32__ |
|
1148 EXPORT_C |
|
1149 #endif |
|
1150 |
|
1151 void |
|
1152 gst_value_set_fraction_range (GValue * value, const GValue * start, |
|
1153 const GValue * end) |
|
1154 { |
|
1155 GValue *vals; |
|
1156 |
|
1157 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); |
|
1158 |
|
1159 vals = (GValue *) value->data[0].v_pointer; |
|
1160 if (vals == NULL) { |
|
1161 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
|
1162 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1163 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1164 } |
|
1165 |
|
1166 g_value_copy (start, &vals[0]); |
|
1167 g_value_copy (end, &vals[1]); |
|
1168 } |
|
1169 |
|
1170 /** |
|
1171 * gst_value_set_fraction_range_full: |
|
1172 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE |
|
1173 * @numerator_start: the numerator start of the range |
|
1174 * @denominator_start: the denominator start of the range |
|
1175 * @numerator_end: the numerator end of the range |
|
1176 * @denominator_end: the denominator end of the range |
|
1177 * |
|
1178 * Sets @value to the range specified by @numerator_start/@denominator_start |
|
1179 * and @numerator_end/@denominator_end. |
|
1180 */ |
|
1181 #ifdef __SYMBIAN32__ |
|
1182 EXPORT_C |
|
1183 #endif |
|
1184 |
|
1185 void |
|
1186 gst_value_set_fraction_range_full (GValue * value, |
|
1187 gint numerator_start, gint denominator_start, |
|
1188 gint numerator_end, gint denominator_end) |
|
1189 { |
|
1190 GValue start = { 0 }; |
|
1191 GValue end = { 0 }; |
|
1192 |
|
1193 g_value_init (&start, GST_TYPE_FRACTION); |
|
1194 g_value_init (&end, GST_TYPE_FRACTION); |
|
1195 |
|
1196 gst_value_set_fraction (&start, numerator_start, denominator_start); |
|
1197 gst_value_set_fraction (&end, numerator_end, denominator_end); |
|
1198 gst_value_set_fraction_range (value, &start, &end); |
|
1199 |
|
1200 g_value_unset (&start); |
|
1201 g_value_unset (&end); |
|
1202 } |
|
1203 |
|
1204 /** |
|
1205 * gst_value_get_fraction_range_min: |
|
1206 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE |
|
1207 * |
|
1208 * Gets the minimum of the range specified by @value. |
|
1209 * |
|
1210 * Returns: the minumum of the range |
|
1211 */ |
|
1212 #ifdef __SYMBIAN32__ |
|
1213 EXPORT_C |
|
1214 #endif |
|
1215 |
|
1216 const GValue * |
|
1217 gst_value_get_fraction_range_min (const GValue * value) |
|
1218 { |
|
1219 GValue *vals; |
|
1220 |
|
1221 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE); |
|
1222 |
|
1223 vals = (GValue *) value->data[0].v_pointer; |
|
1224 if (vals != NULL) { |
|
1225 return &vals[0]; |
|
1226 } |
|
1227 |
|
1228 return NULL; |
|
1229 } |
|
1230 |
|
1231 /** |
|
1232 * gst_value_get_fraction_range_max: |
|
1233 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE |
|
1234 * |
|
1235 * Gets the maximum of the range specified by @value. |
|
1236 * |
|
1237 * Returns: the maximum of the range |
|
1238 */ |
|
1239 #ifdef __SYMBIAN32__ |
|
1240 EXPORT_C |
|
1241 #endif |
|
1242 |
|
1243 const GValue * |
|
1244 gst_value_get_fraction_range_max (const GValue * value) |
|
1245 { |
|
1246 GValue *vals; |
|
1247 |
|
1248 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), FALSE); |
|
1249 |
|
1250 vals = (GValue *) value->data[0].v_pointer; |
|
1251 if (vals != NULL) { |
|
1252 return &vals[1]; |
|
1253 } |
|
1254 |
|
1255 return NULL; |
|
1256 } |
|
1257 |
|
1258 static char * |
|
1259 gst_value_serialize_fraction_range (const GValue * value) |
|
1260 { |
|
1261 GValue *vals = (GValue *) value->data[0].v_pointer; |
|
1262 gchar *retval; |
|
1263 |
|
1264 if (vals == NULL) { |
|
1265 retval = g_strdup ("[ 0/1, 0/1 ]"); |
|
1266 } else { |
|
1267 gchar *start, *end; |
|
1268 |
|
1269 start = gst_value_serialize_fraction (&vals[0]); |
|
1270 end = gst_value_serialize_fraction (&vals[1]); |
|
1271 |
|
1272 retval = g_strdup_printf ("[ %s, %s ]", start, end); |
|
1273 g_free (start); |
|
1274 g_free (end); |
|
1275 } |
|
1276 |
|
1277 return retval; |
|
1278 } |
|
1279 |
|
1280 static void |
|
1281 gst_value_transform_fraction_range_string (const GValue * src_value, |
|
1282 GValue * dest_value) |
|
1283 { |
|
1284 dest_value->data[0].v_pointer = |
|
1285 gst_value_serialize_fraction_range (src_value); |
|
1286 } |
|
1287 |
|
1288 static gint |
|
1289 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2) |
|
1290 { |
|
1291 GValue *vals1, *vals2; |
|
1292 GstValueCompareFunc compare; |
|
1293 |
|
1294 if (value2->data[0].v_pointer == value1->data[0].v_pointer) |
|
1295 return GST_VALUE_EQUAL; /* Only possible if both are NULL */ |
|
1296 |
|
1297 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL) |
|
1298 return GST_VALUE_UNORDERED; |
|
1299 |
|
1300 vals1 = (GValue *) value1->data[0].v_pointer; |
|
1301 vals2 = (GValue *) value2->data[0].v_pointer; |
|
1302 if ((compare = gst_value_get_compare_func (&vals1[0]))) { |
|
1303 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) == |
|
1304 GST_VALUE_EQUAL && |
|
1305 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) == |
|
1306 GST_VALUE_EQUAL) |
|
1307 return GST_VALUE_EQUAL; |
|
1308 } |
|
1309 return GST_VALUE_UNORDERED; |
|
1310 } |
|
1311 |
|
1312 static gboolean |
|
1313 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s) |
|
1314 { |
|
1315 g_warning ("unimplemented"); |
|
1316 return FALSE; |
|
1317 } |
|
1318 |
|
1319 /*********** |
|
1320 * GstCaps * |
|
1321 ***********/ |
|
1322 |
|
1323 /** |
|
1324 * gst_value_set_caps: |
|
1325 * @value: a GValue initialized to GST_TYPE_CAPS |
|
1326 * @caps: the caps to set the value to |
|
1327 * |
|
1328 * Sets the contents of @value to @caps. The actual |
|
1329 * #GstCaps structure is copied before it is used. |
|
1330 */ |
|
1331 #ifdef __SYMBIAN32__ |
|
1332 EXPORT_C |
|
1333 #endif |
|
1334 |
|
1335 void |
|
1336 gst_value_set_caps (GValue * value, const GstCaps * caps) |
|
1337 { |
|
1338 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS); |
|
1339 |
|
1340 g_value_set_boxed (value, caps); |
|
1341 } |
|
1342 |
|
1343 /** |
|
1344 * gst_value_get_caps: |
|
1345 * @value: a GValue initialized to GST_TYPE_CAPS |
|
1346 * |
|
1347 * Gets the contents of @value. |
|
1348 * |
|
1349 * Returns: the contents of @value |
|
1350 */ |
|
1351 #ifdef __SYMBIAN32__ |
|
1352 EXPORT_C |
|
1353 #endif |
|
1354 |
|
1355 const GstCaps * |
|
1356 gst_value_get_caps (const GValue * value) |
|
1357 { |
|
1358 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL); |
|
1359 |
|
1360 return (GstCaps *) g_value_get_boxed (value); |
|
1361 } |
|
1362 |
|
1363 static char * |
|
1364 gst_value_serialize_caps (const GValue * value) |
|
1365 { |
|
1366 GstCaps *caps = g_value_get_boxed (value); |
|
1367 |
|
1368 return gst_caps_to_string (caps); |
|
1369 } |
|
1370 |
|
1371 static gboolean |
|
1372 gst_value_deserialize_caps (GValue * dest, const gchar * s) |
|
1373 { |
|
1374 GstCaps *caps; |
|
1375 |
|
1376 caps = gst_caps_from_string (s); |
|
1377 |
|
1378 if (caps) { |
|
1379 g_value_set_boxed (dest, caps); |
|
1380 return TRUE; |
|
1381 } |
|
1382 return FALSE; |
|
1383 } |
|
1384 |
|
1385 /**************** |
|
1386 * GstStructure * |
|
1387 ****************/ |
|
1388 |
|
1389 /** |
|
1390 * gst_value_set_structure: |
|
1391 * @value: a GValue initialized to GST_TYPE_STRUCTURE |
|
1392 * @structure: the structure to set the value to |
|
1393 * |
|
1394 * Sets the contents of @value to @structure. The actual |
|
1395 * |
|
1396 * Since: 0.10.15 |
|
1397 */ |
|
1398 #ifdef __SYMBIAN32__ |
|
1399 EXPORT_C |
|
1400 #endif |
|
1401 |
|
1402 void |
|
1403 gst_value_set_structure (GValue * value, const GstStructure * structure) |
|
1404 { |
|
1405 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE); |
|
1406 |
|
1407 g_value_set_boxed (value, structure); |
|
1408 } |
|
1409 |
|
1410 /** |
|
1411 * gst_value_get_structure: |
|
1412 * @value: a GValue initialized to GST_TYPE_STRUCTURE |
|
1413 * |
|
1414 * Gets the contents of @value. |
|
1415 * |
|
1416 * Returns: the contents of @value |
|
1417 * |
|
1418 * Since: 0.10.15 |
|
1419 */ |
|
1420 #ifdef __SYMBIAN32__ |
|
1421 EXPORT_C |
|
1422 #endif |
|
1423 |
|
1424 const GstStructure * |
|
1425 gst_value_get_structure (const GValue * value) |
|
1426 { |
|
1427 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL); |
|
1428 |
|
1429 return (GstStructure *) g_value_get_boxed (value); |
|
1430 } |
|
1431 |
|
1432 static char * |
|
1433 gst_value_serialize_structure (const GValue * value) |
|
1434 { |
|
1435 GstStructure *structure = g_value_get_boxed (value); |
|
1436 |
|
1437 return gst_structure_to_string (structure); |
|
1438 } |
|
1439 |
|
1440 static gboolean |
|
1441 gst_value_deserialize_structure (GValue * dest, const gchar * s) |
|
1442 { |
|
1443 GstStructure *structure; |
|
1444 |
|
1445 structure = gst_structure_from_string (s, NULL); |
|
1446 |
|
1447 if (structure) { |
|
1448 g_value_set_boxed (dest, structure); |
|
1449 return TRUE; |
|
1450 } |
|
1451 return FALSE; |
|
1452 } |
|
1453 |
|
1454 /************* |
|
1455 * GstBuffer * |
|
1456 *************/ |
|
1457 |
|
1458 static int |
|
1459 gst_value_compare_buffer (const GValue * value1, const GValue * value2) |
|
1460 { |
|
1461 GstBuffer *buf1 = GST_BUFFER (gst_value_get_mini_object (value1)); |
|
1462 GstBuffer *buf2 = GST_BUFFER (gst_value_get_mini_object (value2)); |
|
1463 |
|
1464 if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2)) |
|
1465 return GST_VALUE_UNORDERED; |
|
1466 if (GST_BUFFER_SIZE (buf1) == 0) |
|
1467 return GST_VALUE_EQUAL; |
|
1468 g_assert (GST_BUFFER_DATA (buf1)); |
|
1469 g_assert (GST_BUFFER_DATA (buf2)); |
|
1470 if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2), |
|
1471 GST_BUFFER_SIZE (buf1)) == 0) |
|
1472 return GST_VALUE_EQUAL; |
|
1473 |
|
1474 return GST_VALUE_UNORDERED; |
|
1475 } |
|
1476 |
|
1477 static char * |
|
1478 gst_value_serialize_buffer (const GValue * value) |
|
1479 { |
|
1480 guint8 *data; |
|
1481 int i; |
|
1482 int size; |
|
1483 char *string; |
|
1484 GstBuffer *buffer; |
|
1485 |
|
1486 buffer = gst_value_get_buffer (value); |
|
1487 if (buffer == NULL) |
|
1488 return NULL; |
|
1489 |
|
1490 data = GST_BUFFER_DATA (buffer); |
|
1491 size = GST_BUFFER_SIZE (buffer); |
|
1492 |
|
1493 string = g_malloc (size * 2 + 1); |
|
1494 for (i = 0; i < size; i++) { |
|
1495 sprintf (string + i * 2, "%02x", data[i]); |
|
1496 } |
|
1497 string[size * 2] = 0; |
|
1498 |
|
1499 return string; |
|
1500 } |
|
1501 |
|
1502 static gboolean |
|
1503 gst_value_deserialize_buffer (GValue * dest, const gchar * s) |
|
1504 { |
|
1505 GstBuffer *buffer; |
|
1506 int len; |
|
1507 char ts[3]; |
|
1508 guint8 *data; |
|
1509 int i; |
|
1510 |
|
1511 len = strlen (s); |
|
1512 if (len & 1) |
|
1513 goto wrong_length; |
|
1514 |
|
1515 buffer = gst_buffer_new_and_alloc (len / 2); |
|
1516 data = GST_BUFFER_DATA (buffer); |
|
1517 for (i = 0; i < len / 2; i++) { |
|
1518 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1])) |
|
1519 goto wrong_char; |
|
1520 |
|
1521 ts[0] = s[i * 2 + 0]; |
|
1522 ts[1] = s[i * 2 + 1]; |
|
1523 ts[2] = 0; |
|
1524 |
|
1525 data[i] = (guint8) strtoul (ts, NULL, 16); |
|
1526 } |
|
1527 |
|
1528 gst_value_take_buffer (dest, buffer); |
|
1529 |
|
1530 return TRUE; |
|
1531 |
|
1532 /* ERRORS */ |
|
1533 wrong_length: |
|
1534 { |
|
1535 return FALSE; |
|
1536 } |
|
1537 wrong_char: |
|
1538 { |
|
1539 gst_buffer_unref (buffer); |
|
1540 return FALSE; |
|
1541 } |
|
1542 } |
|
1543 |
|
1544 |
|
1545 /*********** |
|
1546 * boolean * |
|
1547 ***********/ |
|
1548 |
|
1549 static int |
|
1550 gst_value_compare_boolean (const GValue * value1, const GValue * value2) |
|
1551 { |
|
1552 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0)) |
|
1553 return GST_VALUE_EQUAL; |
|
1554 return GST_VALUE_UNORDERED; |
|
1555 } |
|
1556 |
|
1557 static char * |
|
1558 gst_value_serialize_boolean (const GValue * value) |
|
1559 { |
|
1560 if (value->data[0].v_int) { |
|
1561 return g_strdup ("true"); |
|
1562 } |
|
1563 return g_strdup ("false"); |
|
1564 } |
|
1565 |
|
1566 static gboolean |
|
1567 gst_value_deserialize_boolean (GValue * dest, const gchar * s) |
|
1568 { |
|
1569 gboolean ret = FALSE; |
|
1570 |
|
1571 if (g_ascii_strcasecmp (s, "true") == 0 || |
|
1572 g_ascii_strcasecmp (s, "yes") == 0 || |
|
1573 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) { |
|
1574 g_value_set_boolean (dest, TRUE); |
|
1575 ret = TRUE; |
|
1576 } else if (g_ascii_strcasecmp (s, "false") == 0 || |
|
1577 g_ascii_strcasecmp (s, "no") == 0 || |
|
1578 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) { |
|
1579 g_value_set_boolean (dest, FALSE); |
|
1580 ret = TRUE; |
|
1581 } |
|
1582 |
|
1583 return ret; |
|
1584 } |
|
1585 |
|
1586 #define CREATE_SERIALIZATION_START(_type,_macro) \ |
|
1587 static gint \ |
|
1588 gst_value_compare_ ## _type \ |
|
1589 (const GValue * value1, const GValue * value2) \ |
|
1590 { \ |
|
1591 g ## _type val1 = g_value_get_ ## _type (value1); \ |
|
1592 g ## _type val2 = g_value_get_ ## _type (value2); \ |
|
1593 if (val1 > val2) \ |
|
1594 return GST_VALUE_GREATER_THAN; \ |
|
1595 if (val1 < val2) \ |
|
1596 return GST_VALUE_LESS_THAN; \ |
|
1597 return GST_VALUE_EQUAL; \ |
|
1598 } \ |
|
1599 \ |
|
1600 static char * \ |
|
1601 gst_value_serialize_ ## _type (const GValue * value) \ |
|
1602 { \ |
|
1603 GValue val = { 0, }; \ |
|
1604 g_value_init (&val, G_TYPE_STRING); \ |
|
1605 if (!g_value_transform (value, &val)) \ |
|
1606 g_assert_not_reached (); \ |
|
1607 /* NO_COPY_MADNESS!!! */ \ |
|
1608 return (char *) g_value_get_string (&val); \ |
|
1609 } |
|
1610 |
|
1611 /* deserialize the given s into to as a gint64. |
|
1612 * check if the result is actually storeable in the given size number of |
|
1613 * bytes. |
|
1614 */ |
|
1615 static gboolean |
|
1616 gst_value_deserialize_int_helper (gint64 * to, const gchar * s, |
|
1617 gint64 min, gint64 max, gint size) |
|
1618 { |
|
1619 gboolean ret = FALSE; |
|
1620 char *end; |
|
1621 gint64 mask = -1; |
|
1622 |
|
1623 errno = 0; |
|
1624 *to = g_ascii_strtoull (s, &end, 0); |
|
1625 /* a range error is a definitive no-no */ |
|
1626 if (errno == ERANGE) { |
|
1627 return FALSE; |
|
1628 } |
|
1629 |
|
1630 if (*end == 0) { |
|
1631 ret = TRUE; |
|
1632 } else { |
|
1633 if (g_ascii_strcasecmp (s, "little_endian") == 0) { |
|
1634 *to = G_LITTLE_ENDIAN; |
|
1635 ret = TRUE; |
|
1636 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { |
|
1637 *to = G_BIG_ENDIAN; |
|
1638 ret = TRUE; |
|
1639 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { |
|
1640 *to = G_BYTE_ORDER; |
|
1641 ret = TRUE; |
|
1642 } else if (g_ascii_strcasecmp (s, "min") == 0) { |
|
1643 *to = min; |
|
1644 ret = TRUE; |
|
1645 } else if (g_ascii_strcasecmp (s, "max") == 0) { |
|
1646 *to = max; |
|
1647 ret = TRUE; |
|
1648 } |
|
1649 } |
|
1650 if (ret) { |
|
1651 /* by definition, a gint64 fits into a gint64; so ignore those */ |
|
1652 if (size != sizeof (mask)) { |
|
1653 if (*to >= 0) { |
|
1654 /* for positive numbers, we create a mask of 1's outside of the range |
|
1655 * and 0's inside the range. An and will thus keep only 1 bits |
|
1656 * outside of the range */ |
|
1657 mask <<= (size * 8); |
|
1658 if ((mask & *to) != 0) { |
|
1659 ret = FALSE; |
|
1660 } |
|
1661 } else { |
|
1662 /* for negative numbers, we do a 2's complement version */ |
|
1663 mask <<= ((size * 8) - 1); |
|
1664 if ((mask & *to) != mask) { |
|
1665 ret = FALSE; |
|
1666 } |
|
1667 } |
|
1668 } |
|
1669 } |
|
1670 return ret; |
|
1671 } |
|
1672 |
|
1673 #define CREATE_SERIALIZATION(_type,_macro) \ |
|
1674 CREATE_SERIALIZATION_START(_type,_macro) \ |
|
1675 \ |
|
1676 static gboolean \ |
|
1677 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \ |
|
1678 { \ |
|
1679 gint64 x; \ |
|
1680 \ |
|
1681 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \ |
|
1682 G_MAX ## _macro, sizeof (g ## _type))) { \ |
|
1683 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \ |
|
1684 return TRUE; \ |
|
1685 } else { \ |
|
1686 return FALSE; \ |
|
1687 } \ |
|
1688 } |
|
1689 |
|
1690 #define CREATE_USERIALIZATION(_type,_macro) \ |
|
1691 CREATE_SERIALIZATION_START(_type,_macro) \ |
|
1692 \ |
|
1693 static gboolean \ |
|
1694 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \ |
|
1695 { \ |
|
1696 gint64 x; \ |
|
1697 char *end; \ |
|
1698 gboolean ret = FALSE; \ |
|
1699 \ |
|
1700 errno = 0; \ |
|
1701 x = g_ascii_strtoull (s, &end, 0); \ |
|
1702 /* a range error is a definitive no-no */ \ |
|
1703 if (errno == ERANGE) { \ |
|
1704 return FALSE; \ |
|
1705 } \ |
|
1706 /* the cast ensures the range check later on makes sense */ \ |
|
1707 x = (g ## _type) x; \ |
|
1708 if (*end == 0) { \ |
|
1709 ret = TRUE; \ |
|
1710 } else { \ |
|
1711 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \ |
|
1712 x = G_LITTLE_ENDIAN; \ |
|
1713 ret = TRUE; \ |
|
1714 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \ |
|
1715 x = G_BIG_ENDIAN; \ |
|
1716 ret = TRUE; \ |
|
1717 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \ |
|
1718 x = G_BYTE_ORDER; \ |
|
1719 ret = TRUE; \ |
|
1720 } else if (g_ascii_strcasecmp (s, "min") == 0) { \ |
|
1721 x = 0; \ |
|
1722 ret = TRUE; \ |
|
1723 } else if (g_ascii_strcasecmp (s, "max") == 0) { \ |
|
1724 x = G_MAX ## _macro; \ |
|
1725 ret = TRUE; \ |
|
1726 } \ |
|
1727 } \ |
|
1728 if (ret) { \ |
|
1729 if (x > G_MAX ## _macro) { \ |
|
1730 ret = FALSE; \ |
|
1731 } else { \ |
|
1732 g_value_set_ ## _type (dest, x); \ |
|
1733 } \ |
|
1734 } \ |
|
1735 return ret; \ |
|
1736 } |
|
1737 |
|
1738 #define REGISTER_SERIALIZATION(_gtype, _type) \ |
|
1739 G_STMT_START { \ |
|
1740 static const GstValueTable gst_value = { \ |
|
1741 _gtype, \ |
|
1742 gst_value_compare_ ## _type, \ |
|
1743 gst_value_serialize_ ## _type, \ |
|
1744 gst_value_deserialize_ ## _type, \ |
|
1745 }; \ |
|
1746 \ |
|
1747 gst_value_register (&gst_value); \ |
|
1748 } G_STMT_END |
|
1749 |
|
1750 CREATE_SERIALIZATION (int, INT); |
|
1751 CREATE_SERIALIZATION (int64, INT64); |
|
1752 CREATE_SERIALIZATION (long, LONG); |
|
1753 |
|
1754 CREATE_USERIALIZATION (uint, UINT); |
|
1755 CREATE_USERIALIZATION (uint64, UINT64); |
|
1756 CREATE_USERIALIZATION (ulong, ULONG); |
|
1757 |
|
1758 /********** |
|
1759 * double * |
|
1760 **********/ |
|
1761 static int |
|
1762 gst_value_compare_double (const GValue * value1, const GValue * value2) |
|
1763 { |
|
1764 if (value1->data[0].v_double > value2->data[0].v_double) |
|
1765 return GST_VALUE_GREATER_THAN; |
|
1766 if (value1->data[0].v_double < value2->data[0].v_double) |
|
1767 return GST_VALUE_LESS_THAN; |
|
1768 if (value1->data[0].v_double == value2->data[0].v_double) |
|
1769 return GST_VALUE_EQUAL; |
|
1770 return GST_VALUE_UNORDERED; |
|
1771 } |
|
1772 |
|
1773 static char * |
|
1774 gst_value_serialize_double (const GValue * value) |
|
1775 { |
|
1776 char d[G_ASCII_DTOSTR_BUF_SIZE]; |
|
1777 |
|
1778 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double); |
|
1779 return g_strdup (d); |
|
1780 } |
|
1781 |
|
1782 static gboolean |
|
1783 gst_value_deserialize_double (GValue * dest, const gchar * s) |
|
1784 { |
|
1785 double x; |
|
1786 gboolean ret = FALSE; |
|
1787 char *end; |
|
1788 |
|
1789 x = g_ascii_strtod (s, &end); |
|
1790 if (*end == 0) { |
|
1791 ret = TRUE; |
|
1792 } else { |
|
1793 if (g_ascii_strcasecmp (s, "min") == 0) { |
|
1794 x = -G_MAXDOUBLE; |
|
1795 ret = TRUE; |
|
1796 } else if (g_ascii_strcasecmp (s, "max") == 0) { |
|
1797 x = G_MAXDOUBLE; |
|
1798 ret = TRUE; |
|
1799 } |
|
1800 } |
|
1801 if (ret) { |
|
1802 g_value_set_double (dest, x); |
|
1803 } |
|
1804 return ret; |
|
1805 } |
|
1806 |
|
1807 /********* |
|
1808 * float * |
|
1809 *********/ |
|
1810 |
|
1811 static gint |
|
1812 gst_value_compare_float (const GValue * value1, const GValue * value2) |
|
1813 { |
|
1814 if (value1->data[0].v_float > value2->data[0].v_float) |
|
1815 return GST_VALUE_GREATER_THAN; |
|
1816 if (value1->data[0].v_float < value2->data[0].v_float) |
|
1817 return GST_VALUE_LESS_THAN; |
|
1818 if (value1->data[0].v_float == value2->data[0].v_float) |
|
1819 return GST_VALUE_EQUAL; |
|
1820 return GST_VALUE_UNORDERED; |
|
1821 } |
|
1822 |
|
1823 static gchar * |
|
1824 gst_value_serialize_float (const GValue * value) |
|
1825 { |
|
1826 gchar d[G_ASCII_DTOSTR_BUF_SIZE]; |
|
1827 |
|
1828 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float); |
|
1829 return g_strdup (d); |
|
1830 } |
|
1831 |
|
1832 static gboolean |
|
1833 gst_value_deserialize_float (GValue * dest, const gchar * s) |
|
1834 { |
|
1835 double x; |
|
1836 gboolean ret = FALSE; |
|
1837 char *end; |
|
1838 |
|
1839 x = g_ascii_strtod (s, &end); |
|
1840 if (*end == 0) { |
|
1841 ret = TRUE; |
|
1842 } else { |
|
1843 if (g_ascii_strcasecmp (s, "min") == 0) { |
|
1844 x = -G_MAXFLOAT; |
|
1845 ret = TRUE; |
|
1846 } else if (g_ascii_strcasecmp (s, "max") == 0) { |
|
1847 x = G_MAXFLOAT; |
|
1848 ret = TRUE; |
|
1849 } |
|
1850 } |
|
1851 if (x > G_MAXFLOAT || x < -G_MAXFLOAT) |
|
1852 ret = FALSE; |
|
1853 if (ret) { |
|
1854 g_value_set_float (dest, (float) x); |
|
1855 } |
|
1856 return ret; |
|
1857 } |
|
1858 |
|
1859 /********** |
|
1860 * string * |
|
1861 **********/ |
|
1862 |
|
1863 static gint |
|
1864 gst_value_compare_string (const GValue * value1, const GValue * value2) |
|
1865 { |
|
1866 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer); |
|
1867 |
|
1868 if (x < 0) |
|
1869 return GST_VALUE_LESS_THAN; |
|
1870 if (x > 0) |
|
1871 return GST_VALUE_GREATER_THAN; |
|
1872 return GST_VALUE_EQUAL; |
|
1873 } |
|
1874 |
|
1875 /* keep in sync with gststructure.c */ |
|
1876 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \ |
|
1877 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \ |
|
1878 ((c) == '.')) |
|
1879 |
|
1880 static gchar * |
|
1881 gst_string_wrap (const gchar * s) |
|
1882 { |
|
1883 const gchar *t; |
|
1884 int len; |
|
1885 gchar *d, *e; |
|
1886 gboolean wrap = FALSE; |
|
1887 |
|
1888 len = 0; |
|
1889 t = s; |
|
1890 if (!s) |
|
1891 return NULL; |
|
1892 while (*t) { |
|
1893 if (GST_ASCII_IS_STRING (*t)) { |
|
1894 len++; |
|
1895 } else if (*t < 0x20 || *t >= 0x7f) { |
|
1896 wrap = TRUE; |
|
1897 len += 4; |
|
1898 } else { |
|
1899 wrap = TRUE; |
|
1900 len += 2; |
|
1901 } |
|
1902 t++; |
|
1903 } |
|
1904 |
|
1905 if (!wrap) |
|
1906 return g_strdup (s); |
|
1907 |
|
1908 e = d = g_malloc (len + 3); |
|
1909 |
|
1910 *e++ = '\"'; |
|
1911 t = s; |
|
1912 while (*t) { |
|
1913 if (GST_ASCII_IS_STRING (*t)) { |
|
1914 *e++ = *t++; |
|
1915 } else if (*t < 0x20 || *t >= 0x7f) { |
|
1916 *e++ = '\\'; |
|
1917 *e++ = '0' + ((*(guchar *) t) >> 6); |
|
1918 *e++ = '0' + (((*t) >> 3) & 0x7); |
|
1919 *e++ = '0' + ((*t++) & 0x7); |
|
1920 } else { |
|
1921 *e++ = '\\'; |
|
1922 *e++ = *t++; |
|
1923 } |
|
1924 } |
|
1925 *e++ = '\"'; |
|
1926 *e = 0; |
|
1927 |
|
1928 return d; |
|
1929 } |
|
1930 |
|
1931 /* |
|
1932 * This function takes a string delimited with double quotes (") |
|
1933 * and unescapes any \xxx octal numbers. |
|
1934 * |
|
1935 * If sequences of \y are found where y is not in the range of |
|
1936 * 0->3, y is copied unescaped. |
|
1937 * |
|
1938 * If \xyy is found where x is an octal number but y is not, an |
|
1939 * error is encountered and NULL is returned. |
|
1940 * |
|
1941 * the input string must be \0 terminated. |
|
1942 */ |
|
1943 static gchar * |
|
1944 gst_string_unwrap (const gchar * s) |
|
1945 { |
|
1946 gchar *ret; |
|
1947 gchar *read, *write; |
|
1948 |
|
1949 /* NULL string returns NULL */ |
|
1950 if (s == NULL) |
|
1951 return NULL; |
|
1952 |
|
1953 /* strings not starting with " are invalid */ |
|
1954 if (*s != '"') |
|
1955 return NULL; |
|
1956 |
|
1957 /* make copy of original string to hold the result. This |
|
1958 * string will always be smaller than the original */ |
|
1959 ret = g_strdup (s); |
|
1960 read = ret; |
|
1961 write = ret; |
|
1962 |
|
1963 /* need to move to the next position as we parsed the " */ |
|
1964 read++; |
|
1965 |
|
1966 while (*read) { |
|
1967 if (GST_ASCII_IS_STRING (*read)) { |
|
1968 /* normal chars are just copied */ |
|
1969 *write++ = *read++; |
|
1970 } else if (*read == '"') { |
|
1971 /* quote marks end of string */ |
|
1972 break; |
|
1973 } else if (*read == '\\') { |
|
1974 /* got an escape char, move to next position to read a tripplet |
|
1975 * of octal numbers */ |
|
1976 read++; |
|
1977 /* is the next char a possible first octal number? */ |
|
1978 if (*read >= '0' && *read <= '3') { |
|
1979 /* parse other 2 numbers, if one of them is not in the range of |
|
1980 * an octal number, we error. We also catch the case where a zero |
|
1981 * byte is found here. */ |
|
1982 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7') |
|
1983 goto beach; |
|
1984 |
|
1985 /* now convert the octal number to a byte again. */ |
|
1986 *write++ = ((read[0] - '0') << 6) + |
|
1987 ((read[1] - '0') << 3) + (read[2] - '0'); |
|
1988 |
|
1989 read += 3; |
|
1990 } else { |
|
1991 /* if we run into a \0 here, we definately won't get a quote later */ |
|
1992 if (*read == 0) |
|
1993 goto beach; |
|
1994 |
|
1995 /* else copy \X sequence */ |
|
1996 *write++ = *read++; |
|
1997 } |
|
1998 } else { |
|
1999 /* weird character, error */ |
|
2000 goto beach; |
|
2001 } |
|
2002 } |
|
2003 /* if the string is not ending in " and zero terminated, we error */ |
|
2004 if (*read != '"' || read[1] != '\0') |
|
2005 goto beach; |
|
2006 |
|
2007 /* null terminate result string and return */ |
|
2008 *write++ = '\0'; |
|
2009 return ret; |
|
2010 |
|
2011 beach: |
|
2012 g_free (ret); |
|
2013 return NULL; |
|
2014 } |
|
2015 |
|
2016 static gchar * |
|
2017 gst_value_serialize_string (const GValue * value) |
|
2018 { |
|
2019 return gst_string_wrap (value->data[0].v_pointer); |
|
2020 } |
|
2021 |
|
2022 static gboolean |
|
2023 gst_value_deserialize_string (GValue * dest, const gchar * s) |
|
2024 { |
|
2025 if (*s != '"') { |
|
2026 if (!g_utf8_validate (s, -1, NULL)) |
|
2027 return FALSE; |
|
2028 g_value_set_string (dest, s); |
|
2029 return TRUE; |
|
2030 } else { |
|
2031 gchar *str = gst_string_unwrap (s); |
|
2032 |
|
2033 if (!str) |
|
2034 return FALSE; |
|
2035 g_value_take_string (dest, str); |
|
2036 } |
|
2037 |
|
2038 return TRUE; |
|
2039 } |
|
2040 |
|
2041 /******** |
|
2042 * enum * |
|
2043 ********/ |
|
2044 |
|
2045 static gint |
|
2046 gst_value_compare_enum (const GValue * value1, const GValue * value2) |
|
2047 { |
|
2048 GEnumValue *en1, *en2; |
|
2049 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1)); |
|
2050 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2)); |
|
2051 |
|
2052 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED); |
|
2053 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED); |
|
2054 en1 = g_enum_get_value (klass1, g_value_get_enum (value1)); |
|
2055 en2 = g_enum_get_value (klass2, g_value_get_enum (value2)); |
|
2056 g_type_class_unref (klass1); |
|
2057 g_type_class_unref (klass2); |
|
2058 g_return_val_if_fail (en1, GST_VALUE_UNORDERED); |
|
2059 g_return_val_if_fail (en2, GST_VALUE_UNORDERED); |
|
2060 if (en1->value < en2->value) |
|
2061 return GST_VALUE_LESS_THAN; |
|
2062 if (en1->value > en2->value) |
|
2063 return GST_VALUE_GREATER_THAN; |
|
2064 |
|
2065 return GST_VALUE_EQUAL; |
|
2066 } |
|
2067 |
|
2068 static gchar * |
|
2069 gst_value_serialize_enum (const GValue * value) |
|
2070 { |
|
2071 GEnumValue *en; |
|
2072 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value)); |
|
2073 |
|
2074 g_return_val_if_fail (klass, NULL); |
|
2075 en = g_enum_get_value (klass, g_value_get_enum (value)); |
|
2076 g_type_class_unref (klass); |
|
2077 |
|
2078 /* might be one of the custom formats registered later */ |
|
2079 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) { |
|
2080 const GstFormatDefinition *format_def; |
|
2081 |
|
2082 format_def = gst_format_get_details (g_value_get_enum (value)); |
|
2083 g_return_val_if_fail (format_def != NULL, NULL); |
|
2084 return g_strdup (format_def->description); |
|
2085 } |
|
2086 |
|
2087 g_return_val_if_fail (en, NULL); |
|
2088 return g_strdup (en->value_name); |
|
2089 } |
|
2090 |
|
2091 static gint |
|
2092 gst_value_deserialize_enum_iter_cmp (const GstFormatDefinition * format_def, |
|
2093 const gchar * s) |
|
2094 { |
|
2095 if (g_ascii_strcasecmp (s, format_def->nick) == 0) |
|
2096 return 0; |
|
2097 |
|
2098 return g_ascii_strcasecmp (s, format_def->description); |
|
2099 } |
|
2100 |
|
2101 static gboolean |
|
2102 gst_value_deserialize_enum (GValue * dest, const gchar * s) |
|
2103 { |
|
2104 GEnumValue *en; |
|
2105 gchar *endptr = NULL; |
|
2106 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest)); |
|
2107 |
|
2108 g_return_val_if_fail (klass, FALSE); |
|
2109 if (!(en = g_enum_get_value_by_name (klass, s))) { |
|
2110 if (!(en = g_enum_get_value_by_nick (klass, s))) { |
|
2111 gint i = strtol (s, &endptr, 0); |
|
2112 |
|
2113 if (endptr && *endptr == '\0') { |
|
2114 en = g_enum_get_value (klass, i); |
|
2115 } |
|
2116 } |
|
2117 } |
|
2118 g_type_class_unref (klass); |
|
2119 |
|
2120 /* might be one of the custom formats registered later */ |
|
2121 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) { |
|
2122 const GstFormatDefinition *format_def; |
|
2123 GstIterator *iter; |
|
2124 |
|
2125 iter = gst_format_iterate_definitions (); |
|
2126 |
|
2127 format_def = gst_iterator_find_custom (iter, |
|
2128 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, (gpointer) s); |
|
2129 |
|
2130 g_return_val_if_fail (format_def != NULL, FALSE); |
|
2131 g_value_set_enum (dest, (gint) format_def->value); |
|
2132 gst_iterator_free (iter); |
|
2133 return TRUE; |
|
2134 } |
|
2135 |
|
2136 g_return_val_if_fail (en, FALSE); |
|
2137 g_value_set_enum (dest, en->value); |
|
2138 return TRUE; |
|
2139 } |
|
2140 |
|
2141 /******** |
|
2142 * flags * |
|
2143 ********/ |
|
2144 |
|
2145 /* we just compare the value here */ |
|
2146 static gint |
|
2147 gst_value_compare_flags (const GValue * value1, const GValue * value2) |
|
2148 { |
|
2149 guint fl1, fl2; |
|
2150 GFlagsClass *klass1 = |
|
2151 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1)); |
|
2152 GFlagsClass *klass2 = |
|
2153 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2)); |
|
2154 |
|
2155 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED); |
|
2156 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED); |
|
2157 fl1 = g_value_get_flags (value1); |
|
2158 fl2 = g_value_get_flags (value2); |
|
2159 g_type_class_unref (klass1); |
|
2160 g_type_class_unref (klass2); |
|
2161 if (fl1 < fl2) |
|
2162 return GST_VALUE_LESS_THAN; |
|
2163 if (fl1 > fl2) |
|
2164 return GST_VALUE_GREATER_THAN; |
|
2165 |
|
2166 return GST_VALUE_EQUAL; |
|
2167 } |
|
2168 |
|
2169 /* the different flags are serialized separated with a + */ |
|
2170 static gchar * |
|
2171 gst_value_serialize_flags (const GValue * value) |
|
2172 { |
|
2173 guint flags; |
|
2174 GFlagsValue *fl; |
|
2175 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value)); |
|
2176 gchar *result, *tmp; |
|
2177 gboolean first = TRUE; |
|
2178 |
|
2179 g_return_val_if_fail (klass, NULL); |
|
2180 |
|
2181 flags = g_value_get_flags (value); |
|
2182 |
|
2183 /* if no flags are set, try to serialize to the _NONE string */ |
|
2184 if (!flags) { |
|
2185 fl = g_flags_get_first_value (klass, flags); |
|
2186 return g_strdup (fl->value_name); |
|
2187 } |
|
2188 |
|
2189 /* some flags are set, so serialize one by one */ |
|
2190 result = g_strdup (""); |
|
2191 while (flags) { |
|
2192 fl = g_flags_get_first_value (klass, flags); |
|
2193 if (fl != NULL) { |
|
2194 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL); |
|
2195 g_free (result); |
|
2196 result = tmp; |
|
2197 first = FALSE; |
|
2198 |
|
2199 /* clear flag */ |
|
2200 flags &= ~fl->value; |
|
2201 } |
|
2202 } |
|
2203 g_type_class_unref (klass); |
|
2204 |
|
2205 return result; |
|
2206 } |
|
2207 |
|
2208 static gboolean |
|
2209 gst_value_deserialize_flags (GValue * dest, const gchar * s) |
|
2210 { |
|
2211 GFlagsValue *fl; |
|
2212 gchar *endptr = NULL; |
|
2213 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest)); |
|
2214 gchar **split; |
|
2215 guint flags; |
|
2216 gint i; |
|
2217 |
|
2218 g_return_val_if_fail (klass, FALSE); |
|
2219 |
|
2220 /* split into parts delimited with + */ |
|
2221 split = g_strsplit (s, "+", 0); |
|
2222 |
|
2223 flags = 0; |
|
2224 i = 0; |
|
2225 /* loop over each part */ |
|
2226 while (split[i]) { |
|
2227 if (!(fl = g_flags_get_value_by_name (klass, split[i]))) { |
|
2228 if (!(fl = g_flags_get_value_by_nick (klass, split[i]))) { |
|
2229 gint val = strtol (split[i], &endptr, 0); |
|
2230 |
|
2231 /* just or numeric value */ |
|
2232 if (endptr && *endptr == '\0') { |
|
2233 flags |= val; |
|
2234 } |
|
2235 } |
|
2236 } |
|
2237 if (fl) { |
|
2238 flags |= fl->value; |
|
2239 } |
|
2240 i++; |
|
2241 } |
|
2242 g_strfreev (split); |
|
2243 g_type_class_unref (klass); |
|
2244 g_value_set_flags (dest, flags); |
|
2245 |
|
2246 return TRUE; |
|
2247 } |
|
2248 |
|
2249 /********* |
|
2250 * union * |
|
2251 *********/ |
|
2252 |
|
2253 static gboolean |
|
2254 gst_value_union_int_int_range (GValue * dest, const GValue * src1, |
|
2255 const GValue * src2) |
|
2256 { |
|
2257 if (src2->data[0].v_int <= src1->data[0].v_int && |
|
2258 src2->data[1].v_int >= src1->data[0].v_int) { |
|
2259 gst_value_init_and_copy (dest, src2); |
|
2260 return TRUE; |
|
2261 } |
|
2262 return FALSE; |
|
2263 } |
|
2264 |
|
2265 static gboolean |
|
2266 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1, |
|
2267 const GValue * src2) |
|
2268 { |
|
2269 gint min; |
|
2270 gint max; |
|
2271 |
|
2272 min = MAX (src1->data[0].v_int, src2->data[0].v_int); |
|
2273 max = MIN (src1->data[1].v_int, src2->data[1].v_int); |
|
2274 |
|
2275 if (min <= max) { |
|
2276 g_value_init (dest, GST_TYPE_INT_RANGE); |
|
2277 gst_value_set_int_range (dest, |
|
2278 MIN (src1->data[0].v_int, src2->data[0].v_int), |
|
2279 MAX (src1->data[1].v_int, src2->data[1].v_int)); |
|
2280 return TRUE; |
|
2281 } |
|
2282 |
|
2283 return FALSE; |
|
2284 } |
|
2285 |
|
2286 /**************** |
|
2287 * intersection * |
|
2288 ****************/ |
|
2289 |
|
2290 static gboolean |
|
2291 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1, |
|
2292 const GValue * src2) |
|
2293 { |
|
2294 if (src2->data[0].v_int <= src1->data[0].v_int && |
|
2295 src2->data[1].v_int >= src1->data[0].v_int) { |
|
2296 gst_value_init_and_copy (dest, src1); |
|
2297 return TRUE; |
|
2298 } |
|
2299 |
|
2300 return FALSE; |
|
2301 } |
|
2302 |
|
2303 static gboolean |
|
2304 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1, |
|
2305 const GValue * src2) |
|
2306 { |
|
2307 gint min; |
|
2308 gint max; |
|
2309 |
|
2310 min = MAX (src1->data[0].v_int, src2->data[0].v_int); |
|
2311 max = MIN (src1->data[1].v_int, src2->data[1].v_int); |
|
2312 |
|
2313 if (min < max) { |
|
2314 g_value_init (dest, GST_TYPE_INT_RANGE); |
|
2315 gst_value_set_int_range (dest, min, max); |
|
2316 return TRUE; |
|
2317 } |
|
2318 if (min == max) { |
|
2319 g_value_init (dest, G_TYPE_INT); |
|
2320 g_value_set_int (dest, min); |
|
2321 return TRUE; |
|
2322 } |
|
2323 |
|
2324 return FALSE; |
|
2325 } |
|
2326 |
|
2327 static gboolean |
|
2328 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1, |
|
2329 const GValue * src2) |
|
2330 { |
|
2331 if (src2->data[0].v_double <= src1->data[0].v_double && |
|
2332 src2->data[1].v_double >= src1->data[0].v_double) { |
|
2333 gst_value_init_and_copy (dest, src1); |
|
2334 return TRUE; |
|
2335 } |
|
2336 |
|
2337 return FALSE; |
|
2338 } |
|
2339 |
|
2340 static gboolean |
|
2341 gst_value_intersect_double_range_double_range (GValue * dest, |
|
2342 const GValue * src1, const GValue * src2) |
|
2343 { |
|
2344 gdouble min; |
|
2345 gdouble max; |
|
2346 |
|
2347 min = MAX (src1->data[0].v_double, src2->data[0].v_double); |
|
2348 max = MIN (src1->data[1].v_double, src2->data[1].v_double); |
|
2349 |
|
2350 if (min < max) { |
|
2351 g_value_init (dest, GST_TYPE_DOUBLE_RANGE); |
|
2352 gst_value_set_double_range (dest, min, max); |
|
2353 return TRUE; |
|
2354 } |
|
2355 if (min == max) { |
|
2356 g_value_init (dest, G_TYPE_DOUBLE); |
|
2357 g_value_set_int (dest, (int) min); |
|
2358 return TRUE; |
|
2359 } |
|
2360 |
|
2361 return FALSE; |
|
2362 } |
|
2363 |
|
2364 static gboolean |
|
2365 gst_value_intersect_list (GValue * dest, const GValue * value1, |
|
2366 const GValue * value2) |
|
2367 { |
|
2368 guint i, size; |
|
2369 GValue intersection = { 0, }; |
|
2370 gboolean ret = FALSE; |
|
2371 |
|
2372 size = gst_value_list_get_size (value1); |
|
2373 for (i = 0; i < size; i++) { |
|
2374 const GValue *cur = gst_value_list_get_value (value1, i); |
|
2375 |
|
2376 if (gst_value_intersect (&intersection, cur, value2)) { |
|
2377 /* append value */ |
|
2378 if (!ret) { |
|
2379 gst_value_init_and_copy (dest, &intersection); |
|
2380 ret = TRUE; |
|
2381 } else if (GST_VALUE_HOLDS_LIST (dest)) { |
|
2382 gst_value_list_append_value (dest, &intersection); |
|
2383 } else { |
|
2384 GValue temp = { 0, }; |
|
2385 |
|
2386 gst_value_init_and_copy (&temp, dest); |
|
2387 g_value_unset (dest); |
|
2388 gst_value_list_concat (dest, &temp, &intersection); |
|
2389 g_value_unset (&temp); |
|
2390 } |
|
2391 g_value_unset (&intersection); |
|
2392 } |
|
2393 } |
|
2394 |
|
2395 return ret; |
|
2396 } |
|
2397 |
|
2398 static gboolean |
|
2399 gst_value_intersect_array (GValue * dest, const GValue * src1, |
|
2400 const GValue * src2) |
|
2401 { |
|
2402 guint size; |
|
2403 guint n; |
|
2404 GValue val = { 0 }; |
|
2405 |
|
2406 /* only works on similar-sized arrays */ |
|
2407 size = gst_value_array_get_size (src1); |
|
2408 if (size != gst_value_array_get_size (src2)) |
|
2409 return FALSE; |
|
2410 g_value_init (dest, GST_TYPE_ARRAY); |
|
2411 |
|
2412 for (n = 0; n < size; n++) { |
|
2413 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n), |
|
2414 gst_value_array_get_value (src2, n))) { |
|
2415 g_value_unset (dest); |
|
2416 return FALSE; |
|
2417 } |
|
2418 gst_value_array_append_value (dest, &val); |
|
2419 g_value_unset (&val); |
|
2420 } |
|
2421 |
|
2422 return TRUE; |
|
2423 } |
|
2424 |
|
2425 static gboolean |
|
2426 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1, |
|
2427 const GValue * src2) |
|
2428 { |
|
2429 int res1, res2; |
|
2430 GValue *vals; |
|
2431 GstValueCompareFunc compare; |
|
2432 |
|
2433 vals = src2->data[0].v_pointer; |
|
2434 |
|
2435 if (vals == NULL) |
|
2436 return FALSE; |
|
2437 |
|
2438 if ((compare = gst_value_get_compare_func (src1))) { |
|
2439 res1 = gst_value_compare_with_func (&vals[0], src1, compare); |
|
2440 res2 = gst_value_compare_with_func (&vals[1], src1, compare); |
|
2441 |
|
2442 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) && |
|
2443 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) { |
|
2444 gst_value_init_and_copy (dest, src1); |
|
2445 return TRUE; |
|
2446 } |
|
2447 } |
|
2448 |
|
2449 return FALSE; |
|
2450 } |
|
2451 |
|
2452 static gboolean |
|
2453 gst_value_intersect_fraction_range_fraction_range |
|
2454 (GValue * dest, const GValue * src1, const GValue * src2) |
|
2455 { |
|
2456 GValue *min; |
|
2457 GValue *max; |
|
2458 int res; |
|
2459 GValue *vals1, *vals2; |
|
2460 GstValueCompareFunc compare; |
|
2461 |
|
2462 vals1 = src1->data[0].v_pointer; |
|
2463 vals2 = src2->data[0].v_pointer; |
|
2464 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE); |
|
2465 |
|
2466 if ((compare = gst_value_get_compare_func (&vals1[0]))) { |
|
2467 /* min = MAX (src1.start, src2.start) */ |
|
2468 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare); |
|
2469 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); |
|
2470 if (res == GST_VALUE_LESS_THAN) |
|
2471 min = &vals2[0]; /* Take the max of the 2 */ |
|
2472 else |
|
2473 min = &vals1[0]; |
|
2474 |
|
2475 /* max = MIN (src1.end, src2.end) */ |
|
2476 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare); |
|
2477 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); |
|
2478 if (res == GST_VALUE_GREATER_THAN) |
|
2479 max = &vals2[1]; /* Take the min of the 2 */ |
|
2480 else |
|
2481 max = &vals1[1]; |
|
2482 |
|
2483 res = gst_value_compare_with_func (min, max, compare); |
|
2484 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE); |
|
2485 if (res == GST_VALUE_LESS_THAN) { |
|
2486 g_value_init (dest, GST_TYPE_FRACTION_RANGE); |
|
2487 vals1 = dest->data[0].v_pointer; |
|
2488 g_value_copy (min, &vals1[0]); |
|
2489 g_value_copy (max, &vals1[1]); |
|
2490 return TRUE; |
|
2491 } |
|
2492 if (res == GST_VALUE_EQUAL) { |
|
2493 gst_value_init_and_copy (dest, min); |
|
2494 return TRUE; |
|
2495 } |
|
2496 } |
|
2497 |
|
2498 return FALSE; |
|
2499 } |
|
2500 |
|
2501 /*************** |
|
2502 * subtraction * |
|
2503 ***************/ |
|
2504 |
|
2505 static gboolean |
|
2506 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend, |
|
2507 const GValue * subtrahend) |
|
2508 { |
|
2509 int min = gst_value_get_int_range_min (subtrahend); |
|
2510 int max = gst_value_get_int_range_max (subtrahend); |
|
2511 int val = g_value_get_int (minuend); |
|
2512 |
|
2513 /* subtracting a range from an int only works if the int is not in the |
|
2514 * range */ |
|
2515 if (val < min || val > max) { |
|
2516 /* and the result is the int */ |
|
2517 gst_value_init_and_copy (dest, minuend); |
|
2518 return TRUE; |
|
2519 } |
|
2520 return FALSE; |
|
2521 } |
|
2522 |
|
2523 /* creates a new int range based on input values. |
|
2524 */ |
|
2525 static gboolean |
|
2526 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2, |
|
2527 gint max2) |
|
2528 { |
|
2529 GValue v1 = { 0, }; |
|
2530 GValue v2 = { 0, }; |
|
2531 GValue *pv1, *pv2; /* yeah, hungarian! */ |
|
2532 |
|
2533 if (min1 <= max1 && min2 <= max2) { |
|
2534 pv1 = &v1; |
|
2535 pv2 = &v2; |
|
2536 } else if (min1 <= max1) { |
|
2537 pv1 = dest; |
|
2538 pv2 = NULL; |
|
2539 } else if (min2 <= max2) { |
|
2540 pv1 = NULL; |
|
2541 pv2 = dest; |
|
2542 } else { |
|
2543 return FALSE; |
|
2544 } |
|
2545 |
|
2546 if (min1 < max1) { |
|
2547 g_value_init (pv1, GST_TYPE_INT_RANGE); |
|
2548 gst_value_set_int_range (pv1, min1, max1); |
|
2549 } else if (min1 == max1) { |
|
2550 g_value_init (pv1, G_TYPE_INT); |
|
2551 g_value_set_int (pv1, min1); |
|
2552 } |
|
2553 if (min2 < max2) { |
|
2554 g_value_init (pv2, GST_TYPE_INT_RANGE); |
|
2555 gst_value_set_int_range (pv2, min2, max2); |
|
2556 } else if (min2 == max2) { |
|
2557 g_value_init (pv2, G_TYPE_INT); |
|
2558 g_value_set_int (pv2, min2); |
|
2559 } |
|
2560 |
|
2561 if (min1 <= max1 && min2 <= max2) { |
|
2562 gst_value_list_concat (dest, pv1, pv2); |
|
2563 g_value_unset (pv1); |
|
2564 g_value_unset (pv2); |
|
2565 } |
|
2566 return TRUE; |
|
2567 } |
|
2568 |
|
2569 static gboolean |
|
2570 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend, |
|
2571 const GValue * subtrahend) |
|
2572 { |
|
2573 gint min = gst_value_get_int_range_min (minuend); |
|
2574 gint max = gst_value_get_int_range_max (minuend); |
|
2575 gint val = g_value_get_int (subtrahend); |
|
2576 |
|
2577 g_return_val_if_fail (min < max, FALSE); |
|
2578 |
|
2579 /* value is outside of the range, return range unchanged */ |
|
2580 if (val < min || val > max) { |
|
2581 gst_value_init_and_copy (dest, minuend); |
|
2582 return TRUE; |
|
2583 } else { |
|
2584 /* max must be MAXINT too as val <= max */ |
|
2585 if (val == G_MAXINT) { |
|
2586 max--; |
|
2587 val--; |
|
2588 } |
|
2589 /* min must be MININT too as val >= max */ |
|
2590 if (val == G_MININT) { |
|
2591 min++; |
|
2592 val++; |
|
2593 } |
|
2594 gst_value_create_new_range (dest, min, val - 1, val + 1, max); |
|
2595 } |
|
2596 return TRUE; |
|
2597 } |
|
2598 |
|
2599 static gboolean |
|
2600 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend, |
|
2601 const GValue * subtrahend) |
|
2602 { |
|
2603 gint min1 = gst_value_get_int_range_min (minuend); |
|
2604 gint max1 = gst_value_get_int_range_max (minuend); |
|
2605 gint min2 = gst_value_get_int_range_min (subtrahend); |
|
2606 gint max2 = gst_value_get_int_range_max (subtrahend); |
|
2607 |
|
2608 if (max2 == G_MAXINT && min2 == G_MININT) { |
|
2609 return FALSE; |
|
2610 } else if (max2 == G_MAXINT) { |
|
2611 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0); |
|
2612 } else if (min2 == G_MININT) { |
|
2613 return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0); |
|
2614 } else { |
|
2615 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), |
|
2616 MAX (max2 + 1, min1), max1); |
|
2617 } |
|
2618 } |
|
2619 |
|
2620 static gboolean |
|
2621 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend, |
|
2622 const GValue * subtrahend) |
|
2623 { |
|
2624 gdouble min = gst_value_get_double_range_min (subtrahend); |
|
2625 gdouble max = gst_value_get_double_range_max (subtrahend); |
|
2626 gdouble val = g_value_get_double (minuend); |
|
2627 |
|
2628 if (val < min || val > max) { |
|
2629 gst_value_init_and_copy (dest, minuend); |
|
2630 return TRUE; |
|
2631 } |
|
2632 return FALSE; |
|
2633 } |
|
2634 |
|
2635 static gboolean |
|
2636 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend, |
|
2637 const GValue * subtrahend) |
|
2638 { |
|
2639 /* since we don't have open ranges, we cannot create a hole in |
|
2640 * a double range. We return the original range */ |
|
2641 gst_value_init_and_copy (dest, minuend); |
|
2642 return TRUE; |
|
2643 } |
|
2644 |
|
2645 static gboolean |
|
2646 gst_value_subtract_double_range_double_range (GValue * dest, |
|
2647 const GValue * minuend, const GValue * subtrahend) |
|
2648 { |
|
2649 /* since we don't have open ranges, we have to approximate */ |
|
2650 /* done like with ints */ |
|
2651 gdouble min1 = gst_value_get_double_range_min (minuend); |
|
2652 gdouble max2 = gst_value_get_double_range_max (minuend); |
|
2653 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2); |
|
2654 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1); |
|
2655 GValue v1 = { 0, }; |
|
2656 GValue v2 = { 0, }; |
|
2657 GValue *pv1, *pv2; /* yeah, hungarian! */ |
|
2658 |
|
2659 if (min1 < max1 && min2 < max2) { |
|
2660 pv1 = &v1; |
|
2661 pv2 = &v2; |
|
2662 } else if (min1 < max1) { |
|
2663 pv1 = dest; |
|
2664 pv2 = NULL; |
|
2665 } else if (min2 < max2) { |
|
2666 pv1 = NULL; |
|
2667 pv2 = dest; |
|
2668 } else { |
|
2669 return FALSE; |
|
2670 } |
|
2671 |
|
2672 if (min1 < max1) { |
|
2673 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE); |
|
2674 gst_value_set_double_range (pv1, min1, max1); |
|
2675 } |
|
2676 if (min2 < max2) { |
|
2677 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE); |
|
2678 gst_value_set_double_range (pv2, min2, max2); |
|
2679 } |
|
2680 |
|
2681 if (min1 < max1 && min2 < max2) { |
|
2682 gst_value_list_concat (dest, pv1, pv2); |
|
2683 g_value_unset (pv1); |
|
2684 g_value_unset (pv2); |
|
2685 } |
|
2686 return TRUE; |
|
2687 } |
|
2688 |
|
2689 static gboolean |
|
2690 gst_value_subtract_from_list (GValue * dest, const GValue * minuend, |
|
2691 const GValue * subtrahend) |
|
2692 { |
|
2693 guint i, size; |
|
2694 GValue subtraction = { 0, }; |
|
2695 gboolean ret = FALSE; |
|
2696 |
|
2697 size = gst_value_list_get_size (minuend); |
|
2698 for (i = 0; i < size; i++) { |
|
2699 const GValue *cur = gst_value_list_get_value (minuend, i); |
|
2700 |
|
2701 if (gst_value_subtract (&subtraction, cur, subtrahend)) { |
|
2702 if (!ret) { |
|
2703 gst_value_init_and_copy (dest, &subtraction); |
|
2704 ret = TRUE; |
|
2705 } else if (GST_VALUE_HOLDS_LIST (dest) |
|
2706 && GST_VALUE_HOLDS_LIST (&subtraction)) { |
|
2707 /* unroll */ |
|
2708 GValue unroll = { 0, }; |
|
2709 |
|
2710 gst_value_init_and_copy (&unroll, dest); |
|
2711 g_value_unset (dest); |
|
2712 gst_value_list_concat (dest, &unroll, &subtraction); |
|
2713 } else if (GST_VALUE_HOLDS_LIST (dest)) { |
|
2714 gst_value_list_append_value (dest, &subtraction); |
|
2715 } else { |
|
2716 GValue temp = { 0, }; |
|
2717 |
|
2718 gst_value_init_and_copy (&temp, dest); |
|
2719 g_value_unset (dest); |
|
2720 gst_value_list_concat (dest, &temp, &subtraction); |
|
2721 g_value_unset (&temp); |
|
2722 } |
|
2723 g_value_unset (&subtraction); |
|
2724 } |
|
2725 } |
|
2726 return ret; |
|
2727 } |
|
2728 |
|
2729 static gboolean |
|
2730 gst_value_subtract_list (GValue * dest, const GValue * minuend, |
|
2731 const GValue * subtrahend) |
|
2732 { |
|
2733 guint i, size; |
|
2734 GValue data[2] = { {0,}, {0,} }; |
|
2735 GValue *subtraction = &data[0], *result = &data[1]; |
|
2736 |
|
2737 gst_value_init_and_copy (result, minuend); |
|
2738 size = gst_value_list_get_size (subtrahend); |
|
2739 for (i = 0; i < size; i++) { |
|
2740 const GValue *cur = gst_value_list_get_value (subtrahend, i); |
|
2741 |
|
2742 if (gst_value_subtract (subtraction, result, cur)) { |
|
2743 GValue *temp = result; |
|
2744 |
|
2745 result = subtraction; |
|
2746 subtraction = temp; |
|
2747 g_value_unset (subtraction); |
|
2748 } else { |
|
2749 g_value_unset (result); |
|
2750 return FALSE; |
|
2751 } |
|
2752 } |
|
2753 gst_value_init_and_copy (dest, result); |
|
2754 g_value_unset (result); |
|
2755 return TRUE; |
|
2756 } |
|
2757 |
|
2758 static gboolean |
|
2759 gst_value_subtract_fraction_fraction_range (GValue * dest, |
|
2760 const GValue * minuend, const GValue * subtrahend) |
|
2761 { |
|
2762 const GValue *min = gst_value_get_fraction_range_min (subtrahend); |
|
2763 const GValue *max = gst_value_get_fraction_range_max (subtrahend); |
|
2764 GstValueCompareFunc compare; |
|
2765 |
|
2766 if ((compare = gst_value_get_compare_func (minuend))) { |
|
2767 /* subtracting a range from an fraction only works if the fraction |
|
2768 * is not in the range */ |
|
2769 if (gst_value_compare_with_func (minuend, min, compare) == |
|
2770 GST_VALUE_LESS_THAN || |
|
2771 gst_value_compare_with_func (minuend, max, compare) == |
|
2772 GST_VALUE_GREATER_THAN) { |
|
2773 /* and the result is the value */ |
|
2774 gst_value_init_and_copy (dest, minuend); |
|
2775 return TRUE; |
|
2776 } |
|
2777 } |
|
2778 return FALSE; |
|
2779 } |
|
2780 |
|
2781 static gboolean |
|
2782 gst_value_subtract_fraction_range_fraction (GValue * dest, |
|
2783 const GValue * minuend, const GValue * subtrahend) |
|
2784 { |
|
2785 /* since we don't have open ranges, we cannot create a hole in |
|
2786 * a range. We return the original range */ |
|
2787 gst_value_init_and_copy (dest, minuend); |
|
2788 return TRUE; |
|
2789 } |
|
2790 |
|
2791 static gboolean |
|
2792 gst_value_subtract_fraction_range_fraction_range (GValue * dest, |
|
2793 const GValue * minuend, const GValue * subtrahend) |
|
2794 { |
|
2795 /* since we don't have open ranges, we have to approximate */ |
|
2796 /* done like with ints and doubles. Creates a list of 2 fraction ranges */ |
|
2797 const GValue *min1 = gst_value_get_fraction_range_min (minuend); |
|
2798 const GValue *max2 = gst_value_get_fraction_range_max (minuend); |
|
2799 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend); |
|
2800 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend); |
|
2801 int cmp1, cmp2; |
|
2802 GValue v1 = { 0, }; |
|
2803 GValue v2 = { 0, }; |
|
2804 GValue *pv1, *pv2; /* yeah, hungarian! */ |
|
2805 GstValueCompareFunc compare; |
|
2806 |
|
2807 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE); |
|
2808 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE); |
|
2809 |
|
2810 compare = gst_value_get_compare_func (min1); |
|
2811 g_return_val_if_fail (compare, FALSE); |
|
2812 |
|
2813 cmp1 = gst_value_compare_with_func (max2, max1, compare); |
|
2814 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); |
|
2815 if (cmp1 == GST_VALUE_LESS_THAN) |
|
2816 max1 = max2; |
|
2817 cmp1 = gst_value_compare_with_func (min1, min2, compare); |
|
2818 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE); |
|
2819 if (cmp1 == GST_VALUE_GREATER_THAN) |
|
2820 min2 = min1; |
|
2821 |
|
2822 cmp1 = gst_value_compare_with_func (min1, max1, compare); |
|
2823 cmp2 = gst_value_compare_with_func (min2, max2, compare); |
|
2824 |
|
2825 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { |
|
2826 pv1 = &v1; |
|
2827 pv2 = &v2; |
|
2828 } else if (cmp1 == GST_VALUE_LESS_THAN) { |
|
2829 pv1 = dest; |
|
2830 pv2 = NULL; |
|
2831 } else if (cmp2 == GST_VALUE_LESS_THAN) { |
|
2832 pv1 = NULL; |
|
2833 pv2 = dest; |
|
2834 } else { |
|
2835 return FALSE; |
|
2836 } |
|
2837 |
|
2838 if (cmp1 == GST_VALUE_LESS_THAN) { |
|
2839 g_value_init (pv1, GST_TYPE_FRACTION_RANGE); |
|
2840 gst_value_set_fraction_range (pv1, min1, max1); |
|
2841 } |
|
2842 if (cmp2 == GST_VALUE_LESS_THAN) { |
|
2843 g_value_init (pv2, GST_TYPE_FRACTION_RANGE); |
|
2844 gst_value_set_fraction_range (pv2, min2, max2); |
|
2845 } |
|
2846 |
|
2847 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) { |
|
2848 gst_value_list_concat (dest, pv1, pv2); |
|
2849 g_value_unset (pv1); |
|
2850 g_value_unset (pv2); |
|
2851 } |
|
2852 return TRUE; |
|
2853 } |
|
2854 |
|
2855 |
|
2856 /************** |
|
2857 * comparison * |
|
2858 **************/ |
|
2859 |
|
2860 /** |
|
2861 * gst_value_can_compare: |
|
2862 * @value1: a value to compare |
|
2863 * @value2: another value to compare |
|
2864 * |
|
2865 * Determines if @value1 and @value2 can be compared. |
|
2866 * |
|
2867 * Returns: TRUE if the values can be compared |
|
2868 */ |
|
2869 #ifdef __SYMBIAN32__ |
|
2870 EXPORT_C |
|
2871 #endif |
|
2872 |
|
2873 gboolean |
|
2874 gst_value_can_compare (const GValue * value1, const GValue * value2) |
|
2875 { |
|
2876 GstValueTable *table; |
|
2877 guint i; |
|
2878 |
|
2879 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) |
|
2880 return FALSE; |
|
2881 |
|
2882 for (i = 0; i < gst_value_table->len; i++) { |
|
2883 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
2884 if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare) |
|
2885 return TRUE; |
|
2886 } |
|
2887 |
|
2888 return FALSE; |
|
2889 } |
|
2890 |
|
2891 /* |
|
2892 * gst_value_get_compare_func: |
|
2893 * @value1: a value to get the compare function for |
|
2894 * |
|
2895 * Determines the compare function to be used with values of the same type as |
|
2896 * @value1. The function can be given to gst_value_compare_with_func(). |
|
2897 * |
|
2898 * Returns: A #GstValueCompareFunc value |
|
2899 */ |
|
2900 static GstValueCompareFunc |
|
2901 gst_value_get_compare_func (const GValue * value1) |
|
2902 { |
|
2903 GstValueTable *table, *best = NULL; |
|
2904 guint i; |
|
2905 |
|
2906 for (i = 0; i < gst_value_table->len; i++) { |
|
2907 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
2908 if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) { |
|
2909 best = table; |
|
2910 break; |
|
2911 } |
|
2912 if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) { |
|
2913 if (!best || g_type_is_a (table->type, best->type)) |
|
2914 best = table; |
|
2915 } |
|
2916 } |
|
2917 if (best) { |
|
2918 return best->compare; |
|
2919 } |
|
2920 return NULL; |
|
2921 } |
|
2922 |
|
2923 /** |
|
2924 * gst_value_compare: |
|
2925 * @value1: a value to compare |
|
2926 * @value2: another value to compare |
|
2927 * |
|
2928 * Compares @value1 and @value2. If @value1 and @value2 cannot be |
|
2929 * compared, the function returns GST_VALUE_UNORDERED. Otherwise, |
|
2930 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned. |
|
2931 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned. |
|
2932 * If the values are equal, GST_VALUE_EQUAL is returned. |
|
2933 * |
|
2934 * Returns: A #GstValueCompareType value |
|
2935 */ |
|
2936 #ifdef __SYMBIAN32__ |
|
2937 EXPORT_C |
|
2938 #endif |
|
2939 gint |
|
2940 gst_value_compare (const GValue * value1, const GValue * value2) |
|
2941 { |
|
2942 GstValueCompareFunc compare; |
|
2943 |
|
2944 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) |
|
2945 return GST_VALUE_UNORDERED; |
|
2946 |
|
2947 compare = gst_value_get_compare_func (value1); |
|
2948 if (compare) { |
|
2949 return compare (value1, value2); |
|
2950 } |
|
2951 |
|
2952 g_critical ("unable to compare values of type %s\n", |
|
2953 g_type_name (G_VALUE_TYPE (value1))); |
|
2954 return GST_VALUE_UNORDERED; |
|
2955 } |
|
2956 |
|
2957 /* |
|
2958 * gst_value_compare_with_func: |
|
2959 * @value1: a value to compare |
|
2960 * @value2: another value to compare |
|
2961 * @compare: compare function |
|
2962 * |
|
2963 * Compares @value1 and @value2 using the @compare function. Works like |
|
2964 * gst_value_compare() but allows to save time determining the compare function |
|
2965 * a multiple times. |
|
2966 * |
|
2967 * Returns: A #GstValueCompareType value |
|
2968 */ |
|
2969 static gint |
|
2970 gst_value_compare_with_func (const GValue * value1, const GValue * value2, |
|
2971 GstValueCompareFunc compare) |
|
2972 { |
|
2973 g_assert (compare); |
|
2974 |
|
2975 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) |
|
2976 return GST_VALUE_UNORDERED; |
|
2977 |
|
2978 return compare (value1, value2); |
|
2979 } |
|
2980 |
|
2981 /* union */ |
|
2982 |
|
2983 /** |
|
2984 * gst_value_can_union: |
|
2985 * @value1: a value to union |
|
2986 * @value2: another value to union |
|
2987 * |
|
2988 * Determines if @value1 and @value2 can be non-trivially unioned. |
|
2989 * Any two values can be trivially unioned by adding both of them |
|
2990 * to a GstValueList. However, certain types have the possibility |
|
2991 * to be unioned in a simpler way. For example, an integer range |
|
2992 * and an integer can be unioned if the integer is a subset of the |
|
2993 * integer range. If there is the possibility that two values can |
|
2994 * be unioned, this function returns TRUE. |
|
2995 * |
|
2996 * Returns: TRUE if there is a function allowing the two values to |
|
2997 * be unioned. |
|
2998 */ |
|
2999 #ifdef __SYMBIAN32__ |
|
3000 EXPORT_C |
|
3001 #endif |
|
3002 |
|
3003 gboolean |
|
3004 gst_value_can_union (const GValue * value1, const GValue * value2) |
|
3005 { |
|
3006 GstValueUnionInfo *union_info; |
|
3007 guint i; |
|
3008 |
|
3009 for (i = 0; i < gst_value_union_funcs->len; i++) { |
|
3010 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
|
3011 if (union_info->type1 == G_VALUE_TYPE (value1) && |
|
3012 union_info->type2 == G_VALUE_TYPE (value2)) |
|
3013 return TRUE; |
|
3014 if (union_info->type1 == G_VALUE_TYPE (value2) && |
|
3015 union_info->type2 == G_VALUE_TYPE (value1)) |
|
3016 return TRUE; |
|
3017 } |
|
3018 |
|
3019 return FALSE; |
|
3020 } |
|
3021 |
|
3022 /** |
|
3023 * gst_value_union: |
|
3024 * @dest: the destination value |
|
3025 * @value1: a value to union |
|
3026 * @value2: another value to union |
|
3027 * |
|
3028 * Creates a GValue cooresponding to the union of @value1 and @value2. |
|
3029 * |
|
3030 * Returns: always returns %TRUE |
|
3031 */ |
|
3032 /* FIXME: change return type to 'void'? */ |
|
3033 #ifdef __SYMBIAN32__ |
|
3034 EXPORT_C |
|
3035 #endif |
|
3036 |
|
3037 gboolean |
|
3038 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) |
|
3039 { |
|
3040 GstValueUnionInfo *union_info; |
|
3041 guint i; |
|
3042 |
|
3043 for (i = 0; i < gst_value_union_funcs->len; i++) { |
|
3044 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
|
3045 if (union_info->type1 == G_VALUE_TYPE (value1) && |
|
3046 union_info->type2 == G_VALUE_TYPE (value2)) { |
|
3047 if (union_info->func (dest, value1, value2)) { |
|
3048 return TRUE; |
|
3049 } |
|
3050 } |
|
3051 if (union_info->type1 == G_VALUE_TYPE (value2) && |
|
3052 union_info->type2 == G_VALUE_TYPE (value1)) { |
|
3053 if (union_info->func (dest, value2, value1)) { |
|
3054 return TRUE; |
|
3055 } |
|
3056 } |
|
3057 } |
|
3058 |
|
3059 gst_value_list_concat (dest, value1, value2); |
|
3060 return TRUE; |
|
3061 } |
|
3062 |
|
3063 /** |
|
3064 * gst_value_register_union_func: |
|
3065 * @type1: a type to union |
|
3066 * @type2: another type to union |
|
3067 * @func: a function that implments creating a union between the two types |
|
3068 * |
|
3069 * Registers a union function that can create a union between GValues |
|
3070 * of the type @type1 and @type2. |
|
3071 * |
|
3072 * Union functions should be registered at startup before any pipelines are |
|
3073 * started, as gst_value_register_union_func() is not thread-safe and cannot |
|
3074 * be used at the same time as gst_value_union() or gst_value_can_union(). |
|
3075 */ |
|
3076 #ifdef __SYMBIAN32__ |
|
3077 EXPORT_C |
|
3078 #endif |
|
3079 |
|
3080 void |
|
3081 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func) |
|
3082 { |
|
3083 GstValueUnionInfo union_info; |
|
3084 |
|
3085 union_info.type1 = type1; |
|
3086 union_info.type2 = type2; |
|
3087 union_info.func = func; |
|
3088 |
|
3089 g_array_append_val (gst_value_union_funcs, union_info); |
|
3090 } |
|
3091 |
|
3092 /* intersection */ |
|
3093 |
|
3094 /** |
|
3095 * gst_value_can_intersect: |
|
3096 * @value1: a value to intersect |
|
3097 * @value2: another value to intersect |
|
3098 * |
|
3099 * Determines if intersecting two values will produce a valid result. |
|
3100 * Two values will produce a valid intersection if they have the same |
|
3101 * type, or if there is a method (registered by |
|
3102 * gst_value_register_intersection_func()) to calculate the intersection. |
|
3103 * |
|
3104 * Returns: TRUE if the values can intersect |
|
3105 */ |
|
3106 #ifdef __SYMBIAN32__ |
|
3107 EXPORT_C |
|
3108 #endif |
|
3109 |
|
3110 gboolean |
|
3111 gst_value_can_intersect (const GValue * value1, const GValue * value2) |
|
3112 { |
|
3113 GstValueIntersectInfo *intersect_info; |
|
3114 guint i; |
|
3115 |
|
3116 /* special cases */ |
|
3117 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2)) |
|
3118 return TRUE; |
|
3119 |
|
3120 for (i = 0; i < gst_value_intersect_funcs->len; i++) { |
|
3121 intersect_info = &g_array_index (gst_value_intersect_funcs, |
|
3122 GstValueIntersectInfo, i); |
|
3123 if (intersect_info->type1 == G_VALUE_TYPE (value1) && |
|
3124 intersect_info->type2 == G_VALUE_TYPE (value2)) |
|
3125 if (intersect_info->type2 == G_VALUE_TYPE (value1) && |
|
3126 intersect_info->type1 == G_VALUE_TYPE (value2)) |
|
3127 return TRUE; |
|
3128 } |
|
3129 |
|
3130 return gst_value_can_compare (value1, value2); |
|
3131 } |
|
3132 |
|
3133 /** |
|
3134 * gst_value_intersect: |
|
3135 * @dest: a uninitialized #GValue that will hold the calculated |
|
3136 * intersection value |
|
3137 * @value1: a value to intersect |
|
3138 * @value2: another value to intersect |
|
3139 * |
|
3140 * Calculates the intersection of two values. If the values have |
|
3141 * a non-empty intersection, the value representing the intersection |
|
3142 * is placed in @dest. If the intersection is non-empty, @dest is |
|
3143 * not modified. |
|
3144 * |
|
3145 * Returns: TRUE if the intersection is non-empty |
|
3146 */ |
|
3147 #ifdef __SYMBIAN32__ |
|
3148 EXPORT_C |
|
3149 #endif |
|
3150 |
|
3151 gboolean |
|
3152 gst_value_intersect (GValue * dest, const GValue * value1, |
|
3153 const GValue * value2) |
|
3154 { |
|
3155 GstValueIntersectInfo *intersect_info; |
|
3156 guint i; |
|
3157 gboolean ret = FALSE; |
|
3158 |
|
3159 /* special cases first */ |
|
3160 if (GST_VALUE_HOLDS_LIST (value1)) |
|
3161 return gst_value_intersect_list (dest, value1, value2); |
|
3162 if (GST_VALUE_HOLDS_LIST (value2)) |
|
3163 return gst_value_intersect_list (dest, value2, value1); |
|
3164 |
|
3165 for (i = 0; i < gst_value_intersect_funcs->len; i++) { |
|
3166 intersect_info = &g_array_index (gst_value_intersect_funcs, |
|
3167 GstValueIntersectInfo, i); |
|
3168 if (intersect_info->type1 == G_VALUE_TYPE (value1) && |
|
3169 intersect_info->type2 == G_VALUE_TYPE (value2)) { |
|
3170 ret = intersect_info->func (dest, value1, value2); |
|
3171 return ret; |
|
3172 } |
|
3173 if (intersect_info->type1 == G_VALUE_TYPE (value2) && |
|
3174 intersect_info->type2 == G_VALUE_TYPE (value1)) { |
|
3175 ret = intersect_info->func (dest, value2, value1); |
|
3176 return ret; |
|
3177 } |
|
3178 } |
|
3179 |
|
3180 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) { |
|
3181 gst_value_init_and_copy (dest, value1); |
|
3182 ret = TRUE; |
|
3183 } |
|
3184 |
|
3185 return ret; |
|
3186 } |
|
3187 |
|
3188 /** |
|
3189 * gst_value_register_intersect_func: |
|
3190 * @type1: the first type to intersect |
|
3191 * @type2: the second type to intersect |
|
3192 * @func: the intersection function |
|
3193 * |
|
3194 * Registers a function that is called to calculate the intersection |
|
3195 * of the values having the types @type1 and @type2. |
|
3196 * |
|
3197 * Intersect functions should be registered at startup before any pipelines are |
|
3198 * started, as gst_value_register_intersect_func() is not thread-safe and |
|
3199 * cannot be used at the same time as gst_value_intersect() or |
|
3200 * gst_value_can_intersect(). |
|
3201 */ |
|
3202 #ifdef __SYMBIAN32__ |
|
3203 EXPORT_C |
|
3204 #endif |
|
3205 |
|
3206 void |
|
3207 gst_value_register_intersect_func (GType type1, GType type2, |
|
3208 GstValueIntersectFunc func) |
|
3209 { |
|
3210 GstValueIntersectInfo intersect_info; |
|
3211 |
|
3212 intersect_info.type1 = type1; |
|
3213 intersect_info.type2 = type2; |
|
3214 intersect_info.func = func; |
|
3215 |
|
3216 g_array_append_val (gst_value_intersect_funcs, intersect_info); |
|
3217 } |
|
3218 |
|
3219 |
|
3220 /* subtraction */ |
|
3221 |
|
3222 /** |
|
3223 * gst_value_subtract: |
|
3224 * @dest: the destination value for the result if the subtraction is not empty |
|
3225 * @minuend: the value to subtract from |
|
3226 * @subtrahend: the value to subtract |
|
3227 * |
|
3228 * Subtracts @subtrahend from @minuend and stores the result in @dest. |
|
3229 * Note that this means subtraction as in sets, not as in mathematics. |
|
3230 * |
|
3231 * Returns: %TRUE if the subtraction is not empty |
|
3232 */ |
|
3233 #ifdef __SYMBIAN32__ |
|
3234 EXPORT_C |
|
3235 #endif |
|
3236 |
|
3237 gboolean |
|
3238 gst_value_subtract (GValue * dest, const GValue * minuend, |
|
3239 const GValue * subtrahend) |
|
3240 { |
|
3241 GstValueSubtractInfo *info; |
|
3242 guint i; |
|
3243 |
|
3244 /* special cases first */ |
|
3245 if (GST_VALUE_HOLDS_LIST (minuend)) |
|
3246 return gst_value_subtract_from_list (dest, minuend, subtrahend); |
|
3247 if (GST_VALUE_HOLDS_LIST (subtrahend)) |
|
3248 return gst_value_subtract_list (dest, minuend, subtrahend); |
|
3249 |
|
3250 for (i = 0; i < gst_value_subtract_funcs->len; i++) { |
|
3251 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
|
3252 if (info->minuend == G_VALUE_TYPE (minuend) && |
|
3253 info->subtrahend == G_VALUE_TYPE (subtrahend)) { |
|
3254 return info->func (dest, minuend, subtrahend); |
|
3255 } |
|
3256 } |
|
3257 |
|
3258 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) { |
|
3259 gst_value_init_and_copy (dest, minuend); |
|
3260 return TRUE; |
|
3261 } |
|
3262 |
|
3263 return FALSE; |
|
3264 } |
|
3265 |
|
3266 #if 0 |
|
3267 gboolean |
|
3268 gst_value_subtract (GValue * dest, const GValue * minuend, |
|
3269 const GValue * subtrahend) |
|
3270 { |
|
3271 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend); |
|
3272 |
|
3273 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend), |
|
3274 gst_value_serialize (subtrahend), |
|
3275 ret ? gst_value_serialize (dest) : "---"); |
|
3276 return ret; |
|
3277 } |
|
3278 #endif |
|
3279 |
|
3280 /** |
|
3281 * gst_value_can_subtract: |
|
3282 * @minuend: the value to subtract from |
|
3283 * @subtrahend: the value to subtract |
|
3284 * |
|
3285 * Checks if it's possible to subtract @subtrahend from @minuend. |
|
3286 * |
|
3287 * Returns: TRUE if a subtraction is possible |
|
3288 */ |
|
3289 #ifdef __SYMBIAN32__ |
|
3290 EXPORT_C |
|
3291 #endif |
|
3292 |
|
3293 gboolean |
|
3294 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) |
|
3295 { |
|
3296 GstValueSubtractInfo *info; |
|
3297 guint i; |
|
3298 |
|
3299 /* special cases */ |
|
3300 if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend)) |
|
3301 return TRUE; |
|
3302 |
|
3303 for (i = 0; i < gst_value_subtract_funcs->len; i++) { |
|
3304 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
|
3305 if (info->minuend == G_VALUE_TYPE (minuend) && |
|
3306 info->subtrahend == G_VALUE_TYPE (subtrahend)) |
|
3307 return TRUE; |
|
3308 } |
|
3309 |
|
3310 return gst_value_can_compare (minuend, subtrahend); |
|
3311 } |
|
3312 |
|
3313 /** |
|
3314 * gst_value_register_subtract_func: |
|
3315 * @minuend_type: type of the minuend |
|
3316 * @subtrahend_type: type of the subtrahend |
|
3317 * @func: function to use |
|
3318 * |
|
3319 * Registers @func as a function capable of subtracting the values of |
|
3320 * @subtrahend_type from values of @minuend_type. |
|
3321 * |
|
3322 * Subtract functions should be registered at startup before any pipelines are |
|
3323 * started, as gst_value_register_subtract_func() is not thread-safe and |
|
3324 * cannot be used at the same time as gst_value_subtract(). |
|
3325 */ |
|
3326 #ifdef __SYMBIAN32__ |
|
3327 EXPORT_C |
|
3328 #endif |
|
3329 |
|
3330 void |
|
3331 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type, |
|
3332 GstValueSubtractFunc func) |
|
3333 { |
|
3334 GstValueSubtractInfo info; |
|
3335 |
|
3336 /* one type must be unfixed, other subtractions can be done as comparisons */ |
|
3337 g_return_if_fail (!gst_type_is_fixed (minuend_type) |
|
3338 || !gst_type_is_fixed (subtrahend_type)); |
|
3339 |
|
3340 info.minuend = minuend_type; |
|
3341 info.subtrahend = subtrahend_type; |
|
3342 info.func = func; |
|
3343 |
|
3344 g_array_append_val (gst_value_subtract_funcs, info); |
|
3345 } |
|
3346 |
|
3347 /** |
|
3348 * gst_value_register: |
|
3349 * @table: structure containing functions to register |
|
3350 * |
|
3351 * Registers functions to perform calculations on #GValues of a given |
|
3352 * type. |
|
3353 */ |
|
3354 #ifdef __SYMBIAN32__ |
|
3355 EXPORT_C |
|
3356 #endif |
|
3357 |
|
3358 void |
|
3359 gst_value_register (const GstValueTable * table) |
|
3360 { |
|
3361 g_array_append_val (gst_value_table, *table); |
|
3362 } |
|
3363 |
|
3364 /** |
|
3365 * gst_value_init_and_copy: |
|
3366 * @dest: the target value |
|
3367 * @src: the source value |
|
3368 * |
|
3369 * Initialises the target value to be of the same type as source and then copies |
|
3370 * the contents from source to target. |
|
3371 */ |
|
3372 #ifdef __SYMBIAN32__ |
|
3373 EXPORT_C |
|
3374 #endif |
|
3375 |
|
3376 void |
|
3377 gst_value_init_and_copy (GValue * dest, const GValue * src) |
|
3378 { |
|
3379 g_value_init (dest, G_VALUE_TYPE (src)); |
|
3380 g_value_copy (src, dest); |
|
3381 } |
|
3382 |
|
3383 /** |
|
3384 * gst_value_serialize: |
|
3385 * @value: a #GValue to serialize |
|
3386 * |
|
3387 * tries to transform the given @value into a string representation that allows |
|
3388 * getting back this string later on using gst_value_deserialize(). |
|
3389 * |
|
3390 * Returns: the serialization for @value or NULL if none exists |
|
3391 */ |
|
3392 #ifdef __SYMBIAN32__ |
|
3393 EXPORT_C |
|
3394 #endif |
|
3395 |
|
3396 gchar * |
|
3397 gst_value_serialize (const GValue * value) |
|
3398 { |
|
3399 guint i; |
|
3400 GValue s_val = { 0 }; |
|
3401 GstValueTable *table, *best = NULL; |
|
3402 char *s; |
|
3403 |
|
3404 g_return_val_if_fail (G_IS_VALUE (value), NULL); |
|
3405 |
|
3406 for (i = 0; i < gst_value_table->len; i++) { |
|
3407 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
3408 if (table->serialize == NULL) |
|
3409 continue; |
|
3410 if (table->type == G_VALUE_TYPE (value)) { |
|
3411 best = table; |
|
3412 break; |
|
3413 } |
|
3414 if (g_type_is_a (G_VALUE_TYPE (value), table->type)) { |
|
3415 if (!best || g_type_is_a (table->type, best->type)) |
|
3416 best = table; |
|
3417 } |
|
3418 } |
|
3419 if (best) |
|
3420 return best->serialize (value); |
|
3421 |
|
3422 g_value_init (&s_val, G_TYPE_STRING); |
|
3423 if (g_value_transform (value, &s_val)) { |
|
3424 s = gst_string_wrap (g_value_get_string (&s_val)); |
|
3425 } else { |
|
3426 s = NULL; |
|
3427 } |
|
3428 g_value_unset (&s_val); |
|
3429 |
|
3430 return s; |
|
3431 } |
|
3432 |
|
3433 /** |
|
3434 * gst_value_deserialize: |
|
3435 * @dest: #GValue to fill with contents of deserialization |
|
3436 * @src: string to deserialize |
|
3437 * |
|
3438 * Tries to deserialize a string into the type specified by the given GValue. |
|
3439 * If the operation succeeds, TRUE is returned, FALSE otherwise. |
|
3440 * |
|
3441 * Returns: TRUE on success |
|
3442 */ |
|
3443 #ifdef __SYMBIAN32__ |
|
3444 EXPORT_C |
|
3445 #endif |
|
3446 |
|
3447 gboolean |
|
3448 gst_value_deserialize (GValue * dest, const gchar * src) |
|
3449 { |
|
3450 GstValueTable *table, *best = NULL; |
|
3451 guint i; |
|
3452 |
|
3453 g_return_val_if_fail (src != NULL, FALSE); |
|
3454 g_return_val_if_fail (G_IS_VALUE (dest), FALSE); |
|
3455 |
|
3456 for (i = 0; i < gst_value_table->len; i++) { |
|
3457 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
3458 if (table->serialize == NULL) |
|
3459 continue; |
|
3460 |
|
3461 if (table->type == G_VALUE_TYPE (dest)) { |
|
3462 best = table; |
|
3463 break; |
|
3464 } |
|
3465 |
|
3466 if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) { |
|
3467 if (!best || g_type_is_a (table->type, best->type)) |
|
3468 best = table; |
|
3469 } |
|
3470 } |
|
3471 if (best) { |
|
3472 return best->deserialize (dest, src); |
|
3473 } |
|
3474 |
|
3475 return FALSE; |
|
3476 } |
|
3477 |
|
3478 /** |
|
3479 * gst_value_is_fixed: |
|
3480 * @value: the #GValue to check |
|
3481 * |
|
3482 * Tests if the given GValue, if available in a GstStructure (or any other |
|
3483 * container) contains a "fixed" (which means: one value) or an "unfixed" |
|
3484 * (which means: multiple possible values, such as data lists or data |
|
3485 * ranges) value. |
|
3486 * |
|
3487 * Returns: true if the value is "fixed". |
|
3488 */ |
|
3489 #ifdef __SYMBIAN32__ |
|
3490 EXPORT_C |
|
3491 #endif |
|
3492 |
|
3493 |
|
3494 gboolean |
|
3495 gst_value_is_fixed (const GValue * value) |
|
3496 { |
|
3497 GType type = G_VALUE_TYPE (value); |
|
3498 |
|
3499 if (type == GST_TYPE_ARRAY) { |
|
3500 gint size, n; |
|
3501 const GValue *kid; |
|
3502 |
|
3503 /* check recursively */ |
|
3504 size = gst_value_array_get_size (value); |
|
3505 for (n = 0; n < size; n++) { |
|
3506 kid = gst_value_array_get_value (value, n); |
|
3507 if (!gst_value_is_fixed (kid)) |
|
3508 return FALSE; |
|
3509 } |
|
3510 return TRUE; |
|
3511 } |
|
3512 |
|
3513 return gst_type_is_fixed (type); |
|
3514 } |
|
3515 |
|
3516 /************ |
|
3517 * fraction * |
|
3518 ************/ |
|
3519 |
|
3520 /* helper functions */ |
|
3521 |
|
3522 /* Finds the greatest common divisor. |
|
3523 * Returns 1 if none other found. |
|
3524 * This is Euclid's algorithm. */ |
|
3525 static gint |
|
3526 gst_greatest_common_divisor (gint a, gint b) |
|
3527 { |
|
3528 while (b != 0) { |
|
3529 int temp = a; |
|
3530 |
|
3531 a = b; |
|
3532 b = temp % b; |
|
3533 } |
|
3534 |
|
3535 return ABS (a); |
|
3536 } |
|
3537 |
|
3538 static void |
|
3539 gst_value_init_fraction (GValue * value) |
|
3540 { |
|
3541 value->data[0].v_int = 0; |
|
3542 value->data[1].v_int = 1; |
|
3543 } |
|
3544 |
|
3545 static void |
|
3546 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value) |
|
3547 { |
|
3548 dest_value->data[0].v_int = src_value->data[0].v_int; |
|
3549 dest_value->data[1].v_int = src_value->data[1].v_int; |
|
3550 } |
|
3551 |
|
3552 static gchar * |
|
3553 gst_value_collect_fraction (GValue * value, guint n_collect_values, |
|
3554 GTypeCValue * collect_values, guint collect_flags) |
|
3555 { |
|
3556 gst_value_set_fraction (value, |
|
3557 collect_values[0].v_int, collect_values[1].v_int); |
|
3558 |
|
3559 return NULL; |
|
3560 } |
|
3561 |
|
3562 static gchar * |
|
3563 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values, |
|
3564 GTypeCValue * collect_values, guint collect_flags) |
|
3565 { |
|
3566 gint *numerator = collect_values[0].v_pointer; |
|
3567 gint *denominator = collect_values[1].v_pointer; |
|
3568 |
|
3569 if (!numerator) |
|
3570 return g_strdup_printf ("numerator for `%s' passed as NULL", |
|
3571 G_VALUE_TYPE_NAME (value)); |
|
3572 if (!denominator) |
|
3573 return g_strdup_printf ("denominator for `%s' passed as NULL", |
|
3574 G_VALUE_TYPE_NAME (value)); |
|
3575 |
|
3576 *numerator = value->data[0].v_int; |
|
3577 *denominator = value->data[1].v_int; |
|
3578 |
|
3579 return NULL; |
|
3580 } |
|
3581 |
|
3582 /** |
|
3583 * gst_value_set_fraction: |
|
3584 * @value: a GValue initialized to #GST_TYPE_FRACTION |
|
3585 * @numerator: the numerator of the fraction |
|
3586 * @denominator: the denominator of the fraction |
|
3587 * |
|
3588 * Sets @value to the fraction specified by @numerator over @denominator. |
|
3589 * The fraction gets reduced to the smallest numerator and denominator, |
|
3590 * and if necessary the sign is moved to the numerator. |
|
3591 */ |
|
3592 #ifdef __SYMBIAN32__ |
|
3593 EXPORT_C |
|
3594 #endif |
|
3595 |
|
3596 void |
|
3597 gst_value_set_fraction (GValue * value, gint numerator, gint denominator) |
|
3598 { |
|
3599 gint gcd = 0; |
|
3600 |
|
3601 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value)); |
|
3602 g_return_if_fail (denominator != 0); |
|
3603 g_return_if_fail (denominator >= -G_MAXINT); |
|
3604 g_return_if_fail (numerator >= -G_MAXINT); |
|
3605 |
|
3606 /* normalize sign */ |
|
3607 if (denominator < 0) { |
|
3608 numerator = -numerator; |
|
3609 denominator = -denominator; |
|
3610 } |
|
3611 |
|
3612 /* check for reduction */ |
|
3613 gcd = gst_greatest_common_divisor (numerator, denominator); |
|
3614 if (gcd) { |
|
3615 numerator /= gcd; |
|
3616 denominator /= gcd; |
|
3617 } |
|
3618 |
|
3619 g_assert (denominator > 0); |
|
3620 |
|
3621 value->data[0].v_int = numerator; |
|
3622 value->data[1].v_int = denominator; |
|
3623 } |
|
3624 |
|
3625 /** |
|
3626 * gst_value_get_fraction_numerator: |
|
3627 * @value: a GValue initialized to #GST_TYPE_FRACTION |
|
3628 * |
|
3629 * Gets the numerator of the fraction specified by @value. |
|
3630 * |
|
3631 * Returns: the numerator of the fraction. |
|
3632 */ |
|
3633 #ifdef __SYMBIAN32__ |
|
3634 EXPORT_C |
|
3635 #endif |
|
3636 |
|
3637 gint |
|
3638 gst_value_get_fraction_numerator (const GValue * value) |
|
3639 { |
|
3640 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0); |
|
3641 |
|
3642 return value->data[0].v_int; |
|
3643 } |
|
3644 |
|
3645 /** |
|
3646 * gst_value_get_fraction_denominator: |
|
3647 * @value: a GValue initialized to #GST_TYPE_FRACTION |
|
3648 * |
|
3649 * Gets the denominator of the fraction specified by @value. |
|
3650 * |
|
3651 * Returns: the denominator of the fraction. |
|
3652 */ |
|
3653 #ifdef __SYMBIAN32__ |
|
3654 EXPORT_C |
|
3655 #endif |
|
3656 |
|
3657 gint |
|
3658 gst_value_get_fraction_denominator (const GValue * value) |
|
3659 { |
|
3660 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1); |
|
3661 |
|
3662 return value->data[1].v_int; |
|
3663 } |
|
3664 |
|
3665 /** |
|
3666 * gst_value_fraction_multiply: |
|
3667 * @product: a GValue initialized to #GST_TYPE_FRACTION |
|
3668 * @factor1: a GValue initialized to #GST_TYPE_FRACTION |
|
3669 * @factor2: a GValue initialized to #GST_TYPE_FRACTION |
|
3670 * |
|
3671 * Multiplies the two GValues containing a GstFraction and sets @product |
|
3672 * to the product of the two fractions. |
|
3673 * |
|
3674 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise. |
|
3675 */ |
|
3676 #ifdef __SYMBIAN32__ |
|
3677 EXPORT_C |
|
3678 #endif |
|
3679 |
|
3680 gboolean |
|
3681 gst_value_fraction_multiply (GValue * product, const GValue * factor1, |
|
3682 const GValue * factor2) |
|
3683 { |
|
3684 gint gcd, n1, n2, d1, d2; |
|
3685 |
|
3686 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE); |
|
3687 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE); |
|
3688 |
|
3689 n1 = factor1->data[0].v_int; |
|
3690 n2 = factor2->data[0].v_int; |
|
3691 d1 = factor1->data[1].v_int; |
|
3692 d2 = factor2->data[1].v_int; |
|
3693 |
|
3694 gcd = gst_greatest_common_divisor (n1, d2); |
|
3695 n1 /= gcd; |
|
3696 d2 /= gcd; |
|
3697 gcd = gst_greatest_common_divisor (n2, d1); |
|
3698 n2 /= gcd; |
|
3699 d1 /= gcd; |
|
3700 |
|
3701 g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (n2), FALSE); |
|
3702 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); |
|
3703 |
|
3704 gst_value_set_fraction (product, n1 * n2, d1 * d2); |
|
3705 |
|
3706 return TRUE; |
|
3707 } |
|
3708 |
|
3709 /** |
|
3710 * gst_value_fraction_subtract: |
|
3711 * @dest: a GValue initialized to #GST_TYPE_FRACTION |
|
3712 * @minuend: a GValue initialized to #GST_TYPE_FRACTION |
|
3713 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION |
|
3714 * |
|
3715 * Subtracts the @subtrahend from the @minuend and sets @dest to the result. |
|
3716 * |
|
3717 * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise. |
|
3718 */ |
|
3719 #ifdef __SYMBIAN32__ |
|
3720 EXPORT_C |
|
3721 #endif |
|
3722 |
|
3723 gboolean |
|
3724 gst_value_fraction_subtract (GValue * dest, |
|
3725 const GValue * minuend, const GValue * subtrahend) |
|
3726 { |
|
3727 gint n1, n2, d1, d2; |
|
3728 |
|
3729 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE); |
|
3730 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE); |
|
3731 |
|
3732 n1 = minuend->data[0].v_int; |
|
3733 n2 = subtrahend->data[0].v_int; |
|
3734 d1 = minuend->data[1].v_int; |
|
3735 d2 = subtrahend->data[1].v_int; |
|
3736 |
|
3737 if (n1 == 0) { |
|
3738 gst_value_set_fraction (dest, -n2, d2); |
|
3739 return TRUE; |
|
3740 } |
|
3741 if (n2 == 0) { |
|
3742 gst_value_set_fraction (dest, n1, d1); |
|
3743 return TRUE; |
|
3744 } |
|
3745 |
|
3746 g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (d2), FALSE); |
|
3747 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (n2), FALSE); |
|
3748 g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); |
|
3749 |
|
3750 gst_value_set_fraction (dest, (n1 * d2) - (n2 * d1), d1 * d2); |
|
3751 |
|
3752 return TRUE; |
|
3753 } |
|
3754 |
|
3755 static gchar * |
|
3756 gst_value_serialize_fraction (const GValue * value) |
|
3757 { |
|
3758 gint32 numerator = value->data[0].v_int; |
|
3759 gint32 denominator = value->data[1].v_int; |
|
3760 gboolean positive = TRUE; |
|
3761 |
|
3762 /* get the sign and make components absolute */ |
|
3763 if (numerator < 0) { |
|
3764 numerator = -numerator; |
|
3765 positive = !positive; |
|
3766 } |
|
3767 if (denominator < 0) { |
|
3768 denominator = -denominator; |
|
3769 positive = !positive; |
|
3770 } |
|
3771 |
|
3772 return g_strdup_printf ("%s%d/%d", |
|
3773 positive ? "" : "-", numerator, denominator); |
|
3774 } |
|
3775 |
|
3776 static gboolean |
|
3777 gst_value_deserialize_fraction (GValue * dest, const gchar * s) |
|
3778 { |
|
3779 gint num, den; |
|
3780 |
|
3781 if (G_UNLIKELY (s == NULL)) |
|
3782 return FALSE; |
|
3783 |
|
3784 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest))) |
|
3785 return FALSE; |
|
3786 |
|
3787 if (sscanf (s, "%d/%d", &num, &den) == 2) { |
|
3788 gst_value_set_fraction (dest, num, den); |
|
3789 return TRUE; |
|
3790 } |
|
3791 if (sscanf (s, "%d", &num) == 1) { |
|
3792 gst_value_set_fraction (dest, num, 1); |
|
3793 return TRUE; |
|
3794 } |
|
3795 if (g_ascii_strcasecmp (s, "min") == 0) { |
|
3796 gst_value_set_fraction (dest, -G_MAXINT, 1); |
|
3797 return TRUE; |
|
3798 } else if (g_ascii_strcasecmp (s, "max") == 0) { |
|
3799 gst_value_set_fraction (dest, G_MAXINT, 1); |
|
3800 return TRUE; |
|
3801 } |
|
3802 |
|
3803 return FALSE; |
|
3804 } |
|
3805 |
|
3806 static void |
|
3807 gst_value_transform_fraction_string (const GValue * src_value, |
|
3808 GValue * dest_value) |
|
3809 { |
|
3810 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value); |
|
3811 } |
|
3812 |
|
3813 static void |
|
3814 gst_value_transform_string_fraction (const GValue * src_value, |
|
3815 GValue * dest_value) |
|
3816 { |
|
3817 if (!gst_value_deserialize_fraction (dest_value, |
|
3818 src_value->data[0].v_pointer)) |
|
3819 /* If the deserialize fails, ensure we leave the fraction in a |
|
3820 * valid, if incorrect, state */ |
|
3821 gst_value_set_fraction (dest_value, 0, 1); |
|
3822 } |
|
3823 |
|
3824 #define MAX_TERMS 30 |
|
3825 #define MIN_DIVISOR 1.0e-10 |
|
3826 #define MAX_ERROR 1.0e-20 |
|
3827 |
|
3828 /* use continued fractions to transform a double into a fraction, |
|
3829 * see http://mathforum.org/dr.math/faq/faq.fractions.html#decfrac. |
|
3830 * This algorithm takes care of overflows. |
|
3831 */ |
|
3832 static void |
|
3833 gst_value_transform_double_fraction (const GValue * src_value, |
|
3834 GValue * dest_value) |
|
3835 { |
|
3836 gdouble V, F; /* double being converted */ |
|
3837 gint N, D; /* will contain the result */ |
|
3838 gint A; /* current term in continued fraction */ |
|
3839 gint64 N1, D1; /* numerator, denominator of last approx */ |
|
3840 gint64 N2, D2; /* numerator, denominator of previous approx */ |
|
3841 gint i; |
|
3842 gboolean negative = FALSE; |
|
3843 |
|
3844 /* initialize fraction being converted */ |
|
3845 F = src_value->data[0].v_double; |
|
3846 if (F < 0.0) { |
|
3847 F = -F; |
|
3848 negative = TRUE; |
|
3849 } |
|
3850 |
|
3851 V = F; |
|
3852 /* initialize fractions with 1/0, 0/1 */ |
|
3853 N1 = 1; |
|
3854 D1 = 0; |
|
3855 N2 = 0; |
|
3856 D2 = 1; |
|
3857 N = 1; |
|
3858 D = 1; |
|
3859 |
|
3860 for (i = 0; i < MAX_TERMS; i++) { |
|
3861 /* get next term */ |
|
3862 A = (gint) F; /* no floor() needed, F is always >= 0 */ |
|
3863 /* get new divisor */ |
|
3864 F = F - A; |
|
3865 |
|
3866 /* calculate new fraction in temp */ |
|
3867 N2 = N1 * A + N2; |
|
3868 D2 = D1 * A + D2; |
|
3869 |
|
3870 /* guard against overflow */ |
|
3871 if (N2 > G_MAXINT || D2 > G_MAXINT) { |
|
3872 break; |
|
3873 } |
|
3874 |
|
3875 N = N2; |
|
3876 D = D2; |
|
3877 |
|
3878 /* save last two fractions */ |
|
3879 N2 = N1; |
|
3880 D2 = D1; |
|
3881 N1 = N; |
|
3882 D1 = D; |
|
3883 |
|
3884 /* quit if dividing by zero or close enough to target */ |
|
3885 if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) { |
|
3886 break; |
|
3887 } |
|
3888 |
|
3889 /* Take reciprocal */ |
|
3890 F = 1 / F; |
|
3891 } |
|
3892 /* fix for overflow */ |
|
3893 if (D == 0) { |
|
3894 N = G_MAXINT; |
|
3895 D = 1; |
|
3896 } |
|
3897 /* fix for negative */ |
|
3898 if (negative) |
|
3899 N = -N; |
|
3900 |
|
3901 /* will also simplify */ |
|
3902 gst_value_set_fraction (dest_value, N, D); |
|
3903 } |
|
3904 |
|
3905 static void |
|
3906 gst_value_transform_fraction_double (const GValue * src_value, |
|
3907 GValue * dest_value) |
|
3908 { |
|
3909 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) / |
|
3910 ((double) src_value->data[1].v_int); |
|
3911 } |
|
3912 |
|
3913 static gint |
|
3914 gst_value_compare_fraction (const GValue * value1, const GValue * value2) |
|
3915 { |
|
3916 gint n1, n2; |
|
3917 gint d1, d2; |
|
3918 |
|
3919 gint64 new_num_1; |
|
3920 gint64 new_num_2; |
|
3921 |
|
3922 n1 = value1->data[0].v_int; |
|
3923 n2 = value2->data[0].v_int; |
|
3924 d1 = value1->data[1].v_int; |
|
3925 d2 = value2->data[1].v_int; |
|
3926 |
|
3927 /* fractions are reduced when set, so we can quickly see if they're equal */ |
|
3928 if (n1 == n2 && d1 == d2) |
|
3929 return GST_VALUE_EQUAL; |
|
3930 |
|
3931 /* extend to 64 bits */ |
|
3932 new_num_1 = ((gint64) n1) * d2; |
|
3933 new_num_2 = ((gint64) n2) * d1; |
|
3934 if (new_num_1 < new_num_2) |
|
3935 return GST_VALUE_LESS_THAN; |
|
3936 if (new_num_1 > new_num_2) |
|
3937 return GST_VALUE_GREATER_THAN; |
|
3938 |
|
3939 /* new_num_1 == new_num_2 implies that both denominators must have |
|
3940 * been 0, beause otherwise simplification would have caught the |
|
3941 * equivalence */ |
|
3942 return GST_VALUE_UNORDERED; |
|
3943 } |
|
3944 |
|
3945 /********* |
|
3946 * GDate * |
|
3947 *********/ |
|
3948 |
|
3949 /** |
|
3950 * gst_value_set_date: |
|
3951 * @value: a GValue initialized to GST_TYPE_DATE |
|
3952 * @date: the date to set the value to |
|
3953 * |
|
3954 * Sets the contents of @value to coorespond to @date. The actual |
|
3955 * #GDate structure is copied before it is used. |
|
3956 */ |
|
3957 #ifdef __SYMBIAN32__ |
|
3958 EXPORT_C |
|
3959 #endif |
|
3960 |
|
3961 void |
|
3962 gst_value_set_date (GValue * value, const GDate * date) |
|
3963 { |
|
3964 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE); |
|
3965 g_return_if_fail (g_date_valid (date)); |
|
3966 |
|
3967 g_value_set_boxed (value, date); |
|
3968 } |
|
3969 |
|
3970 /** |
|
3971 * gst_value_get_date: |
|
3972 * @value: a GValue initialized to GST_TYPE_DATE |
|
3973 * |
|
3974 * Gets the contents of @value. |
|
3975 * |
|
3976 * Returns: the contents of @value |
|
3977 */ |
|
3978 #ifdef __SYMBIAN32__ |
|
3979 EXPORT_C |
|
3980 #endif |
|
3981 |
|
3982 const GDate * |
|
3983 gst_value_get_date (const GValue * value) |
|
3984 { |
|
3985 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_DATE, NULL); |
|
3986 |
|
3987 return (const GDate *) g_value_get_boxed (value); |
|
3988 } |
|
3989 |
|
3990 static gpointer |
|
3991 gst_date_copy (gpointer boxed) |
|
3992 { |
|
3993 const GDate *date = (const GDate *) boxed; |
|
3994 |
|
3995 if (!g_date_valid (date)) { |
|
3996 GST_WARNING ("invalid GDate"); |
|
3997 return NULL; |
|
3998 } |
|
3999 |
|
4000 return g_date_new_julian (g_date_get_julian (date)); |
|
4001 } |
|
4002 |
|
4003 static gint |
|
4004 gst_value_compare_date (const GValue * value1, const GValue * value2) |
|
4005 { |
|
4006 const GDate *date1 = (const GDate *) g_value_get_boxed (value1); |
|
4007 const GDate *date2 = (const GDate *) g_value_get_boxed (value2); |
|
4008 guint32 j1, j2; |
|
4009 |
|
4010 if (date1 == date2) |
|
4011 return GST_VALUE_EQUAL; |
|
4012 |
|
4013 if ((date1 == NULL || !g_date_valid (date1)) |
|
4014 && (date2 != NULL && g_date_valid (date2))) { |
|
4015 return GST_VALUE_LESS_THAN; |
|
4016 } |
|
4017 |
|
4018 if ((date2 == NULL || !g_date_valid (date2)) |
|
4019 && (date1 != NULL && g_date_valid (date1))) { |
|
4020 return GST_VALUE_GREATER_THAN; |
|
4021 } |
|
4022 |
|
4023 if (date1 == NULL || date2 == NULL || !g_date_valid (date1) |
|
4024 || !g_date_valid (date2)) { |
|
4025 return GST_VALUE_UNORDERED; |
|
4026 } |
|
4027 |
|
4028 j1 = g_date_get_julian (date1); |
|
4029 j2 = g_date_get_julian (date2); |
|
4030 |
|
4031 if (j1 == j2) |
|
4032 return GST_VALUE_EQUAL; |
|
4033 else if (j1 < j2) |
|
4034 return GST_VALUE_LESS_THAN; |
|
4035 else |
|
4036 return GST_VALUE_GREATER_THAN; |
|
4037 } |
|
4038 |
|
4039 static gchar * |
|
4040 gst_value_serialize_date (const GValue * val) |
|
4041 { |
|
4042 const GDate *date = (const GDate *) g_value_get_boxed (val); |
|
4043 |
|
4044 if (date == NULL || !g_date_valid (date)) |
|
4045 return g_strdup ("9999-99-99"); |
|
4046 |
|
4047 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date), |
|
4048 g_date_get_month (date), g_date_get_day (date)); |
|
4049 } |
|
4050 |
|
4051 static gboolean |
|
4052 gst_value_deserialize_date (GValue * dest, const char *s) |
|
4053 { |
|
4054 guint year, month, day; |
|
4055 |
|
4056 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3) |
|
4057 return FALSE; |
|
4058 |
|
4059 if (!g_date_valid_dmy (day, month, year)) |
|
4060 return FALSE; |
|
4061 |
|
4062 g_value_take_boxed (dest, g_date_new_dmy (day, month, year)); |
|
4063 return TRUE; |
|
4064 } |
|
4065 |
|
4066 static void |
|
4067 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value) |
|
4068 { |
|
4069 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value); |
|
4070 } |
|
4071 |
|
4072 static void |
|
4073 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value) |
|
4074 { |
|
4075 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer); |
|
4076 } |
|
4077 |
|
4078 static void |
|
4079 gst_value_transform_object_string (const GValue * src_value, |
|
4080 GValue * dest_value) |
|
4081 { |
|
4082 GstObject *obj; |
|
4083 gchar *str; |
|
4084 |
|
4085 obj = g_value_get_object (src_value); |
|
4086 str = obj ? GST_OBJECT_NAME (obj) : "NULL"; |
|
4087 |
|
4088 dest_value->data[0].v_pointer = g_strdup (str); |
|
4089 } |
|
4090 |
|
4091 static GTypeInfo _info = { |
|
4092 0, |
|
4093 NULL, |
|
4094 NULL, |
|
4095 NULL, |
|
4096 NULL, |
|
4097 NULL, |
|
4098 0, |
|
4099 0, |
|
4100 NULL, |
|
4101 NULL, |
|
4102 }; |
|
4103 |
|
4104 static GTypeFundamentalInfo _finfo = { |
|
4105 0 |
|
4106 }; |
|
4107 |
|
4108 #define FUNC_VALUE_GET_TYPE(type, name) \ |
|
4109 __declspec(dllexport) GType gst_ ## type ## _get_type (void) \ |
|
4110 { \ |
|
4111 static GType gst_ ## type ## _type = 0; \ |
|
4112 \ |
|
4113 if (G_UNLIKELY (gst_ ## type ## _type == 0)) { \ |
|
4114 _info.value_table = & _gst_ ## type ## _value_table; \ |
|
4115 gst_ ## type ## _type = g_type_register_fundamental ( \ |
|
4116 g_type_fundamental_next (), \ |
|
4117 name, &_info, &_finfo, 0); \ |
|
4118 } \ |
|
4119 \ |
|
4120 return gst_ ## type ## _type; \ |
|
4121 } |
|
4122 |
|
4123 static const GTypeValueTable _gst_fourcc_value_table = { |
|
4124 gst_value_init_fourcc, |
|
4125 NULL, |
|
4126 gst_value_copy_fourcc, |
|
4127 NULL, |
|
4128 "i", |
|
4129 gst_value_collect_fourcc, |
|
4130 "p", |
|
4131 gst_value_lcopy_fourcc |
|
4132 }; |
|
4133 |
|
4134 FUNC_VALUE_GET_TYPE (fourcc, "GstFourcc"); |
|
4135 |
|
4136 static const GTypeValueTable _gst_int_range_value_table = { |
|
4137 gst_value_init_int_range, |
|
4138 NULL, |
|
4139 gst_value_copy_int_range, |
|
4140 NULL, |
|
4141 "ii", |
|
4142 gst_value_collect_int_range, |
|
4143 "pp", |
|
4144 gst_value_lcopy_int_range |
|
4145 }; |
|
4146 |
|
4147 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange"); |
|
4148 |
|
4149 static const GTypeValueTable _gst_double_range_value_table = { |
|
4150 gst_value_init_double_range, |
|
4151 NULL, |
|
4152 gst_value_copy_double_range, |
|
4153 NULL, |
|
4154 "dd", |
|
4155 gst_value_collect_double_range, |
|
4156 "pp", |
|
4157 gst_value_lcopy_double_range |
|
4158 }; |
|
4159 |
|
4160 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange"); |
|
4161 |
|
4162 static const GTypeValueTable _gst_fraction_range_value_table = { |
|
4163 gst_value_init_fraction_range, |
|
4164 gst_value_free_fraction_range, |
|
4165 gst_value_copy_fraction_range, |
|
4166 NULL, |
|
4167 "iiii", |
|
4168 gst_value_collect_fraction_range, |
|
4169 "pppp", |
|
4170 gst_value_lcopy_fraction_range |
|
4171 }; |
|
4172 |
|
4173 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange"); |
|
4174 |
|
4175 static const GTypeValueTable _gst_value_list_value_table = { |
|
4176 gst_value_init_list_or_array, |
|
4177 gst_value_free_list_or_array, |
|
4178 gst_value_copy_list_or_array, |
|
4179 gst_value_list_or_array_peek_pointer, |
|
4180 "p", |
|
4181 gst_value_collect_list_or_array, |
|
4182 "p", |
|
4183 gst_value_lcopy_list_or_array |
|
4184 }; |
|
4185 |
|
4186 FUNC_VALUE_GET_TYPE (value_list, "GstValueList"); |
|
4187 |
|
4188 static const GTypeValueTable _gst_value_array_value_table = { |
|
4189 gst_value_init_list_or_array, |
|
4190 gst_value_free_list_or_array, |
|
4191 gst_value_copy_list_or_array, |
|
4192 gst_value_list_or_array_peek_pointer, |
|
4193 "p", |
|
4194 gst_value_collect_list_or_array, |
|
4195 "p", |
|
4196 gst_value_lcopy_list_or_array |
|
4197 }; |
|
4198 |
|
4199 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray"); |
|
4200 |
|
4201 static const GTypeValueTable _gst_fraction_value_table = { |
|
4202 gst_value_init_fraction, |
|
4203 NULL, |
|
4204 gst_value_copy_fraction, |
|
4205 NULL, |
|
4206 "ii", |
|
4207 gst_value_collect_fraction, |
|
4208 "pp", |
|
4209 gst_value_lcopy_fraction |
|
4210 }; |
|
4211 |
|
4212 FUNC_VALUE_GET_TYPE (fraction, "GstFraction"); |
|
4213 #ifdef __SYMBIAN32__ |
|
4214 EXPORT_C |
|
4215 #endif |
|
4216 |
|
4217 |
|
4218 |
|
4219 GType |
|
4220 gst_date_get_type (void) |
|
4221 { |
|
4222 static GType gst_date_type = 0; |
|
4223 |
|
4224 if (G_UNLIKELY (gst_date_type == 0)) { |
|
4225 /* FIXME 0.11: we require GLib 2.8 already |
|
4226 * Not using G_TYPE_DATE here on purpose, even if we could |
|
4227 * if GLIB_CHECK_VERSION(2,8,0) was true: we don't want the |
|
4228 * serialised strings to have different type strings depending |
|
4229 * on what version is used, so FIXME when we require GLib-2.8 */ |
|
4230 gst_date_type = g_boxed_type_register_static ("GstDate", |
|
4231 (GBoxedCopyFunc) gst_date_copy, (GBoxedFreeFunc) g_date_free); |
|
4232 } |
|
4233 |
|
4234 return gst_date_type; |
|
4235 } |
|
4236 #ifdef __SYMBIAN32__ |
|
4237 EXPORT_C |
|
4238 #endif |
|
4239 |
|
4240 |
|
4241 void |
|
4242 _gst_value_initialize (void) |
|
4243 { |
|
4244 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable)); |
|
4245 gst_value_union_funcs = g_array_new (FALSE, FALSE, |
|
4246 sizeof (GstValueUnionInfo)); |
|
4247 gst_value_intersect_funcs = g_array_new (FALSE, FALSE, |
|
4248 sizeof (GstValueIntersectInfo)); |
|
4249 gst_value_subtract_funcs = g_array_new (FALSE, FALSE, |
|
4250 sizeof (GstValueSubtractInfo)); |
|
4251 |
|
4252 { |
|
4253 static GstValueTable gst_value = { |
|
4254 0, |
|
4255 gst_value_compare_fourcc, |
|
4256 gst_value_serialize_fourcc, |
|
4257 gst_value_deserialize_fourcc, |
|
4258 }; |
|
4259 |
|
4260 gst_value.type = gst_fourcc_get_type (); |
|
4261 gst_value_register (&gst_value); |
|
4262 } |
|
4263 |
|
4264 { |
|
4265 static GstValueTable gst_value = { |
|
4266 0, |
|
4267 gst_value_compare_int_range, |
|
4268 gst_value_serialize_int_range, |
|
4269 gst_value_deserialize_int_range, |
|
4270 }; |
|
4271 |
|
4272 gst_value.type = gst_int_range_get_type (); |
|
4273 gst_value_register (&gst_value); |
|
4274 } |
|
4275 |
|
4276 { |
|
4277 static GstValueTable gst_value = { |
|
4278 0, |
|
4279 gst_value_compare_double_range, |
|
4280 gst_value_serialize_double_range, |
|
4281 gst_value_deserialize_double_range, |
|
4282 }; |
|
4283 |
|
4284 gst_value.type = gst_double_range_get_type (); |
|
4285 gst_value_register (&gst_value); |
|
4286 } |
|
4287 |
|
4288 { |
|
4289 static GstValueTable gst_value = { |
|
4290 0, |
|
4291 gst_value_compare_fraction_range, |
|
4292 gst_value_serialize_fraction_range, |
|
4293 gst_value_deserialize_fraction_range, |
|
4294 }; |
|
4295 |
|
4296 gst_value.type = gst_fraction_range_get_type (); |
|
4297 gst_value_register (&gst_value); |
|
4298 } |
|
4299 |
|
4300 { |
|
4301 static GstValueTable gst_value = { |
|
4302 0, |
|
4303 gst_value_compare_list, |
|
4304 gst_value_serialize_list, |
|
4305 gst_value_deserialize_list, |
|
4306 }; |
|
4307 |
|
4308 gst_value.type = gst_value_list_get_type (); |
|
4309 gst_value_register (&gst_value); |
|
4310 } |
|
4311 |
|
4312 { |
|
4313 static GstValueTable gst_value = { |
|
4314 0, |
|
4315 gst_value_compare_array, |
|
4316 gst_value_serialize_array, |
|
4317 gst_value_deserialize_array, |
|
4318 }; |
|
4319 |
|
4320 gst_value.type = gst_value_array_get_type ();; |
|
4321 gst_value_register (&gst_value); |
|
4322 } |
|
4323 |
|
4324 { |
|
4325 #if 0 |
|
4326 static const GTypeValueTable value_table = { |
|
4327 gst_value_init_buffer, |
|
4328 NULL, |
|
4329 gst_value_copy_buffer, |
|
4330 NULL, |
|
4331 "i", |
|
4332 NULL, /*gst_value_collect_buffer, */ |
|
4333 "p", |
|
4334 NULL /*gst_value_lcopy_buffer */ |
|
4335 }; |
|
4336 #endif |
|
4337 static GstValueTable gst_value = { |
|
4338 0, |
|
4339 gst_value_compare_buffer, |
|
4340 gst_value_serialize_buffer, |
|
4341 gst_value_deserialize_buffer, |
|
4342 }; |
|
4343 |
|
4344 gst_value.type = GST_TYPE_BUFFER; |
|
4345 gst_value_register (&gst_value); |
|
4346 } |
|
4347 { |
|
4348 static GstValueTable gst_value = { |
|
4349 0, |
|
4350 gst_value_compare_fraction, |
|
4351 gst_value_serialize_fraction, |
|
4352 gst_value_deserialize_fraction, |
|
4353 }; |
|
4354 |
|
4355 gst_value.type = gst_fraction_get_type (); |
|
4356 gst_value_register (&gst_value); |
|
4357 } |
|
4358 { |
|
4359 static GstValueTable gst_value = { |
|
4360 0, |
|
4361 NULL, |
|
4362 gst_value_serialize_caps, |
|
4363 gst_value_deserialize_caps, |
|
4364 }; |
|
4365 |
|
4366 gst_value.type = GST_TYPE_CAPS; |
|
4367 gst_value_register (&gst_value); |
|
4368 } |
|
4369 { |
|
4370 static GstValueTable gst_value = { |
|
4371 0, |
|
4372 NULL, |
|
4373 gst_value_serialize_structure, |
|
4374 gst_value_deserialize_structure, |
|
4375 }; |
|
4376 |
|
4377 gst_value.type = GST_TYPE_STRUCTURE; |
|
4378 gst_value_register (&gst_value); |
|
4379 } |
|
4380 { |
|
4381 static GstValueTable gst_value = { |
|
4382 0, |
|
4383 gst_value_compare_date, |
|
4384 gst_value_serialize_date, |
|
4385 gst_value_deserialize_date, |
|
4386 }; |
|
4387 |
|
4388 gst_value.type = gst_date_get_type (); |
|
4389 gst_value_register (&gst_value); |
|
4390 } |
|
4391 |
|
4392 REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double); |
|
4393 REGISTER_SERIALIZATION (G_TYPE_FLOAT, float); |
|
4394 |
|
4395 REGISTER_SERIALIZATION (G_TYPE_STRING, string); |
|
4396 REGISTER_SERIALIZATION (G_TYPE_BOOLEAN, boolean); |
|
4397 REGISTER_SERIALIZATION (G_TYPE_ENUM, enum); |
|
4398 |
|
4399 REGISTER_SERIALIZATION (G_TYPE_FLAGS, flags); |
|
4400 |
|
4401 REGISTER_SERIALIZATION (G_TYPE_INT, int); |
|
4402 |
|
4403 REGISTER_SERIALIZATION (G_TYPE_INT64, int64); |
|
4404 REGISTER_SERIALIZATION (G_TYPE_LONG, long); |
|
4405 |
|
4406 REGISTER_SERIALIZATION (G_TYPE_UINT, uint); |
|
4407 REGISTER_SERIALIZATION (G_TYPE_UINT64, uint64); |
|
4408 REGISTER_SERIALIZATION (G_TYPE_ULONG, ulong); |
|
4409 |
|
4410 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING, |
|
4411 gst_value_transform_fourcc_string); |
|
4412 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING, |
|
4413 gst_value_transform_int_range_string); |
|
4414 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING, |
|
4415 gst_value_transform_double_range_string); |
|
4416 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING, |
|
4417 gst_value_transform_fraction_range_string); |
|
4418 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING, |
|
4419 gst_value_transform_list_string); |
|
4420 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING, |
|
4421 gst_value_transform_array_string); |
|
4422 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING, |
|
4423 gst_value_transform_fraction_string); |
|
4424 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION, |
|
4425 gst_value_transform_string_fraction); |
|
4426 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE, |
|
4427 gst_value_transform_fraction_double); |
|
4428 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION, |
|
4429 gst_value_transform_double_fraction); |
|
4430 g_value_register_transform_func (GST_TYPE_DATE, G_TYPE_STRING, |
|
4431 gst_value_transform_date_string); |
|
4432 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_DATE, |
|
4433 gst_value_transform_string_date); |
|
4434 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING, |
|
4435 gst_value_transform_object_string); |
|
4436 |
|
4437 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE, |
|
4438 gst_value_intersect_int_int_range); |
|
4439 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, |
|
4440 gst_value_intersect_int_range_int_range); |
|
4441 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, |
|
4442 gst_value_intersect_double_double_range); |
|
4443 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE, |
|
4444 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range); |
|
4445 gst_value_register_intersect_func (GST_TYPE_ARRAY, |
|
4446 GST_TYPE_ARRAY, gst_value_intersect_array); |
|
4447 gst_value_register_intersect_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, |
|
4448 gst_value_intersect_fraction_fraction_range); |
|
4449 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE, |
|
4450 GST_TYPE_FRACTION_RANGE, |
|
4451 gst_value_intersect_fraction_range_fraction_range); |
|
4452 |
|
4453 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE, |
|
4454 gst_value_subtract_int_int_range); |
|
4455 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT, |
|
4456 gst_value_subtract_int_range_int); |
|
4457 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, |
|
4458 gst_value_subtract_int_range_int_range); |
|
4459 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, |
|
4460 gst_value_subtract_double_double_range); |
|
4461 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE, |
|
4462 gst_value_subtract_double_range_double); |
|
4463 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, |
|
4464 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range); |
|
4465 |
|
4466 gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, |
|
4467 gst_value_subtract_fraction_fraction_range); |
|
4468 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION, |
|
4469 gst_value_subtract_fraction_range_fraction); |
|
4470 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, |
|
4471 GST_TYPE_FRACTION_RANGE, |
|
4472 gst_value_subtract_fraction_range_fraction_range); |
|
4473 |
|
4474 /* see bug #317246, #64994, #65041 */ |
|
4475 { |
|
4476 volatile GType date_type = G_TYPE_DATE; |
|
4477 |
|
4478 g_type_name (date_type); |
|
4479 } |
|
4480 |
|
4481 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE, |
|
4482 gst_value_union_int_int_range); |
|
4483 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, |
|
4484 gst_value_union_int_range_int_range); |
|
4485 |
|
4486 #if 0 |
|
4487 /* Implement these if needed */ |
|
4488 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, |
|
4489 gst_value_union_fraction_fraction_range); |
|
4490 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE, |
|
4491 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range); |
|
4492 #endif |
|
4493 } |