parse: Refactor grammar, make it more consistent and fix conflicts
authorFabian Kirsch <derFakir@web.de>
Fri, 10 Jan 2014 20:10:17 +0000 (21:10 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 14 Jan 2014 12:46:22 +0000 (13:46 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=710034

gst/parse/grammar.y
gst/parse/parse.l
gst/parse/types.h
tests/check/pipelines/parse-launch.c

index 748205a..c789dff 100644 (file)
 #define YYLTYPE_IS_TRIVIAL 0
 #endif
 
+/*******************************************************************************************
+*** Tracing memory leaks
+*******************************************************************************************/
+
 #ifdef __GST_PARSE_TRACE
 static guint __strings;
 static guint __links;
@@ -56,7 +60,7 @@ __gst_parse_strfree (gchar *str)
     __strings--;
   }
 }
-link_t *__gst_parse_link_new ()
+link_t *__gst_parse_link_new (void)
 {
   link_t *ret;
   __links++;
@@ -75,18 +79,18 @@ __gst_parse_link_free (link_t *data)
   }
 }
 chain_t *
-__gst_parse_chain_new ()
+__gst_parse_chain_new (void)
 {
   chain_t *ret;
   __chains++;
   ret = g_slice_new0 (chain_t);
-  /* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */
+  //g_print ("@%p: ALLOCATED CHAIN (%3u):\n", ret, __chains);
   return ret;
 }
 void
 __gst_parse_chain_free (chain_t *data)
 {
-  /* g_print ("FREEING CHAIN   (%3u): %p\n", __chains - 1, data); */
+  //g_print ("@%p: FREEING CHAIN   (%3u):\n", data, __chains - 1);
   g_slice_free (chain_t, data);
   g_return_if_fail (__chains > 0);
   __chains--;
@@ -94,22 +98,9 @@ __gst_parse_chain_free (chain_t *data)
 
 #endif /* __GST_PARSE_TRACE */
 
-typedef struct {
-  gchar *src_pad;
-  gchar *sink_pad;
-  GstElement *sink;
-  GstCaps *caps;
-  gulong signal_id;
-} DelayedLink;
-
-typedef struct {
-  gchar *name;
-  gchar *value_str;
-  gulong signal_id;
-} DelayedSet;
-
-/*** define SET_ERROR macro/function */
-
+/*******************************************************************************************
+*** define SET_ERROR macro/function
+*******************************************************************************************/
 #ifdef G_HAVE_ISO_VARARGS
 
 #  define SET_ERROR(error, type, ...) \
@@ -204,80 +195,70 @@ YYPRINTF(const char *format, ...)
 #include "grammar.tab.h"
 #include "parse_lex.h"
 
+/*******************************************************************************************
+*** report missing elements/bins/..
+*******************************************************************************************/
 
-#define ADD_MISSING_ELEMENT(graph,name) G_STMT_START {                      \
-    if ((graph)->ctx) {                                                     \
-      (graph)->ctx->missing_elements =                                      \
-          g_list_append ((graph)->ctx->missing_elements, g_strdup (name));  \
-    } } G_STMT_END
 
-static void
-no_free (gconstpointer foo)
-{
-  /* do nothing */
+static void  add_missing_element(graph_t *graph,gchar *name){
+  if ((graph)->ctx){
+    (graph)->ctx->missing_elements = g_list_append ((graph)->ctx->missing_elements, g_strdup (name));
+    }
 }
 
-#define GST_BIN_MAKE(res, type, chainval, assign, type_string_free_func) \
-G_STMT_START { \
-  chain_t *chain = chainval; \
-  GSList *walk; \
-  GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
-  if (!chain) { \
-    SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN, \
-        _("specified empty bin \"%s\", not allowed"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    gst_object_unref (bin); \
-    type_string_free_func (type); /* Need to clean up the string */ \
-    YYERROR; \
-  } else if (!bin) { \
-    ADD_MISSING_ELEMENT(graph, type); \
-    SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
-        _("no bin \"%s\", skipping"), type); \
-    g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
-    g_slist_free (assign); \
-    res = chain; \
-  } else { \
-    for (walk = chain->elements; walk; walk = walk->next ) \
-      gst_bin_add (bin, GST_ELEMENT (walk->data)); \
-    g_slist_free (chain->elements); \
-    chain->elements = g_slist_prepend (NULL, bin); \
-    res = chain; \
-    /* set the properties now */ \
-    for (walk = assign; walk; walk = walk->next) \
-      gst_parse_element_set ((gchar *) walk->data, GST_ELEMENT (bin), graph); \
-    g_slist_free (assign); \
-  } \
-} G_STMT_END
 
-#define MAKE_LINK(link, _src, _src_name, _src_pads, _sink, _sink_name, _sink_pads) \
-G_STMT_START { \
-  link = gst_parse_link_new (); \
-  link->src = _src; \
-  link->sink = _sink; \
-  link->src_name = _src_name; \
-  link->sink_name = _sink_name; \
-  link->src_pads = _src_pads; \
-  link->sink_pads = _sink_pads; \
-  link->caps = NULL; \
+/*******************************************************************************************
+*** helpers for pipeline-setup
+*******************************************************************************************/
+
+#define TRY_SETUP_LINK(l) G_STMT_START { \
+   if( (!(l)->src.element) && (!(l)->src.name) ){ \
+     SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no source [sink=%s@%p]"), \
+       (l)->sink.name ? (l)->sink.name : _(""), \
+       (l)->sink.element); \
+     gst_parse_free_link (l); \
+   }else if( (!(l)->sink.element) && (!(l)->sink.name) ){ \
+     SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no sink [source=%s@%p]"), \
+       (l)->src.name ? (l)->src.name :_(""), \
+       (l)->src.element); \
+     gst_parse_free_link (l); \
+   }else{ \
+     graph->links = g_slist_prepend (graph->links, l ); \
+   }   \
 } G_STMT_END
 
