Merge gstvalue and gststructure from CAPS branch
authorDavid Schleef <ds@schleef.org>
Sat, 29 Nov 2003 06:31:10 +0000 (06:31 +0000)
committerDavid Schleef <ds@schleef.org>
Sat, 29 Nov 2003 06:31:10 +0000 (06:31 +0000)
Original commit message from CVS:
Merge gstvalue and gststructure from CAPS branch

gst/gststructure.c
gst/gststructure.h
gst/gsttag.c
gst/gsttaglist.c
gst/gstvalue.c
gst/gstvalue.h

index f92dd32..763ead5 100644 (file)
@@ -601,7 +601,7 @@ gst_structure_remove_all_fields(GstStructure *structure)
  * @fieldname: the name of the field
  *
  * Finds the field with the given name, and returns the type of the
- * value it contains.  If the field is not found, G_TYPE_NONE is
+ * value it contains.  If the field is not found, G_TYPE_INVALID is
  * returned.
  *
  * Returns: the #GValue of the field
@@ -611,11 +611,11 @@ gst_structure_get_field_type(const GstStructure *structure, const gchar *fieldna
 {
   GstStructureField *field;
 
-  g_return_val_if_fail(structure != NULL, G_TYPE_NONE);
-  g_return_val_if_fail(fieldname != NULL, G_TYPE_NONE);
+  g_return_val_if_fail(structure != NULL, G_TYPE_INVALID);
+  g_return_val_if_fail(fieldname != NULL, G_TYPE_INVALID);
 
   field = gst_structure_get_field(structure, fieldname);
-  if(field == NULL) return G_TYPE_NONE;
+  if(field == NULL) return G_TYPE_INVALID;
 
   return G_VALUE_TYPE(&field->value);
 }
@@ -865,6 +865,67 @@ gst_structure_get_string(const GstStructure *structure, const gchar *fieldname)
   return g_value_get_string(&field->value);
 }
 
