2 #include <glib-object.h>
8 #include "../gst_private.h"
9 #include "../gst-i18n-lib.h"
11 #include "../gstconfig.h"
12 #include "../gstparse.h"
13 #include "../gstinfo.h"
14 #include "../gsterror.h"
15 #include "../gsturi.h"
16 #include "../gstutils.h"
17 #include "../gstvalue.h"
18 #include "../gstchildproxy.h"
21 /* All error messages in this file are user-visible and need to be translated.
22 * Don't start the message with a capital, and don't end them with a period,
23 * as they will be presented inside a sentence/error.
26 #define YYERROR_VERBOSE 1
27 #define YYLEX_PARAM scanner
29 typedef void* yyscan_t;
31 int _gst_parse_yylex (void * yylval_param , yyscan_t yyscanner);
32 int _gst_parse_yylex_init (yyscan_t scanner);
33 int _gst_parse_yylex_destroy (yyscan_t scanner);
34 struct yy_buffer_state * _gst_parse_yy_scan_string (char* , yyscan_t);
35 void _gst_parse_yypush_buffer_state (void * new_buffer ,yyscan_t yyscanner );
36 void _gst_parse_yypop_buffer_state (yyscan_t yyscanner );
39 #ifdef __GST_PARSE_TRACE
40 static guint __strings;
42 static guint __chains;
44 __gst_parse_strdup (gchar *org)
49 /* g_print ("ALLOCATED STR (%3u): %p %s\n", __strings, ret, ret); */
53 __gst_parse_strfree (gchar *str)
56 /* g_print ("FREEING STR (%3u): %p %s\n", __strings - 1, str, str); */
58 g_return_if_fail (__strings > 0);
62 link_t *__gst_parse_link_new ()
66 ret = g_new0 (link_t, 1);
67 /* g_print ("ALLOCATED LINK (%3u): %p\n", __links, ret); */
71 __gst_parse_link_free (link_t *data)
74 /* g_print ("FREEING LINK (%3u): %p\n", __links - 1, data); */
76 g_return_if_fail (__links > 0);
81 __gst_parse_chain_new ()
85 ret = g_new0 (chain_t, 1);
86 /* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */
90 __gst_parse_chain_free (chain_t *data)
92 /* g_print ("FREEING CHAIN (%3u): %p\n", __chains - 1, data); */
94 g_return_if_fail (__chains > 0);
98 #endif /* __GST_PARSE_TRACE */
106 /* FIXME: need to connect to "disposed" signal to clean up,
107 * but there is no such signal */
117 /*** define SET_ERROR and ERROR macros/functions */
119 #ifdef G_HAVE_ISO_VARARGS
121 # define SET_ERROR(error, type, ...) \
123 GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \
124 if ((error) && !*(error)) { \
125 g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \
129 # define ERROR(type, ...) \
130 SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
132 #elif defined(G_HAVE_GNUC_VARARGS)
134 # define SET_ERROR(error, type, args...) \
136 GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \
137 if ((error) && !*(error)) { \
138 g_set_error ((error), GST_PARSE_ERROR, (type), args ); \
142 # define ERROR(type, args...) \
143 SET_ERROR (((graph_t *) graph)->error,(type) , args )
148 SET_ERROR (GError **error, gint type, const char *format, ...)
152 g_warning ("error while parsing");
157 va_start (varargs, format);
158 string = g_strdup_vprintf (format, varargs);
161 g_set_error (error, GST_PARSE_ERROR, type, string);
168 #endif /* G_HAVE_ISO_VARARGS */
170 /*** define YYPRINTF macro/function if we're debugging */
172 /* bison 1.35 calls this macro with side effects, we need to make sure the
173 side effects work - crappy bison */
175 #ifndef GST_DISABLE_GST_DEBUG
178 # ifdef G_HAVE_ISO_VARARGS
180 /* # define YYFPRINTF(a, ...) GST_CAT_DEBUG (GST_CAT_PIPELINE, __VA_ARGS__) */
181 # define YYFPRINTF(a, ...) \
183 gchar *temp = g_strdup_printf (__VA_ARGS__); \
184 GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
188 # elif defined(G_HAVE_GNUC_VARARGS)
190 # define YYFPRINTF(a, args...) \
192 gchar *temp = g_strdup_printf ( args ); \
193 GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
200 YYPRINTF(const char *format, ...)
205 va_start (varargs, format);
206 temp = g_strdup_vprintf (format, varargs);
207 GST_CAT_LOG (GST_CAT_PIPELINE, "%s", temp);
212 # endif /* G_HAVE_ISO_VARARGS */
214 #endif /* GST_DISABLE_GST_DEBUG */
216 #define GST_BIN_MAKE(res, type, chainval, assign, free_string) \
218 chain_t *chain = chainval; \
220 GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
222 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY_BIN, \
223 _("specified empty bin \"%s\", not allowed"), type); \
224 g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
225 g_slist_free (assign); \
226 gst_object_unref (bin); \
228 gst_parse_strfree (type); /* Need to clean up the string */ \
231 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, \
232 _("no bin \"%s\", skipping"), type); \
233 g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
234 g_slist_free (assign); \
237 for (walk = chain->elements; walk; walk = walk->next ) \
238 gst_bin_add (bin, GST_ELEMENT (walk->data)); \
239 g_slist_free (chain->elements); \
240 chain->elements = g_slist_prepend (NULL, bin); \
242 /* set the properties now */ \
243 for (walk = assign; walk; walk = walk->next) \
244 gst_parse_element_set ((gchar *) walk->data, GST_ELEMENT (bin), graph); \
245 g_slist_free (assign); \
249 #define MAKE_LINK(link, _src, _src_name, _src_pads, _sink, _sink_name, _sink_pads) \
251 link = gst_parse_link_new (); \
253 link->sink = _sink; \
254 link->src_name = _src_name; \
255 link->sink_name = _sink_name; \
256 link->src_pads = _src_pads; \
257 link->sink_pads = _sink_pads; \
261 #define MAKE_REF(link, _src, _pads) \
263 gchar *padname = _src; \
264 GSList *pads = _pads; \
266 while (*padname != '.') padname++; \
269 if (*padname != '\0') \
270 pads = g_slist_prepend (pads, gst_parse_strdup (padname)); \
272 MAKE_LINK (link, NULL, _src, pads, NULL, NULL, NULL); \
275 static void gst_parse_new_child(GstChildProxy *child_proxy, GObject *object,
278 DelayedSet *set = (DelayedSet *) data;
281 GstObject *target = NULL;
284 if (gst_child_proxy_lookup (GST_OBJECT (set->parent), set->name, &target, &pspec)) {
285 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
287 GST_CAT_LOG (GST_CAT_PIPELINE, "parsing delayed property %s as a %s from %s", pspec->name,
288 g_type_name (value_type), set->value_str);
289 g_value_init (&v, value_type);
290 if (gst_value_deserialize (&v, set->value_str)) {
291 g_object_set_property (G_OBJECT (target), pspec->name, &v);
293 g_signal_handler_disconnect (child_proxy, set->signal_id);
295 g_free(set->value_str);
302 gst_object_unref (target);
308 gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
313 GstObject *target = NULL;
316 /* parse the string, so the property name is null-terminated an pos points
317 to the beginning of the value */
318 while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++;
324 while (g_ascii_isspace (*pos)) pos++;
327 while (g_ascii_isspace (*pos)) pos++;
330 pos[strlen (pos) - 1] = '\0';
332 gst_parse_unescape (pos);
334 if (gst_child_proxy_lookup (GST_OBJECT (element), value, &target, &pspec)) {
335 value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
336 GST_CAT_LOG (GST_CAT_PIPELINE, "parsing property %s as a %s", pspec->name,
337 g_type_name (value_type));
338 g_value_init (&v, value_type);
339 if (!gst_value_deserialize (&v, pos))
341 g_object_set_property (G_OBJECT (target), pspec->name, &v);
343 /* do a delayed set */
344 if (GST_IS_CHILD_PROXY (element)) {
345 DelayedSet *data = g_new (DelayedSet, 1);
347 data->parent = element;
348 data->name = g_strdup(value);
349 data->value_str = g_strdup(pos);
350 data->signal_id = g_signal_connect(GST_OBJECT (element),"child-added", G_CALLBACK (gst_parse_new_child), data);
353 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
354 _("no property \"%s\" in element \"%s\""), value, \
355 GST_ELEMENT_NAME (element));
360 gst_parse_strfree (value);
364 gst_object_unref (target);
368 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
369 _("could not set property \"%s\" in element \"%s\" to \"%s\""),
370 value, GST_ELEMENT_NAME (element), pos);
374 gst_parse_free_link (link_t *link)
376 gst_parse_strfree (link->src_name);
377 gst_parse_strfree (link->sink_name);
378 g_slist_foreach (link->src_pads, (GFunc) gst_parse_strfree, NULL);
379 g_slist_foreach (link->sink_pads, (GFunc) gst_parse_strfree, NULL);
380 g_slist_free (link->src_pads);
381 g_slist_free (link->sink_pads);
382 if (link->caps) gst_caps_unref (link->caps);
383 gst_parse_link_free (link);
387 gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
389 DelayedLink *link = (DelayedLink *) data;
391 GST_CAT_INFO (GST_CAT_PIPELINE, "trying delayed linking %s:%s to %s:%s",
392 GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
393 GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (link->sink_pad));
395 if (gst_element_link_pads_filtered (src, link->src_pad, link->sink,
396 link->sink_pad, link->caps)) {
397 /* do this here, we don't want to get any problems later on when
398 * unlocking states */
399 GST_CAT_DEBUG (GST_CAT_PIPELINE, "delayed linking %s:%s to %s:%s worked",
400 GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
401 GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (link->sink_pad));
402 g_signal_handler_disconnect (src, link->signal_id);
403 g_free (link->src_pad);
404 g_free (link->sink_pad);
405 if (link->caps) gst_caps_unref (link->caps);
409 /* both padnames and the caps may be NULL */
411 gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
412 GstElement *sink, const gchar *sink_pad,
415 GList *templs = gst_element_class_get_pad_template_list (
416 GST_ELEMENT_GET_CLASS (src));
418 for (; templs; templs = templs->next) {
419 GstPadTemplate *templ = (GstPadTemplate *) templs->data;
420 if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) &&
421 (GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_SOMETIMES))
423 DelayedLink *data = g_new (DelayedLink, 1);
425 /* TODO: maybe we should check if src_pad matches this template's names */
427 GST_CAT_DEBUG (GST_CAT_PIPELINE, "trying delayed link %s:%s to %s:%s",
428 GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (src_pad),
429 GST_STR_NULL (GST_ELEMENT_NAME (sink)), GST_STR_NULL (sink_pad));
431 data->src_pad = g_strdup (src_pad);
433 data->sink_pad = g_strdup (sink_pad);
435 data->caps = gst_caps_copy (caps);
439 data->signal_id = g_signal_connect (G_OBJECT (src), "pad-added",
440 G_CALLBACK (gst_parse_found_pad), data);
447 * performs a link and frees the struct. src and sink elements must be given
448 * return values 0 - link performed
453 gst_parse_perform_link (link_t *link, graph_t *graph)
455 GstElement *src = link->src;
456 GstElement *sink = link->sink;
457 GSList *srcs = link->src_pads;
458 GSList *sinks = link->sink_pads;
459 g_assert (GST_IS_ELEMENT (src));
460 g_assert (GST_IS_ELEMENT (sink));
462 GST_CAT_INFO (GST_CAT_PIPELINE,
463 "linking %s:%s to %s:%s (%u/%u) with caps \"%" GST_PTR_FORMAT "\"",
464 GST_ELEMENT_NAME (src), link->src_name ? link->src_name : "(any)",
465 GST_ELEMENT_NAME (sink), link->sink_name ? link->sink_name : "(any)",
466 g_slist_length (srcs), g_slist_length (sinks), link->caps);
468 if (!srcs || !sinks) {
469 if (gst_element_link_pads_filtered (src,
470 srcs ? (const gchar *) srcs->data : NULL, sink,
471 sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
474 if (gst_parse_perform_delayed_link (src,
475 srcs ? (const gchar *) srcs->data : NULL,
476 sink, sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
483 if (g_slist_length (link->src_pads) != g_slist_length (link->src_pads)) {
486 while (srcs && sinks) {
487 const gchar *src_pad = (const gchar *) srcs->data;
488 const gchar *sink_pad = (const gchar *) sinks->data;
489 srcs = g_slist_next (srcs);
490 sinks = g_slist_next (sinks);
491 if (gst_element_link_pads_filtered (src, src_pad, sink, sink_pad,
495 if (gst_parse_perform_delayed_link (src, src_pad,
506 gst_parse_free_link (link);
510 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
511 _("could not link %s to %s"), GST_ELEMENT_NAME (src),
512 GST_ELEMENT_NAME (sink));
513 gst_parse_free_link (link);
518 static int yyerror (void *scanner, graph_t *graph, const char *s);
531 %token <s> IDENTIFIER
532 %left <s> REF PADREF BINREF
533 %token <s> ASSIGNMENT
539 %type <l> linkpart link
542 %type <p> padlist pads assignments
549 %parse-param { void *scanner }
550 %parse-param { graph_t *graph }
556 element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL);
558 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
559 gst_parse_strfree ($1);
562 gst_parse_strfree ($1);
564 | element ASSIGNMENT { gst_parse_element_set ($2, $1, graph);
568 assignments: /* NOP */ { $$ = NULL; }
569 | assignments ASSIGNMENT { $$ = g_slist_prepend ($1, $2); }
571 bin: '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2, FALSE); }
572 | BINREF assignments chain ')' { GST_BIN_MAKE ($$, $1, $3, $2, TRUE);
573 gst_parse_strfree ($1);
575 | BINREF assignments ')' { GST_BIN_MAKE ($$, $1, NULL, $2, TRUE);
576 gst_parse_strfree ($1);
578 | BINREF assignments error ')' { GST_BIN_MAKE ($$, $1, NULL, $2, TRUE);
579 gst_parse_strfree ($1);
583 pads: PADREF { $$ = g_slist_prepend (NULL, $1); }
584 | PADREF padlist { $$ = $2;
585 $$ = g_slist_prepend ($$, $1);
588 padlist: ',' IDENTIFIER { $$ = g_slist_prepend (NULL, $2); }
589 | ',' IDENTIFIER padlist { $$ = g_slist_prepend ($3, $2); }
592 reference: REF { MAKE_REF ($$, $1, NULL); }
593 | REF padlist { MAKE_REF ($$, $1, $2); }
596 linkpart: reference { $$ = $1; }
597 | pads { MAKE_REF ($$, NULL, $1); }
598 | /* NOP */ { MAKE_REF ($$, NULL, NULL); }
601 link: linkpart LINK linkpart { $$ = $1;
603 $$->caps = gst_caps_from_string ($2);
604 if ($$->caps == NULL)
605 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $2);
606 gst_parse_strfree ($2);
608 $$->sink_name = $3->src_name;
609 $$->sink_pads = $3->src_pads;
610 gst_parse_link_free ($3);
614 linklist: link { $$ = g_slist_prepend (NULL, $1); }
615 | link linklist { $$ = g_slist_prepend ($2, $1); }
616 | linklist error { $$ = $1; }
619 chain: element { $$ = gst_parse_chain_new ();
620 $$->first = $$->last = $1;
621 $$->front = $$->back = NULL;
622 $$->elements = g_slist_prepend (NULL, $1);
625 | chain chain { if ($1->back && $2->front) {
626 if (!$1->back->sink_name) {
627 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
628 gst_parse_free_link ($1->back);
630 ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
632 if (!$2->front->src_name) {
633 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
634 gst_parse_free_link ($2->front);
636 ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
639 } else if ($1->back) {
640 if (!$1->back->sink_name) {
641 $1->back->sink = $2->first;
643 } else if ($2->front) {
644 if (!$2->front->src_name) {
645 $2->front->src = $1->last;
647 $1->back = $2->front;
651 ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
655 $1->elements = g_slist_concat ($1->elements, $2->elements);
657 gst_parse_chain_free ($2);
660 | chain linklist { GSList *walk;
662 $2 = g_slist_prepend ($2, $1->back);
665 if (!((link_t *) $2->data)->src_name) {
666 ((link_t *) $2->data)->src = $1->last;
669 for (walk = $2; walk; walk = walk->next) {
670 link_t *link = (link_t *) walk->data;
671 if (!link->sink_name && walk->next) {
672 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
673 gst_parse_free_link (link);
674 } else if (!link->src_name && !link->src) {
675 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
676 gst_parse_free_link (link);
679 ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, link);
688 | chain error { $$ = $1; }
689 | link chain { if ($2->front) {
690 if (!$2->front->src_name) {
691 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
692 gst_parse_free_link ($2->front);
694 ((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
697 if (!$1->sink_name) {
698 $1->sink = $2->first;
703 | PARSE_URL chain { $$ = $2;
705 GstElement *element =
706 gst_element_make_from_uri (GST_URI_SRC, $1, NULL);
708 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
709 _("no source element for URI \"%s\""), $1);
711 $$->front->src = element;
712 ((graph_t *) graph)->links = g_slist_prepend (
713 ((graph_t *) graph)->links, $$->front);
715 $$->elements = g_slist_prepend ($$->elements, element);
718 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
719 _("no element to link URI \"%s\" to"), $1);
723 | link PARSE_URL { GstElement *element =
724 gst_element_make_from_uri (GST_URI_SINK, $2, NULL);
726 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
727 _("no sink element for URI \"%s\""), $2);
728 gst_parse_link_free ($1);
731 } else if ($1->sink_name || $1->sink_pads) {
732 gst_object_unref (element);
733 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
734 _("could not link sink element for URI \"%s\""), $2);
735 gst_parse_link_free ($1);
739 $$ = gst_parse_chain_new ();
740 $$->first = $$->last = element;
742 $$->front->sink = element;
743 $$->elements = g_slist_prepend (NULL, element);
748 graph: /* NOP */ { SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
749 $$ = (graph_t *) graph;
751 | chain { $$ = (graph_t *) graph;
753 if (!$1->front->src_name) {
754 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
755 gst_parse_free_link ($1->front);
757 $$->links = g_slist_prepend ($$->links, $1->front);
762 if (!$1->back->sink_name) {
763 SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
764 gst_parse_free_link ($1->back);
766 $$->links = g_slist_prepend ($$->links, $1->back);
778 yyerror (void *scanner, graph_t *graph, const char *s)
780 /* FIXME: This should go into the GError somehow, but how? */
781 GST_WARNING ("Error during parsing: %s", s);
787 _gst_parse_launch (const gchar *str, GError **error)
796 g_return_val_if_fail (str != NULL, NULL);
797 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
803 #ifdef __GST_PARSE_TRACE
804 GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
805 __strings = __chains = __links = 0;
806 #endif /* __GST_PARSE_TRACE */
808 dstr = g_strdup (str);
809 _gst_parse_yylex_init (&scanner);
810 _gst_parse_yy_scan_string (dstr, scanner);
816 if (yyparse (scanner, &g) != 0) {
817 SET_ERROR (error, GST_PARSE_ERROR_SYNTAX,
818 "Unrecoverable syntax error while parsing pipeline %s", str);
820 _gst_parse_yylex_destroy (scanner);
825 _gst_parse_yylex_destroy (scanner);
828 GST_CAT_DEBUG (GST_CAT_PIPELINE, "got %u elements and %u links",
829 g.chain ? g_slist_length (g.chain->elements) : 0,
830 g_slist_length (g.links));
834 } else if (!(((chain_t *) g.chain)->elements->next)) {
835 /* only one toplevel element */
836 ret = (GstElement *) ((chain_t *) g.chain)->elements->data;
837 g_slist_free (((chain_t *) g.chain)->elements);
838 if (GST_IS_BIN (ret))
840 gst_parse_chain_free (g.chain);
842 /* put all elements in our bin */
843 bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
846 for (walk = g.chain->elements; walk; walk = walk->next) {
847 if (walk->data != NULL)
848 gst_bin_add (bin, GST_ELEMENT (walk->data));
851 g_slist_free (g.chain->elements);
852 ret = GST_ELEMENT (bin);
853 gst_parse_chain_free (g.chain);
857 for (walk = g.links; walk; walk = walk->next) {
858 link_t *l = (link_t *) walk->data;
862 l->src = gst_bin_get_by_name_recurse_up (bin, l->src_name);
864 gst_object_unref (l->src);
866 l->src = strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL;
870 SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
871 "No element named \"%s\" - omitting link", l->src_name);
872 gst_parse_free_link (l);
879 l->sink = gst_bin_get_by_name_recurse_up (bin, l->sink_name);
881 gst_object_unref (l->sink);
883 l->sink = strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL;
887 SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
888 "No element named \"%s\" - omitting link", l->sink_name);
889 gst_parse_free_link (l);
893 gst_parse_perform_link (l, &g);
895 g_slist_free (g.links);
898 #ifdef __GST_PARSE_TRACE
899 GST_CAT_DEBUG (GST_CAT_PIPELINE,
900 "TRACE: %u strings, %u chains and %u links left", __strings, __chains,
902 if (__strings || __chains || __links) {
903 g_warning ("TRACE: %u strings, %u chains and %u links left", __strings,
906 #endif /* __GST_PARSE_TRACE */
912 g_slist_foreach (g.chain->elements, (GFunc)gst_object_unref, NULL);
913 g_slist_free (g.chain->elements);
914 gst_parse_chain_free (g.chain);
917 g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL);
918 g_slist_free (g.links);