-#define MAKE_REF(link, _src, _pads) \
-G_STMT_START { \
-  gchar *padname = _src; \
-  GSList *pads = _pads; \
-  if (padname) { \
-    while (*padname != '.') padname++; \
-    *padname = '\0'; \
-    padname++; \
-    if (*padname != '\0') \
-      pads = g_slist_prepend (pads, gst_parse_strdup (padname)); \
-  } \
-  MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \
-} G_STMT_END
+typedef struct {
+  gchar *src_pad;
+  gchar *sink_pad;
+  GstElement *sink;
+  GstCaps *caps;
+  gulong signal_id;
+} DelayedLink;
 
-static void
-gst_parse_free_delayed_set (DelayedSet *set)
+typedef struct {
+  gchar *name;
+  gchar *value_str;
+  gulong signal_id;
+} DelayedSet;
+
+static int  gst_resolve_reference(reference_t *rr, GstElement *pipeline){
+  GstBin *bin;
+
+  if(rr->element) return  0;  /* already resolved! */
+  if(!rr->name)   return -2;  /* no chance! */
+
+  if (GST_IS_BIN (pipeline)){
+    bin = GST_BIN (pipeline);
+    rr->element = gst_bin_get_by_name_recurse_up (bin, rr->name);
+  } else {
+    rr->element = strcmp (GST_ELEMENT_NAME (pipeline), rr->name) == 0 ? 
+               gst_object_ref(pipeline) : NULL;
+  }
+  if(rr->element) return 0; /* resolved */
+  else            return -1; /* not found */
+}
+
+static void gst_parse_free_delayed_set (DelayedSet *set)
 {
   g_free(set->name);
   g_free(set->value_str);
@@ -287,8 +268,7 @@ gst_parse_free_delayed_set (DelayedSet *set)
 static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
     const gchar * name, gpointer data);
 
-static void
-gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str)
+static void gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str)
 {
   DelayedSet *data = g_slice_new0 (DelayedSet);
 
@@ -324,8 +304,7 @@ gst_parse_add_delayed_set (GstElement *element, gchar *name, gchar *value_str)
   }
 }
 
-static void
-gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
+static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
     const gchar * name, gpointer data)
 {
   DelayedSet *set = (DelayedSet *) data;
@@ -384,8 +363,7 @@ error:
   goto out;
 }
 
-static void
-gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
+static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
 {
   GParamSpec *pspec = NULL;
   gchar *pos = value;
@@ -473,21 +451,34 @@ error:
   goto out;
 }
 