+typedef struct _GstStructureAbbreviation {
+  char *type_name;
+  GType type;
+} GstStructureAbbreviation;
+
+static GstStructureAbbreviation _gst_structure_abbrs[] = {
+  { "int",     G_TYPE_INT },
+  { "i",       G_TYPE_INT },
+  { "float",   G_TYPE_FLOAT },
+  { "f",       G_TYPE_FLOAT },
+  { "double",  G_TYPE_DOUBLE },
+  { "d",       G_TYPE_DOUBLE },
+//{ "fourcc",  GST_TYPE_FOURCC },
+  { "boolean", G_TYPE_BOOLEAN },
+  { "bool",    G_TYPE_BOOLEAN },
+  { "b",       G_TYPE_BOOLEAN },
+  { "string",  G_TYPE_STRING },
+  { "str",     G_TYPE_STRING },
+  { "s",       G_TYPE_STRING }
+};
+
+static GType _gst_structure_from_abbr(const char *type_name)
+{
+  int i;
+
+  g_return_val_if_fail(type_name != NULL, G_TYPE_INVALID);
+
+  for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
+    if(strcmp(type_name,_gst_structure_abbrs[i].type_name)==0){
+      return _gst_structure_abbrs[i].type;
+    }
+  }
+
+  /* FIXME shouldn't be a special case */
+  if (strcmp (type_name,"fourcc") == 0 || strcmp (type_name, "4") == 0) {
+    return GST_TYPE_FOURCC;
+  }
+
+  return g_type_from_name (type_name);
+}
+
+static const char *_gst_structure_to_abbr(GType type)
+{
+  int i;
+
+  g_return_val_if_fail(type != G_TYPE_INVALID, NULL);
+
+  for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
+    if(type == _gst_structure_abbrs[i].type){
+      return _gst_structure_abbrs[i].type_name;
+    }
+  }
+
+  /* FIXME shouldn't be a special case */
+  if (type == GST_TYPE_FOURCC) {
+    return "fourcc";
+  }
+
+  return g_type_name(type);
+}
+
 /**
  * gst_structure_to_string:
  * @structure: a #GstStructure
@@ -886,19 +947,377 @@ gst_structure_to_string(const GstStructure *structure)
   g_string_append_printf(s, "\"%s\"", g_quark_to_string(structure->name));
   for(i=0;i<structure->fields->len;i++){
     GValue s_val = { 0 };
+    GType type;
 
     field = GST_STRUCTURE_FIELD(structure, i);
 
     g_value_init(&s_val, G_TYPE_STRING);
+    g_value_transform (&field->value, &s_val);
 
-    g_value_transform(&field->value, &s_val);
-    g_string_append_printf(s, ", %s:%s", g_quark_to_string(field->name),
-       g_value_get_string(&s_val));
-    g_value_unset(&s_val);
+    type = G_VALUE_TYPE (&field->value);
+
+    if (type == GST_TYPE_LIST) {
+      GPtrArray *ptr_array = g_value_peek_pointer (&field->value);
+      if (ptr_array->len > 0){
+        GValue *value = g_ptr_array_index (ptr_array, 0);
+
+       type = G_VALUE_TYPE (value);
+      } else {
+       type = G_TYPE_INT;
+      }
+    } else if (G_VALUE_TYPE(&field->value) == GST_TYPE_INT_RANGE) {
+      type = G_TYPE_INT;
+    } else if (G_VALUE_TYPE(&field->value) == GST_TYPE_DOUBLE_RANGE) {
+      type = G_TYPE_DOUBLE;
+    }
+    g_string_append_printf(s, ", %s:%s=%s", g_quark_to_string(field->name),
+       _gst_structure_to_abbr(type), g_value_get_string(&s_val));
+    g_value_unset (&s_val);
   }
   return g_string_free(s, FALSE);
 }
 
+/*
+ * r will still point to the string. if end == next, the string will not be 
+ * null-terminated. In all other cases it will be.
+ * end = pointer to char behind end of string, next = pointer to start of
+ * unread data.
+ * THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING 
+ */
+static gboolean
+_gst_structure_parse_string (gchar *r, gchar **end, gchar **next)
+{
+  gchar *w;
+  gchar c = '\0';
+
+  w = r;
+  if (*r == '\'' || *r == '\"') {
+    c = *r;
+    r++;
+  }
+
+  for (;;r++) {
+    if (*r == '\0') {
+      if (c) {
+        goto error;
+      } else {
+        goto found;
+      }
+    }
+
+    if (*r == '\\') {
+      r++;
+      if (*r == '\0')
+        goto error;
+      *w++ = *r;
+      continue;
+    }
+
+    if (*r == c) {
+      r++;
+      if (*r == '\0')
+        goto found;
+      break;
+    }
+
+    if (!c) {
+      if (g_ascii_isspace (*r))
+        break;
+      /* this needs to be escaped */
+      if (*r == ',' || *r == ')' || *r == ']' || *r == ':' ||
+          *r == ';' || *r == '(' || *r == '[')
+        break;
+    }
+    *w++ = *r;
+  }
+
+found:
+  while (g_ascii_isspace (*r)) r++;
+  if (w != r)
+    *w++ = '\0';
+  *end = w;
+  *next = r;
+  return TRUE;
+
+error:
+  return FALSE;
+}
+
+static gboolean
+_gst_structure_parse_value (gchar *s, gchar **after, GType type,
+    GValue *value)
+{
+  gboolean ret = FALSE;
+  gchar *val;
+  gchar *end;
+
+  if (type == G_TYPE_INVALID) return FALSE;
+
+  while (g_ascii_isspace (*s)) s++;
+
+  g_value_init(value, type);
+
+  val = s;
+  switch (type) {
+    case G_TYPE_INT:
+      {
+       int x;
+       x = strtol (val, &s, 0);
+       if (val != s) {
+         g_value_set_int (value, x);
+         ret = TRUE;
+       }
+      }
+      break;
+    case G_TYPE_FLOAT:
+      {
+       double x;
+       x = g_ascii_strtod (val, &s);
+       if (val != s) {
+         g_value_set_float (value, x);
+         ret = TRUE;
+       }
+      }
+      break;
+    case G_TYPE_DOUBLE:
+      {
+       double x;
+       x = g_ascii_strtod (val, &s);
+       if (val != s) {
+         g_value_set_double (value, x);
+         ret = TRUE;
+       }
+      }
+      break;
+    case G_TYPE_BOOLEAN:
+      {
+       int len;
+
+       ret = _gst_structure_parse_string (val, &end, &s);
+       len = end - val;
+       if (ret && len > 0) {
+         if (g_ascii_strncasecmp (val, "true", len) == 0 ||
+             g_ascii_strncasecmp (val, "yes", len) == 0 ||
+             g_ascii_strncasecmp (val, "t", len) == 0 ||
+             strncmp (val, "1", len)) {
+           g_value_set_boolean (value, TRUE);
+         } else if (g_ascii_strncasecmp (val, "false", len) == 0 ||
+             g_ascii_strncasecmp (val, "no", len) == 0 ||
+             g_ascii_strncasecmp (val, "f", len) == 0 ||
+             strncmp (val, "0", len)) {
+           g_value_set_boolean (value, FALSE);
+         } else {
+           ret = FALSE;
+         }
+       }
+      }
+      break;
+    case G_TYPE_STRING:
+      {
+       ret = _gst_structure_parse_string (val, &end, &s);
+       if (ret) {
+         g_value_set_string_take_ownership (value,
+             g_strndup(val, end - val));
+         ret = TRUE;
+       }
+      }
+      break;
+    default:
+      /* FIXME: make more general */
+      if (type == GST_TYPE_FOURCC) {
+       guint32 fourcc = 0;
+       if (g_ascii_isdigit (*s)) {
+         fourcc = strtoul (val, &s, 0);
+         if (val != s) {
+           ret = TRUE;
+         }
+       } else {
+         ret = _gst_structure_parse_string (val, &end, &s);
+g_print("end - val = %d\n", end - val);
+         if (end - val >= 4) {
+           fourcc = GST_MAKE_FOURCC(val[0], val[1], val[2], val[3]);
+           ret = TRUE;
+         }
+       }
+       gst_value_set_fourcc (value, fourcc);
+      } else {
+       g_critical("type %s not handled", g_type_name(type));
+      }
+      break;
+  }
+
+  *after = s;
+
+  return ret;
+}
+
+static gboolean
+_gst_structure_parse_range (gchar *s, gchar **after, GType type,
+    GValue *value)
+{
+  GValue value1 = { 0 };
+  GValue value2 = { 0 };
+  GType range_type;
+  gboolean ret;
+
+  if (type == G_TYPE_DOUBLE) {
+    range_type = GST_TYPE_DOUBLE_RANGE;
+  } else if (type == G_TYPE_INT) {
+    range_type = GST_TYPE_INT_RANGE;
+  } else {
+    return FALSE;
+  }
+
+g_print("%d \"%s\"\n", __LINE__, s);
+  if (*s != '[') return FALSE;
+  s++;
+
+g_print("%d \"%s\"\n", __LINE__, s);
+  ret = _gst_structure_parse_value(s, &s, type, &value1);
+  if (ret == FALSE) return FALSE;
+
+  while (g_ascii_isspace (*s)) s++;
+    
+g_print("%d \"%s\"\n", __LINE__, s);
+  if (*s != ',') return FALSE;
+  s++;
+
+  while (g_ascii_isspace (*s)) s++;
+
+g_print("%d \"%s\"\n", __LINE__, s);
+  ret = _gst_structure_parse_value(s, &s, type, &value2);
+  if (ret == FALSE) return FALSE;
+
+  while (g_ascii_isspace (*s)) s++;
+
+g_print("%d \"%s\"\n", __LINE__, s);
+  if (*s != ']') return FALSE;
+  s++;
+
+  g_value_init(value, range_type);
+  if (range_type == GST_TYPE_DOUBLE_RANGE) {
+    gst_value_set_double_range(value, g_value_get_double(&value1),
+       g_value_get_double(&value2));
+  } else {
+    gst_value_set_int_range(value, g_value_get_int(&value1),
+       g_value_get_int(&value2));
+  }
+
+  *after = s;
+  return TRUE;
+}
+
+static gboolean
+_gst_structure_parse_list (gchar *s, gchar **after, GType type, GValue *value)
+{
+  GValue list_value = { 0 };
+  gboolean ret;
+
+  g_value_init(value, GST_TYPE_LIST);
+
+  if (*s != '(') return FALSE;
+  s++;
+
+  while (g_ascii_isspace (*s)) s++;
+  if (*s == ')') {
+    s++;
+    *after = s;
+    return TRUE;
+  }
+
+  ret = _gst_structure_parse_value(s, &s, type, &list_value);
+  if (ret == FALSE) return FALSE;
+
+  while (g_ascii_isspace (*s)) s++;
+    
+  while (*s != ')') {
+    if (*s != ',') return FALSE;
+    s++;
+
+    while (g_ascii_isspace (*s)) s++;
+
+    memset (&list_value, 0, sizeof (list_value));
+    ret = _gst_structure_parse_value(s, &s, type, &list_value);
+    if (ret == FALSE) return FALSE;
+
+    while (g_ascii_isspace (*s)) s++;
+  }
+
+  s++;
+
+  *after = s;
+  return TRUE;
+}
+
+static gboolean
+_gst_structure_parse_field (gchar *str, gchar **after, GstStructureField *field)
+{
+  /* NAME[:TYPE]=VALUE */
+  gchar *name;
+  gchar *type_name;
+  gchar *s, *del;
+  gboolean have_type = FALSE;
+  GType type = G_TYPE_INVALID;
+  int ret;
+
+g_print("parsing: \"%s\"\n", str);
+  name = s = str;
+  while (g_ascii_isalnum (*s) || *s == '_' || *s == '-') s++;
+  del = s;
+  while (g_ascii_isspace (*s)) s++;
+  if (!(*s == '=' || *s == ':')) return FALSE;
+  if (*s == ':') have_type = TRUE;
+  s++;
+  while (g_ascii_isspace (*s)) s++;
+  *del = '\0';
+
+  field->name = g_quark_from_string (name);
+
+  if (have_type) {
+    while (g_ascii_isspace (*s)) s++;
+    type_name = s;
+    while (g_ascii_isalnum (*s) || *s == '_' || *s == '-') s++;
+    del = s;
+    while (g_ascii_isspace (*s)) s++;
+    if (*s != '=') return FALSE;
+    s++;
+    while (g_ascii_isspace (*s)) s++;
+    *del = '\0';
+  
+g_print("type name is \"%s\"\n",type_name);
+    type = _gst_structure_from_abbr(type_name);
+g_print("type n is \"%s\"\n",g_type_name(type));
+
+    if (type == G_TYPE_INVALID) return FALSE;
+
+  } else {
+    if (g_ascii_isdigit (*s) ||
+       ((*s == '-' || *s == '+') && g_ascii_isdigit (s[1]))) {
+      char *t = s;
+      while (g_ascii_isdigit (*t)) t++;
+      if (*t == '.'){
+        type = G_TYPE_DOUBLE;
+      } else {
+        type = G_TYPE_INT;
+      }
+    } else if (g_ascii_isalpha (*s) || *s == '"' || *s == '\'') {
+      type = G_TYPE_STRING;
+    }
+  }
+
+  if (*s == '[') {
+    ret = _gst_structure_parse_range (s, &s, type, &field->value);
+  } else if (*s == '(') {
+    ret = _gst_structure_parse_list (s, &s, type, &field->value);
+  } else {
+    ret = _gst_structure_parse_value(s, &s, type, &field->value);
+  }
+  
+  *after = s;
+
+  return ret;
+}
+
 /**
  * gst_structure_from_string:
  * @structure: a #GstStructure
@@ -908,15 +1327,54 @@ gst_structure_to_string(const GstStructure *structure)
  * Returns: a new #GstStructure
  */
 GstStructure *
-gst_structure_from_string (const gchar *string)
+gst_structure_from_string (const gchar *string, gchar **end)
 {
-  /* FIXME */
+  char *name;
+  char *copy;
+  char *w;
+  char *r;
+  char save;
+  GstStructure *structure;
+  GstStructureField field = { 0 };
+  gboolean res;
 
   g_return_val_if_fail(string != NULL, NULL);
 
-  g_assert_not_reached();
+  copy = g_strdup(string);
+  r = copy;
 
-  return NULL;
+  name = r;
+  res = _gst_structure_parse_string (r, &w, &r);
+  if (!res) return NULL;
+  
+  while (g_ascii_isspace(*r)) r++;
+  if(*r != 0 && *r != ';' && *r != ',') return NULL;
+
+  save = *w;
+  *w = 0;
+  structure = gst_structure_empty_new(name);
+  *w = save;
+
+  while (*r && (*r != ';')){
+    if(*r != ',') {
+      return NULL;
+    }
+    r++;
+    while (*r && g_ascii_isspace(*r)) r++;
+
+    memset(&field,0,sizeof(field));
+    res = _gst_structure_parse_field (r, &r, &field);
+g_print("returned %d \"%s\"\n", res, r);
+    if (!res) {
+      gst_structure_free (structure);
+      return NULL;
+    }
+    gst_structure_set_field(structure, &field);
+    while (*r && g_ascii_isspace(*r)) r++;
+  }
+
+  if (end) *end = (char *)string + (r - copy);
+  return structure;
 }
 
 static void
