mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
structured-interface: Factor out method to get element to set property
Used to set properties or keyframes Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/227>
This commit is contained in:
parent
ba763cfaf3
commit
811d63439f
1 changed files with 131 additions and 103 deletions
|
@ -30,6 +30,32 @@
|
||||||
#define LAST_CONTAINER_QDATA g_quark_from_string("ges-structured-last-container")
|
#define LAST_CONTAINER_QDATA g_quark_from_string("ges-structured-last-container")
|
||||||
#define LAST_CHILD_QDATA g_quark_from_string("ges-structured-last-child")
|
#define LAST_CHILD_QDATA g_quark_from_string("ges-structured-last-child")
|
||||||
|
|
||||||
|
#ifdef G_HAVE_ISO_VARARGS
|
||||||
|
#define REPORT_UNLESS(condition, errpoint, ...) \
|
||||||
|
G_STMT_START { \
|
||||||
|
if (!(condition)) { \
|
||||||
|
gchar *tmp = gst_info_strdup_printf(__VA_ARGS__); \
|
||||||
|
*error = g_error_new_literal (GES_ERROR, 0, tmp); \
|
||||||
|
g_free (tmp); \
|
||||||
|
goto errpoint; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
#else /* G_HAVE_GNUC_VARARGS */
|
||||||
|
#ifdef G_HAVE_GNUC_VARARGS
|
||||||
|
#define REPORT_UNLESS(condition, errpoint, args...) \
|
||||||
|
G_STMT_START { \
|
||||||
|
if (!(condition)) { \
|
||||||
|
gchar *tmp = gst_info_strdup_printf(##args); \
|
||||||
|
*error = g_error_new_literal (GES_ERROR, 0, tmp); \
|
||||||
|
g_free (tmp); \
|
||||||
|
goto errpoint; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
#endif /* G_HAVE_ISO_VARARGS */
|
||||||
|
#endif /* G_HAVE_GNUC_VARARGS */
|
||||||
|
|
||||||
#define GET_AND_CHECK(name,type,var,label) G_STMT_START {\
|
#define GET_AND_CHECK(name,type,var,label) G_STMT_START {\
|
||||||
gboolean found = FALSE; \
|
gboolean found = FALSE; \
|
||||||
\
|
\
|
||||||
|
@ -124,6 +150,77 @@ _check_fields (GstStructure * structure, FieldsError fields_error,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GESTimelineElement *
|
||||||
|
find_element_for_property (GESTimeline * timeline, GstStructure * structure,
|
||||||
|
gchar ** property_name, gboolean require_track_element, GError ** error)
|
||||||
|
{
|
||||||
|
GList *tmp;
|
||||||
|
const gchar *element_name;
|
||||||
|
GESTimelineElement *element;
|
||||||
|
|
||||||
|
element_name = gst_structure_get_string (structure, "element-name");
|
||||||
|
if (element_name == NULL) {
|
||||||
|
element = g_object_get_qdata (G_OBJECT (timeline), LAST_CHILD_QDATA);
|
||||||
|
if (element)
|
||||||
|
gst_object_ref (element);
|
||||||
|
} else {
|
||||||
|
element = ges_timeline_get_element (timeline, element_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*property_name == NULL) {
|
||||||
|
gchar *tmpstr = *property_name;
|
||||||
|
const gchar *name = gst_structure_get_name (structure);
|
||||||
|
|
||||||
|
REPORT_UNLESS (g_str_has_prefix (name, "set-"), err,
|
||||||
|
"Could not find any property name in %" GST_PTR_FORMAT, structure);
|
||||||
|
|
||||||
|
*property_name = g_strdup (&tmpstr[4]);
|
||||||
|
|
||||||
|
g_free (tmpstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
if (!ges_timeline_element_lookup_child (element,
|
||||||
|
*property_name, NULL, NULL)) {
|
||||||
|
gst_clear_object (&element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
element = g_object_get_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA);
|
||||||
|
if (element)
|
||||||
|
gst_object_ref (element);
|
||||||
|
}
|
||||||
|
|
||||||
|
REPORT_UNLESS (GES_IS_TIMELINE_ELEMENT (element), err,
|
||||||
|
"Could not find child %s from %" GST_PTR_FORMAT, element_name, structure);
|
||||||
|
|
||||||
|
if (!require_track_element || GES_IS_TRACK_ELEMENT (element))
|
||||||
|
return element;
|
||||||
|
|
||||||
|
|
||||||
|
REPORT_UNLESS (GES_IS_CONTAINER (element), err,
|
||||||
|
"Could not find child %s from %" GST_PTR_FORMAT, element_name, structure);
|
||||||
|
|
||||||
|
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), err,
|
||||||
|
"Could not find TrackElement from %" GST_PTR_FORMAT, structure);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
|
||||||
|
err:
|
||||||
|
g_clear_object (&element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_ges_save_timeline_if_needed (GESTimeline * timeline, GstStructure * structure,
|
_ges_save_timeline_if_needed (GESTimeline * timeline, GstStructure * structure,
|
||||||
GError ** error)
|
GError ** error)
|
||||||
|
@ -144,14 +241,14 @@ gboolean
|
||||||
_ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
|
_ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
|
||||||
GstStructure * structure, GError ** error)
|
GstStructure * structure, GError ** error)
|
||||||
{
|
{
|
||||||
GESTrackElement *element;
|
GESTimelineElement *element = NULL;
|
||||||
|
|
||||||
gboolean absolute;
|
gboolean absolute;
|
||||||
gdouble value;
|
gdouble value;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
GstControlBinding *binding = NULL;
|
GstControlBinding *binding = NULL;
|
||||||
GstTimedValueControlSource *source = NULL;
|
GstTimedValueControlSource *source = NULL;
|
||||||
gchar *element_name = NULL, *property_name = NULL;
|
gchar *property_name = NULL;
|
||||||
|
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gboolean setting_value;
|
gboolean setting_value;
|
||||||
|
@ -166,68 +263,37 @@ _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
|
||||||
if (!_check_fields (structure, fields_error, error))
|
if (!_check_fields (structure, fields_error, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
GET_AND_CHECK ("element-name", G_TYPE_STRING, &element_name, done);
|
|
||||||
GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
|
GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
|
||||||
GET_AND_CHECK ("timestamp", GST_TYPE_CLOCK_TIME, ×tamp, done);
|
GET_AND_CHECK ("timestamp", GST_TYPE_CLOCK_TIME, ×tamp, done);
|
||||||
|
|
||||||
element =
|
GET_AND_CHECK ("property-name", G_TYPE_STRING, &property_name, done);
|
||||||
(GESTrackElement *) ges_timeline_get_element (timeline, element_name);
|
if (!(element =
|
||||||
|
find_element_for_property (timeline, structure, &property_name, TRUE,
|
||||||
if (GES_IS_CLIP (element)) {
|
error)))
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GES_IS_TRACK_ELEMENT (element)) {
|
|
||||||
*error =
|
|
||||||
g_error_new (GES_ERROR, 0, "Could not find TrackElement %s",
|
|
||||||
element_name);
|
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
binding = ges_track_element_get_control_binding (element, property_name);
|
REPORT_UNLESS (binding =
|
||||||
if (binding == NULL) {
|
ges_track_element_get_control_binding (GES_TRACK_ELEMENT (element),
|
||||||
*error = g_error_new (GES_ERROR, 0, "No control binding found for %s:%s"
|
property_name),
|
||||||
" you should first set-control-binding on it",
|
done, "No control binding found for %" GST_PTR_FORMAT, structure);
|
||||||
element_name, property_name);
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_get (binding, "control-source", &source, NULL);
|
g_object_get (binding, "control-source", &source, NULL);
|
||||||
|
REPORT_UNLESS (source, done,
|
||||||
if (source == NULL) {
|
"No control source found for '%" GST_PTR_FORMAT
|
||||||
*error = g_error_new (GES_ERROR, 0, "No control source found for %s:%s"
|
"' you should first set-control-binding on it", structure);
|
||||||
" you should first set-control-binding on it",
|
REPORT_UNLESS (GST_IS_TIMED_VALUE_CONTROL_SOURCE (source), done,
|
||||||
element_name, property_name);
|
"You can use add-keyframe"
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GST_IS_TIMED_VALUE_CONTROL_SOURCE (source)) {
|
|
||||||
*error = g_error_new (GES_ERROR, 0, "You can use add-keyframe"
|
|
||||||
" only on GstTimedValueControlSource not %s",
|
" only on GstTimedValueControlSource not %s",
|
||||||
G_OBJECT_TYPE_NAME (source));
|
G_OBJECT_TYPE_NAME (source));
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_get (binding, "absolute", &absolute, NULL);
|
g_object_get (binding, "absolute", &absolute, NULL);
|
||||||
if (absolute) {
|
if (absolute) {
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
const GValue *v;
|
const GValue *v;
|
||||||
GValue v2 = G_VALUE_INIT;
|
GValue v2 = G_VALUE_INIT;
|
||||||
|
|
||||||
if (!ges_timeline_element_lookup_child (GES_TIMELINE_ELEMENT (element),
|
if (!ges_timeline_element_lookup_child (element, property_name, NULL,
|
||||||
property_name, NULL, &pspec)) {
|
&pspec)) {
|
||||||
*error =
|
*error =
|
||||||
g_error_new (GES_ERROR, 0, "Could not get property %s for %s",
|
g_error_new (GES_ERROR, 0, "Could not get property %s for %s",
|
||||||
property_name, GES_TIMELINE_ELEMENT_NAME (element));
|
property_name, GES_TIMELINE_ELEMENT_NAME (element));
|
||||||
|
@ -262,8 +328,8 @@ _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
|
||||||
} else
|
} else
|
||||||
GET_AND_CHECK ("value", G_TYPE_DOUBLE, &value, done);
|
GET_AND_CHECK ("value", G_TYPE_DOUBLE, &value, done);
|
||||||
|
|
||||||
setting_value
|
setting_value =
|
||||||
= !g_strcmp0 (gst_structure_get_name (structure), "add-keyframe");
|
!g_strcmp0 (gst_structure_get_name (structure), "add-keyframe");
|
||||||
if (setting_value)
|
if (setting_value)
|
||||||
ret = gst_timed_value_control_source_set (source, timestamp, value);
|
ret = gst_timed_value_control_source_set (source, timestamp, value);
|
||||||
else
|
else
|
||||||
|
@ -278,9 +344,8 @@ _ges_add_remove_keyframe_from_struct (GESTimeline * timeline,
|
||||||
ret = _ges_save_timeline_if_needed (timeline, structure, error);
|
ret = _ges_save_timeline_if_needed (timeline, structure, error);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (source)
|
gst_clear_object (&source);
|
||||||
gst_object_unref (source);
|
gst_clear_object (&element);
|
||||||
g_free (element_name);
|
|
||||||
g_free (property_name);
|
g_free (property_name);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -771,8 +836,8 @@ _ges_set_child_property_from_struct (GESTimeline * timeline,
|
||||||
const GValue *value;
|
const GValue *value;
|
||||||
GValue prop_value = G_VALUE_INIT;
|
GValue prop_value = G_VALUE_INIT;
|
||||||
gboolean prop_value_set = FALSE;
|
gboolean prop_value_set = FALSE;
|
||||||
|
gchar *property_name;
|
||||||
GESTimelineElement *element;
|
GESTimelineElement *element;
|
||||||
const gchar *property_name, *element_name;
|
|
||||||
gchar *serialized;
|
gchar *serialized;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
|
||||||
|
@ -784,54 +849,12 @@ _ges_set_child_property_from_struct (GESTimeline * timeline,
|
||||||
if (!_check_fields (structure, fields_error, error))
|
if (!_check_fields (structure, fields_error, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
element_name = gst_structure_get_string (structure, "element-name");
|
GET_AND_CHECK ("property", G_TYPE_STRING, &property_name, err);
|
||||||
if (element_name == NULL)
|
|
||||||
element = g_object_get_qdata (G_OBJECT (timeline), LAST_CHILD_QDATA);
|
|
||||||
else
|
|
||||||
element = ges_timeline_get_element (timeline, element_name);
|
|
||||||
|
|
||||||
property_name = gst_structure_get_string (structure, "property");
|
if (!(element =
|
||||||
if (property_name == NULL) {
|
find_element_for_property (timeline, structure, &property_name, FALSE,
|
||||||
const gchar *name = gst_structure_get_name (structure);
|
error)))
|
||||||
|
goto err;
|
||||||
if (g_str_has_prefix (name, "set-"))
|
|
||||||
property_name = &name[4];
|
|
||||||
else {
|
|
||||||
gchar *struct_str = gst_structure_to_string (structure);
|
|
||||||
|
|
||||||
*error =
|
|
||||||
g_error_new (GES_ERROR, 0, "Could not find any property name in %s",
|
|
||||||
struct_str);
|
|
||||||
g_free (struct_str);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element) {
|
|
||||||
if (!ges_track_element_lookup_child (GES_TRACK_ELEMENT (element),
|
|
||||||
property_name, NULL, NULL))
|
|
||||||
element = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!element) {
|
|
||||||
element = g_object_get_qdata (G_OBJECT (timeline), LAST_CONTAINER_QDATA);
|
|
||||||
|
|
||||||
if (element == NULL) {
|
|
||||||
*error =
|
|
||||||
g_error_new (GES_ERROR, 0,
|
|
||||||
"Could not find anywhere to set property: %s", property_name);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GES_IS_TIMELINE_ELEMENT (element)) {
|
|
||||||
*error =
|
|
||||||
g_error_new (GES_ERROR, 0, "Could not find child %s", element_name);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = gst_structure_get_value (structure, "value");
|
value = gst_structure_get_value (structure, "value");
|
||||||
|
|
||||||
|
@ -888,7 +911,12 @@ _ges_set_child_property_from_struct (GESTimeline * timeline,
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
g_free (property_name);
|
||||||
return _ges_save_timeline_if_needed (timeline, structure, error);
|
return _ges_save_timeline_if_needed (timeline, structure, error);
|
||||||
|
|
||||||
|
err:
|
||||||
|
g_free (property_name);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef GET_AND_CHECK
|
#undef GET_AND_CHECK
|
||||||
|
|
Loading…
Reference in a new issue