-static inline void
-gst_parse_free_link (link_t *link)
+static void gst_parse_free_reference (reference_t *rr)
 {
-  gst_parse_strfree (link->src_name);
-  gst_parse_strfree (link->sink_name);
-  g_slist_foreach (link->src_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_foreach (link->sink_pads, (GFunc) gst_parse_strfree, NULL);
-  g_slist_free (link->src_pads);
-  g_slist_free (link->sink_pads);
+  if(rr->element) gst_object_unref(rr->element);
+  gst_parse_strfree (rr->name);
+  g_slist_foreach (rr->pads, (GFunc) gst_parse_strfree, NULL);
+  g_slist_free (rr->pads);
+}
+
+static void gst_parse_free_link (link_t *link)
+{
+  gst_parse_free_reference (&(link->src));
+  gst_parse_free_reference (&(link->sink));
   if (link->caps) gst_caps_unref (link->caps);
   gst_parse_link_free (link);
 }
 
-static void
-gst_parse_free_delayed_link (DelayedLink *link)
+static void gst_parse_free_chain (chain_t *ch)
+{
+  GSList *walk;
+  gst_parse_free_reference (&(ch->first));
+  gst_parse_free_reference (&(ch->last));
+  for(walk=ch->elements;walk;walk=walk->next)
+    gst_object_unref (walk->data);
+  g_slist_free (ch->elements);
+  gst_parse_chain_free (ch);
+}
+
+static void gst_parse_free_delayed_link (DelayedLink *link)
 {
   g_free (link->src_pad);
   g_free (link->sink_pad);
@@ -495,8 +486,7 @@ gst_parse_free_delayed_link (DelayedLink *link)
   g_slice_free (DelayedLink, link);
 }
 
-static void
-gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
+static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
 {
   DelayedLink *link = data;
 
@@ -563,17 +553,17 @@ gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
 static gint
 gst_parse_perform_link (link_t *link, graph_t *graph)
 {
-  GstElement *src = link->src;
-  GstElement *sink = link->sink;
-  GSList *srcs = link->src_pads;
-  GSList *sinks = link->sink_pads;
+  GstElement *src = link->src.element;
+  GstElement *sink = link->sink.element;
+  GSList *srcs = link->src.pads;
+  GSList *sinks = link->sink.pads;
   g_assert (GST_IS_ELEMENT (src));
   g_assert (GST_IS_ELEMENT (sink));
 
   GST_CAT_INFO (GST_CAT_PIPELINE,
       "linking %s:%s to %s:%s (%u/%u) with caps \"%" GST_PTR_FORMAT "\"",
-      GST_ELEMENT_NAME (src), link->src_name ? link->src_name : "(any)",
-      GST_ELEMENT_NAME (sink), link->sink_name ? link->sink_name : "(any)",
+      GST_ELEMENT_NAME (src), link->src.name ? link->src.name : "(any)",
+      GST_ELEMENT_NAME (sink), link->sink.name ? link->sink.name : "(any)",
       g_slist_length (srcs), g_slist_length (sinks), link->caps);
 
   if (!srcs || !sinks) {
@@ -591,7 +581,7 @@ gst_parse_perform_link (link_t *link, graph_t *graph)
       }
     }
   }
-  if (g_slist_length (link->src_pads) != g_slist_length (link->sink_pads)) {
+  if (g_slist_length (link->src.pads) != g_slist_length (link->sink.pads)) {
     goto error;
   }
   while (srcs && sinks) {
@@ -630,27 +620,40 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
 %}
 
 %union {
-    gchar *s;
-    chain_t *c;
-    link_t *l;
-    GstElement *e;
-    GSList *p;
-    graph_t *g;
+    gchar *ss;
+    chain_t *cc;
+    link_t *ll;
+    reference_t rr;
+    GstElement *ee;
+    GSList *pp;
+    graph_t *gg;
 }
 
-%token <s> PARSE_URL
-%token <s> IDENTIFIER
-%left <s> REF PADREF BINREF
-%token <s> ASSIGNMENT
-%token <s> LINK
+%token <ss> PARSE_URL
+%token <ss> IDENTIFIER
+%left  <ss> REF PADREF BINREF 
+%token <ss> ASSIGNMENT
+%token <ss> LINK
+
+%type <ss> binopener
+%type <gg> graph
+%type <cc> chain bin chainlist openchain elementary
+%type <rr> reference
+%type <ll> link
+%type <ee> element
+%type <pp> morepads pads assignments
+
+%destructor {  gst_parse_strfree ($$);         } <ss>
+%destructor {  gst_parse_free_chain($$);       } <cc>
+%destructor {  gst_parse_free_link ($$);       } <ll>
+%destructor {  gst_parse_free_reference(&($$));} <rr>
+%destructor {  gst_object_unref ($$);          } <ee>
+%destructor {  GSList *walk;
+               for(walk=$$;walk;walk=walk->next)
+                 gst_parse_strfree (walk->data);
+               g_slist_free ($$);              } <pp>
+
 
-%type <g> graph
-%type <c> chain bin
-%type <l> reference
-%type <l> linkpart link
-%type <p> linklist
-%type <e> element
-%type <p> padlist pads assignments
 
 %left '(' ')'
 %left ','
@@ -665,17 +668,19 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
 %start graph
 %%
 
+/*************************************************************
+* Grammar explanation:
+*   _element_s are specified by an identifier of their type.
+*   a name can be give in the optional property-assignments
+*      coffeeelement
+*      fakesrc name=john
+*      identity silence=false name=frodo
+*   (cont'd)
+**************************************************************/
 element:       IDENTIFIER                    { $$ = gst_element_factory_make ($1, NULL);
                                                if ($$ == NULL) {
-                                                 ADD_MISSING_ELEMENT (graph, $1);
+                                                 add_missing_element(graph, $1);
                                                  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
-                                                 /* if FATAL_ERRORS flag is set, we don't have to worry about backwards
-                                                  * compatibility and can continue parsing and check for other missing
-                                                  * elements */
-                                                 if ((graph->flags & GST_PARSE_FLAG_FATAL_ERRORS) == 0) {
-                                                   gst_parse_strfree ($1);
-                                                   YYERROR;
-                                                 }
                                                }
                                                gst_parse_strfree ($1);
                                               }
@@ -683,211 +688,307 @@ element:        IDENTIFIER                    { $$ = gst_element_factory_make ($1, NULL);
                                                $$ = $1;
                                              }
        ;
-assignments:   /* NOP */                     { $$ = NULL; }
-       |       assignments ASSIGNMENT        { $$ = g_slist_prepend ($1, $2); }
+
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   a graph has (pure) _element_s, _bin_s and _link_s.
+*   since bins are special elements, bins and elements can
+*   be generalized as _elementary_.
+*   The construction of _bin_s will be discussed later.
+*   (cont'd)
+*
+**************************************************************/
+elementary:
+       element                               { $$ = gst_parse_chain_new ();
+                                               //g_print ("@%p: CHAINing elementary\n", $$);
+                                               $$->first.element = $1? gst_object_ref($1) : NULL;
+                                               $$->last.element = $1? gst_object_ref($1) : NULL;
+                                               $$->first.name = $$->last.name = NULL;
+                                               $$->first.pads = $$->last.pads = NULL;
+                                               $$->elements = $1 ? g_slist_prepend (NULL, $1) : NULL;
+                                             }
+       | bin                                 { $$=$1; }
        ;
-bin:           '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2, no_free); }
-        |       BINREF assignments chain ')'  { GST_BIN_MAKE ($$, $1, $3, $2, gst_parse_strfree);
-                                               gst_parse_strfree ($1);
+
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   a _chain_ is a list of _elementary_s that have _link_s inbetween
+*   which are represented through infix-notation.
+*
+*      fakesrc ! sometransformation ! fakesink
+*
+*   every _link_ can be augmented with _pads_.
+*
+*      coffeesrc .sound ! speakersink
+*      multisrc  .movie,ads ! .projector,smallscreen multisink
+*
+*   and every _link_ can be setup to filter media-types
+*      mediasrc ! audio/x-raw, signed=TRUE ! stereosink
+*
+* User HINT:
+*   if the lexer does not recognize your media-type it
+*   will make it an element name. that results in errors
+*   like
+*      NO SUCH ELEMENT: no element audio7x-raw
+*   '7' vs. '/' in https://en.wikipedia.org/wiki/QWERTZ
+*
+* Parsing HINT:
+*   in the parser we need to differ between chains that can
+*   be extended by more elementaries (_openchain_) and others
+*   that are syntactically closed (handled later in this file).
+*      (e.g. fakesrc ! sinkreferencename.padname)
+**************************************************************/
+chain: openchain                             { $$=$1; 
+                                               if($$->last.name){
+                                                       SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX,
+                                                       _("unexpected reference \"%s\" - ignoring"), $$->last.name);
+                                                       gst_parse_strfree($$->last.name);
+                                                       $$->last.name=NULL;
+                                               }
+                                               if($$->last.pads){
+                                                       SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX,
+                                                       _("unexpected pad-reference \"%s\" - ignoring"), (gchar*)$$->last.pads->data);
+                                                       g_slist_foreach ($$->last.pads, (GFunc) gst_parse_strfree, NULL);
+                                                       g_slist_free ($$->last.pads);
+                                                       $$->last.pads=NULL;
+                                               }
                                              }
-        |       BINREF assignments ')'       { GST_BIN_MAKE ($$, $1, NULL, $2, gst_parse_strfree);
-                                               gst_parse_strfree ($1);
+       ;
+
+openchain:
+       elementary pads                       { $$=$1;
+                                               $$->last.pads = g_slist_concat ($$->last.pads, $2);
+                                               //g_print ("@%p@%p: FKI elementary pads\n", $1, $$->last.pads);
                                              }
-        |       BINREF assignments error ')'  { GST_BIN_MAKE ($$, $1, NULL, $2, gst_parse_strfree);
-                                               gst_parse_strfree ($1);
+       | openchain link pads elementary pads
+                                             {
+                                               $2->src  = $1->last;
+                                               $2->sink = $4->first;
+                                               $2->sink.pads = g_slist_concat ($3, $2->sink.pads);
+                                               TRY_SETUP_LINK($2);
+                                               $4->first = $1->first;
+                                               $4->elements = g_slist_concat ($1->elements, $4->elements);
+                                               gst_parse_chain_free($1);
+                                               $$ = $4;
+                                               $$->last.pads = g_slist_concat ($$->last.pads, $5);
                                              }
+
        ;
 
-pads:          PADREF                        { $$ = g_slist_prepend (NULL, $1); }
-       |       PADREF padlist                { $$ = $2;
-                                               $$ = g_slist_prepend ($$, $1);
+link:  LINK                                  { $$ = gst_parse_link_new ();
+                                               $$->src.element = NULL;
+                                               $$->sink.element = NULL;
+                                               $$->src.name = NULL;
+                                               $$->sink.name = NULL;
+                                               $$->src.pads = NULL;
+                                               $$->sink.pads = NULL;
+                                               $$->caps = NULL; 
+                                               if ($1) {
+                                                 $$->caps = gst_caps_from_string ($1);
+                                                 if ($$->caps == NULL)
+                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
+                                                 gst_parse_strfree ($1);
+                                               }
                                              }
        ;
-padlist:       ',' IDENTIFIER                { $$ = g_slist_prepend (NULL, $2); }
-       |       ',' IDENTIFIER padlist        { $$ = g_slist_prepend ($3, $2); }
+pads:          /* NOP */                     { $$ = NULL; }
+       |       PADREF morepads               { $$ = $2;
+                                               $$ = g_slist_prepend ($$, $1);
+                                             }
        ;
-
-reference:     REF                           { MAKE_REF ($$, $1, NULL); }
-       |       REF padlist                   { MAKE_REF ($$, $1, $2); }
+morepads:      /* NOP */                     { $$ = NULL; }
+       |       ',' IDENTIFIER morepads       { $$ = g_slist_prepend ($3, $2); }
        ;
 
-linkpart:      reference                     { $$ = $1; }
-       |       pads                          { MAKE_REF ($$, NULL, $1); }
-       |       /* NOP */                     { MAKE_REF ($$, NULL, NULL); }
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   the first and last elements of a _chain_ can be give
+*   as URL. This creates special elements that fit the URL.
+*
+*      fakesrc ! http://fake-sink.org
+*       http://somesource.org ! fakesink
+**************************************************************/
+
+chain: openchain link PARSE_URL              { GstElement *element =
+                                                         gst_element_make_from_uri (GST_URI_SINK, $3, NULL, NULL);
+                                               /* FIXME: get and parse error properly */
+                                               if (!element) {
+                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+                                                         _("no sink element for URI \"%s\""), $3);
+                                               }
+                                               $$ = $1;
+                                               $2->sink.element = element?gst_object_ref(element):NULL;
+                                               $2->src = $1->last;
+                                               TRY_SETUP_LINK($2);
+                                               $$->last.element = NULL;
+                                               $$->last.name = NULL;
+                                               $$->last.pads = NULL;
+                                               if(element) $$->elements = g_slist_append ($$->elements, element);
+                                               g_free ($3);
+                                             }
        ;
-
-link:          linkpart LINK linkpart        { $$ = $1;
-                                               if ($2) {
-                                                 $$->caps = gst_caps_from_string ($2);
-                                                 if ($$->caps == NULL)
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $2);
-                                                 gst_parse_strfree ($2);
+openchain:
+       PARSE_URL                             { GstElement *element =
+                                                         gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL);
+                                               /* FIXME: get and parse error properly */
+                                               if (!element) {
+                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+                                                   _("no source element for URI \"%s\""), $1);
                                                }
-                                               $$->sink_name = $3->src_name;
-                                               $$->sink_pads = $3->src_pads;
-                                               gst_parse_link_free ($3);
+                                               $$ = gst_parse_chain_new ();
+                                               //g_print ("@%p: CHAINing srcURL\n", $$);
+                                               $$->first.element = NULL;
+                                               $$->first.name = NULL;
+                                               $$->first.pads = NULL;
+                                               $$->last.element = element ? gst_object_ref(element):NULL;
+                                               $$->last.name = NULL;
+                                               $$->last.pads = NULL;
+                                               $$->elements = element ? g_slist_prepend (NULL, element)  : NULL;
+                                               g_free($1);
                                              }
        ;
 
-linklist:      link                          { $$ = g_slist_prepend (NULL, $1); }
-       |       link linklist                 { $$ = g_slist_prepend ($2, $1); }
-       |       linklist error                { $$ = $1; }
-       ;
 
-chain:         element                       { $$ = gst_parse_chain_new ();
-                                               $$->first = $$->last = $1;
-                                               $$->front = $$->back = NULL;
-                                               $$->elements = g_slist_prepend (NULL, $1);
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   the first and last elements of a _chain_ can be linked
+*   to a named _reference_ (with optional pads).
+*
+*      fakesrc ! nameOfSinkElement.
+*      fakesrc ! nameOfSinkElement.Padname
+*      fakesrc ! nameOfSinkElement.Padname, anotherPad
+*      nameOfSource.Padname ! fakesink
+**************************************************************/
+
+chain: openchain link reference              { $$ = $1;
+                                               $2->sink= $3;
+                                               $2->src = $1->last;
+                                               TRY_SETUP_LINK($2);
+                                               $$->last.element = NULL;
+                                               $$->last.name = NULL;
+                                               $$->last.pads = NULL;
                                              }
-       |       bin                           { $$ = $1; }
-       |       chain chain                   { if ($1->back && $2->front) {
-                                                 if (!$1->back->sink_name) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-                                                   gst_parse_free_link ($1->back);
-                                                 } else {
-                                                   graph->links = g_slist_prepend (graph->links, $1->back);
-                                                 }
-                                                 if (!$2->front->src_name) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-                                                   gst_parse_free_link ($2->front);
-                                                 } else {
-                                                   graph->links = g_slist_prepend (graph->links, $2->front);
-                                                 }
-                                                 $1->back = NULL;
-                                               } else if ($1->back) {
-                                                 if (!$1->back->sink_name) {
-                                                   $1->back->sink = $2->first;
-                                                 }
-                                               } else if ($2->front) {
-                                                 if (!$2->front->src_name) {
-                                                   $2->front->src = $1->last;
-                                                 }
-                                                 $1->back = $2->front;
-                                               }
+       ;
 
-                                               if ($1->back) {
-                                                 graph->links = g_slist_prepend (graph->links, $1->back);
-                                               }
-                                               $1->last = $2->last;
-                                               $1->back = $2->back;
-                                               $1->elements = g_slist_concat ($1->elements, $2->elements);
-                                               if ($2)
-                                                 gst_parse_chain_free ($2);
-                                               $$ = $1;
+
+openchain:
+       reference                             { $$ = gst_parse_chain_new ();
+                                               $$->last=$1;
+                                               $$->first.element = NULL;
+                                               $$->first.name = NULL;
+                                               $$->first.pads = NULL;
+                                               $$->elements = NULL;
                                              }
-       |       chain linklist                { GSList *walk;
-                                               if ($1->back) {
-                                                 $2 = g_slist_prepend ($2, $1->back);
-                                                 $1->back = NULL;
-                                               } else {
-                                                 if (!((link_t *) $2->data)->src_name) {
-                                                   ((link_t *) $2->data)->src = $1->last;
-                                                 }
-                                               }
-                                               for (walk = $2; walk; walk = walk->next) {
-                                                 link_t *link = (link_t *) walk->data;
-                                                 if (!link->sink_name && walk->next) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-                                                   gst_parse_free_link (link);
-                                                 } else if (!link->src_name && !link->src) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-                                                   gst_parse_free_link (link);
-                                                 } else {
-                                                   if (walk->next) {
-                                                     graph->links = g_slist_prepend (graph->links, link);
-                                                   } else {
-                                                     $1->back = link;
-                                                   }
-                                                 }
+       ;
+reference:     REF morepads                  {
+                                               gchar *padname = $1;
+                                               GSList *pads = $2;
+                                               if (padname) {
+                                                 while (*padname != '.') padname++;
+                                                 *padname = '\0';
+                                                 padname++;
+                                                 if (*padname != '\0')
+                                                   pads = g_slist_prepend (pads, gst_parse_strdup (padname));
                                                }
-                                               g_slist_free ($2);
-                                               $$ = $1;
+                                               $$.element=NULL;
+                                               $$.name=$1;
+                                               $$.pads=pads;
                                              }
-       |       chain error                   { $$ = $1; }
-       |       link chain                    { if ($2->front) {
-                                                 if (!$2->front->src_name) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-                                                   gst_parse_free_link ($2->front);
-                                                 } else {
-                                                   graph->links = g_slist_prepend (graph->links, $2->front);
-                                                 }
-                                               }
-                                               if (!$1->sink_name) {
-                                                 $1->sink = $2->first;
+       ;
+
+
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   a _chainlist_ is just a list of _chain_s.
+*
+*   You can specify _link_s with named
+*   _reference_ on each side. That
+*   works already after the explanations above.
+*      someSourceName.Pad ! someSinkName.
+*      someSourceName.Pad,anotherPad ! someSinkName.Apad,Bpad  
+*
+*   If a syntax error occurs, the already finished _chain_s
+*   and _links_ are kept intact.
+*************************************************************/
+
+chainlist: /* NOP */                         { $$ = NULL; }
+       | chainlist chain                     { if ($1){
+                                                 gst_parse_free_reference(&($1->last));
+                                                 gst_parse_free_reference(&($2->first));
+                                                 $2->first = $1->first;
+                                                 $2->elements = g_slist_concat ($1->elements, $2->elements);
+                                                 gst_parse_chain_free ($1);
                                                }
-                                               $2->front = $1;
                                                $$ = $2;
                                              }
-       |       PARSE_URL chain               { $$ = $2;
-                                               if ($$->front) {
-                                                 GstElement *element =
-                                                         gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL);
-                                                 /* FIXME: get and parse error properly */
-                                                 if (!element) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-                                                           _("no source element for URI \"%s\""), $1);
-                                                 } else {
-                                                   $$->front->src = element;
-                                                   graph->links = g_slist_prepend (
-                                                           graph->links, $$->front);
-                                                   $$->front = NULL;
-                                                   $$->elements = g_slist_prepend ($$->elements, element);
-                                                 }
-                                               } else {
-                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
-                                                         _("no element to link URI \"%s\" to"), $1);
-                                               }
-                                               g_free ($1);
+       | chainlist error                     { $$=$1;
+                                               GST_CAT_DEBUG (GST_CAT_PIPELINE,"trying to recover from syntax error");
+                                               SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, _("syntax error"));
                                              }
