mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
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>
This commit is contained in:
parent
811d63439f
commit
ad5626dab8
3 changed files with 179 additions and 83 deletions
|
@ -100,6 +100,21 @@ typedef struct
|
|||
GList *invalid_fields;
|
||||
} 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)
|
||||
{
|
||||
|
@ -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, ×tamp, 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, ×tamp, 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue