ges: Add a timeline edition mode API

+ timeline: Add a snapping-distance property
        + Bump the GLib dependency to 2.28 in the mean time as we need some functions from GSequence that only landed
	+ Update the testsuite accordingly

    API: GESTimeline:snapping-distance property
    API: ges_timeline_object_edit
    API: ges_timeline_object_ripple
    API: ges_timeline_object_ripple_end
    API: ges_timeline_object_roll_start
    API: ges_timeline_object_roll_end
    API: ges_timeline_object_trim_start
    API: ges_track_object_edit
    API: GESEdge enum
    API: GESEditMode enum
This commit is contained in:
Thibault Saunier 2012-04-23 20:52:45 -04:00
parent 7cced397b6
commit 2fd5364927
11 changed files with 1694 additions and 53 deletions

View file

@ -195,7 +195,7 @@ dnl *** checks for headers ***
dnl *** checks for dependency libraries ***
dnl GLib is required
AG_GST_GLIB_CHECK([2.22])
AG_GST_GLIB_CHECK([2.28])
PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.16, HAVE_GIO=yes, HAVE_GIO=no)
AC_SUBST(GIO_CFLAGS)

View file

@ -30,6 +30,8 @@ GESTextVAlign
DEFAULT_VALIGNMENT
GESVideoTestPattern
GESPipelineFlags
GESEdge
GESEditMode
<SUBSECTION Standard>
GES_TYPE_TRACK_TYPE
ges_track_type_get_type
@ -104,6 +106,7 @@ ges_track_object_set_child_property_by_pspec
ges_track_object_get_child_property
ges_track_object_get_child_property_valist
ges_track_object_get_child_property_by_pspec
ges_track_object_edit
<SUBSECTION Standard>
GES_TRACK_OBJECT_DURATION
GES_TRACK_OBJECT_INPOINT
@ -321,6 +324,12 @@ ges_timeline_object_set_top_effect_priority
ges_timeline_object_set_supported_formats
ges_timeline_object_get_supported_formats
ges_timeline_object_split
ges_timeline_object_edit
ges_timeline_object_ripple
ges_timeline_object_ripple_end
ges_timeline_object_roll_start
ges_timeline_object_roll_end
ges_timeline_object_trim_start
<SUBSECTION Standard>
GES_TIMELINE_OBJECT_DURATION
GES_TIMELINE_OBJECT_INPOINT

View file