-       |       link PARSE_URL                { GstElement *element =
-                                                         gst_element_make_from_uri (GST_URI_SINK, $2, NULL, NULL);
-                                               /* FIXME: get and parse error properly */
-                                               if (!element) {
+       ;
+
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   _bins_
+*************************************************************/
+
+
+assignments:   /* NOP */                     { $$ = NULL; }
+       |       assignments ASSIGNMENT        { $$ = g_slist_prepend ($1, $2); }
+       ;
+
+binopener:     '('                           { $$ = gst_parse_strdup(_("bin")); }
+       |       BINREF                        { $$ = $1; }
+       ;
+bin:   binopener assignments chainlist ')'   { 
+                                               chain_t *chain = $3;
+                                               GSList *walk;
+                                               GstBin *bin = (GstBin *) gst_element_factory_make ($1, NULL);
+                                               if (!chain) {
+                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN,
+                                                   _("specified empty bin \"%s\", not allowed"), $1);
+                                                 chain = gst_parse_chain_new ();
+                                                 chain->first.element = chain->last.element = NULL;
+                                                 chain->first.name    = chain->last.name    = NULL;
+                                                 chain->first.pads    = chain->last.pads    = NULL;
+                                                 chain->elements = NULL;
+                                               }
+                                               if (!bin) {
+                                                 add_missing_element(graph, $1);
                                                  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-                                                         _("no sink element for URI \"%s\""), $2);
-                                                 gst_parse_link_free ($1);
-                                                 g_free ($2);
-                                                 YYERROR;
-                                               } else if ($1->sink_name || $1->sink_pads) {
-                                                  gst_object_unref (element);
-                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
-                                                         _("could not link sink element for URI \"%s\""), $2);
-                                                 gst_parse_link_free ($1);
-                                                 g_free ($2);
-                                                 YYERROR;
+                                                   _("no bin \"%s\", unpacking elements"), $1);
+                                                 /* clear property-list */
+                                                 g_slist_foreach ($2, (GFunc) gst_parse_strfree, NULL);
+                                                 g_slist_free ($2);
+                                                 $2 = NULL;
                                                } else {
-                                                 $$ = gst_parse_chain_new ();
-                                                 $$->first = $$->last = element;
-                                                 $$->front = $1;
-                                                 $$->front->sink = element;
-                                                 $$->elements = g_slist_prepend (NULL, element);
+                                                 for (walk = chain->elements; walk; walk = walk->next )
+                                                   gst_bin_add (bin, GST_ELEMENT (walk->data));
+                                                 g_slist_free (chain->elements);
+                                                 chain->elements = g_slist_prepend (NULL, bin);
                                                }
