static GESTrackObject *
ges_custom_timeline_source_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
- return g_object_new (GES_TYPE_TRACK_SOURCE, NULL);
+ return g_object_new (GES_TYPE_TRACK_SOURCE, "track-type", type, NULL);
}
static void
effect = ges_track_parse_launch_effect_new ((gchar *)
g_hash_table_lookup (props_table, (gchar *) "effect_name"));
+ ges_track_object_set_track_type (GES_TRACK_OBJECT (effect),
+ (video ? GES_TRACK_TYPE_VIDEO : GES_TRACK_TYPE_AUDIO));
effect_table =
g_hash_table_lookup (props_table, (gchar *) "effect_props");
static GESTrackObject
* ges_timeline_filesource_create_track_object (GESTimelineObject * obj,
- GESTrack * track);
+ GESTrackType type);
void
ges_timeline_filesource_set_uri (GESTimelineFileSource * self, gchar * uri);
static GESTrackObject *
ges_timeline_filesource_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineFileSourcePrivate *priv = GES_TIMELINE_FILE_SOURCE (obj)->priv;
GESTrackObject *res;
if (priv->is_image) {
- if (track->type != GES_TRACK_TYPE_VIDEO) {
+ if (type != GES_TRACK_TYPE_VIDEO) {
GST_DEBUG ("Object is still image, not adding any audio source");
return NULL;
} else {
GST_DEBUG ("Creating a GESTrackImageSource");
res = (GESTrackObject *) ges_track_image_source_new (priv->uri);
}
- }
- else {
+ } else {
GST_DEBUG ("Creating a GESTrackFileSource");
/* FIXME : Implement properly ! */
res = (GESTrackObject *) ges_track_filesource_new (priv->uri);
/* If mute and track is audio, deactivate the track object */
- if (track->type == GES_TRACK_TYPE_AUDIO && priv->mute)
+ if (type == GES_TRACK_TYPE_AUDIO && priv->mute)
ges_track_object_set_active (res, FALSE);
}
+ if (res)
+ ges_track_object_set_track_type (res, type);
+
return res;
}
/* GStreamer Editing Services
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
* 2009 Nokia Corporation
+ * 2012 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
ges_timeline_object_fill_track_object_func (GESTimelineObject * object,
GESTrackObject * trackobj, GstElement * gnlobj);
-gboolean
-ges_timeline_object_create_track_objects_func (GESTimelineObject
- * object, GESTrack * track);
+GList *ges_timeline_object_create_track_objects_func (GESTimelineObject
+ * object, GESTrackType type);
void default_set_max_duration (GESTimelineObject * object, guint64 maxduration);
object_class->set_property = ges_timeline_object_set_property;
klass->create_track_objects = ges_timeline_object_create_track_objects_func;
klass->set_max_duration = default_set_max_duration;
+ klass->create_track_object = NULL;
klass->track_object_added = NULL;
klass->track_object_released = NULL;
/**
* ges_timeline_object_create_track_object:
* @object: The origin #GESTimelineObject
- * @track: The #GESTrack to create a #GESTrackObject for.
+ * @type: The #GESTrackType to create a #GESTrackObject for.
*
- * Creates a #GESTrackObject for the provided @track. The timeline object
+ * Creates a #GESTrackObject for the provided @type. The timeline object
* keep a reference to the newly created trackobject, you therefore need to
* call @ges_timeline_object_release_track_object when you are done with it.
*
* Returns: (transfer none): A #GESTrackObject. Returns NULL if the #GESTrackObject could not
* be created.
*/
-
GESTrackObject *
ges_timeline_object_create_track_object (GESTimelineObject * object,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineObjectClass *class;
GESTrackObject *res;
g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), NULL);
- g_return_val_if_fail (GES_IS_TRACK (track), NULL);
- if (!(track->type & object->priv->supportedformats)) {
- GST_DEBUG ("We don't support this track format (supported: %i caps %"
- GST_PTR_FORMAT ")", object->priv->supportedformats,
- ges_track_get_caps (track));
+ GST_DEBUG_OBJECT (object, "Creating track object for %s",
+ ges_track_type_name (type));
+ if (!(type & object->priv->supportedformats)) {
+ GST_DEBUG_OBJECT (object, "We don't support this track type %i", type);
return NULL;
}
return NULL;
}
- res = class->create_track_object (object, track);
+ res = class->create_track_object (object, type);
return res;
}
/**
* ges_timeline_object_create_track_objects:
* @object: The origin #GESTimelineObject
- * @track: The #GESTrack to create each #GESTrackObject for.
+ * @type: The #GESTrackType to create each #GESTrackObject for.
*
- * Creates all #GESTrackObjects supported by this object and adds them to the
- * provided track. The track is responsible for calling
- * #ges_timeline_release_track_object on these objects when it is finished
- * with them.
+ * Creates all #GESTrackObjects supported by this object provided track.
+ * The track is responsible for calling #ges_timeline_release_track_object
+ * on these objects when it is finished with them.
*
- * Returns: %TRUE if each track object was created successfully, or %FALSE if an
- * error occured.
+ * Returns: (element-type GESTrackObject) (transfer-full): A #GList of
+ * newly created #GESTrackObject-s
*/
-gboolean
+GList *
ges_timeline_object_create_track_objects (GESTimelineObject * object,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineObjectClass *klass;
- g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE);
- g_return_val_if_fail (GES_IS_TRACK (track), FALSE);
+ g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), NULL);
klass = GES_TIMELINE_OBJECT_GET_CLASS (object);
if (!(klass->create_track_objects)) {
GST_WARNING ("no GESTimelineObject::create_track_objects implentation");
- return FALSE;
+ return NULL;
}
- return klass->create_track_objects (object, track);
+ GST_DEBUG_OBJECT (object, "Creating TrackObjects for type: %s",
+ ges_track_type_name (type));
+ return klass->create_track_objects (object, type);
}
/* Default implementation of default_set_max_duration */
/*
* default implementation of GESTimelineObjectClass::create_track_objects
*/
-gboolean
+GList *
ges_timeline_object_create_track_objects_func (GESTimelineObject * object,
- GESTrack * track)
+ GESTrackType type)
{
GESTrackObject *result;
- result = ges_timeline_object_create_track_object (object, track);
+ GST_DEBUG_OBJECT (object, "Creating trackobject for track: %s",
+ ges_track_type_name (type));
+ result = ges_timeline_object_create_track_object (object, type);
if (!result) {
GST_DEBUG ("Did not create track object");
- return FALSE;
+ return NULL;
}
- if (ges_timeline_object_add_track_object (object, result) == FALSE)
- return FALSE;
-
- return ges_track_add_object (track, result);
+ return g_list_append (NULL, result);
}
/**
#define GES_TIMELINE_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_TIMELINE_OBJECT, GESTimelineObjectClass))
typedef struct _GESTimelineObjectPrivate GESTimelineObjectPrivate;
+typedef struct _GESTimelineObjectClassPrivate GESTimelineObjectClassPrivate;
/**
* GESFillTrackObjectFunc:
/**
* GESCreateTrackObjectFunc:
* @object: a #GESTimelineObject
- * @track: a #GESTrack
+ * @type: a #GESTrackType
*
* Creates the 'primary' track object for this @object.
*
* Returns: the #GESTrackObject to be used, or %NULL if it can't provide one
* for the given @track.
*/
-typedef GESTrackObject *(*GESCreateTrackObjectFunc) (GESTimelineObject *
- object,
- GESTrack *track);
+typedef GESTrackObject *(*GESCreateTrackObjectFunc) (GESTimelineObject * object,
+ GESTrackType type);
/**
* GESCreateTrackObjectsFunc:
* @object: a #GESTimelineObject
- * @track: a #GESTrack
+ * @type: a #GESTrackType
*
* Create all track objects this object handles for this type of track.
*
*
* For each object created, the subclass must call
* ges_timeline_object_add_track_object() with the newly created object
- * and provided @track.
+ * and provided @type.
*
* Returns: %TRUE on success %FALSE on failure.
*/
-typedef gboolean (*GESCreateTrackObjectsFunc) (GESTimelineObject *object,
- GESTrack *track);
+
+typedef GList * (*GESCreateTrackObjectsFunc) (GESTimelineObject * object, GESTrackType type);
/**
* GES_TIMELINE_OBJECT_START:
/* TrackObject handling */
GList* ges_timeline_object_get_track_objects (GESTimelineObject *object);
GESTrackType ges_timeline_object_get_supported_formats (GESTimelineObject *object);
-GESTrackObject *ges_timeline_object_create_track_object (GESTimelineObject *object, GESTrack *track);
-gboolean ges_timeline_object_create_track_objects (GESTimelineObject *object, GESTrack *track);
+GESTrackObject *ges_timeline_object_create_track_object (GESTimelineObject *object, GESTrackType type);
+GList * ges_timeline_object_create_track_objects (GESTimelineObject *object, GESTrackType type);
gboolean ges_timeline_object_release_track_object (GESTimelineObject *object, GESTrackObject *trackobject);
void ges_timeline_object_set_supported_formats (GESTimelineObject *object, GESTrackType supportedformats);
gboolean ges_timeline_object_add_asset (GESTimelineObject *object, GESAsset *asset);
gboolean ges_timeline_object_fill_track_object (GESTimelineObject *object, GESTrackObject *trackobj, GstElement *gnlobj);
GESTrackObject *ges_timeline_object_find_track_object (GESTimelineObject *object, GESTrack *track, GType type);
-
/* Layer */
GESTimelineLayer *ges_timeline_object_get_layer (GESTimelineObject *object);
gboolean ges_timeline_object_is_moving_from_layer (GESTimelineObject *object);
static void ges_timeline_parse_launch_effect_finalize (GObject * object);
static GESTrackObject
* ges_tl_parse_launch_effect_create_track_obj (GESTimelineObject * self,
- GESTrack * track);
+ GESTrackType type);
static void
ges_timeline_parse_launch_effect_finalize (GObject * object)
static GESTrackObject *
ges_tl_parse_launch_effect_create_track_obj (GESTimelineObject * self,
- GESTrack * track)
+ GESTrackType type)
{
+ const gchar *bin_description = NULL;
GESTimelineParseLaunchEffect *effect =
GES_TIMELINE_PARSE_LAUNCH_EFFECT (self);
- if (track->type == GES_TRACK_TYPE_VIDEO) {
- if (effect->priv->video_bin_description != NULL) {
- GST_DEBUG ("Creating a GESTrackEffect for the video track");
- return GES_TRACK_OBJECT (ges_track_parse_launch_effect_new
- (effect->priv->video_bin_description));
- }
- GST_DEBUG ("Can't create the track Object, the"
- "video_bin_description is not set");
+ if (type == GES_TRACK_TYPE_VIDEO) {
+ bin_description = effect->priv->video_bin_description;
+ } else if (type == GES_TRACK_TYPE_AUDIO) {
+ bin_description = effect->priv->audio_bin_description;
}
- if (track->type == GES_TRACK_TYPE_AUDIO) {
- if (effect->priv->audio_bin_description != NULL) {
- GST_DEBUG ("Creating a GESTrackEffect for the audio track");
- return GES_TRACK_OBJECT (ges_track_parse_launch_effect_new
- (effect->priv->audio_bin_description));
- }
- GST_DEBUG ("Can't create the track Object, the"
- "audio_bin_description is not set");
+
+ if (bin_description) {
+ /* FIXME Work with a GESAsset here! */
+ return g_object_new (GES_TYPE_TRACK_PARSE_LAUNCH_EFFECT, "bin-description",
+ bin_description, "track-type", type, NULL);
}
GST_WARNING ("Effect doesn't handle this track type");
};
static GESTrackObject *ges_tl_transition_create_track_object (GESTimelineObject
- * self, GESTrack * track);
+ * self, GESTrackType type);
static void
ges_timeline_standard_transition_track_object_added (GESTimelineObject * obj,
GESTrackObject * tckobj);
static GESTrackObject *
ges_tl_transition_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineStandardTransition *transition =
(GESTimelineStandardTransition *) obj;
GST_DEBUG ("Creating a GESTrackTransition");
supportedformats = ges_timeline_object_get_supported_formats (obj);
- if (track->type == GES_TRACK_TYPE_VIDEO) {
+ if (type == GES_TRACK_TYPE_VIDEO) {
if (supportedformats == GES_TRACK_TYPE_UNKNOWN ||
supportedformats & GES_TRACK_TYPE_VIDEO) {
GESTrackVideoTransition *trans;
" supportedformats");
}
- } else if (track->type == GES_TRACK_TYPE_AUDIO) {
+ } else if (type == GES_TRACK_TYPE_AUDIO) {
if (supportedformats == GES_TRACK_TYPE_UNKNOWN ||
supportedformats & GES_TRACK_TYPE_AUDIO)
static GESTrackObject
* ges_timeline_test_source_create_track_object (GESTimelineObject * obj,
- GESTrack * track);
+ GESTrackType type);
static void
ges_timeline_test_source_get_property (GObject * object, guint property_id,
static GESTrackObject *
ges_timeline_test_source_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineTestSourcePrivate *priv = GES_TIMELINE_TEST_SOURCE (obj)->priv;
GESTrackObject *res = NULL;
- GST_DEBUG ("Creating a GESTrackTestSource");
+ GST_DEBUG ("Creating a GESTrackTestSource for type: %s",
+ ges_track_type_name (type));
- if (track->type == GES_TRACK_TYPE_VIDEO) {
+ if (type == GES_TRACK_TYPE_VIDEO) {
res = (GESTrackObject *) ges_track_video_test_source_new ();
ges_track_video_test_source_set_pattern (
(GESTrackVideoTestSource *) res, priv->vpattern);
- }
-
- else if (track->type == GES_TRACK_TYPE_AUDIO) {
+ } else if (type == GES_TRACK_TYPE_AUDIO) {
res = (GESTrackObject *) ges_track_audio_test_source_new ();
if (priv->mute)
static GESTrackObject
* ges_timeline_text_overlay_create_track_object (GESTimelineObject * obj,
- GESTrack * track);
+ GESTrackType type);
static void
ges_timeline_text_overlay_get_property (GObject * object, guint property_id,
static GESTrackObject *
ges_timeline_text_overlay_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineTextOverlayPrivate *priv = GES_TIMELINE_TEXT_OVERLAY (obj)->priv;
GST_DEBUG ("Creating a GESTrackOverlay");
- if (track->type == GES_TRACK_TYPE_VIDEO) {
+ if (type == GES_TRACK_TYPE_VIDEO) {
res = (GESTrackObject *) ges_track_text_overlay_new ();
GST_DEBUG ("Setting text property");
ges_track_text_overlay_set_text ((GESTrackTextOverlay *) res, priv->text);
static GESTrackObject
* ges_timeline_title_source_create_track_object (GESTimelineObject * obj,
- GESTrack * track);
+ GESTrackType type);
static void
ges_timeline_title_source_track_object_added (GESTimelineObject * obj,
static GESTrackObject *
ges_timeline_title_source_create_track_object (GESTimelineObject * obj,
- GESTrack * track)
+ GESTrackType type)
{
GESTimelineTitleSourcePrivate *priv = GES_TIMELINE_TITLE_SOURCE (obj)->priv;
GST_DEBUG_OBJECT (obj, "a GESTrackTitleSource");
- if (track->type == GES_TRACK_TYPE_VIDEO) {
+ if (type == GES_TRACK_TYPE_VIDEO) {
res = (GESTrackObject *) ges_track_title_source_new ();
GST_DEBUG_OBJECT (obj, "text property");
ges_track_title_source_set_text ((GESTrackTitleSource *) res, priv->text);
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
* 2009 Nokia Corporation
* 2012 Thibault Saunier <tsaunier@gnome.org>
+ * 2012 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
typedef struct _MoveContext MoveContext;
+static GPtrArray *select_tracks_for_object_default (GESTimeline * timeline,
+ GESTimelineObject * tl_obj, GESTrackObject * tr_obj, gpointer user_data);
static inline void init_movecontext (MoveContext * mv_ctx);
static void ges_extractable_interface_init (GESExtractableInterface * iface);
static void ges_meta_container_interface_init
LAYER_REMOVED,
SNAPING_STARTED,
SNAPING_ENDED,
+ SELECT_TRACKS_FOR_OBJECT,
LAST_SIGNAL
};
G_OBJECT_CLASS (ges_timeline_parent_class)->finalize (object);
}
+/* we collect the first result */
+static gboolean
+_gst_array_accumulator (GSignalInvocationHint * ihint,
+ GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+ gpointer array;
+
+ array = g_value_get_boxed (handler_return);
+ if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
+ g_value_set_boxed (return_accu, array);
+
+ return FALSE;
+}
+
static void
ges_timeline_class_init (GESTimelineClass * klass)
{
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
G_TYPE_NONE, 3, GES_TYPE_TRACK_OBJECT, GES_TYPE_TRACK_OBJECT,
G_TYPE_UINT64);
+
+ /**
+ * GESTimeline::select-tracks-for-object:
+ * @timeline: the #GESTimeline
+ * @timeline-object: The #GESTimelineObject on which @track-object will land
+ * @track-object: The #GESTrackObject for which to choose the tracks it should land into
+ *
+ * Returns: (transfer full) (element-type GESTrack): a #GPtrArray of #GESTrack-s where that object should be added
+ *
+ * Since: 0.10.XX
+ */
+ ges_timeline_signals[SELECT_TRACKS_FOR_OBJECT] =
+ g_signal_new ("select-tracks-for-object", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, _gst_array_accumulator, NULL, NULL,
+ G_TYPE_PTR_ARRAY, 2, GES_TYPE_TIMELINE_OBJECT, GES_TYPE_TRACK_OBJECT);
}
static void
(GDestroyNotify) _destroy_obj_iters);
priv->starts_ends = g_sequence_new (g_free);
priv->tracksources = g_sequence_new (g_object_unref);
+
+ g_signal_connect_after (self, "select-tracks-for-object",
+ G_CALLBACK (select_tracks_for_object_default), NULL);
}
/* Private methods */
}
static void
-add_object_to_track (GESTimelineObject * object, GESTrack * track)
+add_object_to_track (GESTimelineObject * object, GESTrackObject * track_object,
+ GESTrack * track)
{
- if (!ges_timeline_object_create_track_objects (object, track)) {
- if ((track->type & ges_timeline_object_get_supported_formats (object))) {
- GST_WARNING ("Error creating track objects");
- }
+ if (!ges_timeline_object_add_track_object (object, track_object)) {
+ GST_WARNING_OBJECT (object,
+ "Failed to add track object to timeline object");
+ gst_object_unref (track_object);
+ return;
+ }
+
+ if (!ges_track_add_object (track, track_object)) {
+ GST_WARNING_OBJECT (object, "Failed to add track object to track");
+ ges_timeline_object_release_track_object (object, track_object);
+ gst_object_unref (track_object);
+ return;
}
}
-static void
-add_object_to_tracks (GESTimeline * timeline, GESTimelineObject * object)
+static GPtrArray *
+select_tracks_for_object_default (GESTimeline * timeline,
+ GESTimelineObject * tl_obj, GESTrackObject * tr_object, gpointer user_data)
{
+ GPtrArray *result;
GList *tmp;
- for (tmp = timeline->tracks; tmp; tmp = g_list_next (tmp)) {
- GST_LOG_OBJECT (timeline, "Trying with track %" GST_PTR_FORMAT, tmp->data);
- add_object_to_track (object, GES_TRACK (tmp->data));
+ result = g_ptr_array_new ();
+
+ for (tmp = timeline->tracks; tmp; tmp = tmp->next) {
+ GESTrack *track = GES_TRACK (tmp->data);
+
+ if ((track->type & ges_track_object_get_track_type (tr_object))) {
+ gst_object_ref (track);
+ g_ptr_array_add (result, track);
+ }
+ }
+
+ return result;
+}
+
+static void
+add_object_to_tracks (GESTimeline * timeline, GESTimelineObject * object,
+ GESTrack * track)
+{
+ gint i;
+ GPtrArray *tracks = NULL;
+ GESTrackType types, visited_type = 1;
+ GList *tmp, *l, *track_objects;
+
+ GST_DEBUG_OBJECT (timeline, "Creating %" GST_PTR_FORMAT
+ " trackobjects and adding them to our tracks", object);
+
+ types = ges_timeline_object_get_supported_formats (object);
+ if (track) {
+ if ((types & track->type) == 0)
+ return;
+ types = track->type;
+ }
+
+ for (i = 0, tmp = timeline->tracks; tmp; tmp = tmp->next, i++) {
+ GESTrack *track = GES_TRACK (tmp->data);
+
+ if (((track->type & types) == 0 || (track->type & visited_type)))
+ continue;
+
+ track_objects = ges_timeline_object_create_track_objects (object,
+ track->type);
+ for (l = track_objects; l; l = l->next) {
+ GESTrack *tmp_track;
+ GESTrackObject *track_object = l->data;
+
+ GST_DEBUG_OBJECT (timeline, "Got trackobject: %" GST_PTR_FORMAT
+ "Asking to which track it should be added", track_object);
+
+ g_signal_emit (G_OBJECT (timeline),
+ ges_timeline_signals[SELECT_TRACKS_FOR_OBJECT], 0, object,
+ track_object, &tracks);
+
+ if (!tracks || tracks->len == 0) {
+ GST_DEBUG_OBJECT (timeline, "Got no Track to add %p into", object);
+ goto next_track_object;
+ }
+
+ for (i = 0; i < tracks->len; i++) {
+ GESTrackObject *track_object_copy;
+
+ tmp_track = g_ptr_array_index (tracks, i);
+ if (track && tmp_track != track) {
+ GST_LOG_OBJECT (timeline,
+ "Not adding %" GST_PTR_FORMAT " to any track", track_object);
+ continue;
+ }
+
+ track_object_copy = ges_track_object_copy (track_object, TRUE);
+
+ GST_LOG_OBJECT (timeline, "Trying to add %p to track %p",
+ track_object_copy, tmp_track);
+ add_object_to_track (object, track_object_copy, tmp_track);
+
+ gst_object_unref (tmp_track);
+ }
+
+ next_track_object:
+ if (tracks) {
+ g_ptr_array_unref (tracks);
+ tracks = NULL;
+ }
+ gst_object_unref (track_object);
+ }
}
}
}
GST_DEBUG ("New TimelineObject %p added to layer %p", object, layer);
- add_object_to_tracks (timeline, object);
+ add_object_to_tracks (timeline, object, NULL);
GST_DEBUG ("Done");
}
for (tmp = trackobjects; tmp; tmp = tmp->next) {
GESTrackObject *trobj = (GESTrackObject *) tmp->data;
- GST_DEBUG ("Trying to remove TrackObject %p", trobj);
+ GST_DEBUG_OBJECT (timeline, "Trying to remove TrackObject %p", trobj);
if (G_LIKELY (g_list_find_custom (timeline->priv->priv_tracks,
ges_track_object_get_track (trobj),
(GCompareFunc) custom_find_track))) {
objects = ges_timeline_layer_get_objects (tmp->data);
for (obj = objects; obj; obj = obj->next) {
- add_object_to_track (obj->data, track);
- g_object_unref (obj->data);
- obj->data = NULL;
+ GESTimelineObject *object = obj->data;
+
+ add_object_to_tracks (timeline, object, track);
+ g_object_unref (object);
}
g_list_free (objects);
}
GESTrackAudioTestSource *
ges_track_audio_test_source_new (void)
{
- return g_object_new (GES_TYPE_TRACK_AUDIO_TEST_SOURCE, NULL);
+ return g_object_new (GES_TYPE_TRACK_AUDIO_TEST_SOURCE, "track-type",
+ GES_TRACK_TYPE_AUDIO, NULL);
}
GESTrackAudioTransition *
ges_track_audio_transition_new (void)
{
- return g_object_new (GES_TYPE_TRACK_AUDIO_TRANSITION, NULL);
+ return g_object_new (GES_TYPE_TRACK_AUDIO_TRANSITION, "track-type",
+ GES_TRACK_TYPE_AUDIO, NULL);
}
GESTrackImageSource *
ges_track_image_source_new (gchar * uri)
{
- return g_object_new (GES_TYPE_TRACK_IMAGE_SOURCE, "uri", uri, NULL);
+ return g_object_new (GES_TYPE_TRACK_IMAGE_SOURCE, "uri", uri, "track-type",
+ GES_TRACK_TYPE_VIDEO, NULL);
}
struct _GESTrackObjectPrivate
{
+ GESTrackType track_type;
+
/* These fields are only used before the gnlobject is available */
guint64 pending_start;
guint64 pending_inpoint;
PROP_ACTIVE,
PROP_LOCKED,
PROP_MAX_DURATION,
+ PROP_TRACK_TYPE,
PROP_LAST
};
case PROP_MAX_DURATION:
g_value_set_uint64 (value, tobj->priv->maxduration);
break;
+ case PROP_TRACK_TYPE:
+ g_value_set_flags (value, tobj->priv->track_type);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
case PROP_MAX_DURATION:
ges_track_object_set_max_duration (tobj, g_value_get_uint64 (value));
break;
+ case PROP_TRACK_TYPE:
+ tobj->priv->track_type = g_value_get_flags (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
*
* Since: 0.10.XX
*/
- g_object_class_install_property (object_class, PROP_MAX_DURATION,
+ properties[PROP_MAX_DURATION] =
g_param_spec_uint64 ("max-duration", "Maximum duration",
- "The maximum duration of the object", 0, G_MAXUINT64, G_MAXUINT64,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ "The maximum duration of the object", 0, G_MAXUINT64, G_MAXUINT64,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+ g_object_class_install_property (object_class, PROP_MAX_DURATION,
+ properties[PROP_MAX_DURATION]);
+
+ properties[PROP_TRACK_TYPE] = g_param_spec_flags ("track-type", "Track Type",
+ "The track type of the object", GES_TYPE_TRACK_TYPE,
+ GES_TRACK_TYPE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ g_object_class_install_property (object_class, PROP_TRACK_TYPE,
+ properties[PROP_TRACK_TYPE]);
+
/**
* GESTrackObject::deep-notify:
return TRUE;
}
+void
+ges_track_object_set_track_type (GESTrackObject * object, GESTrackType type)
+{
+ g_return_if_fail (GES_IS_TRACK_OBJECT (object));
+
+ if (object->priv->track_type != type) {
+ object->priv->track_type = type;
+ g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_TRACK_TYPE]);
+ }
+}
+
+GESTrackType
+ges_track_object_get_track_type (GESTrackObject * object)
+{
+ g_return_val_if_fail (GES_IS_TRACK_OBJECT (object), GES_TRACK_TYPE_UNKNOWN);
+
+ return object->priv->track_type;
+}
+
/* Callbacks from the GNonLin object */
static void
gnlobject_start_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED,
GESTrack * track);
GESTrack* ges_track_object_get_track (GESTrackObject * object);
+GESTrackType ges_track_object_get_track_type (GESTrackObject * object);
+void ges_track_object_set_track_type (GESTrackObject * object,
+ GESTrackType type);
+
void ges_track_object_set_timeline_object (GESTrackObject * object,
GESTimelineObject * tlobject);
GESTimelineObject *
GESTrackTextOverlay *
ges_track_text_overlay_new (void)
{
- return g_object_new (GES_TYPE_TRACK_TEXT_OVERLAY, NULL);
+ return g_object_new (GES_TYPE_TRACK_TEXT_OVERLAY, "track-type",
+ GES_TRACK_TYPE_VIDEO, NULL);
}
GESTrackTitleSource *
ges_track_title_source_new (void)
{
- return g_object_new (GES_TYPE_TRACK_TITLE_SOURCE, NULL);
+ return g_object_new (GES_TYPE_TRACK_TITLE_SOURCE, "track-type",
+ GES_TRACK_TYPE_VIDEO, NULL);
}
GESTrackVideoTestSource *
ges_track_video_test_source_new (void)
{
- return g_object_new (GES_TYPE_TRACK_VIDEO_TEST_SOURCE, NULL);
+ return g_object_new (GES_TYPE_TRACK_VIDEO_TEST_SOURCE, "track-type",
+ GES_TRACK_TYPE_VIDEO, NULL);
}
GESTrackVideoTransition *
ges_track_video_transition_new (void)
{
- return g_object_new (GES_TYPE_TRACK_VIDEO_TRANSITION, NULL);
+ return g_object_new (GES_TYPE_TRACK_VIDEO_TRANSITION, "track-type",
+ GES_TRACK_TYPE_VIDEO, NULL);
}
GESTrackPrivate *priv;
g_return_if_fail (GES_IS_TRACK (track));
- g_return_if_fail (GST_IS_CAPS (caps));
GST_DEBUG ("track:%p, caps:%" GST_PTR_FORMAT, track, caps);
+ g_return_if_fail (GST_IS_CAPS (caps));
+ GST_DEBUG ("IS CAPS MOFOP:%p, caps:%" GST_PTR_FORMAT, track, caps);
priv = track->priv;
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
ges_timeline_object_find_track_object (GES_TIMELINE_OBJECT (source), v,
GES_TYPE_TRACK_VIDEO_TEST_SOURCE);
+ g_assert (GES_IS_TRACK_VIDEO_TEST_SOURCE (trobj));
+
ptrn = (ges_track_video_test_source_get_pattern ((GESTrackVideoTestSource *)
trobj));
assert_equals_int (ptrn, GES_VIDEO_TEST_PATTERN_WHITE);
assert_equals_uint64 (GES_TIMELINE_OBJECT_START (object), 0);
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 5);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
+
fail_unless (ges_track_add_object (track, trackobject));
fail_unless (trackobject != NULL);
gnlsrc = ges_track_object_get_gnlobject (trackobject);
assert_equals_uint64 (GES_TIMELINE_OBJECT_START (object1), 15);
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object1), 5);
- trackobject1 = ges_timeline_object_create_track_object (object1, track);
+ trackobject1 = ges_timeline_object_create_track_object (object1, track->type);
ges_timeline_object_add_track_object (object1, trackobject1);
fail_unless (ges_track_add_object (track, trackobject1));
fail_unless (trackobject1 != NULL);
object2 = GES_TIMELINE_OBJECT (ges_timeline_test_source_new ());
fail_unless (object2 != NULL);
g_object_set (object2, "start", (guint64) 35, "duration", (guint64) 5, NULL);
- trackobject2 = ges_timeline_object_create_track_object (object2, track);
+ trackobject2 = ges_timeline_object_create_track_object (object2, track->type);
ges_timeline_object_add_track_object (object2, trackobject2);
fail_unless (ges_track_add_object (track, trackobject2));
fail_unless (trackobject2 != NULL);
/* GStreamer Editing Services
* Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
+ * 2012 Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
GST_END_TEST;
+typedef struct
+{
+ GESCustomTimelineSource **o1, **o2, **o3;
+ GESTrack **tr1, **tr2;
+} SelectTracksData;
+
+static GPtrArray *
+select_tracks_cb (GESTimeline * timeline, GESTimelineObject * tobj,
+ GESTrackObject * trobj, SelectTracksData * st_data)
+{
+ GESTrack *track;
+
+ GPtrArray *ret = g_ptr_array_new ();
+ track = (tobj == (GESTimelineObject *) * st_data->o2) ? *st_data->tr2 :
+ *st_data->tr1;
+
+ gst_object_ref (track);
+
+ g_ptr_array_add (ret, track);
+
+ return ret;
+}
+
+GST_START_TEST (test_ges_timeline_multiple_tracks)
+{
+ GESTimeline *timeline;
+ GESTimelineLayer *layer, *tmp_layer;
+ GESTrack *track1, *track2;
+ GESCustomTimelineSource *s1, *s2, *s3;
+ GESTrackObject *t1, *t2, *t3;
+ GList *trackobjects, *tmp, *layers;
+ SelectTracksData st_data = { &s1, &s2, &s3, &track1, &track2 };
+
+ ges_init ();
+
+ /* Timeline and 1 Layer */
+ GST_DEBUG ("Create a timeline");
+ timeline = ges_timeline_new ();
+ fail_unless (timeline != NULL);
+
+ g_signal_connect (timeline, "select-tracks-for-object",
+ G_CALLBACK (select_tracks_cb), &st_data);
+
+ GST_DEBUG ("Create a layer");
+ layer = ges_timeline_layer_new ();
+ fail_unless (layer != NULL);
+ /* Give the Timeline a Track */
+ GST_DEBUG ("Create Track 1");
+ track1 = ges_track_new (GES_TRACK_TYPE_CUSTOM, gst_caps_ref (GST_CAPS_ANY));
+ fail_unless (track1 != NULL);
+ GST_DEBUG ("Create Track 2");
+ track2 = ges_track_new (GES_TRACK_TYPE_CUSTOM, gst_caps_ref (GST_CAPS_ANY));
+ fail_unless (track2 != NULL);
+
+ GST_DEBUG ("Add the track 1 to the timeline");
+ fail_unless (ges_timeline_add_track (timeline, track1));
+ ASSERT_OBJECT_REFCOUNT (track1, "track", 1);
+ fail_unless (ges_track_get_timeline (track1) == timeline);
+ fail_unless ((gpointer) GST_ELEMENT_PARENT (track1) == (gpointer) timeline);
+
+ GST_DEBUG ("Add the track 2 to the timeline");
+ fail_unless (ges_timeline_add_track (timeline, track2));
+ ASSERT_OBJECT_REFCOUNT (track2, "track", 1);
+ fail_unless (ges_track_get_timeline (track2) == timeline);
+ fail_unless ((gpointer) GST_ELEMENT_PARENT (track2) == (gpointer) timeline);
+
+ /* Create a source and add it to the Layer */
+ GST_DEBUG ("Creating a source");
+ s1 = ges_custom_timeline_source_new (my_fill_track_func, NULL);
+ fail_unless (s1 != NULL);
+ fail_unless (ges_timeline_layer_add_object (layer, GES_TIMELINE_OBJECT (s1)));
+ tmp_layer = ges_timeline_object_get_layer (GES_TIMELINE_OBJECT (s1));
+ fail_unless (tmp_layer == layer);
+ g_object_unref (tmp_layer);
+
+ GST_DEBUG ("Creating a source");
+ s2 = ges_custom_timeline_source_new (my_fill_track_func, NULL);
+ fail_unless (s2 != NULL);
+ fail_unless (ges_timeline_layer_add_object (layer, GES_TIMELINE_OBJECT (s2)));
+ tmp_layer = ges_timeline_object_get_layer (GES_TIMELINE_OBJECT (s2));
+ fail_unless (tmp_layer == layer);
+ g_object_unref (tmp_layer);
+
+ GST_DEBUG ("Creating a source");
+ s3 = ges_custom_timeline_source_new (my_fill_track_func, NULL);
+ fail_unless (s3 != NULL);
+ fail_unless (ges_timeline_layer_add_object (layer, GES_TIMELINE_OBJECT (s3)));
+ tmp_layer = ges_timeline_object_get_layer (GES_TIMELINE_OBJECT (s3));
+ fail_unless (tmp_layer == layer);
+ g_object_unref (tmp_layer);
+
+ GST_DEBUG ("Add the layer to the timeline");
+ fail_unless (ges_timeline_add_layer (timeline, layer));
+ /* The timeline steals our reference to the layer */
+ ASSERT_OBJECT_REFCOUNT (layer, "layer", 1);
+ fail_unless (layer->timeline == timeline);
+
+ layers = ges_timeline_get_layers (timeline);
+ fail_unless (g_list_find (layers, layer) != NULL);
+ g_list_foreach (layers, (GFunc) g_object_unref, NULL);
+ g_list_free (layers);
+
+ /* Make sure the associated TrackObjects are in the Track */
+ trackobjects =
+ ges_timeline_object_get_track_objects (GES_TIMELINE_OBJECT (s1));
+ fail_unless (trackobjects != NULL);
+ t1 = GES_TRACK_OBJECT ((trackobjects)->data);
+ for (tmp = trackobjects; tmp; tmp = tmp->next) {
+ /* 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", 4);
+ fail_unless (ges_track_object_get_track (tmp->data) == track1);
+ g_object_unref (GES_TRACK_OBJECT (tmp->data));
+ }
+ g_object_ref (t1);
+ g_list_free (trackobjects);
+ /* 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", 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 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", 4);
+ fail_unless (ges_track_object_get_track (tmp->data) == track2);
+ g_object_unref (GES_TRACK_OBJECT (tmp->data));
+ }
+ g_object_ref (t2);
+ g_list_free (trackobjects);
+ /* 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", 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 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", 4);
+ fail_unless (ges_track_object_get_track (tmp->data) == track1);
+ g_object_unref (GES_TRACK_OBJECT (tmp->data));
+ }
+ g_object_ref (t3);
+ g_list_free (trackobjects);
+ /* 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", 4);
+
+ g_object_unref (t1);
+ g_object_unref (t2);
+ g_object_unref (t3);
+
+ g_object_unref (timeline);
+}
+
+GST_END_TEST;
+
static Suite *
ges_suite (void)
{
tcase_add_test (tc_chain, test_ges_timeline_add_layer);
tcase_add_test (tc_chain, test_ges_timeline_add_layer_first);
tcase_add_test (tc_chain, test_ges_timeline_remove_track);
+ tcase_add_test (tc_chain, test_ges_timeline_multiple_tracks);
return s;
}
GES_TRACK_OBJECT (tck_effect)));
g_object_get (tl_effect, "height", &tl_object_height, NULL);
- fail_unless (tl_object_height == 3);
+ assert_equals_int (tl_object_height, 3);
tck_effect1 = ges_track_parse_launch_effect_new ("identity");
fail_unless (ges_timeline_object_add_track_object (GES_TIMELINE_OBJECT
GES_TRACK_OBJECT (tck_effect1)));
g_object_get (tl_effect, "height", &tl_object_height, NULL);
- fail_unless (tl_object_height == 4);
+ assert_equals_int (tl_object_height, 4);
effects =
ges_timeline_object_get_top_effects (GES_TIMELINE_OBJECT (tl_effect));
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
g_object_set (G_OBJECT (tfs), "is-image", TRUE, NULL);
/* the returned track object should be an image source */
- trobj = ges_timeline_object_create_track_object (tlobj, v);
+ trobj = ges_timeline_object_create_track_object (tlobj, v->type);
ges_timeline_object_add_track_object (tlobj, trobj);
fail_unless (GES_IS_TRACK_IMAGE_SOURCE (trobj));
ges_timeline_object_release_track_object (tlobj, trobj);
/* the timeline object should not create any TrackObject in the audio track */
- trobj = ges_timeline_object_create_track_object (tlobj, a);
+ trobj = ges_timeline_object_create_track_object (tlobj, a->type);
fail_unless (trobj == NULL);
g_object_unref (a);
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
g_object_set (obj2, "start", (guint64) 50, "duration", (guint64) 60,
"in-point", (guint64) 0, NULL);
- tckobj = ges_timeline_object_create_track_object (obj, track);
+ tckobj = ges_timeline_object_create_track_object (obj, track->type);
fail_unless (tckobj != NULL);
fail_unless (ges_timeline_object_add_track_object (obj, tckobj));
fail_unless (ges_track_add_object (track, tckobj));
assert_equals_uint64 (ges_track_object_get_duration (tckobj), 10);
- tckobj1 = ges_timeline_object_create_track_object (obj1, track);
+ tckobj1 = ges_timeline_object_create_track_object (obj1, track->type);
fail_unless (tckobj1 != NULL);
fail_unless (ges_timeline_object_add_track_object (obj1, tckobj1));
fail_unless (ges_track_add_object (track, tckobj1));
assert_equals_uint64 (ges_track_object_get_duration (tckobj1), 10);
- tckobj2 = ges_timeline_object_create_track_object (obj2, track);
+ tckobj2 = ges_timeline_object_create_track_object (obj2, track->type);
fail_unless (ges_timeline_object_add_track_object (obj2, tckobj2));
fail_unless (tckobj2 != NULL);
fail_unless (ges_track_add_object (track, tckobj2));
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 50);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
/* Make sure track object is created and vtype is set */
trackobject =
ges_timeline_object_create_track_object (GES_TIMELINE_OBJECT (tr2),
- track);
+ track->type);
ges_timeline_object_add_track_object (GES_TIMELINE_OBJECT (tr2), trackobject);
fail_unless (trackobject != NULL);
assert_equals_uint64 (GES_TIMELINE_OBJECT_DURATION (object), 51);
assert_equals_uint64 (GES_TIMELINE_OBJECT_INPOINT (object), 12);
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));
g_object_set (object, "vtype", 1, NULL);
GST_DEBUG ("creating track object");
- trackobject = ges_timeline_object_create_track_object (object, track);
+ trackobject = ges_timeline_object_create_track_object (object, track->type);
ges_timeline_object_add_track_object (object, trackobject);
fail_unless (trackobject != NULL);
fail_unless (ges_track_object_set_track (trackobject, track));