Merged the CAPSNEGO1 branch..
authorWim Taymans <wim.taymans@gmail.com>
Mon, 12 Mar 2001 21:02:12 +0000 (21:02 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 12 Mar 2001 21:02:12 +0000 (21:02 +0000)
Original commit message from CVS:
Merged the CAPSNEGO1 branch..

26 files changed:
configure.in
docs/random/wtay/caps-negociation
editor/gsteditorproperty.c
gst/autoplug/gststaticautoplug.c
gst/autoplug/gststaticautoplugrender.c
gst/elements/gstaudiosink.c
gst/gstautoplug.c
gst/gstautoplug.h
gst/gstcaps.c
gst/gstcaps.h
gst/gstelement.c
gst/gstelement.h
gst/gstelementfactory.c
gst/gstpad.c
gst/gstpad.h
gst/gstqueue.c
gstplay/gstplay.c
plugins/elements/gstaudiosink.c
plugins/elements/gstqueue.c
tests/.gitignore
tests/Makefile.am
tests/autoplug.c
tests/capsconnect.c [new file with mode: 0644]
tests/nego/.gitignore [new file with mode: 0644]
tests/nego/Makefile.am [new file with mode: 0644]
tests/nego/nego1.c [new file with mode: 0644]

index cf5e0b8..8a126eb 100644 (file)
@@ -770,6 +770,7 @@ tests/Makefile
 tests/sched/Makefile
 tests/eos/Makefile
 testsuite/Makefile
+tests/nego/Makefile
 examples/Makefile
 examples/autoplug/Makefile
 examples/helloworld/Makefile
index 1207cd9..ad72b9b 100644 (file)
@@ -128,7 +128,7 @@ the element when it knows the values for the caps.
 -----------------------
 
 when two pads are connected the following steps will take
-placei (not sure, FIXME): 
+place (not sure, FIXME): 
 
  - if both pads have caps, the caps are checked. If the caps
    are incompatible, the padtemplates are checked, if they
index 2e5e05a..ca77aed 100644 (file)
@@ -329,14 +329,14 @@ gst_editor_pads_create (GstEditorProperty *property, GstEditorElement *element)
 
   while (pads) {
     GstPad *pad = (GstPad *)pads->data;
-    GList *caps = gst_pad_get_caps_list (pad);
+    GstCaps *caps = gst_pad_get_caps (pad);
     gchar *mime;
     gchar *data[2];
     GtkCTreeNode *padnode;
 
     if (caps) {
       GstType *type;
-      type = gst_type_find_by_id (((GstCaps *)caps->data)->id);
+      type = gst_type_find_by_id (caps->id);
       mime = type->mime;
     }
     else {
@@ -348,13 +348,8 @@ gst_editor_pads_create (GstEditorProperty *property, GstEditorElement *element)
     padnode = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, data, 0, 
                    NULL, NULL, NULL, NULL, FALSE, TRUE);
 
-    while (caps) {
-      GstCaps *cap = (GstCaps *)caps->data;
 
-      gst_editor_add_caps_to_tree (cap, tree, padnode);
-
-      caps = g_list_next (caps);
-    }
+    gst_editor_add_caps_to_tree (caps, tree, padnode);
 
     pads = g_list_next (pads);
   }
index a39ac57..7d42d4b 100644 (file)
@@ -41,7 +41,7 @@ static GList*         gst_autoplug_func               (gpointer src, gpointer sink,
 
 
 static GstElement*     gst_static_autoplug_to_caps     (GstAutoplug *autoplug, 
-                                                        GList *srccaps, GList *sinkcaps, va_list args);
+                                                        GstCaps *srccaps, GstCaps *sinkcaps, va_list args);
 
 static GstAutoplugClass *parent_class = NULL;
 
@@ -118,7 +118,8 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
 
       if (srctemp->direction == GST_PAD_SRC &&
           desttemp->direction == GST_PAD_SINK) {
-       if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
+       if (gst_caps_check_compatibility (gst_padtemplate_get_caps (srctemp), 
+                               gst_padtemplate_get_caps (desttemp))) {
          GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
                          "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
           return TRUE;
@@ -151,7 +152,7 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
     if (gst_pad_get_direction(sinkpad)  == GST_PAD_SINK &&
         !GST_PAD_CONNECTED(sinkpad))
     {
-      if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
+      if (gst_caps_check_compatibility (gst_pad_get_caps(pad), gst_pad_get_caps(sinkpad))) {
         gst_pad_connect(pad, sinkpad);
         GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
                       GST_ELEMENT_NAME(src));
@@ -175,7 +176,7 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
 
 typedef struct {
   GstElement *result;
-  GList *endcap;
+  GstCaps *endcap;
   gint i;
 } dynamic_pad_struct;
 
@@ -190,9 +191,10 @@ autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data)
 
   while (pads) {
     GstPad *pad = GST_PAD (pads->data);
+    GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
     pads = g_list_next (pads);
 
-    if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
+    if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), info->endcap)) {
       gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
       GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
       break;
@@ -232,8 +234,8 @@ gst_autoplug_elementfactory_get_list (gpointer data)
 }
 
 typedef struct {
-  GList *src;
-  GList *sink;
+  GstCaps *src;
+  GstCaps *sink;
 } caps_struct;
 
 #define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
@@ -245,16 +247,13 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
   gboolean res;
 
   if (IS_CAPS (src) && IS_CAPS (dest)) {
-    res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
-    //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
+    res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)dest);
   }
   else if (IS_CAPS (src)) {
-    res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
-    //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
+    res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)src);
   }
   else if (IS_CAPS (dest)) {
-    res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
-    //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
+    res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest);
   }
   else {
     res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
@@ -267,10 +266,10 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
 }
 
 static GstElement*
-gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args)
+gst_static_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args)
 {
   caps_struct caps;
-  GList *capslist;
+  GstCaps *capslist;
   GstElement *result = NULL, *srcelement = NULL;
   GList **factories;
   GList *chains = NULL;
@@ -307,7 +306,7 @@ gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkc
     else {
     }
 
-    capslist = va_arg (args, GList *);
+    capslist = va_arg (args, GstCaps *);
   }
 
   /*
@@ -376,8 +375,9 @@ gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkc
 
       while (pads) {
        GstPad *pad = GST_PAD (pads->data);
+       GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
 
-       if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
+       if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) {
           gst_element_add_ghost_pad (result, pad, "sink");
          break;
        }
@@ -430,7 +430,7 @@ differ:
      * find a suitable pad to turn into a ghostpad
      */
     {
-      GList *endcap = (GList *)(endcaps->data);
+      GstCaps *endcap = (GstCaps *)(endcaps->data);
       GList *pads = gst_element_get_pad_list (thesrcelement);
       gboolean have_pad = FALSE;
       endcaps = g_list_next (endcaps);
@@ -439,9 +439,10 @@ differ:
 
       while (pads) {
        GstPad *pad = GST_PAD (pads->data);
+       GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
        pads = g_list_next (pads);
 
-       if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) {
+       if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), endcap)) {
           gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i));
          have_pad = TRUE;
          break;
index 5533d69..180c29f 100644 (file)
@@ -41,7 +41,7 @@ static GList*         gst_autoplug_func               (gpointer src, gpointer sink,
 
 
 static GstElement*     gst_static_autoplug_to_render   (GstAutoplug *autoplug, 
-                                                        GList *srccaps, GstElement *target, va_list args);
+                                                        GstCaps *srccaps, GstElement *target, va_list args);
 
 static GstAutoplugClass *parent_class = NULL;
 
