static guint __strings;
static guint __links;
static guint __chains;
+static guint __elements;
gchar *
__gst_parse_strdup (gchar *org)
{
__chains--;
}
+element_t *
+__gst_parse_element_new (void)
+{
+ element_t *ret;
+ __elements++;
+ ret = g_slice_new0 (element_t);
+ /* g_print ("@%p: ALLOCATED ELEMENT (%3u):\n", ret, __elements); */
+ return ret;
+}
+void
+__gst_parse_element_free (element_t *data)
+{
+ /* g_print ("@%p: FREEING ELEMENT (%3u):\n", data, __elements - 1); */
+ g_slice_free (element_t, data);
+ g_return_if_fail (__elements > 0);
+ __elements--;
+}
+
#endif /* __GST_PARSE_TRACE */
/*******************************************************************************************
goto out;
}
-static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
-{
- GParamSpec *pspec = NULL;
+static gchar *
+gst_parse_split_assignment (gchar *value) {
gchar *pos = value;
- GValue v = { 0, };
- GObject *target = NULL;
- GType value_type;
-
- /* do nothing if assignment is for missing element */
- if (element == NULL)
- goto out;
/* parse the string, so the property name is null-terminated and pos points
to the beginning of the value */
}
gst_parse_unescape (pos);
- if (GST_IS_CHILD_PROXY (element) && strstr (value, "::") != NULL) {
- if (!gst_child_proxy_lookup (GST_CHILD_PROXY (element), value, &target, &pspec)) {
- /* do a delayed set */
- gst_parse_add_delayed_set (element, value, pos);
- }
- } else {
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value);
- if (pspec != NULL) {
- target = G_OBJECT (g_object_ref (element));
- GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, target, "found %s property", value);
- } else {
- SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
- _("no property \"%s\" in element \"%s\""), value, \
- GST_ELEMENT_NAME (element));
- }
- }
-
- if (pspec != NULL && target != NULL) {
- gboolean got_value = FALSE;
-
- value_type = pspec->value_type;
-
- GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, element, "parsing property %s as a %s",
- pspec->name, g_type_name (value_type));
-
- g_value_init (&v, value_type);
- if (gst_value_deserialize_with_pspec (&v, pos, pspec))
- got_value = TRUE;
- else if (g_type_is_a (value_type, GST_TYPE_ELEMENT)) {
- GstElement *bin;
+ return pos;
+}
- bin = gst_parse_bin_from_description_full (pos, TRUE, NULL,
- GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN, NULL);
- if (bin) {
- g_value_set_object (&v, bin);
- got_value = TRUE;
- }
- }
- if (!got_value)
- goto error;
- g_object_set_property (target, pspec->name, &v);
+static gboolean
+collect_value (GParamSpec *pspec, gchar *value_str, GValue *v)
+{
+ gboolean got_value = FALSE;
+
+ GST_CAT_ERROR (GST_CAT_PIPELINE, "parsing property %s as a %s",
+ pspec->name, g_type_name (pspec->value_type));
+
+ g_value_init (v, pspec->value_type);
+ if (gst_value_deserialize_with_pspec (v, value_str, pspec))
+ got_value = TRUE;
+ else if (g_type_is_a (pspec->value_type, GST_TYPE_ELEMENT)) {
+ GstElement *bin;
+
+ bin = gst_parse_bin_from_description_full (value_str, TRUE, NULL,
+ GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN, NULL);
+ if (bin) {
+ g_value_set_object (v, bin);
+ got_value = TRUE;
+ }
}
-out:
- gst_parse_strfree (value);
- if (G_IS_VALUE (&v))
- g_value_unset (&v);
- if (target)
- gst_object_unref (target);
- return;
-
-error:
- SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
- _("could not set property \"%s\" in element \"%s\" to \"%s\""),
- value, GST_ELEMENT_NAME (element), pos);
- goto out;
+ return got_value;
}
static void gst_parse_element_preset (gchar *value, GstElement *element, graph_t *graph)
goto error;
out:
- gst_parse_strfree (value);
return;
not_a_preset:
goto out;
}
+typedef struct
+{
+ gchar *name;
+ gchar *value;
+} proxied_property_t;
+
+static void
+proxied_property_free (proxied_property_t *pp) {
+ g_slice_free (proxied_property_t, pp);
+}
+
+static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
+ GstElementFactory *loaded_factory;
+ GstElementFactory *factory = gst_element_factory_find (data->factory_name);
+ GObjectClass *klass;
+ GParamSpec *pspec = NULL;
+ GSList *tmp;
+ gboolean is_proxy;
+ GSList *proxied = NULL;
+ guint n_params = 0;
+ guint n_params_alloc = 16;
+ const gchar **names_array;
+ GValue *values_array;
+ GstElement *ret = NULL;
+
+ if (!factory) {
+ SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), data->factory_name);
+ return NULL;
+ }
+
+ loaded_factory =
+ GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
+ (factory)));
+
+ gst_object_unref (factory);
+
+ klass = g_type_class_ref (gst_element_factory_get_element_type (loaded_factory));
+
+ is_proxy = g_type_is_a (gst_element_factory_get_element_type (loaded_factory), GST_TYPE_CHILD_PROXY);
+
+ names_array = g_new0 (const gchar *, n_params_alloc);
+ values_array = g_new0 (GValue, n_params_alloc);
+
+ for (tmp = data->values; tmp; tmp = tmp->next) {
+ gchar *name = tmp->data;
+ gchar *value = gst_parse_split_assignment (tmp->data);
+
+ if (is_proxy && strstr (name, "::") != NULL) {
+ proxied_property_t *pp = g_slice_new (proxied_property_t);
+ pp->name = name;
+ pp->value = value;
+ proxied = g_slist_prepend (proxied, pp);
+ continue;
+ }
+
+ pspec = g_object_class_find_property (klass, name);
+
+ if (pspec != NULL) {
+ if (G_UNLIKELY (n_params == n_params_alloc)) {
+ n_params_alloc *= 2u;
+ names_array =
+ g_realloc (names_array, sizeof (const gchar *) * n_params_alloc);
+ values_array = g_realloc (values_array, sizeof (GValue) * n_params_alloc);
+ memset (&values_array[n_params], 0,
+ sizeof (GValue) * (n_params_alloc - n_params));
+ }
+
+ if (!collect_value (pspec, value, &values_array[n_params])) {
+ SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+ _("could not set property \"%s\" in element \"%s\" to \"%s\""),
+ name, data->factory_name, value);
+ g_value_unset (&values_array[n_params]);
+ goto done;
+ } else {
+ names_array[n_params] = name;
+ }
+
+ ++n_params;
+ } else {
+ SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+ _("no property \"%s\" in element \"%s\""), name, \
+ data->factory_name);
+ goto done;
+ }
+ }
+
+ ret = gst_element_factory_create_with_properties (factory, n_params, names_array,
+ values_array);
+
+ for (tmp = proxied; tmp; tmp = tmp->next) {
+ GObject *target = NULL;
+ proxied_property_t *pp = tmp->data;
+
+ if (!gst_child_proxy_lookup (GST_CHILD_PROXY (ret), pp->name, &target, &pspec)) {
+ /* do a delayed set */
+ gst_parse_add_delayed_set (ret, pp->name, pp->value);
+ } else {
+ GValue v = { 0, };
+
+ if (!collect_value (pspec, pp->value, &v)) {
+ SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+ _("could not set property \"%s\" in child of element \"%s\" to \"%s\""),
+ pp->name, data->factory_name, pp->value);
+ g_value_unset (&v);
+ goto done;
+ } else {
+ g_object_set_property (target, pspec->name, &v);
+ g_value_unset (&v);
+ }
+ }
+ }
+
+ for (tmp = data->presets; tmp; tmp = tmp->next) {
+ gst_parse_element_preset (tmp->data, ret, graph);
+ }
+
+done:
+ g_slist_free_full (proxied, (GDestroyNotify) proxied_property_free);
+ gst_object_unref (loaded_factory);
+ g_type_class_unref (klass);
+ g_free (names_array);
+ while (n_params--)
+ g_value_unset (&values_array[n_params]);
+ g_free (values_array);
+
+ return ret;
+}
+
+static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *graph)
+{
+ GParamSpec *pspec = NULL;
+ gchar *pos;
+ GValue v = { 0, };
+ GObject *target = NULL;
+
+ /* do nothing if assignment is for missing element */
+ if (element == NULL)
+ goto out;
+
+ pos = gst_parse_split_assignment (value);
+
+ if (GST_IS_CHILD_PROXY (element) && strstr (value, "::") != NULL) {
+ if (!gst_child_proxy_lookup (GST_CHILD_PROXY (element), value, &target, &pspec)) {
+ /* do a delayed set */
+ gst_parse_add_delayed_set (element, value, pos);
+ }
+ } else {
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), value);
+ if (pspec != NULL) {
+ target = G_OBJECT (g_object_ref (element));
+ GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, target, "found %s property", value);
+ } else {
+ SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+ _("no property \"%s\" in element \"%s\""), value, \
+ GST_ELEMENT_NAME (element));
+ }
+ }
+
+ if (pspec != NULL && target != NULL) {
+ if (!collect_value (pspec, pos, &v)) {
+ goto error;
+ } else {
+ g_object_set_property (target, pspec->name, &v);
+ }
+ }
+
+out:
+ gst_parse_strfree (value);
+ if (G_IS_VALUE (&v))
+ g_value_unset (&v);
+ if (target)
+ gst_object_unref (target);
+ return;
+
+error:
+ SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+ _("could not set property \"%s\" in element \"%s\" to \"%s\""),
+ value, GST_ELEMENT_NAME (element), pos);
+ goto out;
+}
+
static void gst_parse_free_reference (reference_t *rr)
{
if(rr->element) gst_object_unref(rr->element);
gst_parse_chain_free (ch);
}
+static void gst_parse_free_element (element_t *el)
+{
+ g_slist_free_full (el->values, gst_parse_strfree);
+ g_slist_free_full (el->presets, gst_parse_strfree);
+ gst_parse_strfree (el->factory_name);
+ gst_parse_element_free (el);
+}
+
static void gst_parse_free_delayed_link (DelayedLink *link)
{
g_free (link->src_pad);
chain_t *cc;
link_t *ll;
reference_t rr;
- GstElement *ee;
+ element_t *ee;
GSList *pp;
graph_t *gg;
}
gst_parse_free_chain($$); } <cc>
%destructor { gst_parse_free_link ($$); } <ll>
%destructor { gst_parse_free_reference(&($$));} <rr>
-%destructor { gst_object_unref ($$); } <ee>
+%destructor { gst_parse_free_element ($$); } <ee>
%destructor { GSList *walk;
for(walk=$$;walk;walk=walk->next)
gst_parse_strfree (walk->data);
* identity silence=false name=frodo
* (cont'd)
**************************************************************/
-element: IDENTIFIER { $$ = gst_element_factory_make ($1, NULL);
- if ($$ == NULL) {
- add_missing_element(graph, $1);
- SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), $1);
- }
- gst_parse_strfree ($1);
+element: IDENTIFIER {
+ $$ = gst_parse_element_new();
+ $$->factory_name = $1;
}
- | element PRESET { gst_parse_element_preset ($2, $1, graph);
+ | element PRESET {
+ $$->presets = g_slist_append ($$->presets, $2);
$$ = $1;
}
- | element ASSIGNMENT { gst_parse_element_set ($2, $1, graph);
+ | element ASSIGNMENT {
+ $$->values = g_slist_append ($$->values, $2);
$$ = $1;
}
;
*
**************************************************************/
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;
+ element {
+ GstElement *element = NULL;
+
+ $$ = gst_parse_chain_new ();
+
+ if ($1 && !(element = gst_parse_element_make (graph, $1))) {
+ add_missing_element(graph, $1->factory_name);
+ } else {
+ /* g_print ("@%p: CHAINing elementary\n", $$); */
+ $$->first.element = element ? gst_object_ref(element) : NULL;
+ $$->last.element = element ? gst_object_ref(element) : NULL;
+ $$->first.name = $$->last.name = NULL;
+ $$->first.pads = $$->last.pads = NULL;
+ $$->elements = element ? g_slist_prepend (NULL, element) : NULL;
+ }
+
+ gst_parse_free_element ($1);
+
}
| bin { $$=$1; }
;
#ifdef __GST_PARSE_TRACE
GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
- __strings = __chains = __links = 0;
+ __strings = __chains = __links = __elements = 0;
#endif /* __GST_PARSE_TRACE */
/* g_print("Now scanning: %s\n", str); */
out:
#ifdef __GST_PARSE_TRACE
GST_CAT_DEBUG (GST_CAT_PIPELINE,
- "TRACE: %u strings, %u chains and %u links left", __strings, __chains,
- __links);
- if (__strings || __chains || __links) {
- g_warning ("TRACE: %u strings, %u chains and %u links left", __strings,
- __chains, __links);
+ "TRACE: %u strings, %u chains, %u links and %u elements left", __strings, __chains,
+ __links, __elements);
+ if (__strings || __chains || __links || __elements) {
+ g_warning ("TRACE: %u strings, %u chains, %u links and %u elements left", __strings,
+ __chains, __links, __elements);
}
#endif /* __GST_PARSE_TRACE */