-                                               g_free ($2);
+                                               $$ = chain;
+                                               /* set the properties now
+                                                * HINT: property-list cleared above, if bin==NULL
+                                                */
+                                               for (walk = $2; walk; walk = walk->next)
+                                                 gst_parse_element_set ((gchar *) walk->data,
+                                                       GST_ELEMENT (bin), graph);
+                                               g_slist_free ($2);
+                                               gst_parse_strfree ($1);
                                              }
        ;
-graph:         /* NOP */                     { SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
-                                               $$ = graph;
-                                             }
-       |       chain                         { $$ = graph;
-                                               if ($1->front) {
-                                                 if (!$1->front->src_name) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without source element"));
-                                                   gst_parse_free_link ($1->front);
-                                                 } else {
-                                                   $$->links = g_slist_prepend ($$->links, $1->front);
-                                                 }
-                                                 $1->front = NULL;
-                                               }
-                                               if ($1->back) {
-                                                 if (!$1->back->sink_name) {
-                                                   SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
-                                                   gst_parse_free_link ($1->back);
-                                                 } else {
-                                                   $$->links = g_slist_prepend ($$->links, $1->back);
-                                                 }
-                                                 $1->back = NULL;
-                                               }
+
+/*************************************************************
+* Grammar explanation: (cont'd)
+*   _graph_
+*************************************************************/
+
+graph: chainlist                             { $$ = graph;
                                                $$->chain = $1;
+                                               if(!$1) {
+                                                 SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
+                                               }
                                              }
        ;
 