@@ -118,7 +118,7 @@ gst_autoplug_can_match (GstElementFactory *src, GstElementFactory *dest)
 
       if (srctemp->direction == GST_PAD_SRC &&
           desttemp->direction == GST_PAD_SINK) {
-       if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
+       if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (srctemp), GST_PADTEMPLATE_CAPS (desttemp))) {
          GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
                          "factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
           return TRUE;
@@ -148,20 +148,14 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
     GstPad *sinkpad = (GstPad *)sinkpads->data;
 
     // if we have a match, connect the pads
-    if (gst_pad_get_direction(sinkpad)  == GST_PAD_SINK &&
-        !GST_PAD_CONNECTED(sinkpad))
+    if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
+        !GST_PAD_CONNECTED (pad) && !GST_PAD_CONNECTED(sinkpad))
     {
-      if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
-        gst_pad_connect(pad, sinkpad);
-        GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
-                      GST_ELEMENT_NAME(src));
-        GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
-                     GST_ELEMENT_NAME(sink));
-        connected = TRUE;
-        break;
+      if ((connected = gst_pad_connect (pad, sinkpad))) {
+       break;
       }
       else {
-       GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
+        GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
       }
     }
     sinkpads = g_list_next(sinkpads);
@@ -173,33 +167,6 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
   return connected;
 }
 
-typedef struct {
-  GstElement *result;
-  GList *endcap;
-  gint i;
-} dynamic_pad_struct;
-
-static void
-autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data)
-{
-  dynamic_pad_struct *info = (dynamic_pad_struct *)data;
-  GList *pads = gst_element_get_pad_list (element);
-
-  GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element),
-                 GST_PAD_NAME (pad));
-
-  while (pads) {
-    GstPad *pad = GST_PAD (pads->data);
-    pads = g_list_next (pads);
-
-    if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
-      gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
-      GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
-      break;
-    }
-  }
-}
-
 static void
 gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
 {
@@ -211,8 +178,11 @@ gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
   while (srcpads && !connected) {
     GstPad *srcpad = (GstPad *)srcpads->data;
 
-    if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
+    if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) {
       connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink);
+      if (connected)
+        break;
+    }
 
     srcpads = g_list_next(srcpads);
   }
@@ -234,8 +204,8 @@ gst_autoplug_elementfactory_get_list (gpointer data)
 }
 
 typedef struct {
-  GList *src;
-  GList *sink;
+  GstCaps *src;
+  GstCaps *sink;
 } caps_struct;
 
 #define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
@@ -247,15 +217,15 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
   gboolean res;
 
   if (IS_CAPS (src) && IS_CAPS (dest)) {
-    res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
+    res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)dest);
     //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
   }
   else if (IS_CAPS (src)) {
-    res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
+    res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)src);
     //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
   }
   else if (IS_CAPS (dest)) {
-    res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
+    res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest);
     //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
   }
   else {
@@ -269,7 +239,7 @@ gst_autoplug_caps_find_cost (gpointer src, gpointer dest, gpointer data)
 }
 
 static GstElement*
-gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args)
+gst_static_autoplug_to_render (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args)
 {
   caps_struct caps;
   GstElement *targetelement;
@@ -292,10 +262,12 @@ gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement
   while (targetelement) {
     GList *elements;
     GstPad *pad;
+    GstPadTemplate *templ;
 
     pad = GST_PAD (gst_element_get_pad_list (targetelement)->data);
+    templ = GST_PAD_PADTEMPLATE (pad);
 
-    caps.sink = gst_pad_get_caps_list (pad);
+    caps.sink = GST_PADTEMPLATE_CAPS (templ);
 
     GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
 
@@ -381,8 +353,9 @@ gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement
 
       while (pads) {
        GstPad *pad = GST_PAD (pads->data);
+       GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
 
-       if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
+       if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) {
           gst_element_add_ghost_pad (result, pad, "sink");
          break;
        }
@@ -435,8 +408,7 @@ differ:
       // this element suggests the use of a thread, so we set one up...
       if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
         GstElement *queue;
-        GList *sinkpads;
-        GstPad *srcpad, *sinkpad;
+        GstPad *srcpad;
 
        use_thread = FALSE;
 
@@ -453,22 +425,6 @@ differ:
 
         srcpad = gst_element_get_pad(queue, "src");
 
-        sinkpads = gst_element_get_pad_list(element);
-        while (sinkpads) {
-          sinkpad = (GstPad *)sinkpads->data;
-
-         // FIXME connect matching pads, not just the first one...
-          if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
-             !GST_PAD_CONNECTED(sinkpad)) {
-            GList *caps = gst_pad_get_caps_list (sinkpad);
-
-           // the queue has the type of the elements it connects
-           gst_pad_set_caps_list (srcpad, caps);
-            gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
-           break;
-         }
-          sinkpads = g_list_next(sinkpads);
-        }
         gst_autoplug_pads_autoplug(thesrcelement, queue);
 
        GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
index 1027729..5499e3a 100644 (file)
@@ -417,8 +417,9 @@ gst_audiosink_change_state (GstElement *element)
   /* otherwise (READY or higher) we need to open the sound card */
   } else {
     if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) {
-      if (!gst_audiosink_open_audio (GST_AUDIOSINK (element)))
-        return GST_STATE_FAILURE;
+      if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) {
+        //return GST_STATE_FAILURE;
+      }
     }
   }
       
index 3f74b25..dc2c017 100644 (file)
@@ -102,7 +102,7 @@ gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object)
 
 
 GstElement*
-gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...)
+gst_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...)
 {
   GstAutoplugClass *oclass;
   GstElement *element = NULL;
@@ -120,7 +120,7 @@ gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ..
 }
 
 GstElement*
-gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...)
+gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, ...)
 {
   GstAutoplugClass *oclass;
   GstElement *element = NULL;
index 14d96d5..6bb03c6 100644 (file)
@@ -63,8 +63,8 @@ struct _GstAutoplugClass {
   void (*new_object)  (GstAutoplug *autoplug, GstObject *object);
 
   /* perform the autoplugging */
-  GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args);
-  GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args);
+  GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args);
+  GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args);
 };
 
 typedef struct _GstAutoplugFactory GstAutoplugFactory;
@@ -79,8 +79,8 @@ GtkType                       gst_autoplug_get_type                   (void);
 
 void                   gst_autoplug_signal_new_object          (GstAutoplug *autoplug, GstObject *object);
 
-GstElement*            gst_autoplug_to_caps                    (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...);
-GstElement*            gst_autoplug_to_renderers               (GstAutoplug *autoplug, GList *srccaps, 
+GstElement*            gst_autoplug_to_caps                    (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...);
+GstElement*            gst_autoplug_to_renderers               (GstAutoplug *autoplug, GstCaps *srccaps, 
                                                                 GstElement *target, ...);
 
 
index ebdaccc..24e45b8 100644 (file)
@@ -72,6 +72,7 @@ gst_caps_new (const gchar *name, const gchar *mime)
   caps->name = g_strdup (name);
   caps->id = get_type_for_mime (mime);
   caps->properties = NULL;
+  caps->next = NULL;
 
   return caps;
 }
@@ -297,20 +298,77 @@ gst_caps_get_props (GstCaps *caps)
 }
 
 /**
- * gst_caps_check_compatibility:
- * @fromcaps: a capabilty
- * @tocaps: a capabilty
+ * gst_caps_append:
+ * @caps: a capabilty
+ * @capstoadd: the capability to append
  *
- * Checks whether two capabilities are compatible.
+ * Appends a capability to the existing capability.
  *
- * Returns: TRUE if compatible, FALSE otherwise
+ * Returns: the new capability
  */
