2002-03-31 21:09:17 +00:00
|
|
|
%{
|
2003-04-08 21:59:44 +00:00
|
|
|
#include <glib-object.h>
|
2002-03-31 21:09:17 +00:00
|
|
|
#include <glib.h>
|
|
|
|
#include <stdio.h>
|
2002-04-10 16:50:00 +00:00
|
|
|
#include <string.h>
|
2003-02-10 07:53:58 +00:00
|
|
|
#include <stdlib.h>
|
2003-06-29 14:05:49 +00:00
|
|
|
|
|
|
|
#include "../gst_private.h"
|
2004-01-13 14:23:44 +00:00
|
|
|
#include "../gst-i18n-lib.h"
|
2003-06-29 14:05:49 +00:00
|
|
|
|
2003-11-24 03:21:54 +00:00
|
|
|
#include "../gstconfig.h"
|
2002-04-07 23:32:16 +00:00
|
|
|
#include "../gstparse.h"
|
2003-04-08 21:59:44 +00:00
|
|
|
#include "../gstinfo.h"
|
2004-03-05 13:07:48 +00:00
|
|
|
#include "../gsterror.h"
|
2003-11-24 03:21:54 +00:00
|
|
|
#include "../gsturi.h"
|
2005-03-07 18:27:42 +00:00
|
|
|
#include "../gstutils.h"
|
gst/gstvalue.c: add serialization and comparison functions for long, int64, enum and float values
Original commit message from CVS:
* gst/gstvalue.c: (gst_strtoll), (CREATE_SERIALIZATION),
(CREATE_USERIALIZATION), (_gst_value_initialize),
(gst_value_compare_float), (gst_value_serialize_float),
(gst_value_deserialize_float), (gst_value_compare_enum),
(gst_value_serialize_enum), (gst_value_deserialize_enum):
add serialization and comparison functions for long, int64, enum and
float values
* gst/gstvalue.c: (gst_value_serialize), (gst_value_deserialize):
use best serialization function in type hierarchy instead of only a
matching one. This is required for enums to work.
* gst/parse/grammar.y:
use gst_caps_deserialize
* testsuite/parse/Makefile.am:
parse1 now works
* testsuite/parse/parse1.c: (main):
remove aggregator check, aggregator is broken, this test works now
but fails because of bug #138012
* testsuite/parse/parse2.c: (main):
s/xvideosink/xvimagesink - this test looks a lot like we should
disable it
2004-05-18 01:36:14 +00:00
|
|
|
#include "../gstvalue.h"
|
2002-04-01 06:30:39 +00:00
|
|
|
#include "types.h"
|
2002-04-07 23:32:16 +00:00
|
|
|
|
2004-01-13 14:23:44 +00:00
|
|
|
/* All error messages in this file are user-visible and need to be translated.
|
|
|
|
* Don't start the message with a capital, and don't end them with a period,
|
|
|
|
* as they will be presented inside a sentence/error.
|
|
|
|
*/
|
|
|
|
|
2002-04-01 04:36:56 +00:00
|
|
|
#define YYERROR_VERBOSE 1
|
2003-04-08 21:59:44 +00:00
|
|
|
#define YYPARSE_PARAM graph
|
|
|
|
|
|
|
|
#ifdef __GST_PARSE_TRACE
|
2003-05-18 22:45:27 +00:00
|
|
|
static guint __strings;
|
|
|
|
static guint __links;
|
|
|
|
static guint __chains;
|
2003-04-08 21:59:44 +00:00
|
|
|
gchar *
|
|
|
|
__gst_parse_strdup (gchar *org)
|
|
|
|
{
|
2003-05-01 20:57:40 +00:00
|
|
|
gchar *ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
__strings++;
|
2003-04-16 21:37:35 +00:00
|
|
|
ret = g_strdup (org);
|
|
|
|
/* g_print ("ALLOCATED STR (%3u): %p %s\n", __strings, ret, ret); */
|
|
|
|
return ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
void
|
|
|
|
__gst_parse_strfree (gchar *str)
|
|
|
|
{
|
|
|
|
if (str) {
|
2003-04-16 21:37:35 +00:00
|
|
|
/* g_print ("FREEING STR (%3u): %p %s\n", __strings - 1, str, str); */
|
2003-04-08 21:59:44 +00:00
|
|
|
g_free (str);
|
|
|
|
g_return_if_fail (__strings > 0);
|
|
|
|
__strings--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
link_t *__gst_parse_link_new ()
|
|
|
|
{
|
2003-04-16 21:37:35 +00:00
|
|
|
link_t *ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
__links++;
|
2003-04-16 21:37:35 +00:00
|
|
|
ret = g_new0 (link_t, 1);
|
|
|
|
/* g_print ("ALLOCATED LINK (%3u): %p\n", __links, ret); */
|
|
|
|
return ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
void
|
|
|
|
__gst_parse_link_free (link_t *data)
|
|
|
|
{
|
|
|
|
if (data) {
|
2003-04-16 21:37:35 +00:00
|
|
|
/* g_print ("FREEING LINK (%3u): %p\n", __links - 1, data); */
|
2003-04-08 21:59:44 +00:00
|
|
|
g_free (data);
|
|
|
|
g_return_if_fail (__links > 0);
|
|
|
|
__links--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
chain_t *
|
|
|
|
__gst_parse_chain_new ()
|
|
|
|
{
|
2003-04-16 21:37:35 +00:00
|
|
|
chain_t *ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
__chains++;
|
2003-04-16 21:37:35 +00:00
|
|
|
ret = g_new0 (chain_t, 1);
|
|
|
|
/* g_print ("ALLOCATED CHAIN (%3u): %p\n", __chains, ret); */
|
|
|
|
return ret;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
void
|
|
|
|
__gst_parse_chain_free (chain_t *data)
|
|
|
|
{
|
2004-04-19 17:40:24 +00:00
|
|
|
/* g_print ("FREEING CHAIN (%3u): %p\n", __chains - 1, data); */
|
|
|
|
g_free (data);
|
|
|
|
g_return_if_fail (__chains > 0);
|
|
|
|
__chains--;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __GST_PARSE_TRACE */
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
gchar *src_pad;
|
|
|
|
gchar *sink_pad;
|
|
|
|
GstElement *sink;
|
|
|
|
GstCaps *caps;
|
|
|
|
gulong signal_id;
|
|
|
|
/* FIXME: need to connect to "disposed" signal to clean up, but there is no such signal */
|
|
|
|
} DelayedLink;
|
|
|
|
|
|
|
|
#ifdef G_HAVE_ISO_VARARGS
|
|
|
|
#define SET_ERROR(error, type, ...) G_STMT_START{ \
|
2004-05-04 20:07:38 +00:00
|
|
|
GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \
|
|
|
|
if ((error) && !*(error)) { \
|
|
|
|
g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \
|
2003-04-08 21:59:44 +00:00
|
|
|
} \
|
|
|
|
}G_STMT_END
|
|
|
|
#define ERROR(type, ...) SET_ERROR (((graph_t *) graph)->error, (type), __VA_ARGS__ )
|
2003-11-24 03:21:54 +00:00
|
|
|
#ifndef GST_DISABLE_GST_DEBUG
|
2003-04-08 21:59:44 +00:00
|
|
|
# define YYDEBUG 1
|
2003-04-23 19:16:06 +00:00
|
|
|
/* bison 1.35 calls this macro with side effects, we need to make sure the
|
|
|
|
side effects work - crappy bison
|
2003-06-29 14:05:49 +00:00
|
|
|
# define YYFPRINTF(a, ...) GST_CAT_DEBUG (GST_CAT_PIPELINE, __VA_ARGS__)
|
2003-04-23 19:16:06 +00:00
|
|
|
*/
|
|
|
|
# define YYFPRINTF(a, ...) G_STMT_START{ \
|
|
|
|
gchar *temp = g_strdup_printf (__VA_ARGS__); \
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
|
2003-04-23 19:16:06 +00:00
|
|
|
g_free (temp); \
|
|
|
|
}G_STMT_END
|
2003-04-08 21:59:44 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#elif defined(G_HAVE_GNUC_VARARGS)
|
|
|
|
|
|
|
|
#define SET_ERROR(error, type, args...) G_STMT_START{ \
|
2004-05-04 20:07:38 +00:00
|
|
|
GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \
|
|
|
|
if ((error) && !*(error)) { \
|
|
|
|
g_set_error ((error), GST_PARSE_ERROR, (type), args ); \
|
2003-04-08 21:59:44 +00:00
|
|
|
} \
|
|
|
|
}G_STMT_END
|
2004-02-07 01:23:13 +00:00
|
|
|
#define ERROR(type, args...) SET_ERROR (((graph_t *) graph)->error, (type) , args )
|
2003-11-24 03:21:54 +00:00
|
|
|
#ifndef GST_DISABLE_GST_DEBUG
|
2003-04-08 21:59:44 +00:00
|
|
|
# define YYDEBUG 1
|
2003-04-23 19:16:06 +00:00
|
|
|
/* bison 1.35 calls this macro with side effects, we need to make sure the
|
|
|
|
side effects work - crappy bison
|
2004-02-07 01:23:13 +00:00
|
|
|
# define YYFPRINTF(a, args...) GST_CAT_DEBUG (GST_CAT_PIPELINE, args )
|
2003-04-23 19:16:06 +00:00
|
|
|
*/
|
|
|
|
# define YYFPRINTF(a, args...) G_STMT_START{ \
|
2004-02-07 01:23:13 +00:00
|
|
|
gchar *temp = g_strdup_printf ( args ); \
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_CAT_LOG (GST_CAT_PIPELINE, temp); \
|
2003-04-23 19:16:06 +00:00
|
|
|
g_free (temp); \
|
|
|
|
}G_STMT_END
|
2003-04-08 21:59:44 +00:00
|
|
|
#endif
|
|
|
|
|
2004-05-07 02:36:28 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
SET_ERROR (GError **error, gint type, const char *format, ...)
|
|
|
|
{
|
|
|
|
if (error) {
|
|
|
|
if (*error) {
|
|
|
|
g_warning ("error while parsing");
|
|
|
|
} else {
|
|
|
|
va_list varargs;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
va_start (varargs, format);
|
|
|
|
string = g_strdup_vprintf (format, varargs);
|
|
|
|
va_end (varargs);
|
|
|
|
|
|
|
|
g_set_error (error, GST_PARSE_ERROR, type, string);
|
|
|
|
|
|
|
|
g_free (string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef GST_DISABLE_GST_DEBUG
|
|
|
|
# define YYDEBUG 1
|
|
|
|
static inline void
|
|
|
|
YYPRINTF(const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list varargs;
|
|
|
|
gchar *temp;
|
|
|
|
|
|
|
|
va_start (varargs, format);
|
|
|
|
temp = g_strdup_vprintf ( format, varargs );
|
|
|
|
GST_CAT_LOG (GST_CAT_PIPELINE, "%s", temp);
|
|
|
|
g_free (temp);
|
|
|
|
va_end (varargs);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
2003-04-08 21:59:44 +00:00
|
|
|
|
2003-04-14 18:33:58 +00:00
|
|
|
#define GST_BIN_MAKE(res, type, chainval, assign) G_STMT_START{ \
|
|
|
|
chain_t *chain = chainval; \
|
2003-04-08 21:59:44 +00:00
|
|
|
GSList *walk; \
|
|
|
|
GstBin *bin = (GstBin *) gst_element_factory_make (type, NULL); \
|
2003-04-14 18:33:58 +00:00
|
|
|
if (!chain) { \
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY_BIN, _("specified empty bin \"%s\", not allowed"), type); \
|
2003-04-14 18:33:58 +00:00
|
|
|
g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
|
|
|
|
g_slist_free (assign); \
|
|
|
|
YYERROR; \
|
|
|
|
} else if (!bin) { \
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no bin \"%s\", skipping"), type); \
|
2003-04-14 18:33:58 +00:00
|
|
|
g_slist_foreach (assign, (GFunc) gst_parse_strfree, NULL); \
|
|
|
|
g_slist_free (assign); \
|
|
|
|
res = chain; \
|
2003-04-08 21:59:44 +00:00
|
|
|
} else { \
|
2004-04-19 17:40:24 +00:00
|
|
|
for (walk = chain->elements; walk; walk = walk->next ) \
|
2003-04-08 21:59:44 +00:00
|
|
|
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 */ \
|
2004-04-19 17:40:24 +00:00
|
|
|
for (walk = assign; walk; walk = walk->next) \
|
2003-04-08 21:59:44 +00:00
|
|
|
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; \
|
|
|
|
}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
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
|
|
|
|
{
|
|
|
|
GParamSpec *pspec;
|
|
|
|
gchar *pos = value;
|
2004-02-04 17:24:23 +00:00
|
|
|
GValue v = { 0, };
|
|
|
|
GValue v2 = { 0, };
|
2005-06-22 11:02:57 +00:00
|
|
|
GType value_type;
|
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
/* parse the string, so the property name is null-terminated an pos points
|
|
|
|
to the beginning of the value */
|
|
|
|
while (!g_ascii_isspace (*pos) && (*pos != '=')) pos++;
|
|
|
|
if (*pos == '=') {
|
|
|
|
*pos = '\0';
|
|
|
|
} else {
|
|
|
|
*pos = '\0';
|
|
|
|
pos++;
|
|
|
|
while (g_ascii_isspace (*pos)) pos++;
|
|
|
|
}
|
|
|
|
pos++;
|
|
|
|
while (g_ascii_isspace (*pos)) pos++;
|
|
|
|
if (*pos == '"') {
|
|
|
|
pos++;
|
|
|
|
pos[strlen (pos) - 1] = '\0';
|
|
|
|
}
|
|
|
|
gst_parse_unescape (pos);
|
2005-06-22 11:02:57 +00:00
|
|
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value);
|
|
|
|
if (pspec) {
|
|
|
|
value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
|
|
|
GST_LOG ("parsing property %s as a %s", pspec->name,
|
|
|
|
g_type_name (value_type));
|
|
|
|
g_value_init (&v, value_type);
|
gst/gstvalue.c: add serialization and comparison functions for long, int64, enum and float values
Original commit message from CVS:
* gst/gstvalue.c: (gst_strtoll), (CREATE_SERIALIZATION),
(CREATE_USERIALIZATION), (_gst_value_initialize),
(gst_value_compare_float), (gst_value_serialize_float),
(gst_value_deserialize_float), (gst_value_compare_enum),
(gst_value_serialize_enum), (gst_value_deserialize_enum):
add serialization and comparison functions for long, int64, enum and
float values
* gst/gstvalue.c: (gst_value_serialize), (gst_value_deserialize):
use best serialization function in type hierarchy instead of only a
matching one. This is required for enums to work.
* gst/parse/grammar.y:
use gst_caps_deserialize
* testsuite/parse/Makefile.am:
parse1 now works
* testsuite/parse/parse1.c: (main):
remove aggregator check, aggregator is broken, this test works now
but fails because of bug #138012
* testsuite/parse/parse2.c: (main):
s/xvideosink/xvimagesink - this test looks a lot like we should
disable it
2004-05-18 01:36:14 +00:00
|
|
|
if (!gst_value_deserialize (&v, pos))
|
2003-04-08 21:59:44 +00:00
|
|
|
goto error;
|
|
|
|
g_object_set_property (G_OBJECT (element), value, &v);
|
|
|
|
} else {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, _("no property \"%s\" in element \"%s\""), value, GST_ELEMENT_NAME (element));
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
gst_parse_strfree (value);
|
2004-02-04 17:24:23 +00:00
|
|
|
if (G_IS_VALUE (&v))
|
|
|
|
g_value_unset (&v);
|
|
|
|
if (G_IS_VALUE (&v2))
|
|
|
|
g_value_unset (&v2);
|
2003-04-08 21:59:44 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
|
2004-01-13 14:23:44 +00:00
|
|
|
_("could not set property \"%s\" in element \"%s\" to \"%s\""),
|
2003-05-06 22:58:04 +00:00
|
|
|
value, GST_ELEMENT_NAME (element), pos);
|
|
|
|
goto out;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
gst_parse_free_link (link_t *link)
|
|
|
|
{
|
|
|
|
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);
|
2005-03-07 18:27:42 +00:00
|
|
|
if (link->caps) gst_caps_unref (link->caps);
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_link_free (link);
|
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
static void
|
|
|
|
gst_parse_element_lock (GstElement *element, gboolean lock)
|
|
|
|
{
|
|
|
|
GstPad *pad;
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *pads;
|
2003-04-08 21:59:44 +00:00
|
|
|
gboolean unlocked_peer = FALSE;
|
2005-03-07 18:27:42 +00:00
|
|
|
gboolean done = FALSE;
|
|
|
|
GList *walk;
|
2003-04-08 21:59:44 +00:00
|
|
|
|
2003-04-11 00:00:46 +00:00
|
|
|
if (gst_element_is_locked_state (element) == lock)
|
2003-04-08 21:59:44 +00:00
|
|
|
return;
|
2005-03-07 18:27:42 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
/* check if we have an unlocked peer */
|
2005-03-07 18:27:42 +00:00
|
|
|
pads = gst_element_iterate_pads (element);
|
|
|
|
while (!done) {
|
|
|
|
gpointer data;
|
|
|
|
switch (gst_iterator_next (pads, &data)) {
|
|
|
|
case GST_ITERATOR_OK:
|
|
|
|
{
|
|
|
|
GstPad *pad = GST_PAD_CAST (data);
|
|
|
|
|
|
|
|
if (GST_PAD_IS_SINK (pad) && GST_PAD_PEER (pad) &&
|
|
|
|
!gst_element_is_locked_state (GST_PAD_PARENT (GST_PAD_PEER (pad)))) {
|
|
|
|
unlocked_peer = TRUE;
|
|
|
|
done = TRUE;
|
|
|
|
}
|
|
|
|
gst_object_unref (GST_OBJECT (pad));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_ITERATOR_RESYNC:
|
|
|
|
unlocked_peer = FALSE;
|
|
|
|
gst_iterator_resync (pads);
|
|
|
|
break;
|
|
|
|
case GST_ITERATOR_DONE:
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
}
|
|
|
|
gst_iterator_free (pads);
|
|
|
|
|
2003-04-11 00:00:46 +00:00
|
|
|
if (!(lock && unlocked_peer)) {
|
2004-03-05 13:07:48 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "setting locked state on element");
|
2003-04-11 00:00:46 +00:00
|
|
|
gst_element_set_locked_state (element, lock);
|
|
|
|
if (!lock)
|
2004-03-05 13:07:48 +00:00
|
|
|
{
|
|
|
|
/* try to sync state with parent */
|
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "trying to sync state of element with parent");
|
|
|
|
/* FIXME: it would be nice if we can figure out why it failed
|
|
|
|
(e.g. caps nego) and give an error about that instead. */
|
2004-07-22 16:14:56 +00:00
|
|
|
if (gst_element_set_state (element, GST_STATE_PLAYING) == GST_STATE_FAILURE)
|
2004-03-05 13:07:48 +00:00
|
|
|
GST_ELEMENT_ERROR (element, CORE, STATE_CHANGE, (NULL), (NULL));
|
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if there are other pads to (un)lock */
|
2005-03-07 18:27:42 +00:00
|
|
|
walk = (GList *) element->pads;
|
2004-04-19 17:40:24 +00:00
|
|
|
for (; walk; walk = walk->next) {
|
gst/gstutils.c: RPAD fixes all around.
Original commit message from CVS:
2005-06-08 Andy Wingo <wingo@pobox.com>
* gst/gstutils.c: RPAD fixes all around.
(gst_element_link_pads): Refcounting fixes.
* tools/gst-inspect.c:
* tools/gst-xmlinspect.c:
* parse/grammar.y:
* gst/base/gsttypefindhelper.c:
* gst/base/gstbasesink.c:
* gst/gstqueue.c: RPAD fixes.
* gst/gstghostpad.h:
* gst/gstghostpad.c: New ghost pad implementation as full proxy
pads. The tricky thing is they provide both source and sink
interfaces, since they proxy the internal pad for the external
pad, and vice versa. Implement with lower-level ProxyPad objects,
with the interior proxy pad as a child of the exterior ghost pad.
Should write a doc on this.
* gst/gstpad.h: s/RPAD/PAD/, s/RealPad/Pad/.
(gst_pad_set_name, gst_pad_set_parent): Macros removed, use
gst_object API.
* gst/gstpad.c: Big changes. No more stub base GstPad, now all
pads are real pads. No ghost pads in this file. Not documenting
the myriad s/RPAD/PAD/ and REALIZE fixes.
(gst_pad_class_init): Add properties for "direction" and
"template". Both are construct-only, so they can't change during
the life of the pad. Fixes properly deriving from GstPad.
(gst_pad_custom_new, gst_pad_custom_new_from_template): Gone. For
derived objects, just set properties when creating the objects via
g_object_new.
(gst_pad_get_parent): Implement as a function, return NULL if the
parent is not an element.
(gst_pad_get_real_parent, gst_pad_add_ghost_pad)
(gst_pad_remove_ghost_pad, gst_pad_realize): Removed.
* gst/gstobject.c (gst_object_class_init): Make name a construct
property. Don't set it in the object init.
* gst/gstelement.c (gst_element_add_pad): Don't allow adding pads
with UNKNOWN direction.
(gst_element_add_ghost_pad): Remove non-orthogonal API. Replace
with gst_element_add_pad (e, gst_ghost_pad_new (name, pad)).
(gst_element_remove_pad): Remove ghost-pad special cases.
(gst_element_pads_activate): Remove rpad cruft.
* gst/gstbin.c (gst_bin_change_state): Use gst_pad_get_parent to
catch the pad's-parent-not-an-element case.
* gst/gst.h: Include gstghostpad.h.
* gst/gst.c (init_post): No more real, ghost pads.
* gst/Makefile.am: Add gstghostpad.[ch].
* check/Makefile.am:
* check/gst/gstbin.c:
* check/gst/gstghostpad.c (test_ghost_pads): Check that linking
into a bin creates ghost pads, and that the refcounts are right.
Partly moved from gstbin.c.
2005-06-08 22:16:27 +00:00
|
|
|
pad = GST_PAD_CAST (walk->data);
|
2003-04-08 21:59:44 +00:00
|
|
|
if (GST_PAD_IS_SRC (pad) && GST_PAD_PEER (pad)) {
|
|
|
|
GstElement *next = GST_ELEMENT (GST_OBJECT_PARENT (GST_PAD_PEER (pad)));
|
2003-04-11 00:00:46 +00:00
|
|
|
if (gst_element_is_locked_state (next) != lock)
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_element_lock (next, lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
|
|
gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
|
|
|
|
{
|
|
|
|
DelayedLink *link = (DelayedLink *) data;
|
|
|
|
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_CAT_INFO (GST_CAT_PIPELINE, "trying delayed linking %s:%s to %s:%s",
|
|
|
|
GST_ELEMENT_NAME (src), link->src_pad,
|
|
|
|
GST_ELEMENT_NAME (link->sink), link->sink_pad);
|
2003-04-11 00:00:46 +00:00
|
|
|
|
2005-07-13 16:26:07 +00:00
|
|
|
if (gst_element_link_pads_filtered (src, link->src_pad, link->sink, link->sink_pad, link->caps)) {
|
2003-04-08 21:59:44 +00:00
|
|
|
/* do this here, we don't want to get any problems later on when unlocking states */
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "delayed linking %s:%s to %s:%s worked",
|
|
|
|
GST_ELEMENT_NAME (src), link->src_pad,
|
|
|
|
GST_ELEMENT_NAME (link->sink), link->sink_pad);
|
2003-04-08 21:59:44 +00:00
|
|
|
g_signal_handler_disconnect (src, link->signal_id);
|
|
|
|
g_free (link->src_pad);
|
|
|
|
g_free (link->sink_pad);
|
2005-03-07 18:27:42 +00:00
|
|
|
if (link->caps) gst_caps_unref (link->caps);
|
2003-04-11 00:00:46 +00:00
|
|
|
if (!gst_element_is_locked_state (src))
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_element_lock (link->sink, FALSE);
|
|
|
|
g_free (link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* both padnames and the caps may be NULL */
|
|
|
|
static gboolean
|
|
|
|
gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
|
|
|
|
GstElement *sink, const gchar *sink_pad, GstCaps *caps)
|
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GList *templs = gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS (src));
|
2003-04-08 21:59:44 +00:00
|
|
|
|
2004-04-19 17:40:24 +00:00
|
|
|
for (; templs; templs = templs->next) {
|
2003-04-08 21:59:44 +00:00
|
|
|
GstPadTemplate *templ = (GstPadTemplate *) templs->data;
|
|
|
|
if ((GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) && (GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_SOMETIMES))
|
|
|
|
{
|
2003-05-01 20:57:40 +00:00
|
|
|
DelayedLink *data = g_new (DelayedLink, 1);
|
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
/* TODO: maybe we should check if src_pad matches this template's names */
|
|
|
|
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "trying delayed link %s:%s to %s:%s",
|
|
|
|
GST_ELEMENT_NAME (src), src_pad, GST_ELEMENT_NAME (sink), sink_pad);
|
2003-04-08 21:59:44 +00:00
|
|
|
|
|
|
|
data->src_pad = g_strdup (src_pad);
|
|
|
|
data->sink = sink;
|
|
|
|
data->sink_pad = g_strdup (sink_pad);
|
2003-12-24 00:26:45 +00:00
|
|
|
if (caps) {
|
|
|
|
data->caps = gst_caps_copy (caps);
|
|
|
|
} else {
|
|
|
|
data->caps = NULL;
|
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
data->signal_id = g_signal_connect (G_OBJECT (src), "new_pad",
|
|
|
|
G_CALLBACK (gst_parse_found_pad), data);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-12-24 14:39:46 +00:00
|
|
|
/*
|
2003-04-08 21:59:44 +00:00
|
|
|
* performs a link and frees the struct. src and sink elements must be given
|
2003-05-18 15:03:34 +00:00
|
|
|
* return values 0 - link performed
|
2003-04-08 21:59:44 +00:00
|
|
|
* 1 - link delayed
|
|
|
|
* <0 - error
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
g_assert (GST_IS_ELEMENT (src));
|
|
|
|
g_assert (GST_IS_ELEMENT (sink));
|
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
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)",
|
|
|
|
g_slist_length (srcs), g_slist_length (sinks),
|
2004-01-29 01:44:08 +00:00
|
|
|
link->caps);
|
2003-04-16 21:37:35 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
if (!srcs || !sinks) {
|
2005-07-13 16:26:07 +00:00
|
|
|
if (gst_element_link_pads_filtered (src, srcs ? (const gchar *) srcs->data : NULL,
|
|
|
|
sink, sinks ? (const gchar *) sinks->data : NULL,
|
|
|
|
link->caps)) {
|
2003-04-11 00:00:46 +00:00
|
|
|
gst_parse_element_lock (sink, gst_element_is_locked_state (src));
|
2003-04-08 21:59:44 +00:00
|
|
|
goto success;
|
|
|
|
} else {
|
|
|
|
if (gst_parse_perform_delayed_link (src, srcs ? (const gchar *) srcs->data : NULL,
|
|
|
|
sink, sinks ? (const gchar *) sinks->data : NULL,
|
|
|
|
link->caps)) {
|
|
|
|
gst_parse_element_lock (sink, TRUE);
|
|
|
|
goto success;
|
|
|
|
} else {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_slist_length (link->src_pads) != g_slist_length (link->src_pads)) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
while (srcs && sinks) {
|
|
|
|
const gchar *src_pad = (const gchar *) srcs->data;
|
|
|
|
const gchar *sink_pad = (const gchar *) sinks->data;
|
|
|
|
srcs = g_slist_next (srcs);
|
|
|
|
sinks = g_slist_next (sinks);
|
2005-07-13 16:26:07 +00:00
|
|
|
if (gst_element_link_pads_filtered (src, src_pad, sink, sink_pad, link->caps)) {
|
2003-04-11 00:00:46 +00:00
|
|
|
gst_parse_element_lock (sink, gst_element_is_locked_state (src));
|
2003-04-08 21:59:44 +00:00
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (gst_parse_perform_delayed_link (src, src_pad,
|
|
|
|
sink, sink_pad,
|
|
|
|
link->caps)) {
|
|
|
|
gst_parse_element_lock (sink, TRUE);
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
success:
|
|
|
|
gst_parse_free_link (link);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("could not link %s to %s"), GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link (link);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2002-04-07 23:32:16 +00:00
|
|
|
|
|
|
|
static int yylex (void *lvalp);
|
|
|
|
static int yyerror (const char *s);
|
2002-03-31 21:09:17 +00:00
|
|
|
%}
|
|
|
|
|
|
|
|
%union {
|
|
|
|
gchar *s;
|
2003-04-08 21:59:44 +00:00
|
|
|
chain_t *c;
|
|
|
|
link_t *l;
|
|
|
|
GstElement *e;
|
|
|
|
GSList *p;
|
2002-04-01 06:30:39 +00:00
|
|
|
graph_t *g;
|
2002-03-31 21:09:17 +00:00
|
|
|
}
|
|
|
|
|
2003-11-24 03:21:54 +00:00
|
|
|
%token <s> PARSE_URL
|
2002-04-07 23:32:16 +00:00
|
|
|
%token <s> IDENTIFIER
|
2003-04-08 21:59:44 +00:00
|
|
|
%left <s> REF PADREF BINREF
|
|
|
|
%token <s> ASSIGNMENT
|
2003-05-17 20:45:06 +00:00
|
|
|
%token <s> LINK
|
2002-03-31 21:09:17 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
%type <g> graph
|
|
|
|
%type <c> chain bin
|
|
|
|
%type <l> reference
|
|
|
|
%type <l> linkpart link
|
|
|
|
%type <p> linklist
|
2003-11-24 03:21:54 +00:00
|
|
|
%type <e> element
|
2003-04-08 21:59:44 +00:00
|
|
|
%type <p> padlist pads assignments
|
|
|
|
|
2002-04-01 04:36:56 +00:00
|
|
|
%left '{' '}' '(' ')'
|
2002-04-07 23:32:16 +00:00
|
|
|
%left ','
|
2003-04-08 21:59:44 +00:00
|
|
|
%right '.'
|
|
|
|
%left '!' '='
|
2002-04-01 04:36:56 +00:00
|
|
|
|
2002-04-07 23:32:16 +00:00
|
|
|
%pure_parser
|
|
|
|
|
2002-04-01 04:36:56 +00:00
|
|
|
%start graph
|
2002-03-31 21:09:17 +00:00
|
|
|
%%
|
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL);
|
2003-04-14 18:33:58 +00:00
|
|
|
if (!$$)
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_strfree ($1);
|
2003-04-14 18:33:58 +00:00
|
|
|
if (!$$)
|
|
|
|
YYERROR;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
| element ASSIGNMENT { gst_parse_element_set ($2, $1, graph);
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
assignments: /* NOP */ { $$ = NULL; }
|
|
|
|
| assignments ASSIGNMENT { $$ = g_slist_prepend ($1, $2); }
|
2003-04-23 20:06:54 +00:00
|
|
|
;
|
2003-11-24 03:21:54 +00:00
|
|
|
bin: '{' assignments chain '}' { GST_BIN_MAKE ($$, "thread", $3, $2); }
|
|
|
|
| '(' assignments chain ')' { GST_BIN_MAKE ($$, "bin", $3, $2); }
|
2003-04-08 21:59:44 +00:00
|
|
|
| BINREF assignments chain ')' { GST_BIN_MAKE ($$, $1, $3, $2);
|
|
|
|
gst_parse_strfree ($1);
|
|
|
|
}
|
2003-04-14 18:33:58 +00:00
|
|
|
| '{' assignments '}' { GST_BIN_MAKE ($$, "thread", NULL, $2); }
|
|
|
|
| '(' assignments '}' { GST_BIN_MAKE ($$, "thread", NULL, $2); }
|
|
|
|
| BINREF assignments ')' { GST_BIN_MAKE ($$, $1, NULL, $2);
|
|
|
|
gst_parse_strfree ($1);
|
|
|
|
}
|
|
|
|
| '{' assignments error '}' { GST_BIN_MAKE ($$, "thread", NULL, $2); }
|
|
|
|
| '(' assignments error '}' { GST_BIN_MAKE ($$, "thread", NULL, $2); }
|
|
|
|
| BINREF assignments error ')' { GST_BIN_MAKE ($$, $1, NULL, $2);
|
|
|
|
gst_parse_strfree ($1);
|
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
pads: PADREF { $$ = g_slist_prepend (NULL, $1); }
|
|
|
|
| PADREF padlist { $$ = $2;
|
|
|
|
$$ = g_slist_prepend ($$, $1);
|
2003-04-23 20:06:54 +00:00
|
|
|
}
|
|
|
|
;
|
2003-04-08 21:59:44 +00:00
|
|
|
padlist: ',' IDENTIFIER { $$ = g_slist_prepend (NULL, $2); }
|
|
|
|
| ',' IDENTIFIER padlist { $$ = g_slist_prepend ($3, $2); }
|
|
|
|
;
|
|
|
|
|
|
|
|
reference: REF { MAKE_REF ($$, $1, NULL); }
|
|
|
|
| REF padlist { MAKE_REF ($$, $1, $2); }
|
|
|
|
;
|
|
|
|
|
|
|
|
linkpart: reference { $$ = $1; }
|
|
|
|
| pads { MAKE_REF ($$, NULL, $1); }
|
|
|
|
| /* NOP */ { MAKE_REF ($$, NULL, NULL); }
|
|
|
|
;
|
|
|
|
|
2003-05-17 20:45:06 +00:00
|
|
|
link: linkpart LINK linkpart { $$ = $1;
|
|
|
|
if ($2) {
|
|
|
|
$$->caps = gst_caps_from_string ($2);
|
|
|
|
if (!$$->caps)
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $2);
|
2003-05-17 20:45:06 +00:00
|
|
|
gst_parse_strfree ($2);
|
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
$$->sink_name = $3->src_name;
|
|
|
|
$$->sink_pads = $3->src_pads;
|
|
|
|
gst_parse_link_free ($3);
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
linklist: link { $$ = g_slist_prepend (NULL, $1); }
|
|
|
|
| link linklist { $$ = g_slist_prepend ($2, $1); }
|
2003-04-14 18:33:58 +00:00
|
|
|
| linklist error { $$ = $1; }
|
2003-04-08 21:59:44 +00:00
|
|
|
;
|
2003-04-27 23:56:31 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
chain: element { $$ = gst_parse_chain_new ();
|
|
|
|
$$->first = $$->last = $1;
|
|
|
|
$$->front = $$->back = NULL;
|
|
|
|
$$->elements = g_slist_prepend (NULL, $1);
|
|
|
|
}
|
|
|
|
| bin { $$ = $1; }
|
|
|
|
| chain chain { if ($1->back && $2->front) {
|
|
|
|
if (!$1->back->sink_name) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link ($1->back);
|
|
|
|
} else {
|
|
|
|
((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
|
|
|
|
}
|
|
|
|
if (!$2->front->src_name) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link ($2->front);
|
|
|
|
} else {
|
|
|
|
((graph_t *) graph)->links = g_slist_prepend (((graph_t *) 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;
|
|
|
|
}
|
2003-04-16 21:37:35 +00:00
|
|
|
$1->back = $2->front;
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
|
2003-04-16 21:37:35 +00:00
|
|
|
if ($1->back) {
|
2004-06-24 03:51:02 +00:00
|
|
|
((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $1->back);
|
2003-04-16 21:37:35 +00:00
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
$1->last = $2->last;
|
|
|
|
$1->back = $2->back;
|
|
|
|
$1->elements = g_slist_concat ($1->elements, $2->elements);
|
2004-04-19 17:40:24 +00:00
|
|
|
if ($2)
|
|
|
|
gst_parse_chain_free ($2);
|
2003-04-08 21:59:44 +00:00
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
| chain linklist { GSList *walk;
|
|
|
|
if ($1->back) {
|
2003-04-17 14:52:38 +00:00
|
|
|
$2 = g_slist_prepend ($2, $1->back);
|
2003-04-08 21:59:44 +00:00
|
|
|
$1->back = NULL;
|
|
|
|
} else {
|
|
|
|
if (!((link_t *) $2->data)->src_name) {
|
|
|
|
((link_t *) $2->data)->src = $1->last;
|
|
|
|
}
|
|
|
|
}
|
2004-04-19 17:40:24 +00:00
|
|
|
for (walk = $2; walk; walk = walk->next) {
|
2003-04-08 21:59:44 +00:00
|
|
|
link_t *link = (link_t *) walk->data;
|
2004-04-19 17:40:24 +00:00
|
|
|
if (!link->sink_name && walk->next) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link (link);
|
|
|
|
} else if (!link->src_name && !link->src) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link (link);
|
|
|
|
} else {
|
2004-04-19 17:40:24 +00:00
|
|
|
if (walk->next) {
|
2003-04-08 21:59:44 +00:00
|
|
|
((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, link);
|
|
|
|
} else {
|
|
|
|
$1->back = link;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_slist_free ($2);
|
|
|
|
$$ = $1;
|
|
|
|
}
|
2003-04-14 18:33:58 +00:00
|
|
|
| chain error { $$ = $1; }
|
2003-11-24 03:21:54 +00:00
|
|
|
| link chain { if ($2->front) {
|
|
|
|
if (!$2->front->src_name) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
|
2003-11-24 03:21:54 +00:00
|
|
|
gst_parse_free_link ($2->front);
|
|
|
|
} else {
|
|
|
|
((graph_t *) graph)->links = g_slist_prepend (((graph_t *) graph)->links, $2->front);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$1->sink_name) {
|
|
|
|
$1->sink = $2->first;
|
|
|
|
}
|
|
|
|
$2->front = $1;
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
| PARSE_URL chain { $$ = $2;
|
|
|
|
if ($$->front) {
|
|
|
|
GstElement *element =
|
|
|
|
gst_element_make_from_uri (GST_URI_SRC, $1, NULL);
|
|
|
|
if (!element) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
|
2004-01-13 14:23:44 +00:00
|
|
|
_("no source element for URI \"%s\""), $1);
|
2003-11-24 03:21:54 +00:00
|
|
|
} else {
|
|
|
|
$$->front->src = element;
|
|
|
|
((graph_t *) graph)->links = g_slist_prepend (
|
|
|
|
((graph_t *) graph)->links, $$->front);
|
|
|
|
$$->front = NULL;
|
|
|
|
$$->elements = g_slist_prepend ($$->elements, element);
|
|
|
|
}
|
|
|
|
} else {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
|
2004-01-13 14:23:44 +00:00
|
|
|
_("no element to link URI \"%s\" to"), $1);
|
2003-11-24 03:21:54 +00:00
|
|
|
}
|
|
|
|
g_free ($1);
|
|
|
|
}
|
|
|
|
| link PARSE_URL { GstElement *element =
|
|
|
|
gst_element_make_from_uri (GST_URI_SINK, $2, NULL);
|
|
|
|
if (!element) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
|
2004-01-13 14:23:44 +00:00
|
|
|
_("no sink element for URI \"%s\""), $2);
|
2003-11-24 03:21:54 +00:00
|
|
|
YYERROR;
|
|
|
|
} else if ($1->sink_name || $1->sink_pads) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK,
|
2004-01-13 14:23:44 +00:00
|
|
|
_("could not link sink element for URI \"%s\""), $2);
|
2003-11-24 03:21:54 +00:00
|
|
|
YYERROR;
|
|
|
|
} else {
|
|
|
|
$$ = gst_parse_chain_new ();
|
|
|
|
$$->first = $$->last = element;
|
|
|
|
$$->front = $1;
|
|
|
|
$$->front->sink = element;
|
|
|
|
$$->elements = g_slist_prepend (NULL, element);
|
|
|
|
}
|
|
|
|
g_free ($2);
|
|
|
|
}
|
2003-04-08 21:59:44 +00:00
|
|
|
;
|
2004-05-07 02:36:28 +00:00
|
|
|
graph: /* NOP */ { SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
|
2003-04-27 23:56:31 +00:00
|
|
|
$$ = (graph_t *) graph;
|
|
|
|
}
|
|
|
|
| chain { $$ = (graph_t *) graph;
|
2003-04-08 21:59:44 +00:00
|
|
|
if ($1->front) {
|
|
|
|
if (!$1->front->src_name) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without source element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
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) {
|
2004-05-07 02:36:28 +00:00
|
|
|
SET_ERROR (((graph_t *) graph)->error, GST_PARSE_ERROR_LINK, _("link without sink element"));
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_parse_free_link ($1->back);
|
|
|
|
} else {
|
|
|
|
$$->links = g_slist_prepend ($$->links, $1->back);
|
|
|
|
}
|
|
|
|
$1->back = NULL;
|
|
|
|
}
|
|
|
|
$$->chain = $1;
|
|
|
|
}
|
|
|
|
;
|
2002-03-31 21:09:17 +00:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
2002-09-18 23:23:41 +00:00
|
|
|
extern FILE *_gst_parse_yyin;
|
2002-04-07 23:32:16 +00:00
|
|
|
int _gst_parse_yylex (YYSTYPE *lvalp);
|
|
|
|
|
|
|
|
static int yylex (void *lvalp) {
|
|
|
|
return _gst_parse_yylex ((YYSTYPE*) lvalp);
|
|
|
|
}
|
2002-03-31 21:09:17 +00:00
|
|
|
|
2002-04-07 23:32:16 +00:00
|
|
|
static int
|
2002-03-31 21:09:17 +00:00
|
|
|
yyerror (const char *s)
|
|
|
|
{
|
2003-04-08 21:59:44 +00:00
|
|
|
/* FIXME: This should go into the GError somehow, but how? */
|
2004-02-20 13:18:32 +00:00
|
|
|
g_warning ("error: %s", s);
|
2002-03-31 21:09:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2004-04-20 19:40:05 +00:00
|
|
|
struct yy_buffer_state * _gst_parse_yy_scan_string (char*);
|
|
|
|
void _gst_parse_yy_delete_buffer (struct yy_buffer_state *);
|
2003-04-08 21:59:44 +00:00
|
|
|
GstElement *
|
|
|
|
_gst_parse_launch (const gchar *str, GError **error)
|
2002-03-31 21:09:17 +00:00
|
|
|
{
|
2003-04-08 21:59:44 +00:00
|
|
|
graph_t g;
|
|
|
|
gchar *dstr;
|
|
|
|
GSList *walk;
|
|
|
|
GstBin *bin = NULL;
|
|
|
|
GstElement *ret;
|
2004-04-20 19:40:05 +00:00
|
|
|
struct yy_buffer_state *buf;
|
2003-04-08 21:59:44 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (str != NULL, NULL);
|
2002-04-07 23:32:16 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
g.chain = NULL;
|
|
|
|
g.links = NULL;
|
|
|
|
g.error = error;
|
|
|
|
|
|
|
|
#ifdef __GST_PARSE_TRACE
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
|
2003-04-08 21:59:44 +00:00
|
|
|
__strings = __chains = __links = 0;
|
|
|
|
#endif /* __GST_PARSE_TRACE */
|
|
|
|
|
|
|
|
dstr = g_strdup (str);
|
2004-04-20 19:40:05 +00:00
|
|
|
buf = _gst_parse_yy_scan_string (dstr);
|
2002-04-01 06:30:39 +00:00
|
|
|
|
2003-11-24 03:21:54 +00:00
|
|
|
#ifndef GST_DISABLE_GST_DEBUG
|
2003-04-08 21:59:44 +00:00
|
|
|
yydebug = 1;
|
2002-04-01 06:30:39 +00:00
|
|
|
#endif
|
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
if (yyparse (&g) != 0) {
|
2004-05-06 17:09:10 +00:00
|
|
|
SET_ERROR (error, GST_PARSE_ERROR_SYNTAX, "Unrecoverable syntax error while parsing pipeline %s", str);
|
2002-04-07 23:32:16 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
goto error1;
|
|
|
|
}
|
|
|
|
g_free (dstr);
|
2004-04-20 19:40:05 +00:00
|
|
|
_gst_parse_yy_delete_buffer (buf);
|
2003-04-08 21:59:44 +00:00
|
|
|
|
2004-02-20 13:18:32 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "got %u elements and %u links", g.chain ? g_slist_length (g.chain->elements) : 0, g_slist_length (g.links));
|
2003-04-08 21:59:44 +00:00
|
|
|
|
|
|
|
if (!g.chain) {
|
|
|
|
ret = NULL;
|
|
|
|
} else if (!(((chain_t *) g.chain)->elements->next)) {
|
|
|
|
/* only one toplevel element */
|
|
|
|
ret = (GstElement *) ((chain_t *) g.chain)->elements->data;
|
|
|
|
g_slist_free (((chain_t *) g.chain)->elements);
|
|
|
|
if (GST_IS_BIN (ret))
|
|
|
|
bin = GST_BIN (ret);
|
2004-04-19 17:40:24 +00:00
|
|
|
gst_parse_chain_free (g.chain);
|
2003-04-08 21:59:44 +00:00
|
|
|
} else {
|
|
|
|
/* put all elements in our bin */
|
|
|
|
bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
|
|
|
|
g_assert (bin);
|
2004-04-19 17:40:24 +00:00
|
|
|
|
|
|
|
for (walk = g.chain->elements; walk; walk = walk->next)
|
2003-04-08 21:59:44 +00:00
|
|
|
gst_bin_add (bin, GST_ELEMENT (walk->data));
|
2004-04-19 17:40:24 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
g_slist_free (g.chain->elements);
|
|
|
|
ret = GST_ELEMENT (bin);
|
2004-04-19 17:40:24 +00:00
|
|
|
gst_parse_chain_free (g.chain);
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* remove links */
|
2004-04-19 17:40:24 +00:00
|
|
|
for (walk = g.links; walk; walk = walk->next) {
|
2003-04-08 21:59:44 +00:00
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
l->src = strcmp (GST_ELEMENT_NAME (ret), l->src_name) == 0 ? ret : NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!l->src) {
|
|
|
|
SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, "No element named \"%s\" - omitting link", l->src_name);
|
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
l->sink = strcmp (GST_ELEMENT_NAME (ret), l->sink_name) == 0 ? ret : NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!l->sink) {
|
|
|
|
SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, "No element named \"%s\" - omitting link", l->sink_name);
|
|
|
|
gst_parse_free_link (l);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gst_parse_perform_link (l, &g);
|
|
|
|
}
|
|
|
|
g_slist_free (g.links);
|
2002-04-07 23:32:16 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
out:
|
|
|
|
#ifdef __GST_PARSE_TRACE
|
2003-06-29 14:05:49 +00:00
|
|
|
GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: %u strings, %u chains and %u links left", __strings, __chains, __links);
|
2003-04-08 21:59:44 +00:00
|
|
|
if (__strings || __chains || __links) {
|
|
|
|
g_warning ("TRACE: %u strings, %u chains and %u links left", __strings, __chains, __links);
|
|
|
|
}
|
|
|
|
#endif /* __GST_PARSE_TRACE */
|
2002-04-07 23:32:16 +00:00
|
|
|
|
2003-04-08 21:59:44 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
error1:
|
|
|
|
g_free (dstr);
|
|
|
|
|
|
|
|
if (g.chain) {
|
2004-04-19 17:40:24 +00:00
|
|
|
g_slist_foreach (g.chain->elements, (GFunc)gst_object_unref, NULL);
|
2003-04-08 21:59:44 +00:00
|
|
|
g_slist_free (g.chain->elements);
|
2004-04-19 17:40:24 +00:00
|
|
|
gst_parse_chain_free (g.chain);
|
2003-04-08 21:59:44 +00:00
|
|
|
}
|
2004-04-19 17:40:24 +00:00
|
|
|
|
|
|
|
g_slist_foreach (g.links, (GFunc)gst_parse_free_link, NULL);
|
2003-04-08 21:59:44 +00:00
|
|
|
g_slist_free (g.links);
|
|
|
|
|
2004-05-04 17:00:11 +00:00
|
|
|
if (error)
|
|
|
|
g_assert (*error);
|
2003-04-08 21:59:44 +00:00
|
|
|
ret = NULL;
|
|
|
|
|
|
|
|
goto out;
|
2002-03-31 21:09:17 +00:00
|
|
|
}
|