summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThibault Saunier <tsaunier@igalia.com>2021-01-15 09:25:11 -0300
committerThibault Saunier <tsaunier@igalia.com>2021-02-10 16:14:47 -0300
commitad5626dab81be27310387dd332e7b2f1f9cc0366 (patch)
tree0437b7f7abd7a38600b52be69d5933b26a1bde72
parent811d63439f03c7b48f395753c7900c61117b3c45 (diff)
structured-interface: Move set_control_source from ges-validate
So it can be reused in the command line formatter. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/227>
-rw-r--r--ges/ges-structured-interface.c187
-rw-r--r--ges/ges-structured-interface.h4
-rw-r--r--ges/ges-validate.c71
3 files changed, 179 insertions, 83 deletions
diff --git a/ges/ges-structured-interface.c b/ges/ges-structured-interface.c
index 753e848a..253b9b40 100644
--- a/ges/ges-structured-interface.c
+++ b/ges/ges-structured-interface.c
@@ -101,6 +101,21 @@ typedef struct
} FieldsError;
static gboolean
+enum_from_str (GType type, const gchar * str_enum, guint * enum_value)
+{
+ GValue value = G_VALUE_INIT;
+ g_value_init (&value, type);
+
+ if (!gst_value_deserialize (&value, str_enum))
+ return FALSE;
+
+ *enum_value = g_value_get_enum (&value);
+ g_value_unset (&value);
+
+ return TRUE;
+}
+
+static gboolean
_check_field (GQuark field_id, const GValue * value, FieldsError * fields_error)
{
guint i;
@@ -237,6 +252,69 @@ _ges_save_timeline_if_needed (GESTimeline * timeline, GstStructure * structure,
return res;
}
+typedef struct
+{
+ GstTimedValueControlSource *source;
+ GstStructure *structure;
+ GError *error;
+ const gchar *property_name;
+ gboolean res;
+} SetKeyframesData;
+
+static gboolean
+un_set_keyframes_foreach (GQuark field_id, const GValue * value,
+ SetKeyframesData * d)
+{
+ GValue v = G_VALUE_INIT;
+ GError **error = &d->error;
+ gchar *tmp;
+ gint i;
+ const gchar *valid_fields[] = {
+ "element-name", "property-name", "value", "timestamp", "project-uri",
+ "binding-type", "source-type", "interpolation-mode", "interpolation-mode",
+ NULL
+ };
+ const gchar *field = g_quark_to_string (field_id);
+ gdouble ts;
+
+ for (i = 0; valid_fields[i]; i++) {
+ if (g_quark_from_string (valid_fields[i]) == field_id)
+ return TRUE;
+ }
+
+ errno = 0;
+ ts = g_strtod (field, &tmp);
+
+ REPORT_UNLESS (errno == 0 && field != tmp, err,
+ "Could not convert `%s` to GstClockTime (%s)", field, g_strerror (errno));
+
+ if (gst_structure_has_name (d->structure, "remove-keyframe")) {
+ REPORT_UNLESS (gst_timed_value_control_source_unset (d->source,
+ ts * GST_SECOND), err, "Could not unset keyframe at %f", ts);
+
+ return TRUE;
+ }
+
+ g_value_init (&v, G_TYPE_DOUBLE);
+ REPORT_UNLESS (g_value_transform (value, &v), err,
+ "Could not convert keyframe %f value %s to double", ts,
+ gst_value_serialize (value));
+
+ REPORT_UNLESS (gst_timed_value_control_source_set (d->source, ts * GST_SECOND,
+ g_value_get_double (&v)), err, "Could not set keyframe %f=%f", ts,
+ g_value_get_double (&v));
+
+ g_value_reset (&v);
+ return TRUE;
+
+err:
+ if (v.g_type)
+ g_value_reset (&v);
+ d->res = FALSE;
+ return FALSE;
+}
+
+
gboolean
_ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
GstStructure * structure, GError ** error)
@@ -260,11 +338,15 @@ _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
FieldsError fields_error = { valid_fields, NULL };
- if (!_check_fields (structure, fields_error, error))
- return FALSE;
-
- GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
- GET_AND_CHECK ("timestamp", GST_TYPE_CLOCK_TIME, &timestamp, done);
+ if (gst_structure_has_field (structure, "value")) {
+ if (!_check_fields (structure, fields_error, error))
+ return FALSE;
+ GET_AND_CHECK ("timestamp", GST_TYPE_CLOCK_TIME, &timestamp, done);
+ } else {
+ REPORT_UNLESS (!gst_structure_has_field (structure, "timestamp"), done,
+ "Doesn't have a `value` field in %" GST_PTR_FORMAT
+ " but has a `timestamp`" " that can't work!", structure);
+ }
GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
if (!(element =
@@ -286,6 +368,18 @@ _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
" only on GstTimedValueControlSource not %s",
G_OBJECT_TYPE_NAME (source));
+ if (!gst_structure_has_field (structure, "value")) {
+ SetKeyframesData d = {
+ source, structure, NULL, property_name, TRUE,
+ };
+ gst_structure_foreach (structure,
+ (GstStructureForeachFunc) un_set_keyframes_foreach, &d);
+ if (!d.res)
+ g_propagate_error (error, d.error);
+
+ return d.res;
+ }
+
g_object_get (binding, "absolute", &absolute, NULL);
if (absolute) {
GParamSpec *pspec;
@@ -585,17 +679,11 @@ _ges_add_clip_from_struct (GESTimeline * timeline, GstStructure * structure,
if (GES_IS_TEST_CLIP (clip)) {
if (pattern) {
- GEnumClass *enum_class =
- G_ENUM_CLASS (g_type_class_ref (GES_VIDEO_TEST_PATTERN_TYPE));
- GEnumValue *value = g_enum_get_value_by_nick (enum_class, pattern);
+ guint v;
- if (!value) {
- res = FALSE;
- goto beach;
- }
-
- ges_test_clip_set_vpattern (GES_TEST_CLIP (clip), value->value);
- g_type_class_unref (enum_class);
+ REPORT_UNLESS (enum_from_str (GES_VIDEO_TEST_PATTERN_TYPE, pattern, &v),
+ beach, "Invalid pattern: %s", pattern);
+ ges_test_clip_set_vpattern (GES_TEST_CLIP (clip), v);
}
}
@@ -919,5 +1007,74 @@ err:
return FALSE;
}
+gboolean
+_ges_set_control_source_from_struct (GESTimeline * timeline,
+ GstStructure * structure, GError ** error)
+{
+ guint mode;
+ gboolean res = FALSE;
+ GESTimelineElement *element = NULL;
+
+ GstControlSource *source = NULL;
+ gchar *property_name, *binding_type = NULL,
+ *source_type = NULL, *interpolation_mode = NULL;
+
+ GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, beach);
+
+ if (!(element =
+ find_element_for_property (timeline, structure, &property_name, TRUE,
+ error)))
+ goto beach;
+
+ if (GES_IS_CLIP (element)) {
+ GList *tmp;
+ for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
+ if (ges_timeline_element_lookup_child (tmp->data, property_name, NULL,
+ NULL)) {
+ gst_object_replace ((GstObject **) & element, tmp->data);
+
+ break;
+ }
+ }
+ }
+
+ REPORT_UNLESS (GES_IS_TRACK_ELEMENT (element), beach,
+ "Could not find TrackElement from %" GST_PTR_FORMAT, structure);
+
+ TRY_GET ("binding-type", G_TYPE_STRING, &binding_type, NULL);
+ TRY_GET ("source-type", G_TYPE_STRING, &source_type, NULL);
+ TRY_GET ("interpolation-mode", G_TYPE_STRING, &interpolation_mode, NULL);
+
+ if (!binding_type)
+ binding_type = g_strdup ("direct");
+
+ REPORT_UNLESS (source_type == NULL
+ || !g_strcmp0 (source_type, "interpolation"), beach,
+ "Interpolation type %s not supported", source_type);
+ source = gst_interpolation_control_source_new ();
+
+ if (interpolation_mode)
+ REPORT_UNLESS (enum_from_str (GST_TYPE_INTERPOLATION_MODE,
+ interpolation_mode, &mode), beach,
+ "Wrong interpolation mode: %s", interpolation_mode);
+ else
+ mode = GST_INTERPOLATION_MODE_LINEAR;
+
+ g_object_set (source, "mode", mode, NULL);
+
+ res = ges_track_element_set_control_source (GES_TRACK_ELEMENT (element),
+ source, property_name, binding_type);
+
+beach:
+ gst_clear_object (&element);
+ gst_clear_object (&source);
+ g_free (property_name);
+ g_free (binding_type);
+ g_free (source_type);
+ g_free (interpolation_mode);
+
+ return res;
+}
+
#undef GET_AND_CHECK
#undef TRY_GET
diff --git a/ges/ges-structured-interface.h b/ges/ges-structured-interface.h
index 13efc167..9dd7a69b 100644
--- a/ges/ges-structured-interface.h
+++ b/ges/ges-structured-interface.h
@@ -62,4 +62,8 @@ _ges_get_layer_by_priority (GESTimeline * timeline,
G_GNUC_INTERNAL gboolean
_ges_save_timeline_if_needed (GESTimeline* timeline, GstStructure* structure, GError** error);
+G_GNUC_INTERNAL gboolean
+_ges_set_control_source_from_struct (GESTimeline * timeline,
+ GstStructure * structure, GError ** error);
+
G_END_DECLS
diff --git a/ges/ges-validate.c b/ges/ges-validate.c
index ace70e84..7354b6c7 100644
--- a/ges/ges-validate.c
+++ b/ges/ges-validate.c
@@ -876,73 +876,6 @@ beach:
GST_END_VALIDATE_ACTION;
-GES_START_VALIDATE_ACTION (_set_control_source)
-{
- guint mode;
- GESTrackElement *element = NULL;
-
- GstControlSource *source = NULL;
- gchar *element_name, *property_name, *binding_type = NULL,
- *source_type = NULL, *interpolation_mode = NULL;
-
- REPORT_UNLESS (gst_structure_get (action->structure,
- "element-name", G_TYPE_STRING, &element_name,
- "property-name", G_TYPE_STRING, &property_name, NULL),
- beach, "Wrong parameters");
-
- TRY_GET ("binding-type", G_TYPE_STRING, &binding_type, NULL);
- TRY_GET ("source-type", G_TYPE_STRING, &source_type, NULL);
- TRY_GET ("interpolation-mode", G_TYPE_STRING, &interpolation_mode, NULL);
-
- element =
- (GESTrackElement *) (ges_timeline_get_element (timeline, element_name));
- if (GES_IS_CLIP (element)) {
- GList *tmp;
- for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
- if (ges_timeline_element_lookup_child (tmp->data, property_name, NULL,
- NULL)) {
- gst_object_replace ((GstObject **) & element, tmp->data);
-
- break;
- }
- }
- }
- REPORT_UNLESS (GES_IS_TRACK_ELEMENT (element), beach,
- "Could not find track element element %s (got %" GST_PTR_FORMAT ")",
- element_name, element);
-
- if (!binding_type)
- binding_type = g_strdup ("direct");
-
- REPORT_UNLESS (source_type == NULL
- || !g_strcmp0 (source_type, "interpolation"), beach,
- "Interpolation type %s not supported", source_type);
- source = gst_interpolation_control_source_new ();
-
- if (interpolation_mode)
- REPORT_UNLESS (gst_validate_utils_enum_from_str
- (GST_TYPE_INTERPOLATION_MODE, interpolation_mode, &mode), beach,
- "Wrong intorpolation mode: %s", interpolation_mode);
- else
- mode = GST_INTERPOLATION_MODE_LINEAR;
-
- g_object_set (source, "mode", mode, NULL);
-
- res = ges_track_element_set_control_source (element,
- source, property_name, binding_type);
-
-beach:
- gst_clear_object (&element);
- gst_clear_object (&source);
- g_free (property_name);
- g_free (element_name);
- g_free (binding_type);
- g_free (source_type);
- g_free (interpolation_mode);
-}
-
-GST_END_VALIDATE_ACTION;
-
GES_START_VALIDATE_ACTION (_validate_action_execute)
{
GError *err = NULL;
@@ -952,6 +885,8 @@ GES_START_VALIDATE_ACTION (_validate_action_execute)
if (gst_structure_has_name (action->structure, "add-keyframe") ||
gst_structure_has_name (action->structure, "remove-keyframe")) {
func = _ges_add_remove_keyframe_from_struct;
+ } else if (gst_structure_has_name (action->structure, "set-control-source")) {
+ func = _ges_set_control_source_from_struct;
} else if (gst_structure_has_name (action->structure, "add-clip")) {
func = _ges_add_clip_from_struct;
} else if (gst_structure_has_name (action->structure, "container-add-child")) {
@@ -1743,7 +1678,7 @@ ges_validate_register_action_types (void)
{NULL}
}, "Ungroup children of @container-name.", FALSE);
- gst_validate_register_action_type ("set-control-source", "ges", _set_control_source,
+ gst_validate_register_action_type ("set-control-source", "ges", _validate_action_execute,
(GstValidateActionParameter []) {
{
.name = "element-name",