gstreamer_core/gst/gstvalue.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    17  * Boston, MA 02111-1307, USA.
    17  * Boston, MA 02111-1307, USA.
    18  */
    18  */
    19 
    19 
    20 /**
    20 /**
    21  * SECTION:gstvalue
    21  * SECTION:gstvalue
    22  * @short_description: GValue implementations specific
    22  * @short_description: GValue and GParamSpec implementations specific
    23  * to GStreamer
    23  * to GStreamer
    24  *
    24  *
    25  * GValue implementations specific to GStreamer.
    25  * GValue and GParamSpec implementations specific to GStreamer.
    26  *
    26  *
    27  * Note that operations on the same GstValue (or GValue) from multiple
    27  * Note that operations on the same GstValue (or GValue) from multiple
    28  * threads may lead to undefined behaviour. 
    28  * threads may lead to undefined behaviour. 
    29  *
    29  *
    30  * Last reviewed on 2008-03-11 (0.10.18)
    30  * Last reviewed on 2006-03-07 (0.10.4)
    31  */
    31  */
    32 
    32 
    33 #ifdef HAVE_CONFIG_H
    33 #ifdef HAVE_CONFIG_H
    34 #include "config.h"
    34 #include "config.h"
    35 #endif
    35 #endif
    69   GType minuend;
    69   GType minuend;
    70   GType subtrahend;
    70   GType subtrahend;
    71   GstValueSubtractFunc func;
    71   GstValueSubtractFunc func;
    72 };
    72 };
    73 
    73 
    74 #define FUNDAMENTAL_TYPE_ID_MAX \
       
    75     (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
       
    76 #define FUNDAMENTAL_TYPE_ID(type) \
       
    77     ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
       
    78 
       
    79 static GArray *gst_value_table;
    74 static GArray *gst_value_table;
    80 static GHashTable *gst_value_hash;
       
    81 static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1];
       
    82 static GArray *gst_value_union_funcs;
    75 static GArray *gst_value_union_funcs;
    83 static GArray *gst_value_intersect_funcs;
    76 static GArray *gst_value_intersect_funcs;
    84 static GArray *gst_value_subtract_funcs;
    77 static GArray *gst_value_subtract_funcs;
    85 
    78 
    86 /* Forward declarations */
    79 /* Forward declarations */
    88 static gchar *gst_value_serialize_fraction (const GValue * value);
    81 static gchar *gst_value_serialize_fraction (const GValue * value);
    89 
    82 
    90 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
    83 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
    91 static gint gst_value_compare_with_func (const GValue * value1,
    84 static gint gst_value_compare_with_func (const GValue * value1,
    92     const GValue * value2, GstValueCompareFunc compare);
    85     const GValue * value2, GstValueCompareFunc compare);
    93 
       
    94 static gchar *gst_string_wrap (const gchar * s);
       
    95 static gchar *gst_string_take_and_wrap (gchar * s);
       
    96 static gchar *gst_string_unwrap (const gchar * s);
       
    97 
       
    98 static inline GstValueTable *
       
    99 gst_value_hash_lookup_type (GType type)
       
   100 {
       
   101   if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type)))
       
   102     return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)];
       
   103   else
       
   104     return g_hash_table_lookup (gst_value_hash, (gpointer) type);
       
   105 }
       
   106 
       
   107 static void
       
   108 gst_value_hash_add_type (GType type, const GstValueTable * table)
       
   109 {
       
   110   if (G_TYPE_IS_FUNDAMENTAL (type))
       
   111     gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table;
       
   112 
       
   113   g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table);
       
   114 }
       
   115 
    86 
   116 /********
    87 /********
   117  * list *
    88  * list *
   118  ********/
    89  ********/
   119 
    90 
   127   guint i;
    98   guint i;
   128   GArray *array = value->data[0].v_pointer;
    99   GArray *array = value->data[0].v_pointer;
   129   GString *s;
   100   GString *s;
   130   GValue *v;
   101   GValue *v;
   131   gchar *s_val;
   102   gchar *s_val;
   132   guint alen = array->len;
       
   133 
   103 
   134   /* estimate minimum string length to minimise re-allocs in GString */
   104   /* estimate minimum string length to minimise re-allocs in GString */
   135   s = g_string_sized_new (2 + (6 * alen) + 2);
   105   s = g_string_sized_new (2 + (6 * array->len) + 2);
   136   g_string_append (s, begin);
   106   g_string_append (s, begin);
   137   for (i = 0; i < alen; i++) {
   107   for (i = 0; i < array->len; i++) {
   138     v = &g_array_index (array, GValue, i);
   108     v = &g_array_index (array, GValue, i);
   139     s_val = gst_value_serialize (v);
   109     s_val = gst_value_serialize (v);
   140     g_string_append (s, s_val);
   110     g_string_append (s, s_val);
   141     g_free (s_val);
   111     g_free (s_val);
   142     if (i < alen - 1) {
   112     if (i < array->len - 1) {
   143       g_string_append_len (s, ", ", 2);
   113       g_string_append_len (s, ", ", 2);
   144     }
   114     }
   145   }
   115   }
   146   g_string_append (s, end);
   116   g_string_append (s, end);
   147   return g_string_free (s, FALSE);
   117   return g_string_free (s, FALSE);
   154   GValue *list_value;
   124   GValue *list_value;
   155   GArray *array;
   125   GArray *array;
   156   GString *s;
   126   GString *s;
   157   guint i;
   127   guint i;
   158   gchar *list_s;
   128   gchar *list_s;
   159   guint alen;
       
   160 
   129 
   161   array = src_value->data[0].v_pointer;
   130   array = src_value->data[0].v_pointer;
   162   alen = array->len;
       
   163 
   131 
   164   /* estimate minimum string length to minimise re-allocs in GString */
   132   /* estimate minimum string length to minimise re-allocs in GString */
   165   s = g_string_sized_new (2 + (10 * alen) + 2);
   133   s = g_string_sized_new (2 + (10 * array->len) + 2);
   166   g_string_append (s, begin);
   134   g_string_append (s, begin);
   167   for (i = 0; i < alen; i++) {
   135   for (i = 0; i < array->len; i++) {
   168     list_value = &g_array_index (array, GValue, i);
   136     list_value = &g_array_index (array, GValue, i);
   169 
   137 
   170     if (i != 0) {
   138     if (i != 0) {
   171       g_string_append_len (s, ", ", 2);
   139       g_string_append_len (s, ", ", 2);
   172     }
   140     }
   182 /*
   150 /*
   183  * helper function to see if a type is fixed. Is used internally here and
   151  * helper function to see if a type is fixed. Is used internally here and
   184  * there. Do not export, since it doesn't work for types where the content
   152  * there. Do not export, since it doesn't work for types where the content
   185  * decides the fixedness (e.g. GST_TYPE_ARRAY).
   153  * decides the fixedness (e.g. GST_TYPE_ARRAY).
   186  */
   154  */
       
   155 
   187 static gboolean
   156 static gboolean
   188 gst_type_is_fixed (GType type)
   157 gst_type_is_fixed (GType type)
   189 {
   158 {
   190   /* the basic int, string, double types */
   159   if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
   191   if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
   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)) {
   192     return TRUE;
   165     return TRUE;
   193   }
   166   }
   194   /* our fundamental types that are certainly not fixed */
   167   if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC
   195   if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
   168       || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) {
   196       type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE) {
       
   197     return FALSE;
       
   198   }
       
   199   /* other (boxed) types that are fixed */
       
   200   if (type == GST_TYPE_BUFFER) {
       
   201     return TRUE;
       
   202   }
       
   203   /* heavy checks */
       
   204   if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
       
   205       G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
       
   206     return TRUE;
   169     return TRUE;
   207   }
   170   }
   208 
   171 
   209   return FALSE;
   172   return FALSE;
   210 }
   173 }
   218 
   181 
   219 static GArray *
   182 static GArray *
   220 copy_garray_of_gstvalue (const GArray * src)
   183 copy_garray_of_gstvalue (const GArray * src)
   221 {
   184 {
   222   GArray *dest;
   185   GArray *dest;
   223   guint i, len;
   186   guint i;
   224 
   187 
   225   len = src->len;
   188   dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
   226   dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
   189   g_array_set_size (dest, src->len);
   227   g_array_set_size (dest, len);
   190   for (i = 0; i < src->len; i++) {
   228   for (i = 0; i < len; i++) {
       
   229     gst_value_init_and_copy (&g_array_index (dest, GValue, i),
   191     gst_value_init_and_copy (&g_array_index (dest, GValue, i),
   230         &g_array_index (src, GValue, i));
   192         &g_array_index (src, GValue, i));
   231   }
   193   }
   232 
   194 
   233   return dest;
   195   return dest;
   241 }
   203 }
   242 
   204 
   243 static void
   205 static void
   244 gst_value_free_list_or_array (GValue * value)
   206 gst_value_free_list_or_array (GValue * value)
   245 {
   207 {
   246   guint i, len;
   208   guint i;
   247   GArray *src = (GArray *) value->data[0].v_pointer;
   209   GArray *src = (GArray *) value->data[0].v_pointer;
   248   len = src->len;
       
   249 
   210 
   250   if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
   211   if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
   251     for (i = 0; i < len; i++) {
   212     for (i = 0; i < src->len; i++) {
   252       g_value_unset (&g_array_index (src, GValue, i));
   213       g_value_unset (&g_array_index (src, GValue, i));
   253     }
   214     }
   254     g_array_free (src, TRUE);
   215     g_array_free (src, TRUE);
   255   }
   216   }
   256 }
   217 }
   597 gst_value_compare_array (const GValue * value1, const GValue * value2)
   558 gst_value_compare_array (const GValue * value1, const GValue * value2)
   598 {
   559 {
   599   guint i;
   560   guint i;
   600   GArray *array1 = value1->data[0].v_pointer;
   561   GArray *array1 = value1->data[0].v_pointer;
   601   GArray *array2 = value2->data[0].v_pointer;
   562   GArray *array2 = value2->data[0].v_pointer;
   602   guint len = array1->len;
       
   603   GValue *v1;
   563   GValue *v1;
   604   GValue *v2;
   564   GValue *v2;
   605 
   565 
   606   if (len != array2->len)
   566   if (array1->len != array2->len)
   607     return GST_VALUE_UNORDERED;
   567     return GST_VALUE_UNORDERED;
   608 
   568 
   609   for (i = 0; i < len; i++) {
   569   for (i = 0; i < array1->len; i++) {
   610     v1 = &g_array_index (array1, GValue, i);
   570     v1 = &g_array_index (array1, GValue, i);
   611     v2 = &g_array_index (array2, GValue, i);
   571     v2 = &g_array_index (array2, GValue, i);
   612     if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
   572     if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
   613       return GST_VALUE_UNORDERED;
   573       return GST_VALUE_UNORDERED;
   614   }
   574   }
   996  * gst_value_get_double_range_min:
   956  * gst_value_get_double_range_min:
   997  * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
   957  * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
   998  *
   958  *
   999  * Gets the minimum of the range specified by @value.
   959  * Gets the minimum of the range specified by @value.
  1000  *
   960  *
  1001  * Returns: the minimum of the range
   961  * Returns: the minumum of the range
  1002  */
   962  */
  1003 #ifdef __SYMBIAN32__
   963 #ifdef __SYMBIAN32__
  1004 EXPORT_C
   964 EXPORT_C
  1005 #endif
   965 #endif
  1006 
   966 
  1078 
  1038 
  1079 static void
  1039 static void
  1080 gst_value_init_fraction_range (GValue * value)
  1040 gst_value_init_fraction_range (GValue * value)
  1081 {
  1041 {
  1082   GValue *vals;
  1042   GValue *vals;
  1083   GType ftype;
  1043 
  1084 
  1044   value->data[0].v_pointer = vals = g_new0 (GValue, 2);
  1085   ftype = GST_TYPE_FRACTION;
  1045   g_value_init (&vals[0], GST_TYPE_FRACTION);
  1086 
  1046   g_value_init (&vals[1], GST_TYPE_FRACTION);
  1087   value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
       
  1088   g_value_init (&vals[0], ftype);
       
  1089   g_value_init (&vals[1], ftype);
       
  1090 }
  1047 }
  1091 
  1048 
  1092 static void
  1049 static void
  1093 gst_value_free_fraction_range (GValue * value)
  1050 gst_value_free_fraction_range (GValue * value)
  1094 {
  1051 {
  1095   GValue *vals = (GValue *) value->data[0].v_pointer;
  1052   GValue *vals = (GValue *) value->data[0].v_pointer;
  1096 
  1053 
  1097   if (vals != NULL) {
  1054   if (vals != NULL) {
  1098     g_value_unset (&vals[0]);
  1055     g_value_unset (&vals[0]);
  1099     g_value_unset (&vals[1]);
  1056     g_value_unset (&vals[1]);
  1100     g_slice_free1 (2 * sizeof (GValue), vals);
  1057     g_free (vals);
  1101     value->data[0].v_pointer = NULL;
  1058     value->data[0].v_pointer = NULL;
  1102   }
  1059   }
  1103 }
  1060 }
  1104 
  1061 
  1105 static void
  1062 static void
  1107 {
  1064 {
  1108   GValue *vals = (GValue *) dest_value->data[0].v_pointer;
  1065   GValue *vals = (GValue *) dest_value->data[0].v_pointer;
  1109   GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
  1066   GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
  1110 
  1067 
  1111   if (vals == NULL) {
  1068   if (vals == NULL) {
  1112     gst_value_init_fraction_range (dest_value);
  1069     dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2);
  1113     vals = dest_value->data[0].v_pointer;
  1070     g_return_if_fail (vals != NULL);
  1114   }
  1071     g_value_init (&vals[0], GST_TYPE_FRACTION);
       
  1072     g_value_init (&vals[1], GST_TYPE_FRACTION);
       
  1073   }
       
  1074 
  1115   if (src_vals != NULL) {
  1075   if (src_vals != NULL) {
  1116     g_value_copy (&src_vals[0], &vals[0]);
  1076     g_value_copy (&src_vals[0], &vals[0]);
  1117     g_value_copy (&src_vals[1], &vals[1]);
  1077     g_value_copy (&src_vals[1], &vals[1]);
  1118   }
  1078   }
  1119 }
  1079 }
  1126 
  1086 
  1127   if (n_collect_values != 4)
  1087   if (n_collect_values != 4)
  1128     return g_strdup_printf ("not enough value locations for `%s' passed",
  1088     return g_strdup_printf ("not enough value locations for `%s' passed",
  1129         G_VALUE_TYPE_NAME (value));
  1089         G_VALUE_TYPE_NAME (value));
  1130   if (vals == NULL) {
  1090   if (vals == NULL) {
  1131     gst_value_init_fraction_range (value);
  1091     value->data[0].v_pointer = vals = g_new0 (GValue, 2);
  1132     vals = value->data[0].v_pointer;
  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);
  1133   }
  1097   }
  1134 
  1098 
  1135   gst_value_set_fraction (&vals[0], collect_values[0].v_int,
  1099   gst_value_set_fraction (&vals[0], collect_values[0].v_int,
  1136       collect_values[1].v_int);
  1100       collect_values[1].v_int);
  1137   gst_value_set_fraction (&vals[1], collect_values[2].v_int,
  1101   gst_value_set_fraction (&vals[1], collect_values[2].v_int,
  1146 {
  1110 {
  1147   int i;
  1111   int i;
  1148   int *dest_values[4];
  1112   int *dest_values[4];
  1149   GValue *vals = (GValue *) value->data[0].v_pointer;
  1113   GValue *vals = (GValue *) value->data[0].v_pointer;
  1150 
  1114 
  1151   if (G_UNLIKELY (n_collect_values != 4))
  1115   if (n_collect_values != 4)
  1152     return g_strdup_printf ("not enough value locations for `%s' passed",
  1116     return g_strdup_printf ("not enough value locations for `%s' passed",
  1153         G_VALUE_TYPE_NAME (value));
  1117         G_VALUE_TYPE_NAME (value));
  1154 
  1118 
  1155   for (i = 0; i < 4; i++) {
  1119   for (i = 0; i < 4; i++) {
  1156     if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
  1120     if (collect_values[i].v_pointer == NULL) {
  1157       return g_strdup_printf ("value location for `%s' passed as NULL",
  1121       return g_strdup_printf ("value location for `%s' passed as NULL",
  1158           G_VALUE_TYPE_NAME (value));
  1122           G_VALUE_TYPE_NAME (value));
  1159     }
  1123     }
  1160     dest_values[i] = collect_values[i].v_pointer;
  1124     dest_values[i] = collect_values[i].v_pointer;
  1161   }
  1125   }
  1162 
  1126 
  1163   if (G_UNLIKELY (vals == NULL)) {
  1127   if (vals == NULL) {
  1164     return g_strdup_printf ("Uninitialised `%s' passed",
  1128     return g_strdup_printf ("Uninitialised `%s' passed",
  1165         G_VALUE_TYPE_NAME (value));
  1129         G_VALUE_TYPE_NAME (value));
  1166   }
  1130   }
  1167 
  1131 
  1168   dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
  1132   dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
  1169   dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
  1133   dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
  1170   dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
  1134   dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]);
  1171   dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
  1135   dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
  1172   return NULL;
  1136   return NULL;
  1173 }
  1137 }
  1174 
  1138 
  1175 /**
  1139 /**
  1192 
  1156 
  1193   g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
  1157   g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
  1194 
  1158 
  1195   vals = (GValue *) value->data[0].v_pointer;
  1159   vals = (GValue *) value->data[0].v_pointer;
  1196   if (vals == NULL) {
  1160   if (vals == NULL) {
  1197     gst_value_init_fraction_range (value);
  1161     value->data[0].v_pointer = vals = g_new0 (GValue, 2);
  1198     vals = value->data[0].v_pointer;
  1162     g_value_init (&vals[0], GST_TYPE_FRACTION);
  1199   }
  1163     g_value_init (&vals[1], GST_TYPE_FRACTION);
       
  1164   }
       
  1165 
  1200   g_value_copy (start, &vals[0]);
  1166   g_value_copy (start, &vals[0]);
  1201   g_value_copy (end, &vals[1]);
  1167   g_value_copy (end, &vals[1]);
  1202 }
  1168 }
  1203 
  1169 
  1204 /**
  1170 /**
  1239  * gst_value_get_fraction_range_min:
  1205  * gst_value_get_fraction_range_min:
  1240  * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
  1206  * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
  1241  *
  1207  *
  1242  * Gets the minimum of the range specified by @value.
  1208  * Gets the minimum of the range specified by @value.
  1243  *
  1209  *
  1244  * Returns: the minimum of the range
  1210  * Returns: the minumum of the range
  1245  */
  1211  */
  1246 #ifdef __SYMBIAN32__
  1212 #ifdef __SYMBIAN32__
  1247 EXPORT_C
  1213 EXPORT_C
  1248 #endif
  1214 #endif
  1249 
  1215 
  1408   GstCaps *caps;
  1374   GstCaps *caps;
  1409 
  1375 
  1410   caps = gst_caps_from_string (s);
  1376   caps = gst_caps_from_string (s);
  1411 
  1377 
  1412   if (caps) {
  1378   if (caps) {
  1413     g_value_take_boxed (dest, caps);
  1379     g_value_set_boxed (dest, caps);
  1414     return TRUE;
  1380     return TRUE;
  1415   }
  1381   }
  1416   return FALSE;
  1382   return FALSE;
  1417 }
  1383 }
  1418 
  1384 
  1466 static char *
  1432 static char *
  1467 gst_value_serialize_structure (const GValue * value)
  1433 gst_value_serialize_structure (const GValue * value)
  1468 {
  1434 {
  1469   GstStructure *structure = g_value_get_boxed (value);
  1435   GstStructure *structure = g_value_get_boxed (value);
  1470 
  1436 
  1471   return gst_string_take_and_wrap (gst_structure_to_string (structure));
  1437   return gst_structure_to_string (structure);
  1472 }
  1438 }
  1473 
  1439 
  1474 static gboolean
  1440 static gboolean
  1475 gst_value_deserialize_structure (GValue * dest, const gchar * s)
  1441 gst_value_deserialize_structure (GValue * dest, const gchar * s)
  1476 {
  1442 {
  1477   GstStructure *structure;
  1443   GstStructure *structure;
  1478 
  1444 
  1479   if (*s != '"') {
  1445   structure = gst_structure_from_string (s, NULL);
  1480     structure = gst_structure_from_string (s, NULL);
  1446 
  1481   } else {
  1447   if (structure) {
  1482     gchar *str = gst_string_unwrap (s);
  1448     g_value_set_boxed (dest, structure);
  1483 
       
  1484     if (G_UNLIKELY (!str))
       
  1485       return FALSE;
       
  1486 
       
  1487     structure = gst_structure_from_string (str, NULL);
       
  1488     g_free (str);
       
  1489   }
       
  1490 
       
  1491   if (G_LIKELY (structure)) {
       
  1492     g_value_take_boxed (dest, structure);
       
  1493     return TRUE;
  1449     return TRUE;
  1494   }
  1450   }
  1495   return FALSE;
  1451   return FALSE;
  1496 }
  1452 }
  1497 
  1453 
  1905  **********/
  1861  **********/
  1906 
  1862 
  1907 static gint
  1863 static gint
  1908 gst_value_compare_string (const GValue * value1, const GValue * value2)
  1864 gst_value_compare_string (const GValue * value1, const GValue * value2)
  1909 {
  1865 {
  1910   if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
  1866   int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
  1911     /* if only one is NULL, no match - otherwise both NULL == EQUAL */
  1867 
  1912     if (value1->data[0].v_pointer != value2->data[0].v_pointer)
  1868   if (x < 0)
  1913       return GST_VALUE_UNORDERED;
  1869     return GST_VALUE_LESS_THAN;
  1914   } else {
  1870   if (x > 0)
  1915     int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
  1871     return GST_VALUE_GREATER_THAN;
  1916 
       
  1917     if (x < 0)
       
  1918       return GST_VALUE_LESS_THAN;
       
  1919     if (x > 0)
       
  1920       return GST_VALUE_GREATER_THAN;
       
  1921   }
       
  1922 
       
  1923   return GST_VALUE_EQUAL;
  1872   return GST_VALUE_EQUAL;
  1924 }
  1873 }
  1925 
  1874 
  1926 static int
  1875 /* keep in sync with gststructure.c */
  1927 gst_string_measure_wrapping (const gchar * s)
  1876 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
  1928 {
  1877     ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
       
  1878     ((c) == '.'))
       
  1879 
       
  1880 static gchar *
       
  1881 gst_string_wrap (const gchar * s)
       
  1882 {
       
  1883   const gchar *t;
  1929   int len;
  1884   int len;
       
  1885   gchar *d, *e;
  1930   gboolean wrap = FALSE;
  1886   gboolean wrap = FALSE;
  1931 
  1887 
  1932   if (G_UNLIKELY (s == NULL))
       
  1933     return -1;
       
  1934 
       
  1935   /* Special case: the actual string NULL needs wrapping */
       
  1936   if (G_UNLIKELY (strcmp (s, "NULL") == 0))
       
  1937     return 4;
       
  1938 
       
  1939   len = 0;
  1888   len = 0;
  1940   while (*s) {
  1889   t = s;
  1941     if (GST_ASCII_IS_STRING (*s)) {
  1890   if (!s)
       
  1891     return NULL;
       
  1892   while (*t) {
       
  1893     if (GST_ASCII_IS_STRING (*t)) {
  1942       len++;
  1894       len++;
  1943     } else if (*s < 0x20 || *s >= 0x7f) {
  1895     } else if (*t < 0x20 || *t >= 0x7f) {
  1944       wrap = TRUE;
  1896       wrap = TRUE;
  1945       len += 4;
  1897       len += 4;
  1946     } else {
  1898     } else {
  1947       wrap = TRUE;
  1899       wrap = TRUE;
  1948       len += 2;
  1900       len += 2;
  1949     }
  1901     }
  1950     s++;
  1902     t++;
  1951   }
  1903   }
  1952 
  1904 
  1953   /* Wrap the string if we found something that needs
  1905   if (!wrap)
  1954    * wrapping, or the empty string (len == 0) */
  1906     return g_strdup (s);
  1955   return (wrap || len == 0) ? len : -1;
       
  1956 }
       
  1957 
       
  1958 static gchar *
       
  1959 gst_string_wrap_inner (const gchar * s, int len)
       
  1960 {
       
  1961   gchar *d, *e;
       
  1962 
  1907 
  1963   e = d = g_malloc (len + 3);
  1908   e = d = g_malloc (len + 3);
  1964 
  1909 
  1965   *e++ = '\"';
  1910   *e++ = '\"';
  1966   while (*s) {
  1911   t = s;
  1967     if (GST_ASCII_IS_STRING (*s)) {
  1912   while (*t) {
  1968       *e++ = *s++;
  1913     if (GST_ASCII_IS_STRING (*t)) {
  1969     } else if (*s < 0x20 || *s >= 0x7f) {
  1914       *e++ = *t++;
       
  1915     } else if (*t < 0x20 || *t >= 0x7f) {
  1970       *e++ = '\\';
  1916       *e++ = '\\';
  1971       *e++ = '0' + ((*(guchar *) s) >> 6);
  1917       *e++ = '0' + ((*(guchar *) t) >> 6);
  1972       *e++ = '0' + (((*s) >> 3) & 0x7);
  1918       *e++ = '0' + (((*t) >> 3) & 0x7);
  1973       *e++ = '0' + ((*s++) & 0x7);
  1919       *e++ = '0' + ((*t++) & 0x7);
  1974     } else {
  1920     } else {
  1975       *e++ = '\\';
  1921       *e++ = '\\';
  1976       *e++ = *s++;
  1922       *e++ = *t++;
  1977     }
  1923     }
  1978   }
  1924   }
  1979   *e++ = '\"';
  1925   *e++ = '\"';
  1980   *e = 0;
  1926   *e = 0;
  1981 
  1927 
  1982   g_assert (e - d <= len + 3);
       
  1983   return d;
  1928   return d;
  1984 }
       
  1985 
       
  1986 /* Do string wrapping/escaping */
       
  1987 static gchar *
       
  1988 gst_string_wrap (const gchar * s)
       
  1989 {
       
  1990   int len = gst_string_measure_wrapping (s);
       
  1991 
       
  1992   if (G_LIKELY (len < 0))
       
  1993     return g_strdup (s);
       
  1994 
       
  1995   return gst_string_wrap_inner (s, len);
       
  1996 }
       
  1997 
       
  1998 /* Same as above, but take ownership of the string */
       
  1999 static gchar *
       
  2000 gst_string_take_and_wrap (gchar * s)
       
  2001 {
       
  2002   gchar *out;
       
  2003   int len = gst_string_measure_wrapping (s);
       
  2004 
       
  2005   if (G_LIKELY (len < 0))
       
  2006     return s;
       
  2007 
       
  2008   out = gst_string_wrap_inner (s, len);
       
  2009   g_free (s);
       
  2010 
       
  2011   return out;
       
  2012 }
  1929 }
  2013 
  1930 
  2014 /*
  1931 /*
  2015  * This function takes a string delimited with double quotes (")
  1932  * This function takes a string delimited with double quotes (")
  2016  * and unescapes any \xxx octal numbers.
  1933  * and unescapes any \xxx octal numbers.
  2086   /* if the string is not ending in " and zero terminated, we error */
  2003   /* if the string is not ending in " and zero terminated, we error */
  2087   if (*read != '"' || read[1] != '\0')
  2004   if (*read != '"' || read[1] != '\0')
  2088     goto beach;
  2005     goto beach;
  2089 
  2006 
  2090   /* null terminate result string and return */
  2007   /* null terminate result string and return */
  2091   *write = '\0';
  2008   *write++ = '\0';
  2092   return ret;
  2009   return ret;
  2093 
  2010 
  2094 beach:
  2011 beach:
  2095   g_free (ret);
  2012   g_free (ret);
  2096   return NULL;
  2013   return NULL;
  2103 }
  2020 }
  2104 
  2021 
  2105 static gboolean
  2022 static gboolean
  2106 gst_value_deserialize_string (GValue * dest, const gchar * s)
  2023 gst_value_deserialize_string (GValue * dest, const gchar * s)
  2107 {
  2024 {
  2108   if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
  2025   if (*s != '"') {
  2109     g_value_set_string (dest, NULL);
       
  2110     return TRUE;
       
  2111   } else if (G_LIKELY (*s != '"')) {
       
  2112     if (!g_utf8_validate (s, -1, NULL))
  2026     if (!g_utf8_validate (s, -1, NULL))
  2113       return FALSE;
  2027       return FALSE;
  2114     g_value_set_string (dest, s);
  2028     g_value_set_string (dest, s);
  2115     return TRUE;
  2029     return TRUE;
  2116   } else {
  2030   } else {
  2117     gchar *str = gst_string_unwrap (s);
  2031     gchar *str = gst_string_unwrap (s);
  2118     if (G_UNLIKELY (!str))
  2032 
       
  2033     if (!str)
  2119       return FALSE;
  2034       return FALSE;
  2120     g_value_take_string (dest, str);
  2035     g_value_take_string (dest, str);
  2121   }
  2036   }
  2122 
  2037 
  2123   return TRUE;
  2038   return TRUE;
  2533 
  2448 
  2534   return FALSE;
  2449   return FALSE;
  2535 }
  2450 }
  2536 
  2451 
  2537 static gboolean
  2452 static gboolean
  2538 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
  2453     gst_value_intersect_fraction_range_fraction_range
  2539     const GValue * src1, const GValue * src2)
  2454     (GValue * dest, const GValue * src1, const GValue * src2)
  2540 {
  2455 {
  2541   GValue *min;
  2456   GValue *min;
  2542   GValue *max;
  2457   GValue *max;
  2543   int res;
  2458   int res;
  2544   GValue *vals1, *vals2;
  2459   GValue *vals1, *vals2;
  2776     const GValue * subtrahend)
  2691     const GValue * subtrahend)
  2777 {
  2692 {
  2778   guint i, size;
  2693   guint i, size;
  2779   GValue subtraction = { 0, };
  2694   GValue subtraction = { 0, };
  2780   gboolean ret = FALSE;
  2695   gboolean ret = FALSE;
  2781   GType ltype;
       
  2782 
       
  2783   ltype = gst_value_list_get_type ();
       
  2784 
  2696 
  2785   size = gst_value_list_get_size (minuend);
  2697   size = gst_value_list_get_size (minuend);
  2786   for (i = 0; i < size; i++) {
  2698   for (i = 0; i < size; i++) {
  2787     const GValue *cur = gst_value_list_get_value (minuend, i);
  2699     const GValue *cur = gst_value_list_get_value (minuend, i);
  2788 
  2700 
  2789     if (gst_value_subtract (&subtraction, cur, subtrahend)) {
  2701     if (gst_value_subtract (&subtraction, cur, subtrahend)) {
  2790       if (!ret) {
  2702       if (!ret) {
  2791         gst_value_init_and_copy (dest, &subtraction);
  2703         gst_value_init_and_copy (dest, &subtraction);
  2792         ret = TRUE;
  2704         ret = TRUE;
  2793       } else if (G_VALUE_HOLDS (dest, ltype)
  2705       } else if (GST_VALUE_HOLDS_LIST (dest)
  2794           && !G_VALUE_HOLDS (&subtraction, ltype)) {
  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)) {
  2795         gst_value_list_append_value (dest, &subtraction);
  2714         gst_value_list_append_value (dest, &subtraction);
  2796       } else {
  2715       } else {
  2797         GValue temp = { 0, };
  2716         GValue temp = { 0, };
  2798 
  2717 
  2799         gst_value_init_and_copy (&temp, dest);
  2718         gst_value_init_and_copy (&temp, dest);
  2936 
  2855 
  2937 /**************
  2856 /**************
  2938  * comparison *
  2857  * comparison *
  2939  **************/
  2858  **************/
  2940 
  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 
  2941 /*
  2891 /*
  2942  * gst_value_get_compare_func:
  2892  * gst_value_get_compare_func:
  2943  * @value1: a value to get the compare function for
  2893  * @value1: a value to get the compare function for
  2944  *
  2894  *
  2945  * Determines the compare function to be used with values of the same type as
  2895  * Determines the compare function to be used with values of the same type as
  2950 static GstValueCompareFunc
  2900 static GstValueCompareFunc
  2951 gst_value_get_compare_func (const GValue * value1)
  2901 gst_value_get_compare_func (const GValue * value1)
  2952 {
  2902 {
  2953   GstValueTable *table, *best = NULL;
  2903   GstValueTable *table, *best = NULL;
  2954   guint i;
  2904   guint i;
  2955   GType type1;
  2905 
  2956 
  2906   for (i = 0; i < gst_value_table->len; i++) {
  2957   type1 = G_VALUE_TYPE (value1);
  2907     table = &g_array_index (gst_value_table, GstValueTable, i);
  2958 
  2908     if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) {
  2959   /* this is a fast check */
  2909       best = table;
  2960   best = gst_value_hash_lookup_type (type1);
  2910       break;
  2961 
       
  2962   /* slower checks */
       
  2963   if (G_UNLIKELY (!best || !best->compare)) {
       
  2964     guint len = gst_value_table->len;
       
  2965 
       
  2966     best = NULL;
       
  2967     for (i = 0; i < len; i++) {
       
  2968       table = &g_array_index (gst_value_table, GstValueTable, i);
       
  2969       if (table->compare && g_type_is_a (type1, table->type)) {
       
  2970         if (!best || g_type_is_a (table->type, best->type))
       
  2971           best = table;
       
  2972       }
       
  2973     }
  2911     }
  2974   }
  2912     if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) {
  2975   if (G_LIKELY (best))
  2913       if (!best || g_type_is_a (table->type, best->type))
       
  2914         best = table;
       
  2915     }
       
  2916   }
       
  2917   if (best) {
  2976     return best->compare;
  2918     return best->compare;
  2977 
  2919   }
  2978   return NULL;
  2920   return NULL;
  2979 }
       
  2980 
       
  2981 /**
       
  2982  * gst_value_can_compare:
       
  2983  * @value1: a value to compare
       
  2984  * @value2: another value to compare
       
  2985  *
       
  2986  * Determines if @value1 and @value2 can be compared.
       
  2987  *
       
  2988  * Returns: TRUE if the values can be compared
       
  2989  */
       
  2990 #ifdef __SYMBIAN32__
       
  2991 EXPORT_C
       
  2992 #endif
       
  2993 
       
  2994 gboolean
       
  2995 gst_value_can_compare (const GValue * value1, const GValue * value2)
       
  2996 {
       
  2997   if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
       
  2998     return FALSE;
       
  2999 
       
  3000   return gst_value_get_compare_func (value1) != NULL;
       
  3001 }
  2921 }
  3002 
  2922 
  3003 /**
  2923 /**
  3004  * gst_value_compare:
  2924  * gst_value_compare:
  3005  * @value1: a value to compare
  2925  * @value1: a value to compare
  3013  *
  2933  *
  3014  * Returns: A #GstValueCompareType value
  2934  * Returns: A #GstValueCompareType value
  3015  */
  2935  */
  3016 #ifdef __SYMBIAN32__
  2936 #ifdef __SYMBIAN32__
  3017 EXPORT_C
  2937 EXPORT_C
  3018 #endif
  2938 #endif 
  3019 
       
  3020 gint
  2939 gint
  3021 gst_value_compare (const GValue * value1, const GValue * value2)
  2940 gst_value_compare (const GValue * value1, const GValue * value2)
  3022 {
  2941 {
  3023   GstValueCompareFunc compare;
  2942   GstValueCompareFunc compare;
  3024 
  2943 
  3083 
  3002 
  3084 gboolean
  3003 gboolean
  3085 gst_value_can_union (const GValue * value1, const GValue * value2)
  3004 gst_value_can_union (const GValue * value1, const GValue * value2)
  3086 {
  3005 {
  3087   GstValueUnionInfo *union_info;
  3006   GstValueUnionInfo *union_info;
  3088   guint i, len;
  3007   guint i;
  3089 
  3008 
  3090   len = gst_value_union_funcs->len;
  3009   for (i = 0; i < gst_value_union_funcs->len; i++) {
  3091 
       
  3092   for (i = 0; i < len; i++) {
       
  3093     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
  3010     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
  3094     if (union_info->type1 == G_VALUE_TYPE (value1) &&
  3011     if (union_info->type1 == G_VALUE_TYPE (value1) &&
  3095         union_info->type2 == G_VALUE_TYPE (value2))
  3012         union_info->type2 == G_VALUE_TYPE (value2))
  3096       return TRUE;
  3013       return TRUE;
  3097     if (union_info->type1 == G_VALUE_TYPE (value2) &&
  3014     if (union_info->type1 == G_VALUE_TYPE (value2) &&
  3119 
  3036 
  3120 gboolean
  3037 gboolean
  3121 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
  3038 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
  3122 {
  3039 {
  3123   GstValueUnionInfo *union_info;
  3040   GstValueUnionInfo *union_info;
  3124   guint i, len;
  3041   guint i;
  3125 
  3042 
  3126   len = gst_value_union_funcs->len;
  3043   for (i = 0; i < gst_value_union_funcs->len; i++) {
  3127 
       
  3128   for (i = 0; i < len; i++) {
       
  3129     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
  3044     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
  3130     if (union_info->type1 == G_VALUE_TYPE (value1) &&
  3045     if (union_info->type1 == G_VALUE_TYPE (value1) &&
  3131         union_info->type2 == G_VALUE_TYPE (value2)) {
  3046         union_info->type2 == G_VALUE_TYPE (value2)) {
  3132       if (union_info->func (dest, value1, value2)) {
  3047       if (union_info->func (dest, value1, value2)) {
  3133         return TRUE;
  3048         return TRUE;
  3194 
  3109 
  3195 gboolean
  3110 gboolean
  3196 gst_value_can_intersect (const GValue * value1, const GValue * value2)
  3111 gst_value_can_intersect (const GValue * value1, const GValue * value2)
  3197 {
  3112 {
  3198   GstValueIntersectInfo *intersect_info;
  3113   GstValueIntersectInfo *intersect_info;
  3199   guint i, len;
  3114   guint i;
  3200   GType ltype, type1, type2;
       
  3201 
       
  3202   ltype = gst_value_list_get_type ();
       
  3203 
  3115 
  3204   /* special cases */
  3116   /* special cases */
  3205   if (G_VALUE_HOLDS (value1, ltype) || G_VALUE_HOLDS (value2, ltype))
  3117   if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
  3206     return TRUE;
  3118     return TRUE;
  3207 
  3119 
  3208   type1 = G_VALUE_TYPE (value1);
  3120   for (i = 0; i < gst_value_intersect_funcs->len; i++) {
  3209   type2 = G_VALUE_TYPE (value2);
       
  3210 
       
  3211   /* practically all GstValue types have a compare function (_can_compare=TRUE)
       
  3212    * GstStructure and GstCaps have npot, but are intersectable */
       
  3213   if (type1 == type2)
       
  3214     return TRUE;
       
  3215 
       
  3216   /* check registered intersect functions */
       
  3217   len = gst_value_intersect_funcs->len;
       
  3218   for (i = 0; i < len; i++) {
       
  3219     intersect_info = &g_array_index (gst_value_intersect_funcs,
  3121     intersect_info = &g_array_index (gst_value_intersect_funcs,
  3220         GstValueIntersectInfo, i);
  3122         GstValueIntersectInfo, i);
  3221     if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
  3123     if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
  3222         (intersect_info->type1 == type2 && intersect_info->type2 == type1))
  3124         intersect_info->type2 == G_VALUE_TYPE (value2))
  3223       return TRUE;
  3125       if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
       
  3126           intersect_info->type1 == G_VALUE_TYPE (value2))
       
  3127         return TRUE;
  3224   }
  3128   }
  3225 
  3129 
  3226   return gst_value_can_compare (value1, value2);
  3130   return gst_value_can_compare (value1, value2);
  3227 }
  3131 }
  3228 
  3132 
  3247 gboolean
  3151 gboolean
  3248 gst_value_intersect (GValue * dest, const GValue * value1,
  3152 gst_value_intersect (GValue * dest, const GValue * value1,
  3249     const GValue * value2)
  3153     const GValue * value2)
  3250 {
  3154 {
  3251   GstValueIntersectInfo *intersect_info;
  3155   GstValueIntersectInfo *intersect_info;
  3252   guint i, len;
  3156   guint i;
  3253   GType ltype, type1, type2;
  3157   gboolean ret = FALSE;
  3254 
       
  3255   ltype = gst_value_list_get_type ();
       
  3256 
  3158 
  3257   /* special cases first */
  3159   /* special cases first */
  3258   if (G_VALUE_HOLDS (value1, ltype))
  3160   if (GST_VALUE_HOLDS_LIST (value1))
  3259     return gst_value_intersect_list (dest, value1, value2);
  3161     return gst_value_intersect_list (dest, value1, value2);
  3260   if (G_VALUE_HOLDS (value2, ltype))
  3162   if (GST_VALUE_HOLDS_LIST (value2))
  3261     return gst_value_intersect_list (dest, value2, value1);
  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   }
  3262 
  3179 
  3263   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
  3180   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
  3264     gst_value_init_and_copy (dest, value1);
  3181     gst_value_init_and_copy (dest, value1);
  3265     return TRUE;
  3182     ret = TRUE;
  3266   }
  3183   }
  3267 
  3184 
  3268   type1 = G_VALUE_TYPE (value1);
  3185   return ret;
  3269   type2 = G_VALUE_TYPE (value2);
       
  3270 
       
  3271   len = gst_value_intersect_funcs->len;
       
  3272   for (i = 0; i < len; i++) {
       
  3273     intersect_info = &g_array_index (gst_value_intersect_funcs,
       
  3274         GstValueIntersectInfo, i);
       
  3275     if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
       
  3276       return intersect_info->func (dest, value1, value2);
       
  3277     }
       
  3278     if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
       
  3279       return intersect_info->func (dest, value2, value1);
       
  3280     }
       
  3281   }
       
  3282   return FALSE;
       
  3283 }
  3186 }
  3284 
  3187 
  3285 /**
  3188 /**
  3286  * gst_value_register_intersect_func:
  3189  * gst_value_register_intersect_func:
  3287  * @type1: the first type to intersect
  3190  * @type1: the first type to intersect
  3334 gboolean
  3237 gboolean
  3335 gst_value_subtract (GValue * dest, const GValue * minuend,
  3238 gst_value_subtract (GValue * dest, const GValue * minuend,
  3336     const GValue * subtrahend)
  3239     const GValue * subtrahend)
  3337 {
  3240 {
  3338   GstValueSubtractInfo *info;
  3241   GstValueSubtractInfo *info;
  3339   guint i, len;
  3242   guint i;
  3340   GType ltype, mtype, stype;
       
  3341 
       
  3342   ltype = gst_value_list_get_type ();
       
  3343 
  3243 
  3344   /* special cases first */
  3244   /* special cases first */
  3345   if (G_VALUE_HOLDS (minuend, ltype))
  3245   if (GST_VALUE_HOLDS_LIST (minuend))
  3346     return gst_value_subtract_from_list (dest, minuend, subtrahend);
  3246     return gst_value_subtract_from_list (dest, minuend, subtrahend);
  3347   if (G_VALUE_HOLDS (subtrahend, ltype))
  3247   if (GST_VALUE_HOLDS_LIST (subtrahend))
  3348     return gst_value_subtract_list (dest, minuend, subtrahend);
  3248     return gst_value_subtract_list (dest, minuend, subtrahend);
  3349 
  3249 
  3350   mtype = G_VALUE_TYPE (minuend);
  3250   for (i = 0; i < gst_value_subtract_funcs->len; i++) {
  3351   stype = G_VALUE_TYPE (subtrahend);
       
  3352 
       
  3353   len = gst_value_subtract_funcs->len;
       
  3354   for (i = 0; i < len; i++) {
       
  3355     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
  3251     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
  3356     if (info->minuend == mtype && info->subtrahend == stype) {
  3252     if (info->minuend == G_VALUE_TYPE (minuend) &&
       
  3253         info->subtrahend == G_VALUE_TYPE (subtrahend)) {
  3357       return info->func (dest, minuend, subtrahend);
  3254       return info->func (dest, minuend, subtrahend);
  3358     }
  3255     }
  3359   }
  3256   }
  3360 
  3257 
  3361   if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
  3258   if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
  3395 
  3292 
  3396 gboolean
  3293 gboolean
  3397 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
  3294 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
  3398 {
  3295 {
  3399   GstValueSubtractInfo *info;
  3296   GstValueSubtractInfo *info;
  3400   guint i, len;
  3297   guint i;
  3401   GType ltype, mtype, stype;
       
  3402 
       
  3403   ltype = gst_value_list_get_type ();
       
  3404 
  3298 
  3405   /* special cases */
  3299   /* special cases */
  3406   if (G_VALUE_HOLDS (minuend, ltype) || G_VALUE_HOLDS (subtrahend, ltype))
  3300   if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
  3407     return TRUE;
  3301     return TRUE;
  3408 
  3302 
  3409   mtype = G_VALUE_TYPE (minuend);
  3303   for (i = 0; i < gst_value_subtract_funcs->len; i++) {
  3410   stype = G_VALUE_TYPE (subtrahend);
       
  3411 
       
  3412   len = gst_value_subtract_funcs->len;
       
  3413   for (i = 0; i < len; i++) {
       
  3414     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
  3304     info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
  3415     if (info->minuend == mtype && info->subtrahend == stype)
  3305     if (info->minuend == G_VALUE_TYPE (minuend) &&
       
  3306         info->subtrahend == G_VALUE_TYPE (subtrahend))
  3416       return TRUE;
  3307       return TRUE;
  3417   }
  3308   }
  3418 
  3309 
  3419   return gst_value_can_compare (minuend, subtrahend);
  3310   return gst_value_can_compare (minuend, subtrahend);
  3420 }
  3311 }
  3456 /**
  3347 /**
  3457  * gst_value_register:
  3348  * gst_value_register:
  3458  * @table: structure containing functions to register
  3349  * @table: structure containing functions to register
  3459  *
  3350  *
  3460  * Registers functions to perform calculations on #GValues of a given
  3351  * Registers functions to perform calculations on #GValues of a given
  3461  * type. Each type can only be added once.
  3352  * type.
  3462  */
  3353  */
  3463 #ifdef __SYMBIAN32__
  3354 #ifdef __SYMBIAN32__
  3464 EXPORT_C
  3355 EXPORT_C
  3465 #endif
  3356 #endif
  3466 
  3357 
  3467 void
  3358 void
  3468 gst_value_register (const GstValueTable * table)
  3359 gst_value_register (const GstValueTable * table)
  3469 {
  3360 {
  3470   GstValueTable *found;
       
  3471 
       
  3472   g_array_append_val (gst_value_table, *table);
  3361   g_array_append_val (gst_value_table, *table);
  3473 
       
  3474   found = gst_value_hash_lookup_type (table->type);
       
  3475   if (found)
       
  3476     g_warning ("adding type %s multiple times", g_type_name (table->type));
       
  3477 
       
  3478   /* FIXME: we're not really doing the const justice, we assume the table is
       
  3479    * static */
       
  3480   gst_value_hash_add_type (table->type, table);
       
  3481 }
  3362 }
  3482 
  3363 
  3483 /**
  3364 /**
  3484  * gst_value_init_and_copy:
  3365  * gst_value_init_and_copy:
  3485  * @dest: the target value
  3366  * @dest: the target value
  3513 #endif
  3394 #endif
  3514 
  3395 
  3515 gchar *
  3396 gchar *
  3516 gst_value_serialize (const GValue * value)
  3397 gst_value_serialize (const GValue * value)
  3517 {
  3398 {
  3518   guint i, len;
  3399   guint i;
  3519   GValue s_val = { 0 };
  3400   GValue s_val = { 0 };
  3520   GstValueTable *table, *best;
  3401   GstValueTable *table, *best = NULL;
  3521   char *s;
  3402   char *s;
  3522   GType type;
       
  3523 
  3403 
  3524   g_return_val_if_fail (G_IS_VALUE (value), NULL);
  3404   g_return_val_if_fail (G_IS_VALUE (value), NULL);
  3525 
  3405 
  3526   type = G_VALUE_TYPE (value);
  3406   for (i = 0; i < gst_value_table->len; i++) {
  3527 
  3407     table = &g_array_index (gst_value_table, GstValueTable, i);
  3528   best = gst_value_hash_lookup_type (type);
  3408     if (table->serialize == NULL)
  3529 
  3409       continue;
  3530   if (G_UNLIKELY (!best || !best->serialize)) {
  3410     if (table->type == G_VALUE_TYPE (value)) {
  3531     len = gst_value_table->len;
  3411       best = table;
  3532     best = NULL;
  3412       break;
  3533     for (i = 0; i < len; i++) {
       
  3534       table = &g_array_index (gst_value_table, GstValueTable, i);
       
  3535       if (table->serialize && g_type_is_a (type, table->type)) {
       
  3536         if (!best || g_type_is_a (table->type, best->type))
       
  3537           best = table;
       
  3538       }
       
  3539     }
  3413     }
  3540   }
  3414     if (g_type_is_a (G_VALUE_TYPE (value), table->type)) {
  3541   if (G_LIKELY (best))
  3415       if (!best || g_type_is_a (table->type, best->type))
       
  3416         best = table;
       
  3417     }
       
  3418   }
       
  3419   if (best)
  3542     return best->serialize (value);
  3420     return best->serialize (value);
  3543 
  3421 
  3544   g_value_init (&s_val, G_TYPE_STRING);
  3422   g_value_init (&s_val, G_TYPE_STRING);
  3545   if (g_value_transform (value, &s_val)) {
  3423   if (g_value_transform (value, &s_val)) {
  3546     s = gst_string_wrap (g_value_get_string (&s_val));
  3424     s = gst_string_wrap (g_value_get_string (&s_val));
  3567 #endif
  3445 #endif
  3568 
  3446 
  3569 gboolean
  3447 gboolean
  3570 gst_value_deserialize (GValue * dest, const gchar * src)
  3448 gst_value_deserialize (GValue * dest, const gchar * src)
  3571 {
  3449 {
  3572   GstValueTable *table, *best;
  3450   GstValueTable *table, *best = NULL;
  3573   guint i, len;
  3451   guint i;
  3574   GType type;
       
  3575 
  3452 
  3576   g_return_val_if_fail (src != NULL, FALSE);
  3453   g_return_val_if_fail (src != NULL, FALSE);
  3577   g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
  3454   g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
  3578 
  3455 
  3579   type = G_VALUE_TYPE (dest);
  3456   for (i = 0; i < gst_value_table->len; i++) {
  3580 
  3457     table = &g_array_index (gst_value_table, GstValueTable, i);
  3581   best = gst_value_hash_lookup_type (type);
  3458     if (table->serialize == NULL)
  3582   if (G_UNLIKELY (!best || !best->deserialize)) {
  3459       continue;
  3583     len = gst_value_table->len;
  3460 
  3584     best = NULL;
  3461     if (table->type == G_VALUE_TYPE (dest)) {
  3585     for (i = 0; i < len; i++) {
  3462       best = table;
  3586       table = &g_array_index (gst_value_table, GstValueTable, i);
  3463       break;
  3587       if (table->deserialize && g_type_is_a (type, table->type)) {
       
  3588         if (!best || g_type_is_a (table->type, best->type))
       
  3589           best = table;
       
  3590       }
       
  3591     }
  3464     }
  3592   }
  3465 
  3593   if (G_LIKELY (best))
  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) {
  3594     return best->deserialize (dest, src);
  3472     return best->deserialize (dest, src);
       
  3473   }
  3595 
  3474 
  3596   return FALSE;
  3475   return FALSE;
  3597 }
  3476 }
  3598 
  3477 
  3599 /**
  3478 /**
  3614 
  3493 
  3615 gboolean
  3494 gboolean
  3616 gst_value_is_fixed (const GValue * value)
  3495 gst_value_is_fixed (const GValue * value)
  3617 {
  3496 {
  3618   GType type = G_VALUE_TYPE (value);
  3497   GType type = G_VALUE_TYPE (value);
  3619 
       
  3620   /* the most common types are just basic plain glib types */
       
  3621   if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
       
  3622     return TRUE;
       
  3623   }
       
  3624 
  3498 
  3625   if (type == GST_TYPE_ARRAY) {
  3499   if (type == GST_TYPE_ARRAY) {
  3626     gint size, n;
  3500     gint size, n;
  3627     const GValue *kid;
  3501     const GValue *kid;
  3628 
  3502 
  3633       if (!gst_value_is_fixed (kid))
  3507       if (!gst_value_is_fixed (kid))
  3634         return FALSE;
  3508         return FALSE;
  3635     }
  3509     }
  3636     return TRUE;
  3510     return TRUE;
  3637   }
  3511   }
       
  3512 
  3638   return gst_type_is_fixed (type);
  3513   return gst_type_is_fixed (type);
  3639 }
  3514 }
  3640 
  3515 
  3641 /************
  3516 /************
  3642  * fraction *
  3517  * fraction *
  4206 {
  4081 {
  4207   GstObject *obj;
  4082   GstObject *obj;
  4208   gchar *str;
  4083   gchar *str;
  4209 
  4084 
  4210   obj = g_value_get_object (src_value);
  4085   obj = g_value_get_object (src_value);
  4211   if (obj) {
  4086   str = obj ? GST_OBJECT_NAME (obj) : "NULL";
  4212     str =
  4087 
  4213         g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
  4088   dest_value->data[0].v_pointer = g_strdup (str);
  4214         GST_OBJECT_NAME (obj));
       
  4215   } else {
       
  4216     str = g_strdup ("NULL");
       
  4217   }
       
  4218 
       
  4219   dest_value->data[0].v_pointer = str;
       
  4220 }
  4089 }
  4221 
  4090 
  4222 static GTypeInfo _info = {
  4091 static GTypeInfo _info = {
  4223   0,
  4092   0,
  4224   NULL,
  4093   NULL,
  4371 
  4240 
  4372 void
  4241 void
  4373 _gst_value_initialize (void)
  4242 _gst_value_initialize (void)
  4374 {
  4243 {
  4375   gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
  4244   gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
  4376   gst_value_hash = g_hash_table_new (NULL, NULL);
       
  4377   gst_value_union_funcs = g_array_new (FALSE, FALSE,
  4245   gst_value_union_funcs = g_array_new (FALSE, FALSE,
  4378       sizeof (GstValueUnionInfo));
  4246       sizeof (GstValueUnionInfo));
  4379   gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
  4247   gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
  4380       sizeof (GstValueIntersectInfo));
  4248       sizeof (GstValueIntersectInfo));
  4381   gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
  4249   gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
  4447       gst_value_compare_array,
  4315       gst_value_compare_array,
  4448       gst_value_serialize_array,
  4316       gst_value_serialize_array,
  4449       gst_value_deserialize_array,
  4317       gst_value_deserialize_array,
  4450     };
  4318     };
  4451 
  4319 
  4452     gst_value.type = gst_value_array_get_type ();
  4320     gst_value.type = gst_value_array_get_type ();;
  4453     gst_value_register (&gst_value);
  4321     gst_value_register (&gst_value);
  4454   }
  4322   }
  4455 
  4323 
  4456   {
  4324   {
  4457 #if 0
  4325 #if 0