diff --git a/ges/ges-timeline-layer.c b/ges/ges-timeline-layer.c index f764b0491e..291e2efb89 100644 --- a/ges/ges-timeline-layer.c +++ b/ges/ges-timeline-layer.c @@ -40,7 +40,7 @@ static void track_object_removed_cb (GESTimelineObject * object, GESTrackObject * track_object); static void track_object_added_cb (GESTimelineObject * object, - GESTrackObject * track_object); + GESTrackObject * track_object, GHashTable * signal_table); static void track_object_changed_cb (GESTrackObject * track_object, GParamSpec * arg G_GNUC_UNUSED); static void calculate_transitions (GESTrackObject * track_object); @@ -63,6 +63,9 @@ struct _GESTimelineLayerPrivate * containing timeline */ gboolean auto_transition; + + + GHashTable *signal_table; }; enum @@ -210,6 +213,9 @@ ges_timeline_layer_init (GESTimelineLayer * self) self->priv->auto_transition = FALSE; self->min_gnl_priority = 0; self->max_gnl_priority = LAYER_HEIGHT; + self->priv->signal_table = + g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, + g_free); } /** @@ -312,7 +318,7 @@ ges_timeline_layer_add_object (GESTimelineLayer * layer, if (layer->priv->auto_transition) { if (GES_IS_TIMELINE_SOURCE (object)) { g_signal_connect (G_OBJECT (object), "track-object-added", - G_CALLBACK (track_object_added_cb), NULL); + G_CALLBACK (track_object_added_cb), layer->priv->signal_table); g_signal_connect (G_OBJECT (object), "track-object-removed", G_CALLBACK (track_object_removed_cb), NULL); } @@ -361,9 +367,60 @@ track_object_duration_cb (GESTrackObject * track_object, } static void -track_object_added_cb (GESTimelineObject * object, - GESTrackObject * track_object) +track_object_deleted_cb (GESTrack * track, GESTrackObject * track_object) { + GList *track_objects, *tmp, *cur; + GESTimelineLayer *layer; + + track_objects = ges_track_get_objects (track); + cur = g_list_find (track_objects, track_object); + for (tmp = cur->next; tmp; tmp = tmp->next) { + if (GES_IS_TRACK_SOURCE (tmp->data)) { + break; + } + if (GES_IS_TRACK_AUDIO_TRANSITION (tmp->data) + || GES_IS_TRACK_VIDEO_TRANSITION (tmp->data)) { + layer = + ges_timeline_object_get_layer (ges_track_object_get_timeline_object + (tmp->data)); + if (ges_timeline_layer_get_auto_transition (layer)) { + ges_track_enable_update (track, FALSE); + ges_timeline_layer_remove_object (layer, + ges_track_object_get_timeline_object (tmp->data)); + ges_track_enable_update (track, TRUE); + } + g_object_unref (layer); + } + } + + for (tmp = cur->prev; tmp; tmp = tmp->prev) { + if (GES_IS_TRACK_SOURCE (tmp->data)) { + break; + } + if (GES_IS_TRACK_AUDIO_TRANSITION (tmp->data) + || GES_IS_TRACK_VIDEO_TRANSITION (tmp->data)) { + layer = + ges_timeline_object_get_layer (ges_track_object_get_timeline_object + (tmp->data)); + if (ges_timeline_layer_get_auto_transition (layer)) { + ges_track_enable_update (track, FALSE); + ges_timeline_layer_remove_object (layer, + ges_track_object_get_timeline_object (tmp->data)); + ges_track_enable_update (track, TRUE); + } + g_object_unref (layer); + } + } + g_object_unref (track_object); +} + +static void +track_object_added_cb (GESTimelineObject * object, + GESTrackObject * track_object, GHashTable * signal_table) +{ + GESTrack *track; + gint ptr; + if (GES_IS_TRACK_SOURCE (track_object)) { g_signal_connect (G_OBJECT (track_object), "notify::start", G_CALLBACK (track_object_changed_cb), NULL); @@ -371,6 +428,12 @@ track_object_added_cb (GESTimelineObject * object, G_CALLBACK (track_object_duration_cb), NULL); calculate_transitions (track_object); } + track = ges_track_object_get_track (track_object); + if (!g_hash_table_lookup (signal_table, track)) { + ptr = g_signal_connect (track, "track-object-removed", + (GCallback) track_object_deleted_cb, NULL); + g_hash_table_insert (signal_table, track, &ptr); + } return; } @@ -378,6 +441,7 @@ static void track_object_removed_cb (GESTimelineObject * object, GESTrackObject * track_object) { + return; if (GES_IS_TRACK_SOURCE (track_object)) { g_signal_handlers_disconnect_by_func (track_object, track_object_changed_cb, object); @@ -648,6 +712,41 @@ clean: g_object_unref (layer); } +static void +look_for_transition (GESTrackObject * track_object, GESTimelineLayer * layer) +{ + GESTrack *track; + GList *track_objects, *tmp, *cur; + + track = ges_track_object_get_track (track_object); + + track_objects = ges_track_get_objects (track); + + cur = g_list_find (track_objects, track_object); + + for (tmp = cur->next; tmp; tmp = tmp->next) { + if (GES_IS_TRACK_SOURCE (tmp->data)) { + break; + } + if (GES_IS_TRACK_AUDIO_TRANSITION (tmp->data) + || GES_IS_TRACK_VIDEO_TRANSITION (tmp->data)) { + ges_timeline_layer_remove_object (layer, + ges_track_object_get_timeline_object (tmp->data)); + } + } + + for (tmp = cur->prev; tmp; tmp = tmp->prev) { + if (GES_IS_TRACK_SOURCE (tmp->data)) { + break; + } + if (GES_IS_TRACK_AUDIO_TRANSITION (tmp->data) + || GES_IS_TRACK_VIDEO_TRANSITION (tmp->data)) { + ges_timeline_layer_remove_object (layer, + ges_track_object_get_timeline_object (tmp->data)); + } + } + g_list_free_full (track_objects, g_object_unref); +} /** * ges_timeline_layer_remove_object: @@ -667,6 +766,7 @@ ges_timeline_layer_remove_object (GESTimelineLayer * layer, GESTimelineObject * object) { GESTimelineLayer *tl_obj_layer; + GList *trackobjects, *tmp; g_return_val_if_fail (GES_IS_TIMELINE_LAYER (layer), FALSE); g_return_val_if_fail (GES_IS_TIMELINE_OBJECT (object), FALSE); @@ -682,6 +782,16 @@ ges_timeline_layer_remove_object (GESTimelineLayer * layer, } g_object_unref (tl_obj_layer); + if (layer->priv->auto_transition) { + trackobjects = ges_timeline_object_get_track_objects (object); + + for (tmp = trackobjects; tmp; tmp = tmp->next) { + look_for_transition (tmp->data, layer); + } + + g_list_free_full (trackobjects, g_object_unref); + } + /* emit 'object-removed' */ g_signal_emit (layer, ges_timeline_layer_signals[OBJECT_REMOVED], 0, object); diff --git a/ges/ges-timeline.c b/ges/ges-timeline.c index 4579f4a700..35a79ec9d1 100644 --- a/ges/ges-timeline.c +++ b/ges/ges-timeline.c @@ -114,6 +114,11 @@ static void discoverer_discovered_cb (GstDiscoverer * discoverer, GstDiscovererInfo * info, GError * err, GESTimeline * timeline); +void look_for_transition (GESTrackObject * track_object, + GESTimelineLayer * layer); +void track_object_removed_cb (GESTrack * track, GESTrackObject * track_object, + GESTimeline * timeline); + static void ges_timeline_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) @@ -696,7 +701,7 @@ static void layer_object_removed_cb (GESTimelineLayer * layer, GESTimelineObject * object, GESTimeline * timeline) { - GList *tmp, *trackobjects; + GList *trackobjects, *tmp; if (ges_timeline_object_is_moving_from_layer (object)) { GST_DEBUG ("TimelineObject %p is moving from a layer to another, not doing" @@ -722,10 +727,10 @@ layer_object_removed_cb (GESTimelineLayer * layer, GESTimelineObject * object, ges_timeline_object_release_track_object (object, trobj); } - /* removing the reference added by _get_track_objects() */ g_object_unref (trobj); } + g_list_free (trackobjects); /* if the object is a timeline file source that has not yet been discovered,