1 /* GStreamer Editing Services
2 * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gesmarshal.h"
21 #include "ges-timeline.h"
22 #include "ges-track.h"
23 #include "ges-timeline-layer.h"
29 * Top-level container for pipelines
31 * Contains a list of TimelineLayer which users should use to arrange the
32 * various timeline objects.
36 G_DEFINE_TYPE (GESTimeline, ges_timeline, GST_TYPE_BIN);
38 #define GET_PRIVATE(o) \
39 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GES_TYPE_TIMELINE, GESTimelinePrivate));
41 typedef struct _GESTimelinePrivate GESTimelinePrivate;
43 struct _GESTimelinePrivate
57 static guint ges_timeline_signals[LAST_SIGNAL] = { 0 };
60 ges_timeline_get_property (GObject * object, guint property_id,
61 GValue * value, GParamSpec * pspec)
63 switch (property_id) {
65 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
70 ges_timeline_set_property (GObject * object, guint property_id,
71 const GValue * value, GParamSpec * pspec)
73 switch (property_id) {
75 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
80 ges_timeline_dispose (GObject * object)
82 G_OBJECT_CLASS (ges_timeline_parent_class)->dispose (object);
86 ges_timeline_finalize (GObject * object)
88 G_OBJECT_CLASS (ges_timeline_parent_class)->finalize (object);
92 ges_timeline_class_init (GESTimelineClass * klass)
94 GObjectClass *object_class = G_OBJECT_CLASS (klass);
96 g_type_class_add_private (klass, sizeof (GESTimelinePrivate));
98 object_class->get_property = ges_timeline_get_property;
99 object_class->set_property = ges_timeline_set_property;
100 object_class->dispose = ges_timeline_dispose;
101 object_class->finalize = ges_timeline_finalize;
110 ges_timeline_signals[TRACK_ADDED] =
111 g_signal_new ("track-added", G_TYPE_FROM_CLASS (klass),
112 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineClass, track_added), NULL,
113 NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GES_TYPE_TRACK);
115 ges_timeline_signals[TRACK_REMOVED] =
116 g_signal_new ("track-removed", G_TYPE_FROM_CLASS (klass),
117 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineClass, track_removed),
118 NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GES_TYPE_TRACK);
120 ges_timeline_signals[LAYER_ADDED] =
121 g_signal_new ("layer-added", G_TYPE_FROM_CLASS (klass),
122 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineClass, layer_added), NULL,
123 NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GES_TYPE_TIMELINE_LAYER);
125 ges_timeline_signals[LAYER_REMOVED] =
126 g_signal_new ("layer-removed", G_TYPE_FROM_CLASS (klass),
127 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineClass, layer_removed),
128 NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
129 GES_TYPE_TIMELINE_LAYER);
133 ges_timeline_init (GESTimeline * self)
140 ges_timeline_new (void)
142 return g_object_new (GES_TYPE_TIMELINE, NULL);
146 ges_timeline_load_from_uri (gchar * uri)
148 /* FIXME : IMPLEMENT */
153 ges_timeline_save (GESTimeline * timeline, gchar * uri)
155 /* FIXME : IMPLEMENT */
160 layer_object_added_cb (GESTimelineLayer * layer, GESTimelineObject * object,
161 GESTimeline * timeline)
165 GST_DEBUG ("New TimelineObject %p added to layer %p", object, layer);
167 for (tmp = timeline->tracks; tmp; tmp = g_list_next (tmp)) {
168 GESTrack *track = (GESTrack *) track;
169 GESTrackObject *trobj;
171 GST_LOG ("Trying with track %p", track);
173 if (G_UNLIKELY (!(trobj =
174 ges_timeline_object_create_track_object (object, track)))) {
175 GST_WARNING ("Couldn't create TrackObject for TimelineObject");
179 GST_LOG ("Got new TrackObject %p, adding it to track", trobj);
180 ges_track_add_object (track, trobj);
188 layer_object_removed_cb (GESTimelineLayer * layer, GESTimelineObject * object,
189 GESTimeline * timeline)
191 /* FIXME : IMPLEMENT */
196 ges_timeline_add_layer (GESTimeline * timeline, GESTimelineLayer * layer)
198 GST_DEBUG ("timeline:%p, layer:%p", timeline, layer);
200 /* We can only add a layer that doesn't already belong to another timeline */
201 if (G_UNLIKELY (layer->timeline)) {
202 GST_WARNING ("Layer belongs to another timeline, can't add it");
206 /* Add to the list of layers, make sure we don't already control it */
207 if (G_UNLIKELY (g_list_find (timeline->layers, (gconstpointer) layer))) {
208 GST_WARNING ("Layer is already controlled by this timeline");
212 /* Reference is taken */
213 timeline->layers = g_list_append (timeline->layers, g_object_ref (layer));
215 /* Inform the layer that it belongs to a new timeline */
216 ges_timeline_layer_set_timeline (layer, timeline);
218 /* FIXME : GO OVER THE LIST OF EXISTING TIMELINE OBJECTS IN THAT LAYER
219 * AND ADD THEM !!! */
221 /* Connect to 'object-added'/'object-removed' signal from the new layer */
222 g_signal_connect (layer, "object-added", G_CALLBACK (layer_object_added_cb),
224 g_signal_connect (layer, "object-removed",
225 G_CALLBACK (layer_object_removed_cb), timeline);
227 GST_DEBUG ("Done adding layer, emitting 'layer-added' signal");
228 g_signal_emit (timeline, ges_timeline_signals[LAYER_ADDED], 0, layer);
234 ges_timeline_remove_layer (GESTimeline * timeline, GESTimelineLayer * layer)
236 /* FIXME : IMPLEMENT */
238 /* Unassign tracks from the given layer */
243 ges_timeline_add_track (GESTimeline * timeline, GESTrack * track)
245 GST_DEBUG ("timeline:%p, track:%p", timeline, track);
247 /* Add to the list of tracks, make sure we don't already control it */
248 if (G_UNLIKELY (g_list_find (timeline->tracks, (gconstpointer) track))) {
249 GST_WARNING ("Track is already controlled by this timeline");
253 /* Add the track to ourself (as a GstBin)
254 * Reference is taken ! */
255 if (G_UNLIKELY (!gst_bin_add (GST_BIN (timeline), GST_ELEMENT (track)))) {
256 GST_WARNING ("Couldn't add track to ourself (GST)");
260 /* Add the track to the list of tracks we track */
261 timeline->tracks = g_list_append (timeline->tracks, track);
263 /* Inform the track that it's currently being used by ourself */
264 ges_track_set_timeline (track, timeline);
266 GST_DEBUG ("Done adding track, emitting 'track-added' signal");
268 /* emit 'track-added' */
269 g_signal_emit (timeline, ges_timeline_signals[TRACK_ADDED], 0, track);
275 ges_timeline_remove_track (GESTimeline * timeline, GESTrack * track)
277 /* FIXME : IMPLEMENT */
279 /* Signal track removal to all layers/objects */