-gboolean
-gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
+GstCaps*
+gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
 {
-  g_return_val_if_fail (fromcaps != NULL, FALSE);
-  g_return_val_if_fail (tocaps != NULL, FALSE);
+  GstCaps *orig = caps;
+
+  if (caps == NULL)
+    return capstoadd;
+  
+  while (caps->next) {
+    caps = caps->next;
+  }
+  caps->next = capstoadd;
+
+  return orig;
+}
+
+/**
+ * gst_caps_prepend:
+ * @caps: a capabilty
+ * @capstoadd: a capabilty to prepend
+ *
+ * prepend the capability to the list of capabilities
+ *
+ * Returns: the new capability
+ */
+GstCaps*
+gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
+{
+  GstCaps *orig = capstoadd;
+  
+  if (capstoadd == NULL)
+    return caps;
+
+  while (capstoadd->next) {
+    capstoadd = capstoadd->next;
+  }
+  capstoadd->next = caps;
 
+  return orig;
+}
+
+GstCaps*
+gst_caps_get_by_name (GstCaps *caps, const gchar *name)
+{
+  g_return_val_if_fail (caps != NULL, NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+   
+  while (caps) {
+    if (!strcmp (caps->name, name)) 
+      return caps;
+    caps = caps->next;
+  }
+
+  return NULL;
+}
+                                                                                                                   
+static gboolean
+gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps)
+{
+  if (fromcaps == NULL ||
+      tocaps == NULL) 
+    return TRUE;
+       
   if (fromcaps->id != tocaps->id) {
     GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n",
               fromcaps->id, tocaps->id);
@@ -343,21 +401,18 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
  * Returns: TRUE if compatible, FALSE otherwise
  */
 gboolean
-gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps)
+gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
 {
   while (fromcaps) {
-    GstCaps *fromcap = (GstCaps *)fromcaps->data;
-    GList *destcaps = tocaps;
+    GstCaps *destcaps = tocaps;
 
     while (destcaps) {
-      GstCaps *destcap = (GstCaps *)destcaps->data;
-
-      if (gst_caps_check_compatibility (fromcap, destcap))
+      if (gst_caps_check_compatibility_func (fromcaps, destcaps))
        return TRUE;
 
-      destcaps = g_list_next (destcaps);
+      destcaps =  destcaps->next;
     }
-    fromcaps = g_list_next (fromcaps);
+    fromcaps =  fromcaps->next;
   }
   return FALSE;
 }
@@ -375,15 +430,20 @@ xmlNodePtr
 gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
 {
   xmlNodePtr subtree;
+  xmlNodePtr subsubtree;
 
-  g_return_val_if_fail (caps != NULL, NULL);
+  while (caps) {
+    subtree = xmlNewChild (parent, NULL, "capscomp", NULL);
 
-  xmlNewChild (parent, NULL, "name", caps->name);
-  xmlNewChild (parent, NULL, "type", gst_type_find_by_id (caps->id)->mime);
-  if (caps->properties) {
-    subtree = xmlNewChild (parent, NULL, "properties", NULL);
+    xmlNewChild (subtree, NULL, "name", caps->name);
+    xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime);
+    if (caps->properties) {
+      subsubtree = xmlNewChild (subtree, NULL, "properties", NULL);
 
-    gst_props_save_thyself (caps->properties, subtree);
+      gst_props_save_thyself (caps->properties, subsubtree);
+    }
+
+    caps = caps->next;
   }
 
   return parent;
@@ -400,26 +460,36 @@ gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
 GstCaps*
 gst_caps_load_thyself (xmlNodePtr parent)
 {
-  GstCaps *caps = g_new0 (GstCaps, 1);
+  GstCaps *result = NULL;
   xmlNodePtr field = parent->xmlChildrenNode;
-  gchar *content;
 
   while (field) {
-    if (!strcmp (field->name, "name")) {
-      caps->name = xmlNodeGetContent (field);
-    }
-    if (!strcmp (field->name, "type")) {
-      content = xmlNodeGetContent (field);
-      caps->id = get_type_for_mime (content);
-      g_free (content);
-    }
-    else if (!strcmp (field->name, "properties")) {
-      caps->properties = gst_props_load_thyself (field);
+    if (!strcmp (field->name, "capscomp")) {
+      xmlNodePtr subfield = field->xmlChildrenNode;
+      GstCaps *caps = g_new0 (GstCaps, 1);
+      gchar *content;
+       
+      while (subfield) {
+        if (!strcmp (subfield->name, "name")) {
+          caps->name = xmlNodeGetContent (subfield);
+        }
+        if (!strcmp (subfield->name, "type")) {
+          content = xmlNodeGetContent (subfield);
+          caps->id = get_type_for_mime (content);
+          g_free (content);
+        }
+        else if (!strcmp (subfield->name, "properties")) {
+          caps->properties = gst_props_load_thyself (subfield);
+        }
+       
+        subfield = subfield->next;
+      }
+      result = gst_caps_append (result, caps);
     }
     field = field->next;
   }
 
-  return caps;
+  return result;
 }
 
 
index dffa1cd..8bb6256 100644 (file)
@@ -49,6 +49,8 @@ struct _GstCaps {
   guint16 id;                  /* type id (major type) */
 
   GstProps *properties;                /* properties for this capability */
+
+  GstCaps *next;
 };
 
 /* initialize the subsystem */
@@ -71,8 +73,12 @@ void         gst_caps_set_type_id                    (GstCaps *caps, guint16 type_id);
 GstCaps*       gst_caps_set_props                      (GstCaps *caps, GstProps *props);
 GstProps*      gst_caps_get_props                      (GstCaps *caps);
 
+GstCaps*       gst_caps_get_by_name                    (GstCaps *caps, const gchar *name);
+
+GstCaps*       gst_caps_append                         (GstCaps *caps, GstCaps *capstoadd); 
+GstCaps*       gst_caps_prepend                        (GstCaps *caps, GstCaps *capstoadd); 
+
 gboolean       gst_caps_check_compatibility            (GstCaps *fromcaps, GstCaps *tocaps);
-gboolean       gst_caps_list_check_compatibility       (GList *fromcaps, GList *tocaps);
 
 xmlNodePtr      gst_caps_save_thyself                  (GstCaps *caps, xmlNodePtr parent);
 GstCaps*       gst_caps_load_thyself                   (xmlNodePtr parent);
index e8dc9ce..7241b40 100644 (file)
@@ -461,14 +461,14 @@ gst_element_get_padtemplate_by_compatible (GstElement *element, GstPadTemplate *
     if (padtempl->direction == GST_PAD_SRC &&
       compattempl->direction == GST_PAD_SINK) {
       GST_DEBUG(0,"compatible direction: found src pad template\n");
-      compat = gst_caps_list_check_compatibility(padtempl->caps,
-                                                compattempl->caps);
+      compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (padtempl),
+                                           GST_PADTEMPLATE_CAPS (compattempl));
       GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not "));
     } else if (padtempl->direction == GST_PAD_SINK &&
               compattempl->direction == GST_PAD_SRC) {
       GST_DEBUG(0,"compatible direction: found sink pad template\n");
-      compat = gst_caps_list_check_compatibility(compattempl->caps,
-                                                padtempl->caps);
+      compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (compattempl),
+                                           GST_PADTEMPLATE_CAPS (padtempl));
       GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not "));
     }
 
index 655d18f..87cae5e 100644 (file)
@@ -251,10 +251,10 @@ gboolean          gst_elementfactory_can_src_caps         (GstElementFactory *factory,
                                                                 GstCaps *caps);
 gboolean               gst_elementfactory_can_sink_caps        (GstElementFactory *factory,
                                                                 GstCaps *caps);
-gboolean               gst_elementfactory_can_src_caps_list    (GstElementFactory *factory,
-                                                                GList *caps);
-gboolean               gst_elementfactory_can_sink_caps_list   (GstElementFactory *factory,
-                                                                GList *caps);
+gboolean               gst_elementfactory_can_src_caps         (GstElementFactory *factory,
+                                                                GstCaps *caps);
+gboolean               gst_elementfactory_can_sink_caps        (GstElementFactory *factory,
+                                                                GstCaps *caps);
 
 GstElement*            gst_elementfactory_create               (GstElementFactory *factory,
                                                                 const gchar *name);
index eced12e..997cb20 100644 (file)
@@ -222,17 +222,17 @@ gst_elementfactory_add_padtemplate (GstElementFactory *factory,
 }
 
 /**
- * gst_elementfactory_can_src_caps_list :
+ * gst_elementfactory_can_src_caps :
  * @factory: factory to query
- * @caps: the caps list to check
+ * @caps: the caps to check
  *
- * Checks if the factory can source the given capability list.
+ * Checks if the factory can source the given capability.
  *
  * Returns: true if it can src the capabilities
  */
 gboolean
-gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
-                                     GList *caps)
+gst_elementfactory_can_src_caps (GstElementFactory *factory,
+                                GstCaps *caps)
 {
   GList *templates;
 
@@ -245,7 +245,7 @@ gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
     GstPadTemplate *template = (GstPadTemplate *)templates->data;
 
     if (template->direction == GST_PAD_SRC) {
-      if (gst_caps_list_check_compatibility (template->caps, caps))
+      if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (template), caps))
        return TRUE;
     }
     templates = g_list_next (templates);