index 4ea6b10..15967c8 100644 (file)
@@ -59,7 +59,7 @@ GstStructure *gst_structure_new_valist(const gchar *name,
 GstStructure *gst_structure_copy(GstStructure *structure);
 void gst_structure_free(GstStructure *structure);
 
-const gchar *gst_structure_get_name(GstStructure *structure);
+G_CONST_RETURN gchar *gst_structure_get_name(GstStructure *structure);
 void gst_structure_set_name(GstStructure *structure, const gchar *name);
 void gst_structure_set_field_copy (GstStructure *structure,
     const GstStructureField *field);
@@ -73,7 +73,8 @@ void gst_structure_set_value(GstStructure *structure, const gchar *field,
 void gst_structure_set(GstStructure *structure, const gchar *field, ...);
 void gst_structure_set_valist(GstStructure *structure, const gchar *field,
     va_list varargs);
-const GValue *gst_structure_get_value(const GstStructure *structure, const gchar *field);
+G_CONST_RETURN GValue *gst_structure_get_value(const GstStructure *structure,
+    const gchar *field);
 GstStructureField *gst_structure_get_field(const GstStructure *structure,
         const gchar *fieldname);
 GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
@@ -100,11 +101,11 @@ gboolean gst_structure_get_fourcc(const GstStructure *structure, const gchar *fi
     guint32 *value);
 gboolean gst_structure_get_double(const GstStructure *structure, const gchar *field,
     gdouble *value);
-const gchar *gst_structure_get_string(const GstStructure *structure,
+G_CONST_RETURN gchar *gst_structure_get_string(const GstStructure *structure,
     const gchar *field);
 
 gchar * gst_structure_to_string(const GstStructure *structure);
-GstStructure * gst_structure_from_string (const gchar *string);
+GstStructure * gst_structure_from_string (const gchar *string, gchar **end);
 
 
 G_END_DECLS
index e2761e0..558939b 100644 (file)
@@ -245,7 +245,7 @@ gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
   g_return_if_fail (name != NULL);
   g_return_if_fail (nick != NULL);
   g_return_if_fail (blurb != NULL);
-  g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
+  g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
   
   key = g_quark_from_string (name);
   info = gst_tag_lookup (key);
@@ -547,7 +547,7 @@ gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
   value = gst_structure_get_value ((GstStructure *) list, tag);
   if (value == NULL)
     return 0;
-  if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
+  if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
     return 1;
 
   return gst_value_list_get_size (value);
@@ -761,7 +761,7 @@ gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
   src = gst_structure_get_value ((GstStructure *) list, tag);
   if (!src) return FALSE;
   
-  if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {    
+  if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {    
     GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
     /* must be there or lists aren't allowed */
     g_assert (info->merge_func);
index e2761e0..558939b 100644 (file)
@@ -245,7 +245,7 @@ gst_tag_register (gchar *name, GType type, gchar *nick, gchar *blurb,
   g_return_if_fail (name != NULL);
   g_return_if_fail (nick != NULL);
   g_return_if_fail (blurb != NULL);
-  g_return_if_fail (type != 0 && type != GST_VALUE_TYPE_LIST);
+  g_return_if_fail (type != 0 && type != GST_TYPE_LIST);
   
   key = g_quark_from_string (name);
   info = gst_tag_lookup (key);
@@ -547,7 +547,7 @@ gst_tag_list_get_tag_size (const GstTagList *list, const gchar *tag)
   value = gst_structure_get_value ((GstStructure *) list, tag);
   if (value == NULL)
     return 0;
-  if (G_VALUE_TYPE (value) != GST_VALUE_TYPE_LIST)
+  if (G_VALUE_TYPE (value) != GST_TYPE_LIST)
     return 1;
 
   return gst_value_list_get_size (value);
@@ -761,7 +761,7 @@ gst_tag_list_copy_value (GValue *dest, const GstTagList *list, const gchar *tag)
   src = gst_structure_get_value ((GstStructure *) list, tag);
   if (!src) return FALSE;
   
-  if (G_VALUE_TYPE (src) == GST_VALUE_TYPE_LIST) {    
+  if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {    
     GstTagInfo *info = gst_tag_lookup (g_quark_from_string (tag));
     /* must be there or lists aren't allowed */
     g_assert (info->merge_func);
index 79586e8..c13cc80 100644 (file)
@@ -48,7 +48,7 @@ struct _GstValueIntersectInfo {
 GType gst_type_fourcc;
 GType gst_type_int_range;
 GType gst_type_double_range;
-GType gst_value_type_list;
+GType gst_type_list;
 
 GArray *gst_value_compare_funcs;
 GArray *gst_value_union_funcs;
@@ -169,6 +169,42 @@ gst_value_list_get_value (const GValue *value, guint index)
   return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer, GValue, index);
 }
 
+/* special case function for any union */
+static gboolean
+gst_value_union_lists (GValue *dest, const GValue *value1, const GValue *value2)
+{
+  guint i, value1_length, value2_length;
+  GArray *array;
+  
+  value1_length = (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
+  value2_length = (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
+  g_value_init (dest, GST_TYPE_LIST);
+  array = (GArray *) dest->data[0].v_pointer;
+  g_array_set_size (array, value1_length + value2_length);
+  
+  if (GST_VALUE_HOLDS_LIST (value1)) {
+    for (i = 0; i < value1_length; i++) {
+      g_value_init (&g_array_index(array, GValue, i), G_VALUE_TYPE (gst_value_list_get_value (value1, i)));
+      g_value_copy (gst_value_list_get_value (value1, i), &g_array_index(array, GValue, i));
+    }
+  } else {
+    g_value_init (&g_array_index(array, GValue, 0), G_VALUE_TYPE (value1));
+    g_value_copy (value1, &g_array_index(array, GValue, 0));
+  }
+  
+  if (GST_VALUE_HOLDS_LIST (value2)) {
+    for (i = 0; i < value2_length; i++) {
+      g_value_init (&g_array_index(array, GValue, i + value1_length), G_VALUE_TYPE (gst_value_list_get_value (value2, i)));
+      g_value_copy (gst_value_list_get_value (value2, i), &g_array_index(array, GValue, i + value1_length));
+    }
+  } else {
+    g_value_init (&g_array_index(array, GValue, value1_length), G_VALUE_TYPE (value2));
+    g_value_copy (value2, &g_array_index(array, GValue, value1_length));
+  }
+
+  return TRUE;
+}
+
 /**
  * gst_value_list_concat:
  * @dest: an uninitialized #GValue to take the result
@@ -176,7 +212,7 @@ gst_value_list_get_value (const GValue *value, guint index)
  * @value2: second value to put into the union
  *
  * Concatenates copies of value1 and value2 into a list. dest will be 
- * initialized to the type GST_VALUE_TYPE_LIST.
+ * initialized to the type GST_TYPE_LIST.
  */
 void
 gst_value_list_concat (GValue *dest, const GValue *value1, const GValue *value2)
@@ -191,7 +227,7 @@ gst_value_list_concat (GValue *dest, const GValue *value1, const GValue *value2)
   
   value1_length = (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
   value2_length = (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
-  g_value_init (dest, GST_VALUE_TYPE_LIST);
+  g_value_init (dest, GST_TYPE_LIST);
   array = (GArray *) dest->data[0].v_pointer;
   g_array_set_size (array, value1_length + value2_length);
   
@@ -402,14 +438,43 @@ gst_value_get_double_range_max (const GValue *value)
   return value->data[1].v_double;
 }
 
+/* GstCaps */
+
+#if 0
+void
+gst_value_set_caps (GValue *value, const GstCaps2 *caps)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_CAPS (value));
+
+  value->data[0].v_pointer = gst_caps2_copy (caps);
+}
+
+const GstCaps2 *
+gst_value_get_caps (const GValue *value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_CAPS (value), 0);
+
+  return value->data[0].v_pointer;
+}
+#endif
+
 /* fourcc */
 
 static void
 gst_value_transform_fourcc_string (const GValue *src_value,
     GValue *dest_value)
 {
-  dest_value->data[0].v_pointer = g_strdup_printf(GST_FOURCC_FORMAT,
-      GST_FOURCC_ARGS(src_value->data[0].v_long));
+  guint32 fourcc = src_value->data[0].v_long;
+
+  if (g_ascii_isprint ((fourcc>>0) & 0xff) &&
+      g_ascii_isprint ((fourcc>>8) & 0xff) &&
+      g_ascii_isprint ((fourcc>>16) & 0xff) &&
+      g_ascii_isprint ((fourcc>>24) & 0xff)){
+    dest_value->data[0].v_pointer = g_strdup_printf(
+       "\"" GST_FOURCC_FORMAT "\"", GST_FOURCC_ARGS(fourcc));
+  } else {
+    dest_value->data[0].v_pointer = g_strdup_printf("0x%08x", fourcc);
+  }
 }
 
 static void
@@ -420,6 +485,42 @@ gst_value_transform_int_range_string (const GValue *src_value,
       (int)src_value->data[0].v_long, (int)src_value->data[1].v_long);
 }
 
+static void
+gst_value_transform_double_range_string (const GValue *src_value,
+    GValue *dest_value)
+{
+  dest_value->data[0].v_pointer = g_strdup_printf("[%g,%g]",
+      src_value->data[0].v_double, src_value->data[1].v_double);
+}
+
+static void
+gst_value_transform_list_string (const GValue *src_value,
+    GValue *dest_value)
+{
+  GValue *list_value;
+  GArray *array;
+  GString *s;
+  int i;
+  char *list_s;
+
+  array = src_value->data[0].v_pointer;
+
+  s = g_string_new("(");
+  for(i=0;i<array->len;i++){
+    list_value = &g_array_index(array, GValue, i);
+
+    if (i != 0) {
+      g_string_append (s, ", ");
+    }
+    list_s = g_strdup_value_contents (list_value);
+    g_string_append (s, list_s);
+    g_free (list_s);
+  }
+  g_string_append (s, ")");
+
+  dest_value->data[0].v_pointer = g_string_free (s, FALSE);
+}
+
 /* comparison functions */
 
 static int
@@ -445,6 +546,18 @@ gst_value_compare_double (const GValue *value1, const GValue *value2)
 }
 
 static int
+gst_value_compare_float (const GValue *value1, const GValue *value2)
+{
+  if (value1->data[0].v_float > value2->data[0].v_float)
+    return GST_VALUE_GREATER_THAN;
+  if (value1->data[0].v_float < value2->data[0].v_float)
+    return GST_VALUE_LESS_THAN;
+  if (value1->data[0].v_float == value2->data[0].v_float)
+    return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
+}
+
+static int
 gst_value_compare_string (const GValue *value1, const GValue *value2)
 {
   int x = strcmp(value1->data[0].v_pointer, value2->data[0].v_pointer);
@@ -456,10 +569,53 @@ gst_value_compare_string (const GValue *value1, const GValue *value2)
 static int
 gst_value_compare_fourcc (const GValue *value1, const GValue *value2)
 {
+g_print("comparing fourccs\n");
   if (value2->data[0].v_int == value1->data[0].v_int) return GST_VALUE_EQUAL;
   return GST_VALUE_UNORDERED;
 }
 
+static int
+gst_value_compare_int_range (const GValue *value1, const GValue *value2)
+{
+  if (value2->data[0].v_int == value1->data[0].v_int &&
+      value2->data[0].v_int == value1->data[0].v_int) return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
+}
+
+static int
+gst_value_compare_double_range (const GValue *value1, const GValue *value2)
+{
+  if (value2->data[0].v_double == value1->data[0].v_double &&
+      value2->data[0].v_double == value1->data[0].v_double)
+    return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
+}
+
+static int
+gst_value_compare_list (const GValue *value1, const GValue *value2)
+{
+  int i,j;
+  GArray *array1 = value1->data[0].v_pointer;
+  GArray *array2 = value2->data[0].v_pointer;
+  GValue *v1;
+  GValue *v2;
+
+  if (array1->len != array2->len) return GST_VALUE_UNORDERED;
+
+  for(i=0;i<array1->len;i++){
+    v1 = &g_array_index (array1, GValue, i);
+    for(j=0;j<array1->len;j++){
+      v2 = &g_array_index (array2, GValue, j);
+      if (gst_value_compare(v1, v2) == GST_VALUE_EQUAL) break;
+    }
+    if (j==array1->len) {
+      return GST_VALUE_UNORDERED;
+    }
+  }
+
+  return GST_VALUE_EQUAL;
+}
+
 gboolean
 gst_value_can_compare (const GValue *value1, const GValue *value2)
 {
@@ -482,7 +638,8 @@ gst_value_compare (const GValue *value1, const GValue *value2)
   GstValueCompareInfo *compare_info;
   int i;
 
-  g_return_val_if_fail(G_VALUE_TYPE(value1) == G_VALUE_TYPE(value2), 0);
+  if (G_VALUE_TYPE(value1) != G_VALUE_TYPE(value2)) return GST_VALUE_UNORDERED;
+
   for(i=0;i<gst_value_compare_funcs->len;i++){
     compare_info = &g_array_index(gst_value_compare_funcs,
        GstValueCompareInfo, i);
@@ -491,7 +648,8 @@ gst_value_compare (const GValue *value1, const GValue *value2)
     return compare_info->func(value1, value2);
   }
 
-  g_return_val_if_fail(0 /* type not found */, GST_VALUE_UNORDERED);
+  g_critical("unable to compare values of type %s\n",
+      g_type_name (G_VALUE_TYPE (value1)));
   return GST_VALUE_UNORDERED;
 }
 
@@ -536,8 +694,7 @@ gst_value_union (GValue *dest, const GValue *value1, const GValue *value2)
       return union_info->func(dest, value1, value2);
     }
   }
-  gst_value_list_concat (dest, value1, value2);
-  return TRUE;
+  return gst_value_union_lists (dest, value1, value2);
 }
 
 void
@@ -618,23 +775,31 @@ gst_value_intersect (GValue *dest, const GValue *value1, const GValue *value2)
 {
   GstValueIntersectInfo *intersect_info;
   int i;
+  int ret = FALSE;
 
+g_print("intersecting %s=%s and %s=%s\n",
+    g_type_name(G_VALUE_TYPE(value1)), g_strdup_value_contents(value1),
+    g_type_name(G_VALUE_TYPE(value2)), g_strdup_value_contents(value2));
   for(i=0;i<gst_value_intersect_funcs->len;i++){
     intersect_info = &g_array_index(gst_value_intersect_funcs,
        GstValueIntersectInfo, i);
     if(intersect_info->type1 == G_VALUE_TYPE(value1) &&
        intersect_info->type2 == G_VALUE_TYPE(value2)) {
-      return intersect_info->func(dest, value1, value2);
+      ret = intersect_info->func(dest, value1, value2);
+g_print("result is %d %s\n", ret, ret?g_strdup_value_contents(dest):"none1");
+      return ret;
     }
   }
 
   if(gst_value_compare(value1, value2) == GST_VALUE_EQUAL){
     g_value_init(dest, G_VALUE_TYPE(value1));
     g_value_copy(value1, dest);
-    return TRUE;
+    ret = TRUE;
+g_print("result is %d %s\n", ret, ret?g_strdup_value_contents(dest):"none2");
   }
 
-  return FALSE;
+g_print("result is %d %s\n", ret, ret?g_strdup_value_contents(dest):"none3");
+  return ret;
 }
 
 void
@@ -724,21 +889,29 @@ _gst_value_initialize (void)
       gst_value_lcopy_list
     };
     info.value_table = &value_table;
-    gst_value_type_list = g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
+    gst_type_list = g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
   }
 
   g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
       gst_value_transform_fourcc_string);
   g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
       gst_value_transform_int_range_string);