@@ -928,6 +1029,8 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
   __strings = __chains = __links = 0;
 #endif /* __GST_PARSE_TRACE */
 
+  //g_print("Now scanning: %s\n", str);
+
   dstr = g_strdup (str);
   priv_gst_parse_yylex_init (&scanner);
   priv_gst_parse_yy_scan_string (dstr, scanner);
@@ -952,17 +1055,25 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
       g.chain ? g_slist_length (g.chain->elements) : 0,
       g_slist_length (g.links));
 
-  if (!g.chain) {
-    ret = NULL;
-  } else if (!g.chain->elements->next) {
-    /* only one toplevel element */
-    ret = (GstElement *) g.chain->elements->data;
-    g_slist_free (g.chain->elements);
-    if (GST_IS_BIN (ret))
-      bin = GST_BIN (ret);
-    gst_parse_chain_free (g.chain);
-  } else {
-    /* put all elements in our bin */
+  /* ensure chain is not NULL */
+  if (!g.chain){
+    g.chain=gst_parse_chain_new ();
+    g.chain->elements=NULL;
+    g.chain->first.element=NULL;
+    g.chain->first.name=NULL;
+    g.chain->first.pads=NULL;
+    g.chain->last.element=NULL;
+    g.chain->last.name=NULL;
+    g.chain->last.pads=NULL;
+  };
+  
+  /* ensure elements is not empty */
+  if(!g.chain->elements){
+    g.chain->elements= g_slist_prepend (NULL, NULL);
+  };
+  
+  /* put all elements in our bin if necessary */
+  if(g.chain->elements->next){
     bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
     g_assert (bin);
 
@@ -970,56 +1081,49 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
       if (walk->data != NULL)
         gst_bin_add (bin, GST_ELEMENT (walk->data));
     }
-
     g_slist_free (g.chain->elements);
-    ret = GST_ELEMENT (bin);
-    gst_parse_chain_free (g.chain);
-  }
+    g.chain->elements = g_slist_prepend (NULL, bin);
+  } 
+
+  ret = (GstElement *) g.chain->elements->data;
+  g_slist_free (g.chain->elements);
+  g.chain->elements=NULL;
+  if (GST_IS_BIN (ret))
+    bin = GST_BIN (ret);
+  gst_parse_free_chain (g.chain);
+  g.chain = NULL;
 