@@ -255,17 +255,17 @@ gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
 }
 
 /**
- * gst_elementfactory_can_sink_caps_list :
+ * gst_elementfactory_can_sink_caps :
  * @factory: factory to query
- * @caps: the caps list to check
+ * @caps: the caps to check
  *
- * Checks if the factory can sink the given capability list.
+ * Checks if the factory can sink the given capability.
  *
  * Returns: true if it can sink the capabilities
  */
 gboolean
-gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
-                                      GList *caps)
+gst_elementfactory_can_sink_caps (GstElementFactory *factory,
+                                 GstCaps *caps)
 {
   GList *templates;
 
@@ -278,7 +278,7 @@ gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
     GstPadTemplate *template = (GstPadTemplate *)templates->data;
 
     if (template->direction == GST_PAD_SINK) {
-      if (gst_caps_list_check_compatibility (caps, template->caps))
+      if (gst_caps_check_compatibility (caps, GST_PADTEMPLATE_CAPS (template)))
        return TRUE;
     }
     templates = g_list_next (templates);
@@ -288,56 +288,6 @@ gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
 }
 
 /**
- * gst_elementfactory_can_src_caps :
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can src the given capability.
- *
- * Returns: true if it can sink the capability
- */
-gboolean
-gst_elementfactory_can_src_caps (GstElementFactory *factory,
-                                GstCaps *caps)
-{
-  GList *dummy;
-  gboolean ret;
-
-  dummy = g_list_prepend (NULL, caps);
-
-  ret = gst_elementfactory_can_src_caps_list (factory, dummy);
-
-  g_list_free (dummy);
-
-  return ret;
-}
-
-/**
- * gst_elementfactory_can_sink_caps :
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can sink the given capability.
- *
- * Returns: true if it can sink the capability
- */
-gboolean
-gst_elementfactory_can_sink_caps (GstElementFactory *factory,
-                                 GstCaps *caps)
-{
-  GList *dummy;
-  gboolean ret;
-
-  dummy = g_list_prepend (NULL, caps);
-
-  ret = gst_elementfactory_can_sink_caps_list (factory, dummy);
-
-  g_list_free (dummy);
-
-  return ret;
-}
-
-/**
  * gst_elementfactory_save_thyself:
  * @factory: factory to save
  * @parent: the parent xmlNodePtr
index e613add..4aaab8d 100644 (file)
@@ -259,8 +259,8 @@ gst_pad_new_from_template (GstPadTemplate *templ,
   g_return_val_if_fail (templ != NULL, NULL);
 
   pad = gst_pad_new (name, templ->direction);
-  GST_PAD_CAPS(pad) = templ->caps;
   GST_PAD_PADTEMPLATE(pad) = templ;
+  GST_PAD_CAPS (pad) = GST_PADTEMPLATE_CAPS (templ);
 
   return pad;
 }
@@ -410,6 +410,25 @@ gst_pad_set_eos_function (GstPad *pad,
              GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_EOSFUNC(pad),eos);
 }
 
+/**
+ * gst_pad_set_eos_function:
+ * @pad: the pad to set the eos function for
+ * @eos: the eos function
+ *
+ * Set the given EOS function for the pad.
+ */
+void
+gst_pad_set_negotiate_function (GstPad *pad,
+                               GstPadNegotiateFunction nego)
+{
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_REAL_PAD (pad));
+
+  GST_RPAD_NEGOTIATEFUNC(pad) = nego;
+  GST_DEBUG (0,"negotiatefunc for %s:%s(@%p) at %p is set to %p\n",
+             GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_NEGOTIATEFUNC(pad),nego);
+}
+
 
 
 static void