@ -50,11 +50,14 @@ static void
register_ges_pipeline_flags (GType * id)
{
static const GFlagsValue values[] = {
{C_ENUM (TIMELINE_MODE_PREVIEW_AUDIO), "TIMELINE_MODE_PREVIEW_AUDIO", "audio_preview"},
{C_ENUM (TIMELINE_MODE_PREVIEW_VIDEO), "TIMELINE_MODE_PREVIEW_VIDEO", "video_preview"},
{C_ENUM (TIMELINE_MODE_PREVIEW_AUDIO), "TIMELINE_MODE_PREVIEW_AUDIO",
"audio_preview"},
{C_ENUM (TIMELINE_MODE_PREVIEW_VIDEO), "TIMELINE_MODE_PREVIEW_VIDEO",
"video_preview"},
{C_ENUM (TIMELINE_MODE_PREVIEW), "TIMELINE_MODE_PREVIEW", "full_preview"},
{C_ENUM (TIMELINE_MODE_RENDER), "TIMELINE_MODE_RENDER", "render"},
{C_ENUM (TIMELINE_MODE_SMART_RENDER), "TIMELINE_MODE_SMART_RENDER", "smart_render"},
{C_ENUM (TIMELINE_MODE_SMART_RENDER), "TIMELINE_MODE_SMART_RENDER",
"smart_render"},
{0, NULL, NULL}
};
@ -71,6 +74,64 @@ ges_pipeline_flags_get_type (void)
return id;
}
static void
register_ges_edit_mode (GType * id)
{
static const GEnumValue edit_mode[] = {
{C_ENUM (GES_EDIT_MODE_NORMAL), "GES_EDIT_MODE_NORMAL",
"edit_normal"},
{C_ENUM (GES_EDIT_MODE_RIPPLE), "GES_EDIT_MODE_RIPPLE",
"edit_ripple"},
{C_ENUM (GES_EDIT_MODE_ROLL), "GES_EDIT_MODE_ROLL",
"edit_roll"},
{C_ENUM (GES_EDIT_MODE_TRIM), "GES_EDIT_MODE_TRIM",
"edit_trim"},
{C_ENUM (GES_EDIT_MODE_SLIDE), "GES_EDIT_MODE_SLIDE",
"edit_slide"},
{0, NULL, NULL}
};
*id = g_enum_register_static ("GESEditMode", edit_mode);
}
GType
ges_edit_mode_get_type (void)
{
static GType id;
static GOnce once = G_ONCE_INIT;
g_once (&once, (GThreadFunc) register_ges_edit_mode, &id);
return id;
}
static void
register_ges_edge (GType * id)
{
static const GEnumValue edges[] = {
{C_ENUM (GES_EDGE_START), "GES_EDGE_START", "edge_start"},
{C_ENUM (GES_EDGE_END), "GES_EDGE_END", "edge_end"},
{C_ENUM (GES_EDGE_NONE), "GES_EDGE_NONE", "edge_none"},
{0, NULL, NULL}
};
*id = g_enum_register_static ("GESEdge", edges);
}
GType
ges_edge_get_type (void)
{
static GType id;
static GOnce once = G_ONCE_INIT;
g_once (&once, (GThreadFunc) register_ges_edge, &id);
return id;
}
static GEnumValue transition_types[] = {
{
0,

View file

@ -323,6 +323,60 @@ typedef enum {
GType ges_pipeline_flags_get_type (void);
/**
* GESEditMode:
* @GES_EDIT_MODE_NORMAL: The object is edited the normal way (default).
* @GES_EDIT_MODE_RIPPLE: The objects are edited in ripple mode.
* The Ripple mode allows you to modify the beginning/end of a clip
* and move the neighbours accordingly. This will change the overall
* timeline duration.
* @GES_EDIT_MODE_ROLL: The object is edited in roll mode.
* The Roll mode allows you to modify the position of an editing point
* between two clips without modifying the inpoint of the first clip
* nor the out-point of the second clip. This will not change the
* overall timeline duration.
* @GES_EDIT_MODE_TRIM: The object is edited in trim mode.
* The Trim mode allows you to modify the in-point/out-point of a clip without
* modifying it's duration or position in the timeline.
* @GES_EDIT_MODE_SLIDE: The object is edited in slide mode.
* The Slide mode allows you to modify the position of a clip in a
* timeline without modifying it's duration or it's in-point, but will
* modify the out-point of the previous clip and in-point of the
* following clip so as not to modify the overall timeline duration.
*
* The various edition modes the a clip can be edited with.
*/
typedef enum {
GES_EDIT_MODE_NORMAL,
GES_EDIT_MODE_RIPPLE,
GES_EDIT_MODE_ROLL,
GES_EDIT_MODE_TRIM,
GES_EDIT_MODE_SLIDE
} GESEditMode;
#define GES_TYPE_EDIT_MODE ges_edit_mode_get_type()
GType ges_edit_mode_get_type (void);
/**
* GESEdge:
* @GES_EDGE_START: Represents the start of an object.
* @GES_EDGE_END: Represents the end of an object.
* @GES_EDGE_NONE: Represent the fact we are not workin with any edge of an
* object.
*
* The edges of an object contain in a #GESTimeline or #GESTrack
*/
typedef enum {
GES_EDGE_START,
GES_EDGE_END,
GES_EDGE_NONE
} GESEdge;
#define GES_TYPE_EDGE ges_edge_get_type()
GType ges_edge_get_type (void);
G_END_DECLS
#endif /* __GES_ENUMS_H__ */

View file

@ -22,12 +22,45 @@
#define __GES_INTERNAL_H__
#include <gst/gst.h>
#include "ges-timeline.h"
#include "ges-track-object.h"
GST_DEBUG_CATEGORY_EXTERN (_ges_debug);
#define GST_CAT_DEFAULT _ges_debug
GESTrackObject *
ges_track_object_copy (GESTrackObject * object, gboolean deep);
gboolean
timeline_ripple_object (GESTimeline *timeline, GESTrackObject *obj,
GList * layers, GESEdge edge,
guint64 position);
gboolean
timeline_slide_object (GESTimeline *timeline, GESTrackObject *obj,
GList * layers, GESEdge edge, guint64 position);
gboolean
timeline_roll_object (GESTimeline *timeline, GESTrackObject *obj,
GList * layers, GESEdge edge, guint64 position);
gboolean
timeline_trim_object (GESTimeline *timeline, GESTrackObject * object,
GList * layers, GESEdge edge, guint64 position);
gboolean
ges_timeline_trim_object_simple (GESTimeline * timeline, GESTrackObject * obj,
GList * layers, GESEdge edge, guint64 position, gboolean snapping);
gboolean
ges_timeline_move_object_simple (GESTimeline * timeline, GESTrackObject * object,
GList * layers, GESEdge edge, guint64 position);
gboolean
timeline_move_object (GESTimeline *timeline, GESTrackObject * object,
GList * layers, GESEdge edge, guint64 position);
gboolean
timeline_context_to_layer (GESTimeline *timeline, gint offset);
#endif /* __GES_INTERNAL_H__ */

View file

@ -1304,6 +1304,73 @@ ges_timeline_object_set_top_effect_priority (GESTimelineObject * object,
return TRUE;
}
/**
* ges_timeline_object_edit:
* @object: the #GESTimelineObject to edit
* @layers: (element-type GESTimelineLayer): The layers you want the edit to
* happen in, %NULL means that the edition is done in all the
* #GESTimelineLayers contained in the current timeline.
* @new_layer_priority: The priority of the layer @object should land in.
* If the layer you're trying to move the object to doesn't exist, it will
* be created automatically. -1 means no move.
* @mode: The #GESEditMode in which the editition will happen.
* @edge: The #GESEdge the edit should happen on.
* @position: The position at which to edit @object (in nanosecond)
*
* Edit @object in the different exisiting #GESEditMode modes. In the case of
* slide, and roll, you need to specify a #GESEdge
*
* Returns: %TRUE if the object as been edited properly, %FALSE if an error
* occured
*
* Since: 0.10.XX
*/
gboolean
ges_timeline_object_edit (GESTimelineObject * object, GList * layers,
gint new_layer_priority, GESEditMode mode, GESEdge edge, guint64 position)
{
GList *tmp;
gboolean ret = TRUE;
GESTimelineLayer *layer;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
if (!G_UNLIKELY (object->priv->trackobjects)) {
GST_WARNING_OBJECT (object, "Trying to edit, but not containing"
"any TrackObject yet.");
return FALSE;
} else if (position < 0) {
GST_DEBUG_OBJECT (object, "Trying to move before 0, not moving");
}
for (tmp = object->priv->trackobjects; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret &= ges_track_object_edit (tmp->data, layers, mode, edge, position);
break;
}
}
/* Moving to layer */
if (new_layer_priority == -1) {
GST_DEBUG_OBJECT (object, "Not moving new prio %d", new_layer_priority);
} else {
gint priority_offset;
layer = object->priv->layer;
if (layer == NULL) {
GST_WARNING_OBJECT (object, "Not in any layer yet, not moving");
return FALSE;
}
priority_offset = new_layer_priority -
ges_timeline_layer_get_priority (layer);
ret &= timeline_context_to_layer (layer->timeline, object, priority_offset);
}
return ret;
}
/**
* ges_timeline_object_split:
* @object: the #GESTimelineObject to split
@ -1554,6 +1621,264 @@ ges_timeline_object_set_max_duration (GESTimelineObject * object,
klass->set_max_duration (object, maxduration);
}
/**
* ges_timeline_object_ripple:
* @object: The #GESTimeline to ripple.
* @start: The new start of @object in ripple mode.
*
* Edits @object in ripple mode. It allows you to modify the
* start of @object and move the following neighbours accordingly.
* This will change the overall timeline duration.
*
* You could also use:
*
* #ges_timeline_object_edit (@object, @layers,
* new_layer_priority=-1, GES_EDIT_MODE_RIPPLE, GES_EDGE_NONE,
* @position);
*
* Which lets you more control over layer management.
*
* Returns: %TRUE if the object as been rippled properly, %FALSE if an error
* occured
*/
gboolean
ges_timeline_object_ripple (GESTimelineObject * object, guint64 start)
{
GList *tmp, *tckobjs;
gboolean ret = TRUE;
GESTimeline *timeline;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
timeline = ges_timeline_layer_get_timeline (object->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
tckobjs = ges_timeline_object_get_track_objects (object);
for (tmp = tckobjs; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret = timeline_ripple_object (timeline, GES_TRACK_OBJECT (tmp->data),
NULL, GES_EDGE_NONE, start);
/* As we work only with locked objects, the changes will be reflected
* to others controlled TrackObjects */
break;
}
}
g_list_free_full (tckobjs, g_object_unref);
return ret;
}
/**
* ges_timeline_object_ripple_end:
* @object: The #GESTimeline to ripple.
* @end: The new end (start + duration) of @object in ripple mode. It will
* basically only change the duration of @object.
*
* Edits @object in ripple mode. It allows you to modify the
* duration of a @object and move the following neighbours accordingly.
* This will change the overall timeline duration.
*
* You could also use:
*
* #ges_timeline_object_edit (@object, @layers,
* new_layer_priority=-1, GES_EDIT_MODE_RIPPLE, GES_EDGE_END, @end);
*
* Which lets you more control over layer management.
*
* Returns: %TRUE if the object as been rippled properly, %FALSE if an error
* occured
*/
gboolean
ges_timeline_object_ripple_end (GESTimelineObject * object, guint64 end)
{
GList *tmp, *tckobjs;
gboolean ret = TRUE;
GESTimeline *timeline;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
timeline = ges_timeline_layer_get_timeline (object->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
tckobjs = ges_timeline_object_get_track_objects (object);
for (tmp = tckobjs; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret = timeline_ripple_object (timeline, GES_TRACK_OBJECT (tmp->data),
NULL, GES_EDGE_END, end);
/* As we work only with locked objects, the changes will be reflected
* to others controlled TrackObjects */
break;
}
}
g_list_free_full (tckobjs, g_object_unref);
return ret;
}
/**
* ges_timeline_object_roll_start:
* @start: The new start of @object in roll mode, it will also adapat
* the in-point of @object according
*
* Edits @object in roll mode. It allows you to modify the
* start and inpoint of a @object and "resize" (basicly change the duration
* in this case) of the previous neighbours accordingly.
* This will not change the overall timeline duration.
*
* You could also use:
*
* #ges_timeline_object_edit (@object, @layers,
* new_layer_priority=-1, GES_EDIT_MODE_ROLL, GES_EDGE_START, @start);
*
* Which lets you more control over layer management.
*
* Returns: %TRUE if the object as been roll properly, %FALSE if an error
* occured
*/
gboolean
ges_timeline_object_roll_start (GESTimelineObject * object, guint64 start)
{
GList *tmp, *tckobjs;
gboolean ret = TRUE;
GESTimeline *timeline;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
timeline = ges_timeline_layer_get_timeline (object->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
tckobjs = ges_timeline_object_get_track_objects (object);
for (tmp = tckobjs; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret = timeline_roll_object (timeline, GES_TRACK_OBJECT (tmp->data),
NULL, GES_EDGE_START, start);
/* As we work only with locked objects, the changes will be reflected
* to others controlled TrackObjects */
break;
}
}
g_list_free_full (tckobjs, g_object_unref);
return ret;
}
/**
* ges_timeline_object_roll_end:
* @object: The #GESTimeline to roll.
* @end: The new end (start + duration) of @object in roll mode
*
* Edits @object in roll mode. It allows you to modify the
* duration of a @object and trim (basicly change the start + inpoint
* in this case) the following neighbours accordingly.
* This will not change the overall timeline duration.
*
* You could also use:
*
* #ges_timeline_object_edit (@object, @layers,
* new_layer_priority=-1, GES_EDIT_MODE_ROLL, GES_EDGE_END, @end);
*
* Which lets you more control over layer management.
*
* Returns: %TRUE if the object as been rolled properly, %FALSE if an error
* occured
*/
gboolean
ges_timeline_object_roll_end (GESTimelineObject * object, guint64 end)
{
GList *tmp, *tckobjs;
gboolean ret = TRUE;
GESTimeline *timeline;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
timeline = ges_timeline_layer_get_timeline (object->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
tckobjs = ges_timeline_object_get_track_objects (object);
for (tmp = tckobjs; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret = timeline_roll_object (timeline, GES_TRACK_OBJECT (tmp->data),
NULL, GES_EDGE_END, end);
/* As we work only with locked objects, the changes will be reflected
* to others controlled TrackObjects */
break;
}
}
g_list_free_full (tckobjs, g_object_unref);
return ret;
}
/**
* ges_timeline_object_trim_start:
* @object: The #GESTimeline to trim.
* @start: The new start of @object in trim mode, will adapt the inpoint
* of @object accordingly
*
* Edits @object in trim mode. It allows you to modify the
* inpoint and start of @object.
* This will not change the overall timeline duration.
*
* You could also use:
*
* #ges_timeline_object_edit (@object, @layers,
* new_layer_priority=-1, GES_EDIT_MODE_TRIM, GES_EDGE_START, @start);
*
* Which lets you more control over layer management.
*
* Note that to trim the end of an object you can just set its duration. The same way
* as this method, it will take into account the snapping-distance property of the
* timeline in which @object is.
*
* Returns: %TRUE if the object as been trimmed properly, %FALSE if an error
* occured
*/
gboolean
ges_timeline_object_trim_start (GESTimelineObject * object, guint64 start)
{
GList *tmp, *tckobjs;
gboolean ret = TRUE;
GESTimeline *timeline;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
timeline = ges_timeline_layer_get_timeline (object->priv->layer);
if (timeline == NULL) {
GST_DEBUG ("Not in a timeline yet");
return FALSE;
}
tckobjs = ges_timeline_object_get_track_objects (object);
for (tmp = tckobjs; tmp; tmp = g_list_next (tmp)) {
if (ges_track_object_is_locked (tmp->data)) {
ret = timeline_trim_object (timeline, GES_TRACK_OBJECT (tmp->data),
NULL, GES_EDGE_START, start);
break;
}
}
g_list_free_full (tckobjs, g_object_unref);
return ret;
}
static void
update_height (GESTimelineObject * object)
{

View file

@ -300,8 +300,29 @@ ges_timeline_object_set_supported_formats (GESTimelineObject * object,
GESTimelineObject *
ges_timeline_object_split (GESTimelineObject * object, guint64 position);
gboolean
ges_timeline_object_edit (GESTimelineObject * object,
GList *layers, gint new_layer_priority,
GESEditMode mode, GESEdge edge,
guint64 position);
void
ges_timeline_object_objects_set_locked (GESTimelineObject * object, gboolean locked);
gboolean ges_timeline_object_ripple (GESTimelineObject *object,
guint64 start);
gboolean ges_timeline_object_ripple_end (GESTimelineObject *object,
guint64 end);
gboolean ges_timeline_object_roll_start (GESTimelineObject *object,
guint64 start);
gboolean ges_timeline_object_roll_end (GESTimelineObject *object,
guint64 end);
gboolean ges_timeline_object_trim_start (GESTimelineObject *object,
guint64 start);
G_END_DECLS
#endif /* _GES_TIMELINE_OBJECT */

File diff suppressed because it is too large Load diff

View file

@ -1544,3 +1544,70 @@ ges_track_object_copy (GESTrackObject * object, gboolean deep)
return ret;
}
/**
* ges_track_object_edit:
* @object: the #GESTrackObject to edit
* @layers: (element-type GESTimelineLayer): The layers you want the edit to
* happen in, %NULL means that the edition is done in all the
* #GESTimelineLayers contained in the current timeline.
* FIXME: This is not implemented yet.
* @mode: The #GESEditMode in which the editition will happen.
* @edge: The #GESEdge the edit should happen on.
* @position: The position at which to edit @object (in nanosecond)
*
* Edit @object in the different exisiting #GESEditMode modes. In the case of
* slide, and roll, you need to specify a #GESEdge
*
* Returns: %TRUE if the object as been edited properly, %FALSE if an error
* occured
*
* Since: 0.10.XX
*/
gboolean
ges_track_object_edit (GESTrackObject * object,
GList * layers, GESEditMode mode, GESEdge edge, guint64 position)
{
GESTrack *track = ges_track_object_get_track (object);
GESTimeline *timeline;
if (G_UNLIKELY (!track)) {
GST_WARNING_OBJECT (object, "Trying to edit in %d mode but not in"
"any Track yet.", mode);
return FALSE;
} else if (position < 0) {
GST_DEBUG_OBJECT (object, "Trying to move before 0, not moving");
return FALSE;
}
timeline = GES_TIMELINE (ges_track_get_timeline (track));
if (G_UNLIKELY (!timeline)) {
GST_WARNING_OBJECT (object, "Trying to edit in %d mode but not in"
"track %p no in any timeline yet.", mode, track);
return FALSE;
}
switch (mode) {
case GES_EDIT_MODE_NORMAL:
timeline_move_object (timeline, object, layers, edge, position);
break;
case GES_EDIT_MODE_TRIM:
timeline_trim_object (timeline, object, layers, edge, position);
break;
case GES_EDIT_MODE_RIPPLE:
timeline_ripple_object (timeline, object, layers, edge, position);
break;
case GES_EDIT_MODE_ROLL:
timeline_roll_object (timeline, object, layers, edge, position);
break;
case GES_EDIT_MODE_SLIDE:
timeline_slide_object (timeline, object, layers, edge, position);
break;
default:
GST_ERROR ("Unkown edit mode: %d", mode);
return FALSE;
}
return TRUE;
}

View file

@ -226,6 +226,10 @@ void ges_track_object_set_child_property (GESTrackObject * object,
const gchar * first_property_name,
...) G_GNUC_NULL_TERMINATED;
gboolean
ges_track_object_edit (GESTrackObject * object,
GList *layers, GESEditMode mode,
GESEdge edge, guint64 position);
G_END_DECLS
#endif /* _GES_TRACK_OBJECT */

View file

@ -115,19 +115,21 @@ GST_START_TEST (test_ges_scenario)
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (source));
fail_unless (trackobjects != NULL);
trackobject = GES_TRACK_OBJECT (trackobjects->data);
/* There are 3 references:
/* There are 4 references:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by the call to _get_track_objects() above */
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 4);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
/* There are 2 references:
/* There are 3 references:
* 1 by the timelineobject
* 1 by the timeline
* 1 by the track */
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 3);
GST_DEBUG ("Remove the TimelineObject from the layer");
@ -252,19 +254,21 @@ GST_START_TEST (test_ges_timeline_add_layer)
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s1));
fail_unless (trackobjects != NULL);
trackobject = GES_TRACK_OBJECT (trackobjects->data);
/* There are 3 references:
/* There are 4 references:
* 1 by the timelineobject
* 1 by the trackobject
* 1 by the timeline
* 1 added by the call to _get_track_objects() above */
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 4);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
/* There are 2 references:
/* There are 3 references:
* 1 by the timelineobject
* 1 by the timeline
* 1 by the trackobject */
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 3);
trackobjects =
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s2));
@ -274,10 +278,11 @@ GST_START_TEST (test_ges_timeline_add_layer)
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
/* There are 2 references:
/* There are 3 references:
* 1 by the timelineobject
* 1 by the timeline
* 1 by the trackobject */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (trackobject), "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (trackobject), "trackobject", 3);
trackobjects =
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s3));
@ -287,10 +292,11 @@ GST_START_TEST (test_ges_timeline_add_layer)
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
/* There are 2 references:
/* There are 3 references:
* 1 by the timelineobject
* 1 by the timeline
* 1 by the trackobject */
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (trackobject, "trackobject", 3);
/* theoretically this is all we need to do to ensure cleanup */
g_object_unref (timeline);
@ -369,11 +375,12 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s1));
fail_unless (trackobjects != NULL);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* Each object has 3 references:
/* Each object has 4 references:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by _get_track_object() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
@ -382,11 +389,12 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s2));
fail_unless (trackobjects != NULL);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* Each object has 3 references:
/* Each object has 4 references:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by _get_track_object() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
@ -395,11 +403,12 @@ GST_START_TEST (test_ges_timeline_add_layer_first)
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s3));
fail_unless (trackobjects != NULL);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* Each object has 3 references:
/* Each object has 4 references:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by _get_track_object() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_list_free (trackobjects);
@ -482,67 +491,73 @@ GST_START_TEST (test_ges_timeline_remove_track)
fail_unless (trackobjects != NULL);
t1 = GES_TRACK_OBJECT ((trackobjects)->data);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by the call to _get_track_objects() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_object_ref (t1);
g_list_free (trackobjects);
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelinobject
* 1 by the track
* 1 by the timeline
* 1 added by ourselves above (g_object_ref (t1)) */
ASSERT_OBJECT_REFCOUNT (t1, "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (t1, "trackobject", 4);
trackobjects =
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s2));
fail_unless (trackobjects != NULL);
t2 = GES_TRACK_OBJECT (trackobjects->data);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by the call to _get_track_objects() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_object_ref (t2);
g_list_free (trackobjects);
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelinobject
* 1 by the track
* 1 by the timeline
* 1 added by ourselves above (g_object_ref (t1)) */
ASSERT_OBJECT_REFCOUNT (t2, "t2", 3);
ASSERT_OBJECT_REFCOUNT (t2, "t2", 4);
trackobjects =
ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s3));
fail_unless (trackobjects != NULL);
t3 = GES_TRACK_OBJECT (trackobjects->data);
for (tmp = trackobjects; tmp; tmp = tmp->next) {
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelineobject
* 1 by the track
* 1 by the timeline
* 1 added by the call to _get_track_objects() above */
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 3);
ASSERT_OBJECT_REFCOUNT (GES_TRACK_OBJECT (tmp->data), "trackobject", 4);
g_object_unref (GES_TRACK_OBJECT (tmp->data));
}
g_object_ref (t3);
g_list_free (trackobjects);
/* There are 3 references held:
/* There are 4 references held:
* 1 by the timelinobject
* 1 by the track
* 1 by the timeline
* 1 added by ourselves above (g_object_ref (t1)) */
ASSERT_OBJECT_REFCOUNT (t3, "t3", 3);
ASSERT_OBJECT_REFCOUNT (t3, "t3", 4);
/* remove the track and check that the track objects have been released */
fail_unless (ges_timeline_remove_track (timeline, track));
ASSERT_OBJECT_REFCOUNT (t1, "trackobject", 1);
ASSERT_OBJECT_REFCOUNT (t2, "trackobject", 1);
ASSERT_OBJECT_REFCOUNT (t3, "trackobject", 1);
ASSERT_OBJECT_REFCOUNT (t1, "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (t2, "trackobject", 2);
ASSERT_OBJECT_REFCOUNT (t3, "trackobject", 2);
g_object_unref (t1);
g_object_unref (t2);