-  /* remove links */
+
+  /* resolve and perform links */
   for (walk = g.links; walk; walk = walk->next) {
     link_t *l = (link_t *) walk->data;
-    if (!l->src) {
-      if (l->src_name) {
-        if (bin) {
-          l->src = gst_bin_get_by_name_recurse_up (bin, l->src_name);
-          if (l->src)
-            gst_object_unref (l->src);
-        } else {
-          l->src = strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->src) {
-        if (l->src_name) {
+    int err;
+    err=gst_resolve_reference( &(l->src), ret);
+    if (err) {
+       if(-1==err){
           SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-              "No element named \"%s\" - omitting link", l->src_name);
-        } else {
+              "No src-element named \"%s\" - omitting link", l->src.name);
+       }else{
           /* probably a missing element which we've handled already */
-        }
-        gst_parse_free_link (l);
-        continue;
-      }
+          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+              "No src-element found - omitting link");
+       }
+       gst_parse_free_link (l);
+       continue;
     }
-    if (!l->sink) {
-      if (l->sink_name) {
-        if (bin) {
-          l->sink = gst_bin_get_by_name_recurse_up (bin, l->sink_name);
-          if (l->sink)
-            gst_object_unref (l->sink);
-        } else {
-          l->sink = strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL;
-        }
-      }
-      if (!l->sink) {
-        if (l->sink_name) {
+
+    err=gst_resolve_reference( &(l->sink), ret);
+    if (err) {
+       if(-1==err){
           SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
-              "No element named \"%s\" - omitting link", l->sink_name);
-        } else {
+              "No sink-element named \"%s\" - omitting link", l->src.name);
+       }else{
           /* probably a missing element which we've handled already */
-        }
-        gst_parse_free_link (l);
-        continue;
-      }
+          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+              "No sink-element found - omitting link");
+       }
+       gst_parse_free_link (l);
+       continue;
     }
     gst_parse_perform_link (l, &g);
   }
@@ -1042,7 +1146,7 @@ error1:
   if (g.chain) {
     g_slist_foreach (g.chain->elements, (GFunc)gst_object_unref, NULL);
     g_slist_free (g.chain->elements);
-    gst_parse_chain_free (g.chain);
+    gst_parse_free_chain (g.chain);
   }
 
   g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL);
index 97b8cce..53afba8 100644 (file)
@@ -89,7 +89,7 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)
 {_assignment} {
     /* "=" */
     PRINT ("ASSIGNMENT: %s", yytext);
-    yylval->s = gst_parse_strdup (yytext);
+    yylval->ss = gst_parse_strdup (yytext);
     BEGIN (INITIAL);
     return ASSIGNMENT;
 }
@@ -97,14 +97,14 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)
 {_padref} {
     yytext++;
     PRINT ("PADREF: %s", yytext);
-    yylval->s = gst_parse_strdup (yytext);
+    yylval->ss = gst_parse_strdup (yytext);
     BEGIN (INITIAL);
     return PADREF;
 }
 
 {_ref} {
     PRINT ("REF: %s", yytext);
-    yylval->s = gst_parse_strdup (yytext);
+    yylval->ss = gst_parse_strdup (yytext);
     BEGIN (INITIAL);
     return REF;
 }
@@ -114,14 +114,14 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)
     while (!g_ascii_isspace (*pos) && (*pos != '.')) pos++;
     *pos = '\0';
     PRINT ("BINREF: %s", yytext);
-    yylval->s = gst_parse_strdup (yytext);
+    yylval->ss = gst_parse_strdup (yytext);
     BEGIN (INITIAL);
     return BINREF;
 }
 
 {_identifier} {
     PRINT ("IDENTIFIER: %s", yytext);
-    yylval->s = gst_parse_strdup (yytext);
+    yylval->ss = gst_parse_strdup (yytext);
     BEGIN (INITIAL);
     return IDENTIFIER;
 }
@@ -132,22 +132,22 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)
     c++;
     if (*c) {
       while (g_ascii_isspace (*c)) c++;
-      c = yylval->s = gst_parse_strdup (c);
+      c = yylval->ss = gst_parse_strdup (c);
       while (*c) c++;
       if (*--c != '!')
        g_assert_not_reached ();
       while (g_ascii_isspace (*--c));
       *++c = '\0';
     } else {
-      yylval->s = NULL;
+      yylval->ss = NULL;
     }
     BEGIN (INITIAL);
     return LINK;
 }
 {_url} {
   PRINT ("URL: %s", yytext);
-  yylval->s = g_strdup (yytext);
-  gst_parse_unescape (yylval->s);
+  yylval->ss = g_strdup (yytext);
+  gst_parse_unescape (yylval->ss);
   BEGIN (INITIAL);
   return PARSE_URL;
 }
index 79a14c6..e3e541d 100644 (file)
@@ -6,21 +6,23 @@
 #include "../gstparse.h"
 
 typedef struct {
-  GstElement *src;
-  GstElement *sink;
-  gchar *src_name;
-  gchar *sink_name;
-  GSList *src_pads;
-  GSList *sink_pads;
+  GstElement *element;
+  gchar *name;
+  GSList *pads;
+} reference_t;
+
+typedef struct {
+  reference_t src;
+  reference_t sink;
   GstCaps *caps;
 } link_t;
 
 typedef struct {
   GSList *elements;
-  GstElement *first;
-  GstElement *last;
-  link_t *front;
-  link_t *back;
+  reference_t first;
+  reference_t last;
+  //link_t *front;
+  //link_t *back;
 } chain_t;
 
 typedef struct _graph_t graph_t;
