+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;
+}
+