1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
4 * Copyright (C) 2013 Thibault Saunier <thibault.saunier@collabora.com>
6 * gst-editing-services is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * gst-editing-services is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.";
20 /* This class warps a GESBaseTransitionClip, letting any implementation
21 * of a GESBaseTransitionClip to be used.
23 * NOTE: This is for internal use exclusively
29 #include "ges-auto-transition.h"
30 #include "ges-internal.h"
37 static guint auto_transition_signals[LAST_SIGNAL] = { 0 };
39 G_DEFINE_TYPE (GESAutoTransition, ges_auto_transition, G_TYPE_OBJECT);
42 neighbour_changed_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
43 GESAutoTransition * self)
46 GESTimelineElement *parent =
47 ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT (clip));
50 GESTimelineElement *prev_topparent =
51 ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT
53 GESTimelineElement *next_topparent =
54 ges_timeline_element_get_toplevel_parent (GES_TIMELINE_ELEMENT
55 (self->previous_source));
57 if (parent == prev_topparent && parent == next_topparent) {
58 GST_DEBUG_OBJECT (self,
59 "Moving all inside the same group, nothing to do");
64 if (_ges_track_element_get_layer_priority (self->next_source) !=
65 _ges_track_element_get_layer_priority (self->previous_source)) {
66 GST_DEBUG_OBJECT (self, "Destroy changed layer");
67 g_signal_emit (self, auto_transition_signals[DESTROY_ME], 0);
72 (_START (self->previous_source) +
73 _DURATION (self->previous_source)) - _START (self->next_source);
75 if (new_duration <= 0 || new_duration >= _DURATION (self->previous_source)
76 || new_duration >= _DURATION (self->next_source)) {
78 GST_DEBUG_OBJECT (self, "Destroy %" G_GINT64_FORMAT " not a valid duration",
80 g_signal_emit (self, auto_transition_signals[DESTROY_ME], 0);
84 self->positioning = TRUE;
85 _set_start0 (GES_TIMELINE_ELEMENT (self->transition_clip),
86 _START (self->next_source));
87 _set_duration0 (GES_TIMELINE_ELEMENT (self->transition_clip), new_duration);
88 self->positioning = FALSE;
92 _track_changed_cb (GESTrackElement * track_element,
93 GParamSpec * arg G_GNUC_UNUSED, GESAutoTransition * self)
95 if (ges_track_element_get_track (track_element) == NULL) {
96 GST_DEBUG_OBJECT (self, "Neighboor %" GST_PTR_FORMAT
97 " removed from track ... auto destructing", track_element);
99 g_signal_emit (self, auto_transition_signals[DESTROY_ME], 0);
105 ges_auto_transition_init (GESAutoTransition * ges_auto_transition)
110 ges_auto_transition_finalize (GObject * object)
112 GESAutoTransition *self = GES_AUTO_TRANSITION (object);
114 g_signal_handlers_disconnect_by_func (self->previous_source,
115 neighbour_changed_cb, self);
116 g_signal_handlers_disconnect_by_func (self->next_source, neighbour_changed_cb,
118 g_signal_handlers_disconnect_by_func (self->next_source, _track_changed_cb,
120 g_signal_handlers_disconnect_by_func (self->previous_source,
121 _track_changed_cb, self);
125 G_OBJECT_CLASS (ges_auto_transition_parent_class)->finalize (object);
129 ges_auto_transition_class_init (GESAutoTransitionClass * klass)
131 GObjectClass *object_class = G_OBJECT_CLASS (klass);
133 auto_transition_signals[DESTROY_ME] =
134 g_signal_new ("destroy-me", G_TYPE_FROM_CLASS (klass),
135 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, 0, NULL, NULL, NULL,
137 object_class->finalize = ges_auto_transition_finalize;
142 ges_auto_transition_new (GESTrackElement * transition,
143 GESTrackElement * previous_source, GESTrackElement * next_source)
145 GESAutoTransition *self = g_object_new (GES_TYPE_AUTO_TRANSITION, NULL);
147 self->previous_source = previous_source;
148 self->next_source = next_source;
149 self->transition = transition;
151 self->previous_clip =
152 GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (previous_source));
153 self->next_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (next_source));
154 self->transition_clip = GES_CLIP (GES_TIMELINE_ELEMENT_PARENT (transition));
156 g_signal_connect (previous_source, "notify::start",
157 G_CALLBACK (neighbour_changed_cb), self);
158 g_signal_connect_after (previous_source, "notify::priority",
159 G_CALLBACK (neighbour_changed_cb), self);
160 g_signal_connect (next_source, "notify::start",
161 G_CALLBACK (neighbour_changed_cb), self);
162 g_signal_connect (next_source, "notify::priority",
163 G_CALLBACK (neighbour_changed_cb), self);
164 g_signal_connect (previous_source, "notify::duration",
165 G_CALLBACK (neighbour_changed_cb), self);
166 g_signal_connect (next_source, "notify::duration",
167 G_CALLBACK (neighbour_changed_cb), self);
169 g_signal_connect (next_source, "notify::track",
170 G_CALLBACK (_track_changed_cb), self);
171 g_signal_connect (previous_source, "notify::track",
172 G_CALLBACK (_track_changed_cb), self);
174 GST_DEBUG_OBJECT (self, "Created transition %" GST_PTR_FORMAT
175 " between %" GST_PTR_FORMAT "[%" GST_TIME_FORMAT
176 " - %" GST_TIME_FORMAT "] and: %" GST_PTR_FORMAT
177 "[%" GST_TIME_FORMAT " - %" GST_TIME_FORMAT "]"
178 " in layer nb %i, start: %" GST_TIME_FORMAT " duration: %"
179 GST_TIME_FORMAT, transition, previous_source,
180 GST_TIME_ARGS (_START (previous_source)),
181 GST_TIME_ARGS (_END (previous_source)),
183 GST_TIME_ARGS (_START (next_source)),
184 GST_TIME_ARGS (_END (next_source)),
185 ges_layer_get_priority (ges_clip_get_layer
186 (self->previous_clip)),
187 GST_TIME_ARGS (_START (transition)),
188 GST_TIME_ARGS (_DURATION (transition)));
190 self->key = g_strdup_printf ("%p%p", self->previous_source,