@@ -503,26 +522,32 @@ gst_pad_disconnect (GstPad *srcpad,
  * @sinkpad: the sink pad to connect
  *
  * Connects the source pad to the sink pad.
+ *
+ * Returns: TRUE if the pad could be connected
  */
-void
+gboolean
 gst_pad_connect (GstPad *srcpad,
                 GstPad *sinkpad)
 {
   GstRealPad *realsrc, *realsink;
   GstRealPad *temppad;
+  gboolean negotiated = FALSE;
 
   /* generic checks */
-  g_return_if_fail(srcpad != NULL);
-  g_return_if_fail(GST_IS_PAD(srcpad));
-  g_return_if_fail(sinkpad != NULL);
-  g_return_if_fail(GST_IS_PAD(sinkpad));
+  g_return_val_if_fail(srcpad != NULL, FALSE);
+  g_return_val_if_fail(GST_IS_PAD(srcpad), FALSE);
+  g_return_val_if_fail(sinkpad != NULL, FALSE);
+  g_return_val_if_fail(GST_IS_PAD(sinkpad), FALSE);
+
+  GST_INFO (GST_CAT_ELEMENT_PADS, "about to connect %s:%s and %s:%s",
+            GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
 
   // now we need to deal with the real/ghost stuff
   realsrc = GST_PAD_REALIZE(srcpad);
   realsink = GST_PAD_REALIZE(sinkpad);
 
-  g_return_if_fail(GST_RPAD_PEER(realsrc) == NULL);
-  g_return_if_fail(GST_RPAD_PEER(realsink) == NULL);
+  g_return_val_if_fail(GST_RPAD_PEER(realsrc) == NULL, FALSE);
+  g_return_val_if_fail(GST_RPAD_PEER(realsink) == NULL, FALSE);
 
   /* check for reversed directions and swap if necessary */
   if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
@@ -531,27 +556,31 @@ gst_pad_connect (GstPad *srcpad,
     realsrc = realsink;
     realsink = temppad;
   }
-  g_return_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
-                   (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
+  g_return_val_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
+                   (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK), FALSE);
 
-  if (!gst_pad_check_compatibility (srcpad, sinkpad)) {
-    g_warning ("gstpad: connecting incompatible pads (%s:%s) and (%s:%s)\n",
-                       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-  }
-  else {
-    GST_DEBUG (0,"gstpad: connecting compatible pads (%s:%s) and (%s:%s)\n",
-                       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-  }
 
   /* first set peers */
   GST_RPAD_PEER(realsrc) = realsink;
   GST_RPAD_PEER(realsink) = realsrc;
 
-  /* set the connected flag */
   /* FIXME: set connected flag */
 
   GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s",
             GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+
+  if (GST_PAD_CAPS (srcpad)) {
+    negotiated = gst_pad_renegotiate (srcpad);
+  }
+  else {
+    negotiated = gst_pad_renegotiate (sinkpad);
+  }
+
+  if (!negotiated) {
+    gst_pad_disconnect (srcpad, sinkpad);
+    return FALSE;
+  }
+  return TRUE;
 }
 
 /**
@@ -583,6 +612,23 @@ gst_pad_set_parent (GstPad *pad,
  *
  * Returns: the parent object
  */
+GstPadTemplate*
+gst_pad_get_padtemplate (GstPad *pad)
+{
+  g_return_val_if_fail (pad != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+  return GST_PAD_PADTEMPLATE (pad); 
+}
+
+/**
+ * gst_pad_get_parent:
+ * @pad: the pad to get the parent from
+ *
+ * Get the parent object of this pad.
+ *
+ * Returns: the parent object
+ */
 GstObject*
 gst_pad_get_parent (GstPad *pad)
 {
@@ -676,20 +722,22 @@ gst_pad_get_ghost_pad_list (GstPad *pad)
 }
 
 /**
- * gst_pad_set_caps_list:
+ * gst_pad_set_caps:
  * @pad: the pad to set the caps to
  * @caps: a GList of the capabilities to attach to this pad
  *
  * Set the capabilities of this pad.
  */
 void
-gst_pad_set_caps_list (GstPad *pad,
-                       GList *caps)
+gst_pad_set_caps (GstPad *pad,
+                  GstCaps *caps)
 {
   g_return_if_fail (pad != NULL);
   g_return_if_fail (GST_IS_REAL_PAD (pad));            // NOTE this restriction
 
   GST_PAD_CAPS(pad) = caps;
+
+  gst_pad_renegotiate (pad);
 }
 
 /**
@@ -700,8 +748,8 @@ gst_pad_set_caps_list (GstPad *pad,
  *
  * Returns: a list of the capabilities of this pad
  */
-GList *
-gst_pad_get_caps_list (GstPad *pad)
+GstCaps*
+gst_pad_get_caps (GstPad *pad)
 {
   g_return_val_if_fail (pad != NULL, NULL);
   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
@@ -718,26 +766,18 @@ gst_pad_get_caps_list (GstPad *pad)
  *
  * Returns: a capability or NULL if not found
  */
-GstCaps *
-gst_pad_get_caps_by_name (GstPad *pad, gchar *name)
+GstCaps*
+gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
 {
-  GList *caps;
-
-  g_return_val_if_fail (pad != NULL, NULL);
-  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+  GstCaps *caps;
 
-  caps = GST_PAD_CAPS(pad);
-
-  while (caps) {
-    GstCaps *cap = (GstCaps *)caps->data;
-
-    if (!strcmp (cap->name, name))
-      return cap;
+  g_return_val_if_fail (templ != NULL, NULL);
 
-    caps = g_list_next (caps);
-  }
+  caps = GST_PADTEMPLATE_CAPS (templ);
+  if (!caps) 
+    return NULL;
 
-  return NULL;
+  return gst_caps_get_by_name (caps, name);
 }
 
 /**
@@ -753,18 +793,13 @@ gst_pad_get_caps_by_name (GstPad *pad, gchar *name)
 gboolean
 gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
 {
-  GstRealPad *realsrc, *realsink;
-
   g_return_val_if_fail (srcpad != NULL, FALSE);
   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
   g_return_val_if_fail (sinkpad != NULL, FALSE);
   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
 
-  realsrc = GST_PAD_REALIZE(srcpad);
-  realsink = GST_PAD_REALIZE(sinkpad);
-
-  if (GST_RPAD_CAPS(realsrc) && GST_RPAD_CAPS(realsink)) {
-    if (!gst_caps_list_check_compatibility (GST_RPAD_CAPS(realsrc), GST_RPAD_CAPS(realsink))) {
+  if (GST_PAD_CAPS(srcpad) && GST_PAD_CAPS(sinkpad)) {
+    if (!gst_caps_check_compatibility (GST_PAD_CAPS(srcpad), GST_PAD_CAPS(sinkpad))) {
       return FALSE;
     }
     else {
@@ -772,8 +807,9 @@ gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
     }
   }
   else {
-    GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s)\n",
-                   GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+    GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n",
+                   GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad), 
+                   GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
     return TRUE;
   }
 }
@@ -864,6 +900,143 @@ cleanup:
   g_strfreev (split);
 }
 
+/**
+ * gst_pad_renegotiate:
+ * @pad: the pad to perform the negotiation on
+ *
+ * Perform the negotiation process with the peer pad.
+ *
+ * Returns: TRUE if the negotiation process succeded
+ */
+gboolean
+gst_pad_renegotiate (GstPad *pad)
+{
+  gint counter = 0;
+  GstCaps *newcaps = NULL;
+  GstRealPad *peerpad, *currentpad, *otherpad;
+  GstCaps *currentcaps;
+  
+  g_return_val_if_fail (pad != NULL, FALSE);
+
+  peerpad = GST_PAD_PEER (pad);
+
+  currentpad = GST_PAD_REALIZE (pad);
+
+  if (!peerpad) {
+    GST_DEBUG (GST_CAT_ELEMENT_PADS, "no peer pad for pad %s:%s\n",
+                 GST_DEBUG_PAD_NAME(currentpad));
+    return TRUE;
+  }
+   
+  otherpad = GST_REAL_PAD (peerpad);
+
+  GST_INFO (GST_CAT_ELEMENT_PADS, "negotiating pad %s:%s and %s:%s",
+            GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad));
+
+  newcaps = GST_PAD_CAPS (pad);
+
+  do {
+    currentcaps = newcaps;
+
+    /* this pad wants to negotiate */
+    if (currentpad->negotiatefunc) {
+
+      GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s, count=%d\n",
+                 GST_DEBUG_PAD_NAME(currentpad), counter);
+      newcaps = (currentpad->negotiatefunc) (GST_PAD (currentpad), currentcaps, counter);
+
+      if (newcaps == NULL) {
+        GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has refused, negotiation failed :(, count=%d\n",
+                   GST_DEBUG_PAD_NAME(currentpad), counter);
+       return FALSE;
+      }
+      if (newcaps == currentcaps) {
+        GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s aggreed with caps, count=%d\n",
+                   GST_DEBUG_PAD_NAME(currentpad), counter);
+       break;
+      }
+    }
+    /* this pad doesn't want to negotiate, take its caps and that will be it then */
+    else {
+      GST_DEBUG (GST_CAT_ELEMENT_PADS, "getting caps from pad %s:%s, count=%d\n",
+                 GST_DEBUG_PAD_NAME(currentpad), counter);
+      newcaps = GST_PAD_CAPS (currentpad);
+    }
+    /* we have a caps structure now */
+
+    /* check if the other pad wants to negotiate */
+    if (!otherpad->negotiatefunc) {
+      /* the pad doesn't want to negotiate, so we check if the caps
+       * we got from the current pad are compatible */
+        GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s doesn't want to negotiate, count=%d\n",
+                   GST_DEBUG_PAD_NAME(otherpad), counter);
+       if (!otherpad->caps ||
+           gst_caps_check_compatibility (newcaps, otherpad->caps)) {
+          GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps, count=%d\n",
+                   GST_DEBUG_PAD_NAME(otherpad), counter);
+        /* we're lucky */
+         break;
+       }
+       /* else, we let the current pad select another caps */
+    }
+    /* if the other pad wants to negotiate, setup the pointers */
+    else {
+      GstRealPad *temp;
+
+      GST_DEBUG (GST_CAT_ELEMENT_PADS, "switching pads for next phase\n");
+
+      temp = currentpad;
+      currentpad = otherpad;
+      otherpad = temp;
+    }
+
+    counter++;
+
+  } while (counter < 100); // FIXME
+
+  GST_DEBUG (GST_CAT_ELEMENT_PADS, "pads aggreed on caps :)\n");
+
+  /* here we have some sort of aggreement of the caps */
+  GST_PAD_CAPS (currentpad) = newcaps;
+  GST_PAD_CAPS (otherpad) = newcaps;
+   
+  return TRUE;
+}
+
+GstCaps*
+gst_pad_negotiate_proxy (GstPad *pad, GstCaps *caps, gint count)
+{
+  GstRealPad *peer;
+  GstCaps *newcaps = caps;
+
+  g_return_val_if_fail (pad != NULL, NULL);
+
+  GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad (%s:%s) proxied\n", GST_DEBUG_PAD_NAME (pad));
+
+  peer = GST_RPAD_PEER (pad);
+
+  GST_PAD_CAPS (pad) = caps;
+
+  if (peer) {
+    if (peer->negotiatefunc) {
+      GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate on peer (%s:%s)\n", GST_DEBUG_PAD_NAME (peer));
+      newcaps = peer->negotiatefunc (pad, caps, count);
+    }
+    else if (!peer->caps ||
+      gst_caps_check_compatibility (newcaps, peer->caps)) {
+        GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps\n",
+                 GST_DEBUG_PAD_NAME(peer));
+    }
+    else return NULL;
+  }
+
+  if (caps == newcaps) {
+    GST_PAD_CAPS (pad) = newcaps;
+    if (peer) GST_PAD_CAPS (peer) = newcaps;
+  }
+
+  return newcaps;
+}
 
 /**
  * gst_pad_save_thyself:
@@ -1113,8 +1286,9 @@ gst_padtemplate_new (GstPadFactory *factory)
 
   tag = (*factory)[i++];
 
-  while (GPOINTER_TO_INT (tag) == 1) {
-    new->caps = g_list_append (new->caps, gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
+  while (GPOINTER_TO_INT (tag) == GST_PAD_FACTORY_CAPS_ID) {
+    GST_PADTEMPLATE_CAPS (new) = gst_caps_append (GST_PADTEMPLATE_CAPS (new), 
+                   gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
     i+=counter;
     tag = (*factory)[i++];
   }
@@ -1136,7 +1310,7 @@ gst_padtemplate_new (GstPadFactory *factory)
 GstPadTemplate*
 gst_padtemplate_create (gchar *name_template,
                        GstPadDirection direction, GstPadPresence presence,
-                       GList *caps)
+                       GstCaps *caps)
 {
   GstPadTemplate *new;
 
@@ -1144,14 +1318,29 @@ gst_padtemplate_create (gchar *name_template,
 
   new = gtk_type_new (gst_padtemplate_get_type ());
 
-  new->name_template = name_template;
-  new->direction = direction;
-  new->presence = presence;
-  new->caps = caps;
+  GST_PADTEMPLATE_NAME_TEMPLATE (new) = name_template;
+  GST_PADTEMPLATE_DIRECTION (new) = direction;
+  GST_PADTEMPLATE_PRESENCE (new) = presence;
+  GST_PADTEMPLATE_CAPS (new) = caps;
 
   return new;
 }
 
+/**
+ * gst_padtemplate_get_caps:
+ * @templ: the padtemplate to use
+ *
+ * Get the capabilities of the padtemplate
+ *
+ * Returns: a GstCaps*
+ */
+GstCaps*
+gst_padtemplate_get_caps (GstPadTemplate *templ)
+{
+  g_return_val_if_fail (templ != NULL, NULL);
+
+  return GST_PADTEMPLATE_CAPS (templ);
+}
 
 /**
  * gst_padtemplate_save_thyself:
@@ -1166,9 +1355,10 @@ xmlNodePtr
 gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
 {
   xmlNodePtr subtree;
-  GList *caps;
   guchar *presence;
 
+  GST_DEBUG (0,"saving padtemplate %s\n", templ->name_template);
+
   xmlNewChild(parent,NULL,"nametemplate", templ->name_template);
   xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src"));
 
@@ -1188,14 +1378,9 @@ gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
   }
   xmlNewChild(parent,NULL,"presence", presence);
 
-  caps = templ->caps;
-  while (caps) {
-    GstCaps *cap = (GstCaps *)caps->data;
-
+  if (GST_PADTEMPLATE_CAPS (templ)) {
     subtree = xmlNewChild (parent, NULL, "caps", NULL);
-    gst_caps_save_thyself (cap, subtree);
-
-    caps = g_list_next (caps);
+    gst_caps_save_thyself (GST_PADTEMPLATE_CAPS (templ), subtree);
   }
 
   return parent;
@@ -1217,7 +1402,7 @@ gst_padtemplate_load_thyself (xmlNodePtr parent)
   gchar *name_template = NULL;
   GstPadDirection direction = GST_PAD_UNKNOWN;
   GstPadPresence presence = GST_PAD_ALWAYS;
-  GList *caps = NULL;
+  GstCaps *caps = NULL;
 
   while (field) {
     if (!strcmp(field->name, "nametemplate")) {
@@ -1249,7 +1434,7 @@ gst_padtemplate_load_thyself (xmlNodePtr parent)
       g_free (value);
     }
     else if (!strcmp(field->name, "caps")) {
-      caps = g_list_append (caps, gst_caps_load_thyself (field));
+      caps = gst_caps_load_thyself (field);
     }
     field = field->next;
   }
index ef21617..a392719 100644 (file)
@@ -92,6 +92,7 @@ typedef void (*GstPadPushFunction) (GstPad *pad, GstBuffer *buf);
 typedef GstBuffer *(*GstPadPullFunction) (GstPad *pad);
 typedef GstBuffer *(*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
 typedef gboolean (*GstPadEOSFunction) (GstPad *pad);
+typedef GstCaps* (*GstPadNegotiateFunction) (GstPad *pad, GstCaps *caps, gint count);
 
 typedef enum {
   GST_PAD_UNKNOWN,
@@ -121,7 +122,7 @@ struct _GstPadClass {
 struct _GstRealPad {
   GstPad pad;
 
-  GList *caps;
+  GstCaps *caps;
   GstPadDirection direction;
 
   cothread_state *threadstate;
@@ -143,6 +144,8 @@ struct _GstRealPad {
   GstPadPullFunction pullfunc;
   GstPadPullRegionFunction pullregionfunc;
 
+  GstPadNegotiateFunction negotiatefunc;
+
   GList *ghostpads;
 };
 
@@ -186,6 +189,7 @@ struct _GstGhostPadClass {
 #define GST_RPAD_PULLREGIONFUNC(pad)   (((GstRealPad *)(pad))->pullregionfunc)
 #define GST_RPAD_QOSFUNC(pad)          (((GstRealPad *)(pad))->qosfunc)
 #define GST_RPAD_EOSFUNC(pad)          (((GstRealPad *)(pad))->eosfunc)
+#define GST_RPAD_NEGOTIATEFUNC(pad)    (((GstRealPad *)(pad))->negotiatefunc)
 
 #define GST_RPAD_REGIONTYPE(pad)       (((GstRealPad *)(pad))->regiontype)
 #define GST_RPAD_OFFSET(pad)           (((GstRealPad *)(pad))->offset)
@@ -201,7 +205,7 @@ struct _GstGhostPadClass {
 #define GST_PAD_PEER(pad)              GST_RPAD_PEER(GST_PAD_REALIZE(pad))
 
 /* Some check functions (unused?) */