@@ -39,16 +41,16 @@ struct _graph_t {
  * This is not safe from reentrance issues, but that doesn't matter as long as
  * we lock a mutex before parsing anyway.
  */
-#ifdef GST_DEBUG_ENABLED
+//#ifdef GST_DEBUG_ENABLED
 #  define __GST_PARSE_TRACE
-#endif
+//#endif
 
 #ifdef __GST_PARSE_TRACE
 G_GNUC_INTERNAL  gchar  *__gst_parse_strdup (gchar *org);
 G_GNUC_INTERNAL  void  __gst_parse_strfree (gchar *str);
-G_GNUC_INTERNAL  link_t *__gst_parse_link_new ();
+G_GNUC_INTERNAL  link_t *__gst_parse_link_new (void);
 G_GNUC_INTERNAL  void  __gst_parse_link_free (link_t *data);
-G_GNUC_INTERNAL  chain_t *__gst_parse_chain_new ();
+G_GNUC_INTERNAL  chain_t *__gst_parse_chain_new (void);
 G_GNUC_INTERNAL  void  __gst_parse_chain_free (chain_t *data);
 #  define gst_parse_strdup __gst_parse_strdup
 #  define gst_parse_strfree __gst_parse_strfree
index fe292df..74a26e6 100644 (file)
@@ -38,9 +38,11 @@ setup_pipeline (const gchar * pipe_descr)
   GstElement *pipeline;
   GError *error = NULL;
 
+  GST_DEBUG ("creating [%s] setup_pipeline", pipe_descr);
+
   pipeline = gst_parse_launch (pipe_descr, &error);
 
-  GST_DEBUG ("created %s", pipe_descr);
+  GST_DEBUG ("created [%s] setup_pipeline", pipe_descr);
 
   if (error != NULL) {
     fail_if (error != NULL, "Error parsing pipeline %s: %s", pipe_descr,
@@ -136,14 +138,14 @@ GST_END_TEST;
 #define PIPELINE3  "fakesrc identity silent=true fakesink silent=true"
 #define PIPELINE4  "fakesrc num-buffers=4 .src ! identity silent=true !.sink identity silent=true .src ! .sink fakesink silent=true"
 #define PIPELINE5  "fakesrc num-buffers=4 name=src identity silent=true name=id1 identity silent=true name = id2 fakesink silent=true name =sink src. ! id1. id1.! id2.sink id2.src!sink.sink"
-#define PIPELINE6  "pipeline.(name=\"john\" fakesrc num-buffers=4 ( bin. ( ! queue ! identity silent=true !( queue ! fakesink silent=true )) ))"
-#define PIPELINE7  "fakesrc num-buffers=4 ! tee name=tee .src_%u! queue ! fakesink silent=true tee.src_%u ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src_%u ! foo."
+#define PIPELINE6  "pipeline.(name=\"john\" fakesrc num-buffers=4 ! ( bin. (  queue ! identity silent=true !( queue ! fakesink silent=true )) ))"
+#define PIPELINE7  "fakesrc num-buffers=4 ! tee name=tee .src_%u ! queue ! fakesink silent=true tee.src_%u ! queue ! fakesink silent=true queue name =\"foo\" ! fakesink silent=true tee.src_%u ! foo."
 /* aggregator is borked
  * #define PIPELINE8  "fakesrc num-buffers=4 ! tee name=tee1 .src0,src1 ! .sink0, sink1 aggregator ! fakesink silent=true"
  * */
 #define PIPELINE8  "fakesrc num-buffers=4 ! fakesink silent=true"
 #define PIPELINE9  "fakesrc num-buffers=4 ! test. fakesink silent=true name=test"
-#define PIPELINE10 "( fakesrc num-buffers=\"4\" ! ) identity silent=true ! fakesink silent=true"
+#define PIPELINE10 "( fakesrc num-buffers=\"4\"  ) ! identity silent=true ! fakesink silent=true"
 #define PIPELINE11 "fakesink silent=true name = sink identity silent=true name=id ( fakesrc num-buffers=\"4\" ! id. ) id. ! sink."
 #define PIPELINE12 "file:///tmp/test.file ! fakesink silent=true"
 #define PIPELINE13 "fakesrc ! file:///tmp/test.file"
@@ -224,6 +226,7 @@ GST_START_TEST (test_launch_lines2)
    * - test if escaping strings works
    */
   cur = setup_pipeline (PIPELINE6);
+  /*** <-- valgrind finds element later*/
   fail_unless (GST_IS_PIPELINE (cur), "Parse did not produce a pipeline");
   g_object_get (G_OBJECT (cur), "name", &s, NULL);
   fail_if (s == NULL, "name was NULL");
@@ -287,8 +290,8 @@ GST_START_TEST (test_launch_lines2)
 
   /* Checks handling of a assignment followed by error inside a bin. 
    * This should warn, but ignore the error and carry on */
-  cur = setup_pipeline ("( filesrc blocksize=4 location=/dev/null @ )");
-  gst_object_unref (cur);
+  //cur = setup_pipeline ("( filesrc blocksize=4 location=/dev/null @ )");
+  //gst_object_unref (cur);
 
   /**
    * Checks if characters inside quotes are not escaped.
@@ -461,10 +464,12 @@ GST_START_TEST (delayed_link)
   run_delayed_test
       ("parsetestelement name=src ! fakesink silent=true name=sink", "sink",
       TRUE);
+  /*** <-- valgrind finds one element ***/
 
   /* Test, but this time specifying both pad names */
   run_delayed_test ("parsetestelement name=src .src ! "
       ".sink fakesink silent=true name=sink", "sink", TRUE);
+  /*** <-- valgrind finds one element ***/
 
   /* Now try with a caps filter, but not testing that
    * the peerpad == sinkpad, because the peer will actually