+  g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
+      gst_value_transform_double_range_string);
+  g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
+      gst_value_transform_list_string);
 
   gst_value_compare_funcs = g_array_new(FALSE, FALSE,
       sizeof(GstValueCompareInfo));
 
   gst_value_register_compare_func (G_TYPE_INT, gst_value_compare_int);
+  gst_value_register_compare_func (G_TYPE_FLOAT, gst_value_compare_float);
   gst_value_register_compare_func (G_TYPE_DOUBLE, gst_value_compare_double);
   gst_value_register_compare_func (G_TYPE_STRING, gst_value_compare_string);
   gst_value_register_compare_func (GST_TYPE_FOURCC, gst_value_compare_fourcc);
+  gst_value_register_compare_func (GST_TYPE_INT_RANGE, gst_value_compare_int_range);
+  gst_value_register_compare_func (GST_TYPE_DOUBLE_RANGE, gst_value_compare_double_range);
+  gst_value_register_compare_func (GST_TYPE_LIST, gst_value_compare_list);
 
   gst_value_union_funcs = g_array_new(FALSE, FALSE,
       sizeof(GstValueUnionInfo));
index 0fa57ca..a6cc2a4 100644 (file)
@@ -21,6 +21,7 @@
 #define __GST_VALUE_H__
 
 #include <gst/gstconfig.h>