-#define GST_PAD_CONNECTED(pad)         (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->peer != NULL)
+#define GST_PAD_CONNECTED(pad)         (GST_PAD_PEER(pad) != NULL)
 #define GST_PAD_CAN_PULL(pad)          (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->pullfunc != NULL)
 
 
@@ -218,13 +222,18 @@ typedef enum {
   GST_PAD_REQUEST,
 } GstPadPresence;
 
+#define GST_PADTEMPLATE_NAME_TEMPLATE(templ)   (((GstPadTemplate *)(templ))->name_template)
+#define GST_PADTEMPLATE_DIRECTION(templ)       (((GstPadTemplate *)(templ))->direction)
+#define GST_PADTEMPLATE_PRESENCE(templ)                (((GstPadTemplate *)(templ))->presence)
+#define GST_PADTEMPLATE_CAPS(templ)            (((GstPadTemplate *)(templ))->caps)
+
 struct _GstPadTemplate {
   GstObject      object;
 
   gchar           *name_template;
   GstPadDirection direction;
   GstPadPresence  presence;
-  GList                  *caps;
+  GstCaps        *caps;
 };
 
 struct _GstPadTemplateClass {
@@ -246,7 +255,8 @@ typedef GstPadFactoryEntry GstPadFactory[];
 #define GST_PAD_FACTORY_SRC            GINT_TO_POINTER(GST_PAD_SRC)
 #define GST_PAD_FACTORY_SINK           GINT_TO_POINTER(GST_PAD_SINK)
 
-#define GST_PAD_FACTORY_CAPS(a...)     GINT_TO_POINTER(1),##a,NULL
+#define GST_PAD_FACTORY_CAPS_ID                1
+#define GST_PAD_FACTORY_CAPS(a...)     GINT_TO_POINTER(GST_PAD_FACTORY_CAPS_ID),##a,NULL
 
 
 GtkType                        gst_pad_get_type                (void);
@@ -264,10 +274,10 @@ void                      gst_pad_set_get_function        (GstPad *pad, GstPadGetFunction get);
 void                   gst_pad_set_getregion_function  (GstPad *pad, GstPadGetRegionFunction getregion);
 void                   gst_pad_set_qos_function        (GstPad *pad, GstPadQoSFunction qos);
 void                   gst_pad_set_eos_function        (GstPad *pad, GstPadEOSFunction eos);
+void                   gst_pad_set_negotiate_function  (GstPad *pad, GstPadNegotiateFunction nego);
 
-void                   gst_pad_set_caps_list           (GstPad *pad, GList *caps);
-GList*                 gst_pad_get_caps_list           (GstPad *pad);
-GstCaps*               gst_pad_get_caps_by_name        (GstPad *pad, gchar *name);
+void                   gst_pad_set_caps                (GstPad *pad, GstCaps *caps);
+GstCaps*               gst_pad_get_caps                (GstPad *pad);
 gboolean               gst_pad_check_compatibility     (GstPad *srcpad, GstPad *sinkpad);
 
 void                   gst_pad_set_element_private     (GstPad *pad, gpointer priv);
@@ -284,11 +294,16 @@ void                      gst_pad_add_ghost_pad           (GstPad *pad, GstPad *ghostpad);
 void                   gst_pad_remove_ghost_pad        (GstPad *pad, GstPad *ghostpad);
 GList*                 gst_pad_get_ghost_pad_list      (GstPad *pad);
 
+GstPadTemplate*                gst_pad_get_padtemplate         (GstPad *pad);
+
 GstPad*                        gst_pad_get_peer                (GstPad *pad);
 
-void                   gst_pad_connect                 (GstPad *srcpad, GstPad *sinkpad);
+gboolean               gst_pad_connect                 (GstPad *srcpad, GstPad *sinkpad);
 void                   gst_pad_disconnect              (GstPad *srcpad, GstPad *sinkpad);
 
+gboolean               gst_pad_renegotiate             (GstPad *pad);
+GstCaps*               gst_pad_negotiate_proxy         (GstPad *pad, GstCaps* caps, gint count);
+
 #if 1
 void                   gst_pad_push                    (GstPad *pad, GstBuffer *buf);
 #else
@@ -325,7 +340,10 @@ GtkType                    gst_padtemplate_get_type        (void);
 GstPadTemplate*                gst_padtemplate_new             (GstPadFactory *factory);
 GstPadTemplate*                gst_padtemplate_create          (gchar *name_template,
                                                         GstPadDirection direction, GstPadPresence presence,
-                                                        GList *caps);
+                                                        GstCaps *caps);
+
+GstCaps*               gst_padtemplate_get_caps        (GstPadTemplate *templ);
+GstCaps*               gst_padtemplate_get_caps_by_name        (GstPadTemplate *templ, const gchar *name);
 
 xmlNodePtr             gst_padtemplate_save_thyself    (GstPadTemplate *templ, xmlNodePtr parent);
 GstPadTemplate*                gst_padtemplate_load_thyself    (xmlNodePtr parent);
