mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
clip: enforce duration-limit
Prevent setting of properties or that of children, if the clip would not be able to set the corresponding duration if the duration-limit would drop below the currently set duration. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/169>
This commit is contained in:
parent
fd353705b9
commit
0fab5f45cb
5 changed files with 1087 additions and 101 deletions
522
ges/ges-clip.c
522
ges/ges-clip.c
|
@ -128,8 +128,10 @@ struct _GESClipPrivate
|
|||
gboolean prevent_resort;
|
||||
|
||||
gboolean updating_max_duration;
|
||||
gboolean prevent_max_duration_update;
|
||||
gboolean setting_max_duration;
|
||||
gboolean setting_inpoint;
|
||||
gboolean setting_priority;
|
||||
gboolean setting_active;
|
||||
|
||||
gboolean allow_any_track;
|
||||
|
||||
|
@ -138,6 +140,8 @@ struct _GESClipPrivate
|
|||
|
||||
GstClockTime duration_limit;
|
||||
gboolean prevent_duration_limit_update;
|
||||
|
||||
gboolean allow_any_remove;
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -163,7 +167,10 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GESClip, ges_clip,
|
|||
ges_extractable_interface_init));
|
||||
|
||||
/****************************************************
|
||||
* *
|
||||
* Listen to our children *
|
||||
* and restrict them *
|
||||
* *
|
||||
****************************************************/
|
||||
|
||||
#define _IS_CORE_CHILD(child) GES_TRACK_ELEMENT_IS_CORE(child)
|
||||
|
@ -183,6 +190,9 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GESClip, ges_clip,
|
|||
(GST_CLOCK_TIME_IS_VALID (first) && (!GST_CLOCK_TIME_IS_VALID (second) \
|
||||
|| first < second))
|
||||
|
||||
/****************************************************
|
||||
* duration-limit *
|
||||
****************************************************/
|
||||
|
||||
typedef struct _DurationLimitData
|
||||
{
|
||||
|
@ -230,6 +240,22 @@ _duration_limit_data_list (GESClip * clip)
|
|||
return list;
|
||||
}
|
||||
|
||||
/* transfer-full of data */
|
||||
static GList *
|
||||
_duration_limit_data_list_with_data (GESClip * clip, DurationLimitData * data)
|
||||
{
|
||||
GList *tmp, *list = g_list_append (NULL, data);
|
||||
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTrackElement *child = tmp->data;
|
||||
if (data->child == child)
|
||||
continue;
|
||||
list = g_list_prepend (list, _duration_limit_data_new (child));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static gint
|
||||
_cmp_by_track_then_priority (gconstpointer a_p, gconstpointer b_p)
|
||||
{
|
||||
|
@ -250,6 +276,7 @@ _cmp_by_track_then_priority (gconstpointer a_p, gconstpointer b_p)
|
|||
((data->active && GST_CLOCK_TIME_IS_VALID (data->max_duration)) ? \
|
||||
data->max_duration - data->inpoint : GST_CLOCK_TIME_NONE)
|
||||
|
||||
/* transfer-full of child_data */
|
||||
static GstClockTime
|
||||
_calculate_duration_limit (GESClip * self, GList * child_data)
|
||||
{
|
||||
|
@ -341,6 +368,30 @@ _update_duration_limit (GESClip * self)
|
|||
}
|
||||
}
|
||||
|
||||
/* transfer full of child_data */
|
||||
static gboolean
|
||||
_can_update_duration_limit (GESClip * self, GList * child_data)
|
||||
{
|
||||
GESTimeline *timeline = GES_TIMELINE_ELEMENT_TIMELINE (self);
|
||||
GstClockTime duration = _calculate_duration_limit (self, child_data);
|
||||
GESTimelineElement *element = GES_TIMELINE_ELEMENT (self);
|
||||
|
||||
if (_CLOCK_TIME_IS_LESS (duration, element->duration)) {
|
||||
/* NOTE: timeline would normally not be NULL at this point */
|
||||
if (timeline
|
||||
&& !timeline_tree_can_move_element (timeline_get_tree (timeline),
|
||||
element, ges_timeline_element_get_layer_priority (element),
|
||||
element->start, duration)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* priority *
|
||||
****************************************************/
|
||||
|
||||
/* @min_priority: The absolute minimum priority a child of @container should have
|
||||
* @max_priority: The absolute maximum priority a child of @container should have
|
||||
*/
|
||||
|
@ -367,6 +418,32 @@ _get_priority_range (GESContainer * container, guint32 * min_priority,
|
|||
_PRIORITY (container));
|
||||
}
|
||||
|
||||
gboolean
|
||||
ges_clip_can_set_priority_of_child (GESClip * clip, GESTrackElement * child,
|
||||
guint32 priority)
|
||||
{
|
||||
GList *child_data;
|
||||
DurationLimitData *data;
|
||||
|
||||
if (clip->priv->setting_priority)
|
||||
return TRUE;
|
||||
|
||||
data = _duration_limit_data_new (child);
|
||||
data->priority = priority;
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (clip, data);
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot move the child %" GES_FORMAT " from "
|
||||
"priority %" G_GUINT32_FORMAT " to %" G_GUINT32_FORMAT " because "
|
||||
"the duration-limit cannot be adjusted", GES_ARGS (child),
|
||||
_PRIORITY (child), priority);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_child_priority_changed (GESContainer * container, GESTimelineElement * child)
|
||||
{
|
||||
|
@ -381,6 +458,93 @@ _child_priority_changed (GESContainer * container, GESTimelineElement * child)
|
|||
}
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* in-point *
|
||||
****************************************************/
|
||||
|
||||
static gboolean
|
||||
_can_set_inpoint_of_core_children (GESClip * clip, GstClockTime inpoint)
|
||||
{
|
||||
GList *tmp;
|
||||
GList *child_data = NULL;
|
||||
|
||||
if (GES_TIMELINE_ELEMENT_BEING_EDITED (clip))
|
||||
return TRUE;
|
||||
|
||||
/* setting the in-point of a core child will shift the in-point of all
|
||||
* core children with an internal source */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
DurationLimitData *data =
|
||||
_duration_limit_data_new (GES_TRACK_ELEMENT (child));
|
||||
|
||||
if (_IS_CORE_INTERNAL_SOURCE_CHILD (child)) {
|
||||
if (GST_CLOCK_TIME_IS_VALID (child->maxduration)
|
||||
&& child->maxduration < inpoint) {
|
||||
GST_INFO_OBJECT (clip, "Cannot set the in-point from %"
|
||||
G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT " because it would "
|
||||
"cause the in-point of its core child %" GES_FORMAT
|
||||
" to exceed its max-duration", _INPOINT (clip), inpoint,
|
||||
GES_ARGS (child));
|
||||
|
||||
_duration_limit_data_free (data);
|
||||
g_list_free_full (child_data, _duration_limit_data_free);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data->inpoint = inpoint;
|
||||
}
|
||||
|
||||
child_data = g_list_prepend (child_data, data);
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot set the in-point from %" G_GUINT64_FORMAT
|
||||
" to %" G_GUINT64_FORMAT " because the duration-limit cannot be "
|
||||
"adjusted", _INPOINT (clip), inpoint);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Whether @clip can have its in-point set to @inpoint because none of
|
||||
* its children have a max-duration below it */
|
||||
gboolean
|
||||
ges_clip_can_set_inpoint_of_child (GESClip * clip, GESTrackElement * child,
|
||||
GstClockTime inpoint)
|
||||
{
|
||||
/* don't bother checking if we are setting the value */
|
||||
if (clip->priv->setting_inpoint)
|
||||
return TRUE;
|
||||
|
||||
if (GES_TIMELINE_ELEMENT_BEING_EDITED (child))
|
||||
return TRUE;
|
||||
|
||||
if (!_IS_CORE_CHILD (child)) {
|
||||
/* no other sibling will move */
|
||||
GList *child_data;
|
||||
DurationLimitData *data = _duration_limit_data_new (child);
|
||||
data->inpoint = inpoint;
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (clip, data);
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot set the in-point of non-core child %"
|
||||
GES_FORMAT " from %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT
|
||||
" because the duration-limit cannot be adjusted", GES_ARGS (child),
|
||||
_INPOINT (child), inpoint);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* setting the in-point of a core child will shift the in-point of all
|
||||
* core children with an internal source */
|
||||
return _can_set_inpoint_of_core_children (clip, inpoint);
|
||||
}
|
||||
|
||||
/* returns TRUE if duration-limit needs to be updated */
|
||||
static gboolean
|
||||
_child_inpoint_changed (GESClip * self, GESTimelineElement * child)
|
||||
|
@ -406,7 +570,10 @@ _child_inpoint_changed (GESClip * self, GESTimelineElement * child)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* called when a child is added, removed or their max-duration changes */
|
||||
/****************************************************
|
||||
* max-duration *
|
||||
****************************************************/
|
||||
|
||||
static void
|
||||
_update_max_duration (GESContainer * container)
|
||||
{
|
||||
|
@ -414,7 +581,7 @@ _update_max_duration (GESContainer * container)
|
|||
GstClockTime min = GST_CLOCK_TIME_NONE;
|
||||
GESClipPrivate *priv = GES_CLIP (container)->priv;
|
||||
|
||||
if (priv->prevent_max_duration_update)
|
||||
if (priv->setting_max_duration)
|
||||
return;
|
||||
|
||||
for (tmp = container->children; tmp; tmp = tmp->next) {
|
||||
|
@ -427,6 +594,32 @@ _update_max_duration (GESContainer * container)
|
|||
priv->updating_max_duration = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ges_clip_can_set_max_duration_of_child (GESClip * clip, GESTrackElement * child,
|
||||
GstClockTime max_duration)
|
||||
{
|
||||
GList *child_data;
|
||||
DurationLimitData *data;
|
||||
|
||||
if (clip->priv->setting_max_duration)
|
||||
return TRUE;
|
||||
|
||||
data = _duration_limit_data_new (child);
|
||||
data->max_duration = max_duration;
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (clip, data);
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot set the max-duration of child %"
|
||||
GES_FORMAT " from %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT
|
||||
" because the duration-limit cannot be adjusted", GES_ARGS (child),
|
||||
_MAXDURATION (child), max_duration);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_child_max_duration_changed (GESContainer * container,
|
||||
GESTimelineElement * child)
|
||||
|
@ -438,20 +631,80 @@ _child_max_duration_changed (GESContainer * container,
|
|||
_update_max_duration (container);
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* has-internal-source *
|
||||
****************************************************/
|
||||
|
||||
static void
|
||||
_child_has_internal_source_changed (GESClip * self, GESTimelineElement * child)
|
||||
{
|
||||
/* ignore non-core */
|
||||
/* if the track element is now registered to have no internal content,
|
||||
* we don't have to do anything */
|
||||
* we don't have to do anything
|
||||
* Note that the change in max-duration and in-point will already trigger
|
||||
* a change in the duration-limit, which can only increase since the
|
||||
* max-duration is now GST_CLOCK_TIME_NONE */
|
||||
if (!_IS_CORE_INTERNAL_SOURCE_CHILD (child))
|
||||
return;
|
||||
|
||||
/* otherwise, we need to make its in-point match ours */
|
||||
/* otherwise, we need to make its in-point match ours
|
||||
* Note that the duration-limit will be GST_CLOCK_TIME_NONE, so this
|
||||
* should not change the duration-limit */
|
||||
_set_inpoint0 (child, _INPOINT (self));
|
||||
}
|
||||
|
||||
#define _IS_PROP(prop) (g_strcmp0 (name, prop) == 0)
|
||||
/****************************************************
|
||||
* active *
|
||||
****************************************************/
|
||||
|
||||
gboolean
|
||||
ges_clip_can_set_active_of_child (GESClip * clip, GESTrackElement * child,
|
||||
gboolean active)
|
||||
{
|
||||
GESTrack *track = ges_track_element_get_track (child);
|
||||
gboolean is_core = _IS_CORE_CHILD (child);
|
||||
GList *child_data = NULL;
|
||||
DurationLimitData *data;
|
||||
|
||||
if (clip->priv->setting_active)
|
||||
return TRUE;
|
||||
|
||||
/* We want to ensure that each active non-core element has a
|
||||
* corresponding active core element in the same track */
|
||||
if (!track || is_core == active) {
|
||||
/* only the one child will change */
|
||||
data = _duration_limit_data_new (child);
|
||||
data->active = active;
|
||||
child_data = _duration_limit_data_list_with_data (clip, data);
|
||||
} else {
|
||||
GList *tmp;
|
||||
/* If we are core, make all the non-core elements in-active
|
||||
* If we are non-core, make the core element active */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTrackElement *sibling = tmp->data;
|
||||
data = _duration_limit_data_new (sibling);
|
||||
|
||||
if (sibling == child)
|
||||
data->active = active;
|
||||
|
||||
if (ges_track_element_get_track (sibling) == track
|
||||
&& _IS_CORE_CHILD (sibling) != is_core
|
||||
&& ges_track_element_is_active (sibling) != active)
|
||||
data->active = active;
|
||||
|
||||
child_data = g_list_prepend (child_data, data);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot set the active of child %" GES_FORMAT
|
||||
" from %i to %i because the duration-limit cannot be adjusted",
|
||||
GES_ARGS (child), ges_track_element_is_active (child), active);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_child_active_changed (GESClip * self, GESTrackElement * child)
|
||||
|
@ -467,6 +720,7 @@ _child_active_changed (GESClip * self, GESTrackElement * child)
|
|||
if (self->priv->setting_active || !track || is_core == active)
|
||||
return;
|
||||
|
||||
self->priv->setting_active = TRUE;
|
||||
self->priv->prevent_duration_limit_update = TRUE;
|
||||
|
||||
/* If we are core, make all the non-core elements in-active
|
||||
|
@ -489,11 +743,12 @@ _child_active_changed (GESClip * self, GESTrackElement * child)
|
|||
}
|
||||
}
|
||||
|
||||
self->priv->setting_active = FALSE;
|
||||
self->priv->prevent_duration_limit_update = prev_prevent;
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Restrict our children *
|
||||
* track *
|
||||
****************************************************/
|
||||
|
||||
static GESTrackElement *
|
||||
|
@ -524,6 +779,8 @@ gboolean
|
|||
ges_clip_can_set_track_of_child (GESClip * clip, GESTrackElement * child,
|
||||
GESTrack * track)
|
||||
{
|
||||
GList *child_data;
|
||||
DurationLimitData *data;
|
||||
GESTrack *current_track = ges_track_element_get_track (child);
|
||||
GESTrackElement *core = NULL;
|
||||
|
||||
|
@ -584,6 +841,28 @@ ges_clip_can_set_track_of_child (GESClip * clip, GESTrackElement * child,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = _duration_limit_data_new (child);
|
||||
gst_clear_object (&data->track);
|
||||
data->track = track ? gst_object_ref (track) : NULL;
|
||||
if (core && !ges_track_element_is_active (core)) {
|
||||
/* if core is set, then we are adding a non-core to a track containing
|
||||
* a core track element. If this happens, but the core is in-active
|
||||
* then we will make the non-core element also inactive upon setting
|
||||
* its track */
|
||||
data->active = FALSE;
|
||||
}
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (clip, data);
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_INFO_OBJECT (clip, "Cannot move the child %" GES_FORMAT " from "
|
||||
"track %" GST_PTR_FORMAT " to track %" GST_PTR_FORMAT " because "
|
||||
"the duration-limit cannot be adjusted", GES_ARGS (child),
|
||||
current_track, track);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -617,12 +896,14 @@ _update_active_for_track (GESClip * self, GESTrackElement * child)
|
|||
" since the core child in the same track %" GST_PTR_FORMAT " is "
|
||||
"not active", GES_ARGS (child), track);
|
||||
|
||||
self->priv->setting_active = TRUE;
|
||||
self->priv->prevent_duration_limit_update = TRUE;
|
||||
|
||||
if (!ges_track_element_set_active (child, FALSE))
|
||||
GST_ERROR_OBJECT (self, "Failed to de-activate child %" GES_FORMAT,
|
||||
GES_ARGS (child));
|
||||
|
||||
self->priv->setting_active = FALSE;
|
||||
self->priv->prevent_duration_limit_update = prev_prevent;
|
||||
}
|
||||
}
|
||||
|
@ -688,33 +969,6 @@ _set_start (GESTimelineElement * element, GstClockTime start)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Whether @clip can have its in-point set to @inpoint because none of
|
||||
* its children have a max-duration below it */
|
||||
gboolean
|
||||
ges_clip_can_set_inpoint_of_child (GESClip * clip, GESTimelineElement * child,
|
||||
GstClockTime inpoint)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
/* don't bother checking if we are setting the value */
|
||||
if (clip->priv->setting_inpoint)
|
||||
return TRUE;
|
||||
|
||||
/* non-core children do not effect our in-point */
|
||||
if (!_IS_CORE_CHILD (child))
|
||||
return TRUE;
|
||||
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
|
||||
if (_IS_CORE_INTERNAL_SOURCE_CHILD (child)
|
||||
&& GST_CLOCK_TIME_IS_VALID (child->maxduration)
|
||||
&& child->maxduration < inpoint)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* returns TRUE if we did not break early */
|
||||
static gboolean
|
||||
_set_childrens_inpoint (GESTimelineElement * element, GstClockTime inpoint,
|
||||
|
@ -754,6 +1008,12 @@ _set_childrens_inpoint (GESTimelineElement * element, GstClockTime inpoint,
|
|||
static gboolean
|
||||
_set_inpoint (GESTimelineElement * element, GstClockTime inpoint)
|
||||
{
|
||||
if (!_can_set_inpoint_of_core_children (GES_CLIP (element), inpoint)) {
|
||||
GST_WARNING_OBJECT (element, "Cannot set the in-point to %"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (inpoint));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_set_childrens_inpoint (element, inpoint, TRUE)) {
|
||||
_set_childrens_inpoint (element, element->inpoint, FALSE);
|
||||
return FALSE;
|
||||
|
@ -786,6 +1046,7 @@ static gboolean
|
|||
_set_max_duration (GESTimelineElement * element, GstClockTime maxduration)
|
||||
{
|
||||
GList *tmp;
|
||||
GList *child_data = NULL;
|
||||
GESClip *self = GES_CLIP (element);
|
||||
GESClipPrivate *priv = self->priv;
|
||||
GstClockTime new_min = GST_CLOCK_TIME_NONE;
|
||||
|
@ -799,8 +1060,26 @@ _set_max_duration (GESTimelineElement * element, GstClockTime maxduration)
|
|||
|
||||
/* else, we set every core child to have the same max duration */
|
||||
|
||||
/* check that the duration-limit can be changed */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (self); tmp; tmp = tmp->next) {
|
||||
GESTrackElement *child = tmp->data;
|
||||
DurationLimitData *data = _duration_limit_data_new (child);
|
||||
|
||||
if (_IS_CORE_INTERNAL_SOURCE_CHILD (child))
|
||||
data->max_duration = maxduration;
|
||||
|
||||
child_data = g_list_prepend (child_data, data);
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (self, child_data)) {
|
||||
GST_WARNING_OBJECT (self, "Cannot set the max-duration from %"
|
||||
G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT " because the "
|
||||
"duration-limit cannot be adjusted", element->maxduration, maxduration);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->prevent_duration_limit_update = TRUE;
|
||||
priv->prevent_max_duration_update = TRUE;
|
||||
priv->setting_max_duration = TRUE;
|
||||
for (tmp = GES_CONTAINER_CHILDREN (element); tmp; tmp = tmp->next) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
|
||||
|
@ -815,7 +1094,7 @@ _set_max_duration (GESTimelineElement * element, GstClockTime maxduration)
|
|||
}
|
||||
}
|
||||
}
|
||||
priv->prevent_max_duration_update = FALSE;
|
||||
priv->setting_max_duration = FALSE;
|
||||
priv->prevent_duration_limit_update = prev_prevent;
|
||||
|
||||
if (!has_core) {
|
||||
|
@ -874,6 +1153,7 @@ _set_priority (GESTimelineElement * element, guint32 priority)
|
|||
/* offsets will remain constant for the children */
|
||||
priv->prevent_resort = TRUE;
|
||||
priv->prevent_duration_limit_update = TRUE;
|
||||
priv->setting_priority = TRUE;
|
||||
for (tmp = container->children; tmp; tmp = g_list_next (tmp)) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
guint32 track_element_prio = min_prio + (child->priority - min_child_prio);
|
||||
|
@ -891,6 +1171,7 @@ _set_priority (GESTimelineElement * element, guint32 priority)
|
|||
* offsets. As such, the height and duration-limit remains the same as
|
||||
* well. */
|
||||
priv->prevent_resort = FALSE;
|
||||
priv->setting_priority = FALSE;
|
||||
priv->prevent_duration_limit_update = prev_prevent;
|
||||
|
||||
return TRUE;
|
||||
|
@ -1010,33 +1291,19 @@ _add_child (GESContainer * container, GESTimelineElement * element)
|
|||
/* NOTE: Core track elements that are base effects are added like any
|
||||
* other core elements. In particular, they are *not* added to the
|
||||
* list of added effects, so we do not increase nb_effects. */
|
||||
GESTrackElement *core = (track && !priv->allow_any_track) ?
|
||||
_find_core_in_track (self, track) : NULL;
|
||||
|
||||
if (core) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add the core child %" GES_FORMAT
|
||||
" because it is in the same track %" GST_PTR_FORMAT " as an "
|
||||
"existing core child %" GES_FORMAT, GES_ARGS (element), track,
|
||||
GES_ARGS (core));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set the core element to have the same in-point, which we don't
|
||||
* apply to effects */
|
||||
if (ges_track_element_has_internal_source (track_el)) {
|
||||
/* adding can fail if the max-duration of the element is smaller
|
||||
* than the current in-point of the clip */
|
||||
if (!_set_inpoint0 (element, _INPOINT (self))) {
|
||||
GST_ERROR_OBJECT (element, "Could not set the in-point of the "
|
||||
"element %" GES_FORMAT " to %" GST_TIME_FORMAT ". Not adding "
|
||||
"as a child", GES_ARGS (element), GST_TIME_ARGS (_INPOINT (self)));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
GstClockTime new_inpoint;
|
||||
if (ges_track_element_has_internal_source (track_el))
|
||||
new_inpoint = _INPOINT (self);
|
||||
else
|
||||
new_inpoint = 0;
|
||||
|
||||
/* new priority is that of the lowest priority core child. Usually
|
||||
* each core child has the same priority.
|
||||
* Also must be lower than all effects */
|
||||
|
||||
new_prio = min_prio;
|
||||
for (tmp = container->children; tmp; tmp = tmp->next) {
|
||||
if (_IS_CORE_CHILD (tmp->data))
|
||||
|
@ -1044,20 +1311,50 @@ _add_child (GESContainer * container, GESTimelineElement * element)
|
|||
else if (_IS_TOP_EFFECT (tmp->data))
|
||||
new_prio = MAX (new_prio, _PRIORITY (tmp->data) + 1);
|
||||
}
|
||||
|
||||
if (track && !priv->allow_any_track) {
|
||||
GList *child_data;
|
||||
DurationLimitData *data;
|
||||
GESTrackElement *core = _find_core_in_track (self, track);
|
||||
|
||||
if (core) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add the core child %" GES_FORMAT
|
||||
" because it is in the same track %" GST_PTR_FORMAT " as an "
|
||||
"existing core child %" GES_FORMAT, GES_ARGS (element), track,
|
||||
GES_ARGS (core));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data = _duration_limit_data_new (track_el);
|
||||
data->inpoint = new_inpoint;
|
||||
data->priority = new_prio;
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (self, data);
|
||||
|
||||
if (!_can_update_duration_limit (self, child_data)) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add core %" GES_FORMAT " as a "
|
||||
"child because the duration-limit cannot be adjusted",
|
||||
GES_ARGS (element));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* adding can fail if the max-duration of the element is smaller
|
||||
* than the current in-point of the clip */
|
||||
if (!_set_inpoint0 (element, new_inpoint)) {
|
||||
GST_WARNING_OBJECT (self, "Could not set the in-point of the "
|
||||
"element %" GES_FORMAT " to %" GST_TIME_FORMAT ". Not adding "
|
||||
"as a child", GES_ARGS (element), GST_TIME_ARGS (new_inpoint));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_set_priority0 (element, new_prio);
|
||||
|
||||
} else if (GES_CLIP_CLASS_CAN_ADD_EFFECTS (klass) && _IS_TOP_EFFECT (element)) {
|
||||
/* Add the effect at the lowest priority among effects (just after
|
||||
* the core elements). Need to shift the core elements up by 1
|
||||
* to make room. */
|
||||
|
||||
if (track && !priv->allow_any_track && !_find_core_in_track (self, track)) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add the effect %" GES_FORMAT
|
||||
" because its track %" GST_PTR_FORMAT " does not contain one "
|
||||
"of the clip's core children", GES_ARGS (element), track);
|
||||
return FALSE;
|
||||
}
|
||||
_update_active_for_track (self, track_el);
|
||||
|
||||
/* new priority is the lowest priority effect */
|
||||
new_prio = min_prio;
|
||||
for (tmp = container->children; tmp; tmp = tmp->next) {
|
||||
|
@ -1070,12 +1367,48 @@ _add_child (GESContainer * container, GESTimelineElement * element)
|
|||
new_prio = MIN (new_prio, _PRIORITY (tmp->data));
|
||||
}
|
||||
|
||||
if (track && !priv->allow_any_track) {
|
||||
GList *child_data, *tmp;
|
||||
DurationLimitData *data;
|
||||
GESTrackElement *core = _find_core_in_track (self, track);
|
||||
|
||||
if (!core) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add the effect %" GES_FORMAT
|
||||
" because its track %" GST_PTR_FORMAT " does not contain one "
|
||||
"of the clip's core children", GES_ARGS (element), track);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
data = _duration_limit_data_new (track_el);
|
||||
data->priority = new_prio;
|
||||
if (!ges_track_element_is_active (core))
|
||||
data->active = FALSE;
|
||||
|
||||
child_data = _duration_limit_data_list_with_data (self, data);
|
||||
|
||||
for (tmp = child_data; tmp; tmp = tmp->next) {
|
||||
data = tmp->data;
|
||||
if (data->priority >= new_prio)
|
||||
data->priority++;
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (self, child_data)) {
|
||||
GST_WARNING_OBJECT (self, "Cannot add effect %" GES_FORMAT " as "
|
||||
"a child because the duration-limit cannot be adjusted",
|
||||
GES_ARGS (element));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
_update_active_for_track (self, track_el);
|
||||
|
||||
priv->nb_effects++;
|
||||
GST_DEBUG_OBJECT (self, "Adding %ith effect: %" GES_FORMAT
|
||||
" Priority %i", priv->nb_effects, GES_ARGS (element), new_prio);
|
||||
|
||||
/* changing priorities, and updating their offset */
|
||||
priv->prevent_resort = TRUE;
|
||||
priv->setting_priority = TRUE;
|
||||
priv->prevent_duration_limit_update = TRUE;
|
||||
|
||||
/* increase the priority of anything with a lower priority */
|
||||
|
@ -1087,6 +1420,7 @@ _add_child (GESContainer * container, GESTimelineElement * element)
|
|||
_set_priority0 (element, new_prio);
|
||||
|
||||
priv->prevent_resort = FALSE;
|
||||
priv->setting_priority = FALSE;
|
||||
priv->prevent_duration_limit_update = prev_prevent;
|
||||
/* no need to call _ges_container_sort_children (container) since
|
||||
* there is no change to the ordering yet (this happens after the
|
||||
|
@ -1120,7 +1454,34 @@ _add_child (GESContainer * container, GESTimelineElement * element)
|
|||
static gboolean
|
||||
_remove_child (GESContainer * container, GESTimelineElement * element)
|
||||
{
|
||||
GESClipPrivate *priv = GES_CLIP (container)->priv;
|
||||
GESTrackElement *el = GES_TRACK_ELEMENT (element);
|
||||
GESClip *self = GES_CLIP (container);
|
||||
GESClipPrivate *priv = self->priv;
|
||||
|
||||
/* check that the duration-limit can be changed */
|
||||
/* If we are removing a core child, then all other children in the
|
||||
* same track will be removed from the track, which will make the
|
||||
* duration-limit increase, which is safe
|
||||
* Similarly, if it has no track, the duration-limit will not change */
|
||||
if (!priv->allow_any_remove && !_IS_CORE_CHILD (element) &&
|
||||
ges_track_element_get_track (el)) {
|
||||
GList *child_data = NULL;
|
||||
GList *tmp;
|
||||
|
||||
for (tmp = container->children; tmp; tmp = tmp->next) {
|
||||
GESTrackElement *child = tmp->data;
|
||||
if (child == el)
|
||||
continue;
|
||||
child_data =
|
||||
g_list_prepend (child_data, _duration_limit_data_new (child));
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (self, child_data)) {
|
||||
GST_WARNING_OBJECT (self, "Cannot remove the child %" GES_FORMAT
|
||||
" because the duration-limit cannot be adjusted", GES_ARGS (el));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: notifies are currently frozen by ges_container_add */
|
||||
if (_IS_TOP_EFFECT (element)) {
|
||||
|
@ -1130,6 +1491,7 @@ _remove_child (GESContainer * container, GESTimelineElement * element)
|
|||
|
||||
/* changing priorities, so preventing a re-sort */
|
||||
priv->prevent_resort = TRUE;
|
||||
priv->setting_priority = TRUE;
|
||||
priv->prevent_duration_limit_update = TRUE;
|
||||
for (tmp = container->children; tmp; tmp = tmp->next) {
|
||||
guint32 sibling_prio = GES_TIMELINE_ELEMENT_PRIORITY (tmp->data);
|
||||
|
@ -1139,6 +1501,7 @@ _remove_child (GESContainer * container, GESTimelineElement * element)
|
|||
}
|
||||
priv->nb_effects--;
|
||||
priv->prevent_resort = FALSE;
|
||||
priv->setting_priority = FALSE;
|
||||
priv->prevent_duration_limit_update = prev_prevent;
|
||||
/* no need to re-sort the children since the rest keep the same
|
||||
* relative priorities */
|
||||
|
@ -1212,8 +1575,10 @@ _transfer_child (GESClip * from_clip, GESClip * to_clip,
|
|||
from_clip->priv->prevent_duration_limit_update = TRUE;
|
||||
to_clip->priv->prevent_duration_limit_update = TRUE;
|
||||
|
||||
from_clip->priv->allow_any_remove = TRUE;
|
||||
ges_container_remove (GES_CONTAINER (from_clip),
|
||||
GES_TIMELINE_ELEMENT (child));
|
||||
from_clip->priv->allow_any_remove = FALSE;
|
||||
|
||||
to_clip->priv->allow_any_track = TRUE;
|
||||
if (!ges_container_add (GES_CONTAINER (to_clip),
|
||||
|
@ -1669,6 +2034,8 @@ ges_clip_dispose (GObject * object)
|
|||
{
|
||||
GESClip *self = GES_CLIP (object);
|
||||
|
||||
self->priv->allow_any_remove = TRUE;
|
||||
|
||||
g_list_free_full (self->priv->copied_track_elements, gst_object_unref);
|
||||
self->priv->copied_track_elements = NULL;
|
||||
g_clear_object (&self->priv->copied_layer);
|
||||
|
@ -2261,11 +2628,35 @@ ges_clip_set_top_effect_index (GESClip * clip, GESBaseEffect * effect,
|
|||
else
|
||||
inc = +1;
|
||||
|
||||
/* check that the duration-limit can be changed */
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
guint32 priority = child->priority;
|
||||
DurationLimitData *data =
|
||||
_duration_limit_data_new (GES_TRACK_ELEMENT (child));
|
||||
|
||||
if (child == element)
|
||||
data->priority = new_prio;
|
||||
else if ((inc == +1 && priority >= new_prio && priority < current_prio)
|
||||
|| (inc == -1 && priority <= new_prio && priority > current_prio))
|
||||
data->priority = child->priority + inc;
|
||||
|
||||
child_data = g_list_prepend (child_data, data);
|
||||
}
|
||||
|
||||
if (!_can_update_duration_limit (clip, child_data)) {
|
||||
GST_WARNING_OBJECT (clip, "Cannot move top effect %" GES_FORMAT
|
||||
" to index %i because the duration-limit cannot adjust",
|
||||
GES_ARGS (effect), newindex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (clip, "Setting top effect %" GST_PTR_FORMAT "priority: %i",
|
||||
effect, new_prio);
|
||||
|
||||
/* prevent a re-sort of the list whilst we are traversing it! */
|
||||
clip->priv->prevent_resort = TRUE;
|
||||
clip->priv->setting_priority = TRUE;
|
||||
for (tmp = GES_CONTAINER_CHILDREN (clip); tmp; tmp = tmp->next) {
|
||||
GESTimelineElement *child = tmp->data;
|
||||
guint32 priority = child->priority;
|
||||
|
@ -2282,6 +2673,7 @@ ges_clip_set_top_effect_index (GESClip * clip, GESBaseEffect * effect,
|
|||
_set_priority0 (element, new_prio);
|
||||
|
||||
clip->priv->prevent_resort = FALSE;
|
||||
clip->priv->setting_priority = FALSE;
|
||||
_ges_container_sort_children (GES_CONTAINER (clip));
|
||||
/* height should have stayed the same */
|
||||
|
||||
|
|
|
@ -404,7 +404,10 @@ G_GNUC_INTERNAL gboolean ges_clip_is_moving_from_layer (GESClip *clip
|
|||
G_GNUC_INTERNAL void ges_clip_set_moving_from_layer (GESClip *clip, gboolean is_moving);
|
||||
G_GNUC_INTERNAL GESTrackElement* ges_clip_create_track_element (GESClip *clip, GESTrackType type);
|
||||
G_GNUC_INTERNAL GList* ges_clip_create_track_elements (GESClip *clip, GESTrackType type);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_inpoint_of_child (GESClip * clip, GESTimelineElement * child, GstClockTime inpoint);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_inpoint_of_child (GESClip * clip, GESTrackElement * child, GstClockTime inpoint);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_max_duration_of_child (GESClip * clip, GESTrackElement * child, GstClockTime max_duration);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_active_of_child (GESClip * clip, GESTrackElement * child, gboolean active);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_priority_of_child (GESClip * clip, GESTrackElement * child, guint32 priority);
|
||||
G_GNUC_INTERNAL gboolean ges_clip_can_set_track_of_child (GESClip * clip, GESTrackElement * child, GESTrack * tack);
|
||||
G_GNUC_INTERNAL void ges_clip_empty_from_track (GESClip * clip, GESTrack * track);
|
||||
|
||||
|
|
|
@ -629,21 +629,21 @@ static gboolean
|
|||
_set_inpoint (GESTimelineElement * element, GstClockTime inpoint)
|
||||
{
|
||||
GESTrackElement *object = GES_TRACK_ELEMENT (element);
|
||||
GESTimelineElement *parent = element->parent;
|
||||
|
||||
g_return_val_if_fail (object->priv->nleobject, FALSE);
|
||||
if (inpoint && !object->priv->has_internal_source) {
|
||||
GST_WARNING_OBJECT (element, "Can not set an in-point for a track "
|
||||
GST_WARNING_OBJECT (element, "Cannot set an in-point for a track "
|
||||
"element that is not registered with internal content");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GES_IS_CLIP (element->parent)
|
||||
&& !ges_clip_can_set_inpoint_of_child (GES_CLIP (element->parent),
|
||||
element, inpoint)) {
|
||||
GST_WARNING_OBJECT (element, "Can not set an in-point of %"
|
||||
if (GES_IS_CLIP (parent)
|
||||
&& !ges_clip_can_set_inpoint_of_child (GES_CLIP (parent), object,
|
||||
inpoint)) {
|
||||
GST_WARNING_OBJECT (element, "Cannot set an in-point of %"
|
||||
GST_TIME_FORMAT " because the parent clip %" GES_FORMAT
|
||||
" would not be able to follow",
|
||||
GST_TIME_ARGS (inpoint), GES_ARGS (element->parent));
|
||||
" would not allow it", GST_TIME_ARGS (inpoint), GES_ARGS (parent));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -677,14 +677,24 @@ static gboolean
|
|||
_set_max_duration (GESTimelineElement * element, GstClockTime max_duration)
|
||||
{
|
||||
GESTrackElement *object = GES_TRACK_ELEMENT (element);
|
||||
GESTimelineElement *parent = element->parent;
|
||||
|
||||
if (GST_CLOCK_TIME_IS_VALID (max_duration)
|
||||
&& !object->priv->has_internal_source) {
|
||||
GST_WARNING_OBJECT (element, "Can not set a max-duration for a track "
|
||||
GST_WARNING_OBJECT (element, "Cannot set a max-duration for a track "
|
||||
"element that is not registered with internal content");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GES_IS_CLIP (parent)
|
||||
&& !ges_clip_can_set_max_duration_of_child (GES_CLIP (parent), object,
|
||||
max_duration)) {
|
||||
GST_WARNING_OBJECT (element, "Cannot set a max-duration of %"
|
||||
GST_TIME_FORMAT " because the parent clip %" GES_FORMAT
|
||||
" would not allow it", GST_TIME_ARGS (max_duration), GES_ARGS (parent));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -693,6 +703,7 @@ static gboolean
|
|||
_set_priority (GESTimelineElement * element, guint32 priority)
|
||||
{
|
||||
GESTrackElement *object = GES_TRACK_ELEMENT (element);
|
||||
GESTimelineElement *parent = element->parent;
|
||||
|
||||
g_return_val_if_fail (object->priv->nleobject, FALSE);
|
||||
|
||||
|
@ -707,6 +718,15 @@ _set_priority (GESTimelineElement * element, guint32 priority)
|
|||
if (G_UNLIKELY (priority == _PRIORITY (object)))
|
||||
return FALSE;
|
||||
|
||||
if (GES_IS_CLIP (parent)
|
||||
&& !ges_clip_can_set_priority_of_child (GES_CLIP (parent), object,
|
||||
priority)) {
|
||||
GST_WARNING_OBJECT (element, "Cannot set a priority of %"
|
||||
G_GUINT32_FORMAT " because the parent clip %" GES_FORMAT
|
||||
" would not allow it", priority, GES_ARGS (parent));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_set (object->priv->nleobject, "priority", priority, NULL);
|
||||
|
||||
return TRUE;
|
||||
|
@ -730,6 +750,7 @@ _get_track_types (GESTimelineElement * object)
|
|||
gboolean
|
||||
ges_track_element_set_active (GESTrackElement * object, gboolean active)
|
||||
{
|
||||
GESTimelineElement *parent;
|
||||
g_return_val_if_fail (GES_IS_TRACK_ELEMENT (object), FALSE);
|
||||
g_return_val_if_fail (object->priv->nleobject, FALSE);
|
||||
|
||||
|
@ -738,6 +759,14 @@ ges_track_element_set_active (GESTrackElement * object, gboolean active)
|
|||
if (G_UNLIKELY (active == object->active))
|
||||
return FALSE;
|
||||
|
||||
parent = GES_TIMELINE_ELEMENT_PARENT (object);
|
||||
if (GES_IS_CLIP (parent)
|
||||
&& !ges_clip_can_set_active_of_child (GES_CLIP (parent), object, active)) {
|
||||
GST_WARNING_OBJECT (object, "Cannot set active to %i because the parent "
|
||||
"clip %" GES_FORMAT " would not allow it", active, GES_ARGS (parent));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_set (object->priv->nleobject, "active",
|
||||
active & object->priv->layer_active, NULL);
|
||||
|
||||
|
|
|
@ -2316,7 +2316,7 @@ GST_START_TEST (test_children_inpoint)
|
|||
CHECK_OBJECT_PROPS (effect, 5, 67, 20);
|
||||
|
||||
/* should not be able to set the in-point to non-zero */
|
||||
fail_if (ges_timeline_element_set_inpoint (child0, 40));
|
||||
assert_fail_set_inpoint (child0, 40);
|
||||
|
||||
CHECK_OBJECT_PROPS (clip, 5, 30, 20);
|
||||
CHECK_OBJECT_PROPS (child0, 5, 0, 20);
|
||||
|
@ -2506,21 +2506,21 @@ GST_START_TEST (test_children_max_duration)
|
|||
/* can not set in-point above max_duration, nor max_duration below
|
||||
* in-point */
|
||||
|
||||
fail_if (ges_timeline_element_set_max_duration (child0, 29));
|
||||
assert_fail_set_max_duration (child0, 29);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
CHECK_OBJECT_PROPS_MAX (child1, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (effect, 5, 0, 20, 400);
|
||||
|
||||
fail_if (ges_timeline_element_set_max_duration (child1, 29));
|
||||
assert_fail_set_max_duration (child1, 29);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
CHECK_OBJECT_PROPS_MAX (child1, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (effect, 5, 0, 20, 400);
|
||||
|
||||
fail_if (ges_timeline_element_set_max_duration (clip, 29));
|
||||
assert_fail_set_max_duration (clip, 29);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
|
@ -2530,21 +2530,21 @@ GST_START_TEST (test_children_max_duration)
|
|||
/* can't set the inpoint to (new_max), even though it is lower than
|
||||
* our own max-duration (new_max + 1) because it is too high for our
|
||||
* sibling child1 */
|
||||
fail_if (ges_timeline_element_set_inpoint (child0, new_max));
|
||||
assert_fail_set_inpoint (child0, new_max);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
CHECK_OBJECT_PROPS_MAX (child1, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (effect, 5, 0, 20, 400);
|
||||
|
||||
fail_if (ges_timeline_element_set_inpoint (child1, new_max));
|
||||
assert_fail_set_inpoint (child1, new_max);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
CHECK_OBJECT_PROPS_MAX (child1, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (effect, 5, 0, 20, 400);
|
||||
|
||||
fail_if (ges_timeline_element_set_inpoint (clip, new_max));
|
||||
assert_fail_set_inpoint (clip, new_max);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
|
@ -2591,14 +2591,14 @@ GST_START_TEST (test_children_max_duration)
|
|||
CHECK_OBJECT_PROPS_MAX (effect, 5, new_max + 2, 20, new_max + 500);
|
||||
|
||||
/* but not higher than our own */
|
||||
fail_if (ges_timeline_element_set_inpoint (effect, new_max + 501));
|
||||
assert_fail_set_inpoint (effect, new_max + 501);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
CHECK_OBJECT_PROPS_MAX (child1, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (effect, 5, new_max + 2, 20, new_max + 500);
|
||||
|
||||
fail_if (ges_timeline_element_set_max_duration (effect, new_max + 1));
|
||||
assert_fail_set_max_duration (effect, new_max + 1);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, new_max - 2);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 30, 20, new_max + 1);
|
||||
|
@ -2640,7 +2640,7 @@ GST_START_TEST (test_children_max_duration)
|
|||
CHECK_OBJECT_PROPS_MAX (effect, 5, 0, 20, 400);
|
||||
|
||||
/* should not be able to set the max-duration to a valid time */
|
||||
fail_if (ges_timeline_element_set_max_duration (child0, 40));
|
||||
assert_fail_set_max_duration (child0, 40);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, 180);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
@ -2659,7 +2659,7 @@ GST_START_TEST (test_children_max_duration)
|
|||
|
||||
/* should not be able to set the max of the clip to anything else
|
||||
* when it has no core children with an internal source */
|
||||
fail_if (ges_timeline_element_set_max_duration (clip, 150));
|
||||
assert_fail_set_max_duration (clip, 150);
|
||||
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 5, 30, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (child0, 5, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
@ -3060,6 +3060,549 @@ GST_START_TEST (test_duration_limit)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_can_set_duration_limit)
|
||||
{
|
||||
GESTimeline *timeline;
|
||||
GESLayer *layer;
|
||||
GESClip *clip;
|
||||
GESTrackElement *source0, *source1;
|
||||
GESTrackElement *effect0, *effect1, *effect2;
|
||||
GESTrack *track0, *track1;
|
||||
gint limit_notify_count = 0;
|
||||
|
||||
ges_init ();
|
||||
|
||||
timeline = ges_timeline_new ();
|
||||
track0 = GES_TRACK (ges_video_track_new ());
|
||||
track1 = GES_TRACK (ges_audio_track_new ());
|
||||
|
||||
fail_unless (ges_timeline_add_track (timeline, track0));
|
||||
fail_unless (ges_timeline_add_track (timeline, track1));
|
||||
/* add track3 later */
|
||||
|
||||
layer = ges_timeline_append_layer (timeline);
|
||||
|
||||
/* place a dummy clip at the start of the layer */
|
||||
clip = GES_CLIP (ges_test_clip_new ());
|
||||
assert_set_start (clip, 0);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
fail_unless (ges_layer_add_clip (layer, clip));
|
||||
|
||||
/* the clip we will be editing overlaps the first clip at its start */
|
||||
clip = GES_CLIP (ges_test_clip_new ());
|
||||
|
||||
g_signal_connect (clip, "notify::duration-limit", G_CALLBACK (_count_cb),
|
||||
&limit_notify_count);
|
||||
|
||||
assert_set_start (clip, 10);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
fail_unless (ges_layer_add_clip (layer, clip));
|
||||
|
||||
source0 =
|
||||
ges_clip_find_track_element (clip, track0, GES_TYPE_VIDEO_TEST_SOURCE);
|
||||
source1 =
|
||||
ges_clip_find_track_element (clip, track1, GES_TYPE_AUDIO_TEST_SOURCE);
|
||||
|
||||
fail_unless (source0);
|
||||
fail_unless (source1);
|
||||
|
||||
gst_object_unref (source0);
|
||||
gst_object_unref (source1);
|
||||
|
||||
assert_equals_int (limit_notify_count, 0);
|
||||
_assert_duration_limit (clip, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
||||
assert_set_inpoint (clip, 16);
|
||||
|
||||
assert_equals_int (limit_notify_count, 0);
|
||||
_assert_duration_limit (clip, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, GST_CLOCK_TIME_NONE);
|
||||
|
||||
assert_set_max_duration (clip, 36);
|
||||
|
||||
assert_equals_int (limit_notify_count, 1);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
|
||||
/* add effects */
|
||||
effect0 = GES_TRACK_ELEMENT (ges_effect_new ("agingtv"));
|
||||
effect1 = GES_TRACK_ELEMENT (ges_effect_new ("vertigotv"));
|
||||
effect2 = GES_TRACK_ELEMENT (ges_effect_new ("alpha"));
|
||||
|
||||
ges_track_element_set_has_internal_source (effect0, TRUE);
|
||||
fail_unless (ges_track_element_has_internal_source (effect1) == FALSE);
|
||||
ges_track_element_set_has_internal_source (effect2, TRUE);
|
||||
|
||||
assert_set_max_duration (effect0, 10);
|
||||
/* already set the track */
|
||||
fail_unless (ges_track_add_element (track0, effect0));
|
||||
/* cannot add because it would cause the duration-limit to go to 10,
|
||||
* causing a full overlap with the clip at the beginning of the layer */
|
||||
|
||||
gst_object_ref (effect0);
|
||||
fail_if (ges_container_add (GES_CONTAINER (clip),
|
||||
GES_TIMELINE_ELEMENT (effect0)));
|
||||
|
||||
assert_equals_int (limit_notify_count, 1);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
|
||||
/* removing from the track and adding will work, but track selection
|
||||
* will fail */
|
||||
fail_unless (ges_track_remove_element (track0, effect0));
|
||||
|
||||
_assert_add (clip, effect0);
|
||||
fail_if (ges_track_element_get_track (effect0));
|
||||
gst_object_unref (effect0);
|
||||
|
||||
assert_equals_int (limit_notify_count, 1);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 10);
|
||||
|
||||
fail_if (ges_clip_add_child_to_track (clip, effect0, track0, NULL));
|
||||
|
||||
/* set max-duration to 11 and we are fine to select a track */
|
||||
assert_set_max_duration (effect0, 11);
|
||||
assert_equals_int (limit_notify_count, 1);
|
||||
_assert_duration_limit (clip, 20);
|
||||
|
||||
fail_unless (ges_clip_add_child_to_track (clip, effect0, track0,
|
||||
NULL) == effect0);
|
||||
|
||||
assert_equals_int (limit_notify_count, 2);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 11);
|
||||
|
||||
/* cannot set duration above the limit */
|
||||
assert_fail_set_duration (clip, 12);
|
||||
assert_fail_set_duration (source0, 12);
|
||||
assert_fail_set_duration (effect0, 12);
|
||||
|
||||
/* allow the max_duration to increase again */
|
||||
assert_set_max_duration (effect0, 25);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
|
||||
/* add another effect */
|
||||
_assert_add (clip, effect1);
|
||||
fail_unless (ges_track_element_get_track (effect1) == track0);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
||||
/* make source0 inactive and reduce its max-duration
|
||||
* note that this causes effect0 and effect1 to also become in-active */
|
||||
_assert_set_active (source0, FALSE);
|
||||
_assert_active (source0, FALSE);
|
||||
_assert_active (effect0, FALSE);
|
||||
_assert_active (effect1, FALSE);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
||||
/* can set a low max duration whilst the source is inactive */
|
||||
assert_set_max_duration (source0, 26);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
|
||||
/* add the last effect */
|
||||
assert_set_inpoint (effect2, 7);
|
||||
assert_set_max_duration (effect2, 17);
|
||||
_assert_active (effect2, TRUE);
|
||||
|
||||
/* safe to add because the source is inactive */
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_add (clip, effect2);
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_active (source0, FALSE);
|
||||
_assert_active (effect0, FALSE);
|
||||
_assert_active (effect1, FALSE);
|
||||
_assert_active (effect2, FALSE);
|
||||
|
||||
fail_unless (ges_track_element_get_track (effect2) == track0);
|
||||
|
||||
assert_equals_int (limit_notify_count, 3);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 16, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 16, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 16, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 17);
|
||||
|
||||
/* want to make the source and its effects active again */
|
||||
assert_set_inpoint (source0, 6);
|
||||
assert_set_max_duration (effect2, 33);
|
||||
|
||||
assert_equals_int (limit_notify_count, 4);
|
||||
_assert_duration_limit (clip, 30);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
_assert_set_active (source0, TRUE);
|
||||
_assert_set_active (effect0, TRUE);
|
||||
_assert_set_active (effect1, TRUE);
|
||||
_assert_set_active (effect2, TRUE);
|
||||
|
||||
assert_equals_int (limit_notify_count, 5);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* cannot set in-point of clip to 16, nor of either source */
|
||||
assert_fail_set_inpoint (clip, 16);
|
||||
assert_fail_set_inpoint (source0, 16);
|
||||
assert_fail_set_inpoint (source1, 16);
|
||||
|
||||
assert_equals_int (limit_notify_count, 5);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* can set just below */
|
||||
assert_set_inpoint (source1, 15);
|
||||
|
||||
assert_equals_int (limit_notify_count, 6);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 15, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 15, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 15, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 11, 33);
|
||||
|
||||
assert_set_inpoint (clip, 6);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 7);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* cannot set in-point of non-core in a way that would cause limit to
|
||||
* drop */
|
||||
assert_fail_set_inpoint (effect2, 23);
|
||||
assert_fail_set_inpoint (effect0, 15);
|
||||
|
||||
assert_equals_int (limit_notify_count, 7);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* can set just below */
|
||||
assert_set_inpoint (effect2, 22);
|
||||
|
||||
assert_equals_int (limit_notify_count, 8);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 11, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 22, 11, 33);
|
||||
|
||||
assert_set_inpoint (effect2, 7);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 9);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* same but with max-duration */
|
||||
|
||||
/* core */
|
||||
assert_fail_set_max_duration (clip, 16);
|
||||
assert_fail_set_max_duration (source0, 16);
|
||||
assert_fail_set_max_duration (source1, 16);
|
||||
|
||||
assert_equals_int (limit_notify_count, 9);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 36);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
assert_set_max_duration (source1, 17);
|
||||
|
||||
assert_equals_int (limit_notify_count, 10);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 11, 17);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 11, 17);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 11, 33);
|
||||
|
||||
assert_set_max_duration (source1, 30);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 11);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 30);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
assert_set_max_duration (clip, 17);
|
||||
|
||||
assert_equals_int (limit_notify_count, 12);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 11, 17);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 11, 17);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 11, 17);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 11, 33);
|
||||
|
||||
assert_set_max_duration (clip, 26);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 13);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* non-core */
|
||||
assert_fail_set_max_duration (effect0, 10);
|
||||
assert_fail_set_max_duration (effect2, 17);
|
||||
|
||||
assert_equals_int (limit_notify_count, 13);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
assert_set_max_duration (effect2, 18);
|
||||
|
||||
assert_equals_int (limit_notify_count, 14);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 11, 18);
|
||||
|
||||
assert_set_max_duration (effect2, 33);
|
||||
assert_set_duration (clip, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 15);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 33);
|
||||
|
||||
/* test setting active */
|
||||
_assert_active (effect2, TRUE);
|
||||
_assert_set_active (effect2, FALSE);
|
||||
assert_set_max_duration (effect2, 17);
|
||||
|
||||
assert_equals_int (limit_notify_count, 15);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 17);
|
||||
|
||||
fail_if (ges_track_element_set_active (effect2, TRUE));
|
||||
|
||||
assert_equals_int (limit_notify_count, 15);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 7, 20, 17);
|
||||
|
||||
assert_set_inpoint (effect2, 6);
|
||||
_assert_set_active (effect2, TRUE);
|
||||
|
||||
assert_equals_int (limit_notify_count, 16);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 11, 17);
|
||||
|
||||
/* make source0 in-active */
|
||||
_assert_active (source0, TRUE);
|
||||
_assert_set_active (source0, FALSE);
|
||||
_assert_active (source0, FALSE);
|
||||
_assert_active (effect0, FALSE);
|
||||
_assert_active (effect1, FALSE);
|
||||
_assert_active (effect2, FALSE);
|
||||
|
||||
assert_set_duration (source0, 20);
|
||||
|
||||
assert_equals_int (limit_notify_count, 17);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 20, 17);
|
||||
|
||||
/* lower duration-limit for source for when it becomes active */
|
||||
assert_set_max_duration (source0, 16);
|
||||
|
||||
assert_equals_int (limit_notify_count, 17);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 20, 17);
|
||||
|
||||
/* cannot make the source active */
|
||||
fail_if (ges_track_element_set_active (source0, TRUE));
|
||||
|
||||
assert_equals_int (limit_notify_count, 17);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 20, 17);
|
||||
|
||||
/* nor can we make the effects active because this would activate the
|
||||
* source */
|
||||
fail_if (ges_track_element_set_active (effect0, TRUE));
|
||||
fail_if (ges_track_element_set_active (effect1, TRUE));
|
||||
fail_if (ges_track_element_set_active (effect2, TRUE));
|
||||
|
||||
assert_equals_int (limit_notify_count, 17);
|
||||
_assert_duration_limit (clip, 20);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 6, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 6, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 20, 17);
|
||||
|
||||
/* allow it to just succeed */
|
||||
assert_set_inpoint (source0, 5);
|
||||
|
||||
assert_equals_int (limit_notify_count, 18);
|
||||
_assert_duration_limit (clip, 21);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 5, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 5, 20, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 5, 20, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 20, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 20, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 20, 17);
|
||||
|
||||
_assert_set_active (effect1, TRUE);
|
||||
|
||||
assert_equals_int (limit_notify_count, 19);
|
||||
_assert_duration_limit (clip, 11);
|
||||
CHECK_OBJECT_PROPS_MAX (clip, 10, 5, 11, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source0, 10, 5, 11, 16);
|
||||
CHECK_OBJECT_PROPS_MAX (source1, 10, 5, 11, 26);
|
||||
CHECK_OBJECT_PROPS_MAX (effect0, 10, 0, 11, 25);
|
||||
CHECK_OBJECT_PROPS_MAX (effect1, 10, 0, 11, GST_CLOCK_TIME_NONE);
|
||||
CHECK_OBJECT_PROPS_MAX (effect2, 10, 6, 11, 17);
|
||||
|
||||
gst_object_unref (timeline);
|
||||
|
||||
ges_deinit ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_children_properties_contain)
|
||||
{
|
||||
GESTimeline *timeline;
|
||||
|
@ -3670,6 +4213,7 @@ ges_suite (void)
|
|||
tcase_add_test (tc_chain, test_children_inpoint);
|
||||
tcase_add_test (tc_chain, test_children_max_duration);
|
||||
tcase_add_test (tc_chain, test_duration_limit);
|
||||
tcase_add_test (tc_chain, test_can_set_duration_limit);
|
||||
tcase_add_test (tc_chain, test_children_properties_contain);
|
||||
tcase_add_test (tc_chain, test_children_properties_change);
|
||||
tcase_add_test (tc_chain, test_copy_paste_children_properties);
|
||||
|
|
|
@ -106,25 +106,43 @@ G_STMT_START { \
|
|||
GST_TIME_ARGS (_MAX_DURATION(obj)), GST_TIME_ARGS (max_duration)); \
|
||||
}
|
||||
|
||||
#define assert_set_start(obj, start) \
|
||||
fail_unless (ges_timeline_element_set_start (\
|
||||
GES_TIMELINE_ELEMENT (obj), start), \
|
||||
"Could not set the start of " #obj " to " #start)
|
||||
#define __assert_timeline_element_set(obj, prop, val) \
|
||||
fail_unless (ges_timeline_element_set_ ## prop ( \
|
||||
GES_TIMELINE_ELEMENT (obj), val), "Could not set the " # prop \
|
||||
" of " #obj "(%s) to " #val, GES_TIMELINE_ELEMENT_NAME (obj))
|
||||
|
||||
#define assert_set_duration(obj, duration) \
|
||||
fail_unless (ges_timeline_element_set_duration (\
|
||||
GES_TIMELINE_ELEMENT (obj), duration), \
|
||||
"Could not set the duration of " #obj " to " #duration)
|
||||
#define __fail_timeline_element_set(obj, prop, val) \
|
||||
fail_if (ges_timeline_element_set_ ## prop ( \
|
||||
GES_TIMELINE_ELEMENT (obj), val), "Setting the " # prop \
|
||||
" of " #obj "(%s) to " #val " did not fail as expected", \
|
||||
GES_TIMELINE_ELEMENT_NAME (obj))
|
||||
|
||||
#define assert_set_inpoint(obj, inpoint) \
|
||||
fail_unless (ges_timeline_element_set_inpoint (\
|
||||
GES_TIMELINE_ELEMENT (obj), inpoint), \
|
||||
"Could not set the in-point of " #obj " to " #inpoint)
|
||||
|
||||
#define assert_set_max_duration(obj, max_duration) \
|
||||
fail_unless (ges_timeline_element_set_max_duration (\
|
||||
GES_TIMELINE_ELEMENT (obj), max_duration), \
|
||||
"Could not set the max-duration of " #obj " to " #max_duration)
|
||||
#define assert_set_start(obj, val) \
|
||||
__assert_timeline_element_set (obj, start, val)
|
||||
|
||||
#define assert_set_duration(obj, val) \
|
||||
__assert_timeline_element_set (obj, duration, val)
|
||||
|
||||
#define assert_set_inpoint(obj, val) \
|
||||
__assert_timeline_element_set (obj, inpoint, val)
|
||||
|
||||
#define assert_set_max_duration(obj, val) \
|
||||
__assert_timeline_element_set (obj, max_duration, val)
|
||||
|
||||
|
||||
#define assert_fail_set_start(obj, val) \
|
||||
__fail_timeline_element_set (obj, start, val)
|
||||
|
||||
#define assert_fail_set_duration(obj, val) \
|
||||
__fail_timeline_element_set (obj, duration, val)
|
||||
|
||||
#define assert_fail_set_inpoint(obj, val) \
|
||||
__fail_timeline_element_set (obj, inpoint, val)
|
||||
|
||||
#define assert_fail_set_max_duration(obj, val) \
|
||||
__fail_timeline_element_set (obj, max_duration, val)
|
||||
|
||||
|
||||
#define assert_num_in_track(track, val) \
|
||||
{ \
|
||||
|
|
Loading…
Reference in a new issue