+#include <gst/gstcaps2.h>
 
 G_BEGIN_DECLS
 
@@ -41,16 +42,16 @@ typedef int (* GstValueIntersectFunc) (GValue *dest, const GValue *value1,
         ((gchar) (((fourcc)>>16)&0xff)), \
         ((gchar) (((fourcc)>>24)&0xff))
 
+#define GST_VALUE_HOLDS_FOURCC(x)       (G_VALUE_HOLDS(x, gst_type_fourcc))
+#define GST_VALUE_HOLDS_INT_RANGE(x)    (G_VALUE_HOLDS(x, gst_type_int_range))
+#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_HOLDS(x, gst_type_double_range))
+#define GST_VALUE_HOLDS_LIST(x)         (G_VALUE_HOLDS(x, gst_type_list))
+#define GST_VALUE_HOLDS_CAPS(x)         TRUE /* FIXME */
+
 #define GST_TYPE_FOURCC gst_type_fourcc
 #define GST_TYPE_INT_RANGE gst_type_int_range
 #define GST_TYPE_DOUBLE_RANGE gst_type_double_range
-#define GST_VALUE_TYPE_LIST gst_value_type_list
-
-#define GST_VALUE_HOLDS_FOURCC(x) (G_VALUE_TYPE(x) == gst_type_fourcc)
-#define GST_VALUE_HOLDS_INT_RANGE(x) (G_VALUE_TYPE(x) == gst_type_int_range)
-#define GST_VALUE_HOLDS_DOUBLE_RANGE(x) (G_VALUE_TYPE(x) == gst_type_double_range)
-#define GST_VALUE_HOLDS_LIST(x) (G_VALUE_TYPE(x) == GST_VALUE_TYPE_LIST)
-#define GST_VALUE_HOLDS_CAPS(x) TRUE /* FIXME */
+#define GST_TYPE_LIST gst_type_list
 
 #define GST_VALUE_LESS_THAN (-1)
 #define GST_VALUE_EQUAL 0
@@ -60,7 +61,7 @@ typedef int (* GstValueIntersectFunc) (GValue *dest, const GValue *value1,
 extern GType gst_type_fourcc;
 extern GType gst_type_int_range;
 extern GType gst_type_double_range;
-extern GType gst_value_type_list;
+extern GType gst_type_list;
 
 void gst_value_set_fourcc (GValue *value, guint32 fourcc);
 guint32 gst_value_get_fourcc (const GValue *value);
@@ -73,6 +74,9 @@ void gst_value_set_double_range (GValue *value, double start, double end);
 double gst_value_get_double_range_min (const GValue *value);
 double gst_value_get_double_range_max (const GValue *value);
 
+const GstCaps2 *gst_value_get_caps (const GValue *value);
+void gst_value_set_caps (GValue *calue, const GstCaps2 *caps);
+
 void gst_value_list_prepend_value (GValue *value, const GValue *prepend_value);
 void gst_value_list_append_value (GValue *value, const GValue *prepend_value);
 guint gst_value_list_get_size (const GValue *value);