separated the properties from the capabilities as we might use the properties for...
authorWim Taymans <wim.taymans@gmail.com>
Thu, 7 Dec 2000 18:37:56 +0000 (18:37 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 7 Dec 2000 18:37:56 +0000 (18:37 +0000)
Original commit message from CVS:
separated the properties from the capabilities as we might use the properties
for metadata too.

gst/Makefile.am
gst/gst.h
gst/gstcaps.c
gst/gstcaps.h
gst/gstcapsprivate.h [deleted file]
gst/gstprops.c [new file with mode: 0644]
gst/gstprops.h [new file with mode: 0644]
gst/gstpropsprivate.h [new file with mode: 0644]

index 386f5520590395ff2fe0f036fbc633591f294720..ecbab0ea63322f6fe9d1fbbd0295b7eaa9f7e951 100644 (file)
@@ -38,6 +38,7 @@ libgst_la_SOURCES =   \
        gstconnection.c \
        gsttype.c       \
        gstcaps.c       \
+       gstprops.c      \
        gstplugin.c     \
        gstutils.c      \
        gsttrace.c      \
@@ -67,6 +68,7 @@ libgstinclude_HEADERS =       \
        gstconnection.h \
        gsttype.h       \
        gstcaps.h       \
+       gstprops.h      \
        gstplugin.h     \
        gstutils.h      \
        gsttrace.h      \
index 709eebc762c6272db3c79f1963d13918475d803e..c005dcf860e6ada6c897919e640621f2f22a0db6 100644 (file)
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -49,6 +49,7 @@
 #include <gst/gstconnection.h>
 #include <gst/gsttype.h>
 #include <gst/gstcaps.h>
+#include <gst/gstprops.h>
 #include <gst/gstplugin.h>
 #include <gst/gstutils.h>
 #include <gst/gsttrace.h>
index 58a0bc834a1ef3a3df1fbcb65097232b92718190..2e8a4e991109f78c834707c579dfd3f6b9213655 100644 (file)
 //#define DEBUG_ENABLED
 
 #include <stdarg.h>
-#include <gst/gstcapsprivate.h>
-
-static gboolean        gst_caps_entry_check_compatibility      (GstCapsEntry *entry1, GstCapsEntry *entry2);
-       
+#include <gst/gst.h>
 
 void 
 _gst_caps_initialize (void) 
 {
 }
-
-static GstCapsEntry *
-gst_caps_create_entry (GstCapsFactory factory, gint *skipped)
-{
-  GstCapsFactoryEntry tag;
-  GstCapsEntry *entry;
-  guint i=0;
-
-  entry = g_new0 (GstCapsEntry, 1);
-
-  tag = factory[i++];
-  switch (GPOINTER_TO_INT (tag)) {
-    case GST_CAPS_INT_ID:
-      entry->capstype = GST_CAPS_INT_ID_NUM;
-      entry->data.int_data = GPOINTER_TO_INT (factory[i++]);
-      break;
-    case GST_CAPS_INT_RANGE_ID:
-      entry->capstype = GST_CAPS_INT_RANGE_ID_NUM;
-      entry->data.int_range_data.min = GPOINTER_TO_INT (factory[i++]);
-      entry->data.int_range_data.max = GPOINTER_TO_INT (factory[i++]);
-      break;
-    case GST_CAPS_FOURCC_ID:
-      entry->capstype = GST_CAPS_FOURCC_ID_NUM;
-      entry->data.fourcc_data = GPOINTER_TO_INT (factory[i++]);
-      break;
-    case GST_CAPS_LIST_ID:
-      g_print("gstcaps: list not allowed in list\n");
-      break;
-    case GST_CAPS_BOOL_ID:
-      entry->capstype = GST_CAPS_BOOL_ID_NUM;
-      entry->data.bool_data = GPOINTER_TO_INT (factory[i++]);
-      break;
-    default:
-      g_print("gstcaps: unknown caps id found\n");
-      g_free (entry);
-      entry = NULL;
-      break;
-  }
-
-  *skipped = i;
-
-  return entry;
-}
-
-
-static gint 
-caps_compare_func (gconstpointer a,
-                  gconstpointer b) 
-{
-  GstCapsEntry *entry1 = (GstCapsEntry *)a;
-  GstCapsEntry *entry2 = (GstCapsEntry *)b;
-
-  return (entry1->propid - entry2->propid);
-}
-
 /**
  * gst_caps_register:
  * @factory: the factory to register
@@ -99,7 +41,6 @@ gst_caps_register (GstCapsFactory factory)
   gint i = 0;
   guint16 typeid;
   GstCaps *caps;
-  gint skipped;
   
   g_return_val_if_fail (factory != NULL, NULL);
 
@@ -122,110 +63,11 @@ gst_caps_register (GstCapsFactory factory)
   g_return_val_if_fail (caps != NULL, NULL);
 
   caps->id = typeid;
-  caps->properties = NULL;
-
-  tag = factory[i++];
-  
-  while (tag) {
-    GQuark quark;
-    GstCapsEntry *entry;
-    
-    quark = g_quark_from_string ((gchar *)tag);
-
-    tag = factory[i];
-    switch (GPOINTER_TO_INT (tag)) {
-      case GST_CAPS_LIST_ID: 
-      {
-        GstCapsEntry *list_entry;
-
-        entry = g_new0 (GstCapsEntry, 1);
-       entry->propid = quark;
-       entry->capstype = GST_CAPS_LIST_ID_NUM;
-       entry->data.list_data.entries = NULL;
-
-       i++; // skip list tag
-        tag = factory[i];
-       while (tag) {
-         list_entry = gst_caps_create_entry (&factory[i], &skipped);
-         list_entry->propid = quark;
-         i += skipped;
-          tag = factory[i];
-         entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, list_entry);
-       }
-       entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
-       i++; //skip NULL (list end)
-       break;
-      }
-      default:
-      {
-       entry = gst_caps_create_entry (&factory[i], &skipped);
-       entry->propid = quark;
-       i += skipped;
-       break;
-      }
-    }
-    caps->properties = g_slist_insert_sorted (caps->properties, entry, caps_compare_func);
-     
-    tag = factory[i++];
-  }
+  caps->properties = gst_props_register (&factory[i]);
 
   return caps;
 }
 
-static void
-gst_caps_dump_entry_func (GstCapsEntry *entry)
-{
-  switch (entry->capstype) {
-    case GST_CAPS_INT_ID_NUM: 
-      g_print("gstcaps:    int %d\n", entry->data.int_data);
-      break;
-    case GST_CAPS_INT_RANGE_ID_NUM: 
-      g_print("gstcaps:    int range %d %d\n", 
-                     entry->data.int_range_data.min,
-                     entry->data.int_range_data.max);
-      break;
-    case GST_CAPS_FOURCC_ID_NUM: 
-      g_print("gstcaps:    fourcc 0x%08x (%4.4s)\n", entry->data.fourcc_data, (gchar *)&entry->data.fourcc_data);
-      break;
-    case GST_CAPS_BOOL_ID_NUM: 
-      g_print("gstcaps:    boolean %d\n", entry->data.bool_data);
-      break;
-    default:
-      g_print("gstcaps:    **illegal entry**\n");
-      break;
-  }
-}
-
-static void
-gst_caps_dump_list_func (gpointer entry,
-                        gpointer list_entry)
-{
-  gst_caps_dump_entry_func ((GstCapsEntry *)entry);
-}
-
-static void
-gst_caps_dump_func (gpointer data,
-                   gpointer user_data)
-{
-  GstCapsEntry *entry;
-
-  entry = (GstCapsEntry *)data;
-
-  g_print("gstcaps:  property type \"%s\"\n", g_quark_to_string (entry->propid));
-
-  switch (entry->capstype) {
-    case GST_CAPS_LIST_ID_NUM: 
-    {
-      g_print("gstcaps:   list type (\n");
-      g_list_foreach (entry->data.list_data.entries, gst_caps_dump_list_func, entry);
-      g_print("gstcaps:   )\n");
-      break;
-    }
-    default:
-      gst_caps_dump_entry_func (entry);
-      break;
-  }
-}
 
 /**
  * gst_caps_dump:
@@ -240,105 +82,11 @@ gst_caps_dump (GstCaps *caps)
 
   g_print("gstcaps: {\ngstcaps:  mime type \"%d\"\n", caps->id);
 
-  g_slist_foreach (caps->properties, gst_caps_dump_func, caps);
+  gst_props_dump (caps->properties);
+
   g_print("gstcaps: }\n");
 }
        
-/* entry2 is always a list, entry1 never is */
-static gboolean
-gst_caps_entry_check_list_compatibility (GstCapsEntry *entry1, GstCapsEntry *entry2)
-{
-  GList *entrylist = entry2->data.list_data.entries;
-  gboolean found = FALSE;
-
-  while (entrylist && !found) {
-    GstCapsEntry *entry = (GstCapsEntry *) entrylist->data;
-
-    found |= gst_caps_entry_check_compatibility (entry1, entry);
-
-    entrylist = g_list_next (entrylist);
-  }
-
-  return found;
-}
-
-static gboolean
-gst_caps_entry_check_compatibility (GstCapsEntry *entry1, GstCapsEntry *entry2)
-{
-  DEBUG ("compare: %s %s\n", g_quark_to_string (entry1->propid),
-                            g_quark_to_string (entry2->propid));
-  switch (entry1->capstype) {
-    case GST_CAPS_LIST_ID_NUM:
-    {
-      GList *entrylist = entry1->data.list_data.entries;
-      gboolean valid = TRUE;    // innocent until proven guilty
-
-      while (entrylist && valid) {
-       GstCapsEntry *entry = (GstCapsEntry *) entrylist->data;
-
-       valid &= gst_caps_entry_check_compatibility (entry, entry2);
-       
-       entrylist = g_list_next (entrylist);
-      }
-      
-      return valid;
-    }
-    case GST_CAPS_INT_RANGE_ID_NUM:
-      switch (entry2->capstype) {
-       // a - b   <--->   a - c
-        case GST_CAPS_INT_RANGE_ID_NUM:
-         return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
-                 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
-        case GST_CAPS_LIST_ID_NUM:
-         return gst_caps_entry_check_list_compatibility (entry1, entry2);
-        default:
-          return FALSE;
-      }
-      break;
-    case GST_CAPS_FOURCC_ID_NUM:
-      switch (entry2->capstype) {
-       // b   <--->   a
-        case GST_CAPS_FOURCC_ID_NUM:
-         return (entry2->data.fourcc_data == entry1->data.fourcc_data);
-       // b   <--->   a,b,c
-        case GST_CAPS_LIST_ID_NUM:
-         return gst_caps_entry_check_list_compatibility (entry1, entry2);
-        default:
-          return FALSE;
-      }
-      break;
-    case GST_CAPS_INT_ID_NUM:
-      switch (entry2->capstype) {
-       // b   <--->   a - d
-        case GST_CAPS_INT_RANGE_ID_NUM:
-         return (entry2->data.int_range_data.min <= entry1->data.int_data &&
-                 entry2->data.int_range_data.max >= entry1->data.int_data);
-       // b   <--->   a
-        case GST_CAPS_INT_ID_NUM:
-         return (entry2->data.int_data == entry1->data.int_data);
-       // b   <--->   a,b,c
-        case GST_CAPS_LIST_ID_NUM:
-         return gst_caps_entry_check_list_compatibility (entry1, entry2);
-        default:
-          return FALSE;
-      }
-      break;
-    case GST_CAPS_BOOL_ID_NUM:
-      switch (entry2->capstype) {
-       // t   <--->   t
-        case GST_CAPS_BOOL_ID_NUM:
-          return (entry2->data.bool_data == entry1->data.bool_data);
-        case GST_CAPS_LIST_ID_NUM:
-         return gst_caps_entry_check_list_compatibility (entry1, entry2);
-        default:
-          return FALSE;
-      }
-    default:
-      break;
-  }
-
-  return FALSE;
-}
 
 /**
  * gst_caps_check_compatibility:
@@ -352,81 +100,12 @@ gst_caps_entry_check_compatibility (GstCapsEntry *entry1, GstCapsEntry *entry2)
 gboolean
 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
 {
-  GSList *sourcelist;
-  GSList *sinklist;
-  gint missing = 0;
-  gint more = 0;
-  gboolean compatible = TRUE;
-
   g_return_val_if_fail (fromcaps != NULL, FALSE);
   g_return_val_if_fail (tocaps != NULL, FALSE);
        
   if (fromcaps->id != tocaps->id)
     return FALSE;
 
-  sourcelist = fromcaps->properties;
-  sinklist   = tocaps->properties;
-
-  while (sourcelist && sinklist && compatible) {
-    GstCapsEntry *entry1;
-    GstCapsEntry *entry2;
-
-    entry1 = (GstCapsEntry *)sourcelist->data;
-    entry2 = (GstCapsEntry *)sinklist->data;
-
-    while (entry1->propid < entry2->propid) {
-      DEBUG ("source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
-      more++;
-      sourcelist = g_slist_next (sourcelist);
-      if (sourcelist) entry1 = (GstCapsEntry *)sourcelist->data;
-      else goto end;
-    }
-    while (entry1->propid > entry2->propid) {
-      DEBUG ("source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
-      missing++;
-      sinklist = g_slist_next (sinklist);
-      if (sinklist) entry2 = (GstCapsEntry *)sinklist->data;
-      else goto end;
-    }
-
-    compatible &= gst_caps_entry_check_compatibility (entry1, entry2);
-
-    sourcelist = g_slist_next (sourcelist);
-    sinklist = g_slist_next (sinklist);
-  }
-end:
-
-  if (missing)
-    return FALSE;
-
-  return compatible;
+  return gst_props_check_compatibility (fromcaps->properties, tocaps->properties);
 }
 
-/**
- * gst_caps_register_va:
- * @factory: the factories to register
- *
- * Register the given factories. 
- *
- * Returns: A list of the registered factories
- */
-GList *
-gst_caps_register_va (GstCapsFactory factory, ...)
-{
-  va_list var_args;
-  GstCapsFactoryEntry *current_factory;
-
-  va_start (var_args, factory);
-
-  current_factory = (GstCapsFactoryEntry *) factory;
-  
-  while (current_factory) {
-    gst_caps_register (current_factory);
-    
-    current_factory = va_arg (var_args, GstCapsFactoryEntry *);
-  }
-  
-  va_end(var_args);
-
-  return NULL;
-}
index 20c4b6de5917f034a21f3326ac6bc90b8d9c8d95..b499105f1284efc91d4a075de472d5b90273a0a2 100644 (file)
 #ifndef __GST_CAPS_H__
 #define __GST_CAPS_H__
 
-#include <gst/gst.h>
+#include <glib.h>
+#include <gst/gstprops.h>
 
 typedef struct _GstCaps GstCaps;
 typedef gpointer GstCapsFactoryEntry;
 typedef GstCapsFactoryEntry GstCapsFactory[];
 typedef GstCapsFactory *GstCapsListFactory[];
 
-typedef enum {
-   GST_CAPS_END_ID_NUM = 0,
-   GST_CAPS_LIST_ID_NUM,
-   GST_CAPS_INT_ID_NUM,
-   GST_CAPS_INT_RANGE_ID_NUM,
-   GST_CAPS_FOURCC_ID_NUM,
-   GST_CAPS_BOOL_ID_NUM,
-} GstCapsId;
-
-#define GST_CAPS_LIST_ID GINT_TO_POINTER(GST_CAPS_LIST_ID_NUM)
-#define GST_CAPS_INT_ID GINT_TO_POINTER(GST_CAPS_INT_ID_NUM)
-#define GST_CAPS_INT_RANGE_ID GINT_TO_POINTER(GST_CAPS_INT_RANGE_ID_NUM)
-#define GST_CAPS_FOURCC_ID GINT_TO_POINTER(GST_CAPS_FOURCC_ID_NUM)
-#define GST_CAPS_BOOL_ID GINT_TO_POINTER(GST_CAPS_BOOL_ID_NUM)
-
-#define GST_CAPS_LIST(a...) GST_CAPS_LIST_ID,##a,NULL
-#define GST_CAPS_INT(a) GST_CAPS_INT_ID,(GINT_TO_POINTER(a))
-#define GST_CAPS_INT_RANGE(a,b) GST_CAPS_INT_RANGE_ID,(GINT_TO_POINTER(a)),(GINT_TO_POINTER(b))
-#define GST_CAPS_FOURCC(a,b,c,d) GST_CAPS_FOURCC_ID,(GINT_TO_POINTER((a)|(b)<<8|(c)<<16|(d)<<24))
-#define GST_CAPS_FOURCC_INT(a) GST_CAPS_FOURCC_ID,(GINT_TO_POINTER(a))
-#define GST_CAPS_BOOLEAN(a) GST_CAPS_BOOL_ID,(GINT_TO_POINTER(a))
-
-
 struct _GstCaps {
   guint16 id;                  /* type id (major type) */
 
-  GSList *properties;          /* properties for this capability */
+  GstProps *properties;                /* properties for this capability */
 };
 
 /* initialize the subsystem */
 void           _gst_caps_initialize            (void);
 
 GstCaps*       gst_caps_register               (GstCapsFactory factory);
-GList*         gst_caps_register_va            (GstCapsFactory factory,...);
 
 void           gst_caps_dump                   (GstCaps *caps);
 
diff --git a/gst/gstcapsprivate.h b/gst/gstcapsprivate.h
deleted file mode 100644 (file)
index 978e4e6..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Gnome-Streamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __GST_CAPS_PRIV_H__
-#define __GST_CAPS_PRIV_H__
-
-#include <gst/gstcaps.h>
-
-typedef struct _GstCapsEntry GstCapsEntry;
-
-struct _GstCapsEntry {
-  GQuark    propid;
-  GstCapsId capstype;          
-
-  union {
-    /* flat values */
-    gboolean bool_data;
-    guint32  fourcc_data;
-    gint     int_data;
-
-    /* structured values */
-    struct {
-      GList *entries;
-    } list_data;
-    struct {
-      gint min;
-      gint max;
-    } int_range_data;
-  } data;
-};
-
-#endif /* __GST_CAPS_PRIV_H__ */
diff --git a/gst/gstprops.c b/gst/gstprops.c
new file mode 100644 (file)
index 0000000..a3a37eb
--- /dev/null
@@ -0,0 +1,385 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+//#define DEBUG_ENABLED
+
+#include <stdarg.h>
+#include <gst/gst.h>
+#include <gst/gstpropsprivate.h>
+
+static gboolean        gst_props_entry_check_compatibility     (GstPropsEntry *entry1, GstPropsEntry *entry2);
+       
+
+void 
+_gst_props_initialize (void) 
+{
+}
+
+static GstPropsEntry *
+gst_props_create_entry (GstPropsFactory factory, gint *skipped)
+{
+  GstPropsFactoryEntry tag;
+  GstPropsEntry *entry;
+  guint i=0;
+
+  entry = g_new0 (GstPropsEntry, 1);
+
+  tag = factory[i++];
+  switch (GPOINTER_TO_INT (tag)) {
+    case GST_PROPS_INT_ID:
+      entry->propstype = GST_PROPS_INT_ID_NUM;
+      entry->data.int_data = GPOINTER_TO_INT (factory[i++]);
+      break;
+    case GST_PROPS_INT_RANGE_ID:
+      entry->propstype = GST_PROPS_INT_RANGE_ID_NUM;
+      entry->data.int_range_data.min = GPOINTER_TO_INT (factory[i++]);
+      entry->data.int_range_data.max = GPOINTER_TO_INT (factory[i++]);
+      break;
+    case GST_PROPS_FOURCC_ID:
+      entry->propstype = GST_PROPS_FOURCC_ID_NUM;
+      entry->data.fourcc_data = GPOINTER_TO_INT (factory[i++]);
+      break;
+    case GST_PROPS_LIST_ID:
+      g_print("gstprops: list not allowed in list\n");
+      break;
+    case GST_PROPS_BOOL_ID:
+      entry->propstype = GST_PROPS_BOOL_ID_NUM;
+      entry->data.bool_data = GPOINTER_TO_INT (factory[i++]);
+      break;
+    default:
+      g_print("gstprops: unknown props id found\n");
+      g_free (entry);
+      entry = NULL;
+      break;
+  }
+
+  *skipped = i;
+
+  return entry;
+}
+
+
+static gint 
+props_compare_func (gconstpointer a,
+                  gconstpointer b) 
+{
+  GstPropsEntry *entry1 = (GstPropsEntry *)a;
+  GstPropsEntry *entry2 = (GstPropsEntry *)b;
+
+  return (entry1->propid - entry2->propid);
+}
+
+/**
+ * gst_props_register:
+ * @factory: the factory to register
+ *
+ * Register the factory. 
+ *
+ * Returns: The registered capability
+ */
+GstProps *
+gst_props_register (GstPropsFactory factory)
+{
+  GstPropsFactoryEntry tag;
+  gint i = 0;
+  GstProps *props;
+  gint skipped;
+  
+  g_return_val_if_fail (factory != NULL, NULL);
+
+  props = g_new0 (GstProps, 1);
+  g_return_val_if_fail (props != NULL, NULL);
+
+  props->properties = NULL;
+
+  tag = factory[i++];
+  
+  while (tag) {
+    GQuark quark;
+    GstPropsEntry *entry;
+    
+    quark = g_quark_from_string ((gchar *)tag);
+
+    tag = factory[i];
+    switch (GPOINTER_TO_INT (tag)) {
+      case GST_PROPS_LIST_ID: 
+      {
+        GstPropsEntry *list_entry;
+
+        entry = g_new0 (GstPropsEntry, 1);
+       entry->propid = quark;
+       entry->propstype = GST_PROPS_LIST_ID_NUM;
+       entry->data.list_data.entries = NULL;
+
+       i++; // skip list tag
+        tag = factory[i];
+       while (tag) {
+         list_entry = gst_props_create_entry (&factory[i], &skipped);
+         list_entry->propid = quark;
+         i += skipped;
+          tag = factory[i];
+         entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, list_entry);
+       }
+       entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
+       i++; //skip NULL (list end)
+       break;
+      }
+      default:
+      {
+       entry = gst_props_create_entry (&factory[i], &skipped);
+       entry->propid = quark;
+       i += skipped;
+       break;
+      }
+    }
+    props->properties = g_slist_insert_sorted (props->properties, entry, props_compare_func);
+     
+    tag = factory[i++];
+  }
+
+  return props;
+}
+
+static void
+gst_props_dump_entry_func (GstPropsEntry *entry)
+{
+  switch (entry->propstype) {
+    case GST_PROPS_INT_ID_NUM: 
+      g_print("gstprops:    int %d\n", entry->data.int_data);
+      break;
+    case GST_PROPS_INT_RANGE_ID_NUM: 
+      g_print("gstprops:    int range %d %d\n", 
+                     entry->data.int_range_data.min,
+                     entry->data.int_range_data.max);
+      break;
+    case GST_PROPS_FOURCC_ID_NUM: 
+      g_print("gstprops:    fourcc 0x%08x (%4.4s)\n", entry->data.fourcc_data, (gchar *)&entry->data.fourcc_data);
+      break;
+    case GST_PROPS_BOOL_ID_NUM: 
+      g_print("gstprops:    boolean %d\n", entry->data.bool_data);
+      break;
+    default:
+      g_print("gstprops:    **illegal entry**\n");
+      break;
+  }
+}
+
+static void
+gst_props_dump_list_func (gpointer entry,
+                        gpointer list_entry)
+{
+  gst_props_dump_entry_func ((GstPropsEntry *)entry);
+}
+
+static void
+gst_props_dump_func (gpointer data,
+                   gpointer user_data)
+{
+  GstPropsEntry *entry;
+
+  entry = (GstPropsEntry *)data;
+
+  g_print("gstprops:  property type \"%s\"\n", g_quark_to_string (entry->propid));
+
+  switch (entry->propstype) {
+    case GST_PROPS_LIST_ID_NUM: 
+    {
+      g_print("gstprops:   list type (\n");
+      g_list_foreach (entry->data.list_data.entries, gst_props_dump_list_func, entry);
+      g_print("gstprops:   )\n");
+      break;
+    }
+    default:
+      gst_props_dump_entry_func (entry);
+      break;
+  }
+}
+
+/**
+ * gst_props_dump:
+ * @props: the capability to dump
+ *
+ * Dumps the contents of the capabilty one the console
+ */
+void
+gst_props_dump (GstProps *props)
+{
+  g_return_if_fail (props != NULL);
+
+  g_print("gstprops: {\n");
+
+  g_slist_foreach (props->properties, gst_props_dump_func, props);
+  g_print("gstprops: }\n");
+}
+       
+/* entry2 is always a list, entry1 never is */
+static gboolean
+gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
+{
+  GList *entrylist = entry2->data.list_data.entries;
+  gboolean found = FALSE;
+
+  while (entrylist && !found) {
+    GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
+
+    found |= gst_props_entry_check_compatibility (entry1, entry);
+
+    entrylist = g_list_next (entrylist);
+  }
+
+  return found;
+}
+
+static gboolean
+gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
+{
+  DEBUG ("compare: %s %s\n", g_quark_to_string (entry1->propid),
+                            g_quark_to_string (entry2->propid));
+  switch (entry1->propstype) {
+    case GST_PROPS_LIST_ID_NUM:
+    {
+      GList *entrylist = entry1->data.list_data.entries;
+      gboolean valid = TRUE;    // innocent until proven guilty
+
+      while (entrylist && valid) {
+       GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
+
+       valid &= gst_props_entry_check_compatibility (entry, entry2);
+       
+       entrylist = g_list_next (entrylist);
+      }
+      
+      return valid;
+    }
+    case GST_PROPS_INT_RANGE_ID_NUM:
+      switch (entry2->propstype) {
+       // a - b   <--->   a - c
+        case GST_PROPS_INT_RANGE_ID_NUM:
+         return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
+                 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
+        case GST_PROPS_LIST_ID_NUM:
+         return gst_props_entry_check_list_compatibility (entry1, entry2);
+        default:
+          return FALSE;
+      }
+      break;
+    case GST_PROPS_FOURCC_ID_NUM:
+      switch (entry2->propstype) {
+       // b   <--->   a
+        case GST_PROPS_FOURCC_ID_NUM:
+         return (entry2->data.fourcc_data == entry1->data.fourcc_data);
+       // b   <--->   a,b,c
+        case GST_PROPS_LIST_ID_NUM:
+         return gst_props_entry_check_list_compatibility (entry1, entry2);
+        default:
+          return FALSE;
+      }
+      break;
+    case GST_PROPS_INT_ID_NUM:
+      switch (entry2->propstype) {
+       // b   <--->   a - d
+        case GST_PROPS_INT_RANGE_ID_NUM:
+         return (entry2->data.int_range_data.min <= entry1->data.int_data &&
+                 entry2->data.int_range_data.max >= entry1->data.int_data);
+       // b   <--->   a
+        case GST_PROPS_INT_ID_NUM:
+         return (entry2->data.int_data == entry1->data.int_data);
+       // b   <--->   a,b,c
+        case GST_PROPS_LIST_ID_NUM:
+         return gst_props_entry_check_list_compatibility (entry1, entry2);
+        default:
+          return FALSE;
+      }
+      break;
+    case GST_PROPS_BOOL_ID_NUM:
+      switch (entry2->propstype) {
+       // t   <--->   t
+        case GST_PROPS_BOOL_ID_NUM:
+          return (entry2->data.bool_data == entry1->data.bool_data);
+        case GST_PROPS_LIST_ID_NUM:
+         return gst_props_entry_check_list_compatibility (entry1, entry2);
+        default:
+          return FALSE;
+      }
+    default:
+      break;
+  }
+
+  return FALSE;
+}
+
+/**
+ * gst_props_check_compatibility:
+ * @fromprops: a capabilty
+ * @toprops: a capabilty
+ *
+ * Checks whether two capabilities are compatible
+ *
+ * Returns: true if compatible, false otherwise
+ */
+gboolean
+gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
+{
+  GSList *sourcelist;
+  GSList *sinklist;
+  gint missing = 0;
+  gint more = 0;
+  gboolean compatible = TRUE;
+
+  g_return_val_if_fail (fromprops != NULL, FALSE);
+  g_return_val_if_fail (toprops != NULL, FALSE);
+       
+  sourcelist = fromprops->properties;
+  sinklist   = toprops->properties;
+
+  while (sourcelist && sinklist && compatible) {
+    GstPropsEntry *entry1;
+    GstPropsEntry *entry2;
+
+    entry1 = (GstPropsEntry *)sourcelist->data;
+    entry2 = (GstPropsEntry *)sinklist->data;
+
+    while (entry1->propid < entry2->propid) {
+      DEBUG ("source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
+      more++;
+      sourcelist = g_slist_next (sourcelist);
+      if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
+      else goto end;
+    }
+    while (entry1->propid > entry2->propid) {
+      DEBUG ("source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
+      missing++;
+      sinklist = g_slist_next (sinklist);
+      if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
+      else goto end;
+    }
+
+    compatible &= gst_props_entry_check_compatibility (entry1, entry2);
+
+    sourcelist = g_slist_next (sourcelist);
+    sinklist = g_slist_next (sinklist);
+  }
+end:
+
+  if (missing)
+    return FALSE;
+
+  return compatible;
+}
+
diff --git a/gst/gstprops.h b/gst/gstprops.h
new file mode 100644 (file)
index 0000000..7b81f1b
--- /dev/null
@@ -0,0 +1,67 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_PROPS_H__
+#define __GST_PROPS_H__
+
+#include <glib.h>
+
+typedef struct _GstProps GstProps;
+typedef gpointer GstPropsFactoryEntry;
+typedef GstPropsFactoryEntry GstPropsFactory[];
+typedef GstPropsFactory *GstPropsListFactory[];
+
+typedef enum {
+   GST_PROPS_END_ID_NUM = 0,
+   GST_PROPS_LIST_ID_NUM,
+   GST_PROPS_INT_ID_NUM,
+   GST_PROPS_INT_RANGE_ID_NUM,
+   GST_PROPS_FOURCC_ID_NUM,
+   GST_PROPS_BOOL_ID_NUM,
+} GstPropsId;
+
+#define GST_PROPS_LIST_ID GINT_TO_POINTER(GST_PROPS_LIST_ID_NUM)
+#define GST_PROPS_INT_ID GINT_TO_POINTER(GST_PROPS_INT_ID_NUM)
+#define GST_PROPS_INT_RANGE_ID GINT_TO_POINTER(GST_PROPS_INT_RANGE_ID_NUM)
+#define GST_PROPS_FOURCC_ID GINT_TO_POINTER(GST_PROPS_FOURCC_ID_NUM)
+#define GST_PROPS_BOOL_ID GINT_TO_POINTER(GST_PROPS_BOOL_ID_NUM)
+
+#define GST_PROPS_LIST(a...) GST_PROPS_LIST_ID,##a,NULL
+#define GST_PROPS_INT(a) GST_PROPS_INT_ID,(GINT_TO_POINTER(a))
+#define GST_PROPS_INT_RANGE(a,b) GST_PROPS_INT_RANGE_ID,(GINT_TO_POINTER(a)),(GINT_TO_POINTER(b))
+#define GST_PROPS_FOURCC(a,b,c,d) GST_PROPS_FOURCC_ID,(GINT_TO_POINTER((a)|(b)<<8|(c)<<16|(d)<<24))
+#define GST_PROPS_FOURCC_INT(a) GST_PROPS_FOURCC_ID,(GINT_TO_POINTER(a))
+#define GST_PROPS_BOOLEAN(a) GST_PROPS_BOOL_ID,(GINT_TO_POINTER(a))
+
+
+struct _GstProps {
+  GSList *properties;          /* properties for this capability */
+};
+
+/* initialize the subsystem */
+void           _gst_props_initialize           (void);
+
+GstProps*      gst_props_register              (GstPropsFactory factory);
+
+void           gst_props_dump                  (GstProps *props);
+
+gboolean       gst_props_check_compatibility   (GstProps *props1, GstProps *props2);
+
+#endif /* __GST_PROPS_H__ */
diff --git a/gst/gstpropsprivate.h b/gst/gstpropsprivate.h
new file mode 100644 (file)
index 0000000..ebdec45
--- /dev/null
@@ -0,0 +1,49 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_PROPS_PRIV_H__
+#define __GST_PROPS_PRIV_H__
+
+#include <gst/gstprops.h>
+
+typedef struct _GstPropsEntry GstPropsEntry;
+
+struct _GstPropsEntry {
+  GQuark    propid;
+  GstPropsId propstype;                
+
+  union {
+    /* flat values */
+    gboolean bool_data;
+    guint32  fourcc_data;
+    gint     int_data;
+
+    /* structured values */
+    struct {
+      GList *entries;
+    } list_data;
+    struct {
+      gint min;
+      gint max;
+    } int_range_data;
+  } data;
+};
+
+#endif /* __GST_PROPS_PRIV_H__ */