index a500f91..3f2eea8 100644 (file)
@@ -66,6 +66,8 @@ static void                   gst_queue_set_arg       (GtkObject *object, GtkArg *arg, guint id);
 static void                    gst_queue_get_arg       (GtkObject *object, GtkArg *arg, guint id);
 
 static gboolean                        gst_queue_handle_eos    (GstPad *pad);
+static GstCaps*                gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count);
+static GstCaps*                gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count);
 static void                    gst_queue_chain         (GstPad *pad, GstBuffer *buf);
 static GstBuffer *             gst_queue_get           (GstPad *pad);
 
@@ -131,10 +133,12 @@ gst_queue_init (GstQueue *queue)
   gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
   gst_pad_set_eos_function (queue->sinkpad, gst_queue_handle_eos);
+  gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink);
 
   queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
   gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
+  gst_pad_set_negotiate_function (queue->srcpad, gst_queue_handle_negotiate_src);
 
   queue->queue = NULL;
   queue->level_buffers = 0;
@@ -148,6 +152,26 @@ gst_queue_init (GstQueue *queue)
   queue->fullcond = g_cond_new ();
 }
 
+static GstCaps*
+gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  return gst_pad_negotiate_proxy (queue->sinkpad, caps, count);
+}
+
+static GstCaps*
+gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  return gst_pad_negotiate_proxy (queue->srcpad, caps, count);
+}
+
 static gboolean
 gst_queue_handle_eos (GstPad *pad)
 {
index f0b7459..1310588 100644 (file)
@@ -285,7 +285,7 @@ gst_play_typefind (GstBin *bin, GstElement *element)
   if (found) {
     caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps");
 
-    gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps));
+    gst_pad_set_caps (gst_element_get_pad (element, "src"), caps);
   }
 
   gst_pad_disconnect (gst_element_get_pad (element, "src"),
@@ -360,7 +360,7 @@ gst_play_set_uri (GstPlay *play,
   gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play);
 
   new_element = gst_autoplug_to_renderers (autoplug,
-          gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
+          gst_pad_get_caps (gst_element_get_pad (priv->src, "src")),
           priv->video_element,
           priv->audio_element,
           NULL);
index 1027729..5499e3a 100644 (file)
@@ -417,8 +417,9 @@ gst_audiosink_change_state (GstElement *element)
   /* otherwise (READY or higher) we need to open the sound card */
   } else {
     if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) {
-      if (!gst_audiosink_open_audio (GST_AUDIOSINK (element)))
-        return GST_STATE_FAILURE;
+      if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) {
+        //return GST_STATE_FAILURE;
+      }
     }
   }
       
index a500f91..3f2eea8 100644 (file)
@@ -66,6 +66,8 @@ static void                   gst_queue_set_arg       (GtkObject *object, GtkArg *arg, guint id);
 static void                    gst_queue_get_arg       (GtkObject *object, GtkArg *arg, guint id);
 
 static gboolean                        gst_queue_handle_eos    (GstPad *pad);
+static GstCaps*                gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count);
+static GstCaps*                gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count);
 static void                    gst_queue_chain         (GstPad *pad, GstBuffer *buf);
 static GstBuffer *             gst_queue_get           (GstPad *pad);
 
@@ -131,10 +133,12 @@ gst_queue_init (GstQueue *queue)
   gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
   gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
   gst_pad_set_eos_function (queue->sinkpad, gst_queue_handle_eos);
+  gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink);
 
   queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
   gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
   gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
+  gst_pad_set_negotiate_function (queue->srcpad, gst_queue_handle_negotiate_src);
 
   queue->queue = NULL;
   queue->level_buffers = 0;
@@ -148,6 +152,26 @@ gst_queue_init (GstQueue *queue)
   queue->fullcond = g_cond_new ();
 }
 
+static GstCaps*
+gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  return gst_pad_negotiate_proxy (queue->sinkpad, caps, count);
+}
+
+static GstCaps*
+gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count)
+{
+  GstQueue *queue;
+
+  queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+  return gst_pad_negotiate_proxy (queue->srcpad, caps, count);
+}
+
 static gboolean
 gst_queue_handle_eos (GstPad *pad)
 {
index fc4f7a1..2c686c0 100644 (file)
@@ -26,3 +26,4 @@ padfactory
 tee
 autoplug2
 autoplug3
+capsconnect
index 1d82923..27b8a74 100644 (file)
@@ -1,7 +1,8 @@
 SUBDIRS = sched eos 
 
 noinst_PROGRAMS = init loadall simplefake states caps queue registry \
-paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3
+paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 \
+capsconnect
 
 # we have nothing but apps here, we can do this safely
 LIBS += $(GST_LIBS)
index 87913c6..4c1a05c 100644 (file)
@@ -34,8 +34,8 @@ main (int argc, char *argv[])
   gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL);
 
   element = gst_autoplug_to_caps (autoplugger, testcaps,
-                 gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
-                 gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")),
+                 gst_pad_get_caps (gst_element_get_pad (audiosink, "sink")),
+                 gst_pad_get_caps (gst_element_get_pad (videosink, "sink")),
                  NULL);
   g_assert (element != NULL);
 
diff --git a/tests/capsconnect.c b/tests/capsconnect.c
new file mode 100644 (file)
index 0000000..01e8e7b
--- /dev/null
@@ -0,0 +1,62 @@
+#include <gst/gst.h>
+
+int main(int argc,char *argv[]) 
+{
+  gboolean testret;
+  xmlDocPtr doc;
+  xmlNodePtr parent;
+  GstElement *mpg123;
+  GstElement *mp3parse;
+  GstElement *queue;
+  GstPad *sinkpad;
+  GstPad *srcpad;
+  GstPad *qsinkpad;
+
+  doc = xmlNewDoc ("1.0");
+  doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
+
+  gst_init (&argc, &argv);
+
+  mpg123 = gst_elementfactory_make ("mpg123", "mpg123");
+  g_assert (mpg123 != NULL);
+
+  sinkpad = gst_element_get_pad (mpg123, "sink");
+  g_assert (sinkpad != NULL);
+
+  queue = gst_elementfactory_make ("queue", "queue");
+  g_assert (queue != NULL);
+  
+  srcpad = gst_element_get_pad (queue, "src");
+  g_assert (srcpad != NULL);
+  qsinkpad = gst_element_get_pad (queue, "sink");
+  g_assert (qsinkpad != NULL);
+  
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent);
+
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent);
+
+  gst_pad_connect (srcpad, sinkpad);
+  
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect src", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent);
+
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent);
+
+  mp3parse = gst_elementfactory_make ("mp3parse", "mp3parse");
+  g_assert (mp3parse != NULL);
+
+  gst_pad_connect (gst_element_get_pad (mp3parse, "src"), qsinkpad);
+
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent);
+
+  parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps after connect sink", NULL);
+  gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent);
+
+  xmlDocDump(stdout, doc);
+
+  return 0;
+}
diff --git a/tests/nego/.gitignore b/tests/nego/.gitignore
new file mode 100644 (file)
index 0000000..3224b98
--- /dev/null
@@ -0,0 +1,9 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+nego1
diff --git a/tests/nego/Makefile.am b/tests/nego/Makefile.am
new file mode 100644 (file)
index 0000000..4260472
--- /dev/null
@@ -0,0 +1,5 @@
+noinst_PROGRAMS = nego1
+
+# jsut apps here, this is safe
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/tests/nego/nego1.c b/tests/nego/nego1.c
new file mode 100644 (file)
index 0000000..23848bc
--- /dev/null
@@ -0,0 +1,59 @@
+#include <gst/gst.h>
+
+/* this is an example of the src pad dictating the caps
+ * the sink pad only accepts audio/raw */
+
+static GstCaps*
+negotiate (GstPad *pad, GstCaps *caps, gint count) 
+{
+  g_print ("negotiation entered\n");
+
+  if (!strcmp (gst_caps_get_mime (caps), "audio/raw"))
+    return caps;
+
+  return NULL;
+}
+
+int 
+main(int argc,char *argv[]) 
+{
+  GstPad *srcpad, *sinkpad;
+  GstCaps *new;
+
+  gst_init(&argc,&argv);
+
+  srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+
+  gst_pad_connect (srcpad, sinkpad);
+
+  gst_pad_set_negotiate_function (sinkpad, negotiate);
+
+ /* fill in our desired caps */
+  new = gst_caps_new_with_props (
+          "src_caps",                       /* name */
+          "audio/raw",                      /* mime */
+          gst_props_new (
+            "format",   GST_PROPS_INT (16),
+            "depth",    GST_PROPS_INT (16),
+            "rate",     GST_PROPS_INT (48000),
+            "channels", GST_PROPS_INT (2),
+            NULL
+          )
+        );
+
+  gst_pad_set_caps (srcpad, new);
+
+  new = gst_caps_new_with_props (
+          "src_caps",                       /* name */
+          "video/raw",                      /* mime */
+          gst_props_new (
+            "format",   GST_PROPS_FOURCC ('Y','U','Y','V'),
+            NULL
+          )
+        );
+
+  gst_pad_set_caps (srcpad, new);
+
+  exit (0);
+}