ges/: Fix copyright in headers
[platform/upstream/gstreamer.git] / ges / ges-timeline-layer.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3  *               2009 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:ges-timeline-layer
23  * @short_description: Non-overlaping sequence of #GESTimelineObject
24  *
25  * Responsible for the ordering of the various contained TimelineObject(s)
26  */
27
28 #include "ges-internal.h"
29 #include "gesmarshal.h"
30 #include "ges-timeline-layer.h"
31 #include "ges.h"
32
33 G_DEFINE_TYPE (GESTimelineLayer, ges_timeline_layer, G_TYPE_OBJECT);
34
35 enum
36 {
37   OBJECT_ADDED,
38   OBJECT_REMOVED,
39   LAST_SIGNAL
40 };
41
42 static guint ges_timeline_layer_signals[LAST_SIGNAL] = { 0 };
43
44 static void
45 ges_timeline_layer_get_property (GObject * object, guint property_id,
46     GValue * value, GParamSpec * pspec)
47 {
48   switch (property_id) {
49     default:
50       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
51   }
52 }
53
54 static void
55 ges_timeline_layer_set_property (GObject * object, guint property_id,
56     const GValue * value, GParamSpec * pspec)
57 {
58   switch (property_id) {
59     default:
60       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
61   }
62 }
63
64 static void
65 ges_timeline_layer_dispose (GObject * object)
66 {
67   GESTimelineLayer *layer = GES_TIMELINE_LAYER (object);
68
69   if (layer->objects_start) {
70     g_slist_foreach (layer->objects_start, (GFunc) g_object_unref, NULL);
71     g_slist_free (layer->objects_start);
72     layer->objects_start = NULL;
73   }
74   G_OBJECT_CLASS (ges_timeline_layer_parent_class)->dispose (object);
75 }
76
77 static void
78 ges_timeline_layer_finalize (GObject * object)
79 {
80   G_OBJECT_CLASS (ges_timeline_layer_parent_class)->finalize (object);
81 }
82
83 static void
84 ges_timeline_layer_class_init (GESTimelineLayerClass * klass)
85 {
86   GObjectClass *object_class = G_OBJECT_CLASS (klass);
87
88   object_class->get_property = ges_timeline_layer_get_property;
89   object_class->set_property = ges_timeline_layer_set_property;
90   object_class->dispose = ges_timeline_layer_dispose;
91   object_class->finalize = ges_timeline_layer_finalize;
92
93   /**
94    * GESTimelineLayer::object-added
95    * @layer: the #GESTimelineLayer
96    * @object: the #GESTimelineObject that was added.
97    *
98    * Will be emitted after the object was added to the layer.
99    */
100   ges_timeline_layer_signals[OBJECT_ADDED] =
101       g_signal_new ("object-added", G_TYPE_FROM_CLASS (klass),
102       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineLayerClass, object_added),
103       NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
104       GES_TYPE_TIMELINE_OBJECT);
105
106   /**
107    * GESTimelineLayer::object-removed
108    * @layer: the #GESTimelineLayer
109    * @object: the #GESTimelineObject that was removed
110    *
111    * Will be emitted after the object was removed from the layer.
112    */
113   ges_timeline_layer_signals[OBJECT_REMOVED] =
114       g_signal_new ("object-removed", G_TYPE_FROM_CLASS (klass),
115       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineLayerClass,
116           object_removed), NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
117       GES_TYPE_TIMELINE_OBJECT);
118
119 }
120
121 static void
122 ges_timeline_layer_init (GESTimelineLayer * self)
123 {
124 }
125
126 /**
127  * ges_timeline_layer_new:
128  *
129  * Creates a new #GESTimelineLayer.
130  *
131  * Returns: A new #GESTimelineLayer
132  */
133 GESTimelineLayer *
134 ges_timeline_layer_new (void)
135 {
136   return g_object_new (GES_TYPE_TIMELINE_LAYER, NULL);
137 }
138
139 void
140 ges_timeline_layer_set_timeline (GESTimelineLayer * layer,
141     GESTimeline * timeline)
142 {
143   GST_DEBUG ("layer:%p, timeline:%p", layer, timeline);
144
145   layer->timeline = timeline;
146 }
147
148 static gint
149 objects_start_compare (GESTimelineObject * a, GESTimelineObject * b)
150 {
151   if (a->start == b->start) {
152     if (a->priority < b->priority)
153       return -1;
154     if (a->priority > b->priority)
155       return 1;
156     return 0;
157   }
158   if (a->start < b->start)
159     return -1;
160   if (a->start > b->start)
161     return 1;
162   return 0;
163 }
164
165 /**
166  * ges_timeline_layer_add_object:
167  * @layer: a #GESTimelineLayer
168  * @object: the #GESTimelineObject to add.
169  *
170  * Adds the object to the layer. The layer will steal a reference to the
171  * provided object.
172  *
173  * Returns: TRUE if the object was properly added to the layer, or FALSE
174  * if the @layer refused to add the object.
175  */
176
177 gboolean
178 ges_timeline_layer_add_object (GESTimelineLayer * layer,
179     GESTimelineObject * object)
180 {
181   GST_DEBUG ("layer:%p, object:%p", layer, object);
182
183   if (G_UNLIKELY (object->layer)) {
184     GST_WARNING ("TimelineObject %p already belongs to another layer");
185     return FALSE;
186   }
187
188   /* Take a reference to the object and store it stored by start/priority */
189   layer->objects_start =
190       g_slist_insert_sorted (layer->objects_start, object,
191       (GCompareFunc) objects_start_compare);
192
193   /* Inform the object it's now in this layer */
194   ges_timeline_object_set_layer (object, layer);
195
196   /* emit 'object-added' */
197   g_signal_emit (layer, ges_timeline_layer_signals[OBJECT_ADDED], 0, object);
198
199   return TRUE;
200 }
201
202 /**
203  * ges_timeline_layer_remove_object:
204  * @layer: a #GESTimelineLayer
205  * @object: the #GESTimelineObject to remove
206  *
207  * Removes the given @object from the @layer. The reference stolen by the @layer
208  * when the object was added will be removed. If you wish to use the object after
209  * this function, make sure you take an extra reference to the object before
210  * calling this function.
211  *
212  * Returns: TRUE if the object was properly remove, else FALSE.
213  */
214 gboolean
215 ges_timeline_layer_remove_object (GESTimelineLayer * layer,
216     GESTimelineObject * object)
217 {
218   GST_DEBUG ("layer:%p, object:%p", layer, object);
219
220   if (G_UNLIKELY (object->layer != layer)) {
221     GST_WARNING ("TimelineObject doesn't belong to this layer");
222     return FALSE;
223   }
224
225   /* emit 'object-removed' */
226   g_signal_emit (layer, ges_timeline_layer_signals[OBJECT_REMOVED], 0, object);
227
228   /* inform the object it's no longer in a layer */
229   ges_timeline_object_set_layer (object, NULL);
230
231   /* Remove it from our list of controlled objects */
232   layer->objects_start = g_slist_remove (layer->objects_start, object);
233
234   /* Remove our reference to the object */
235   g_object_unref (object);
236
237   return TRUE;
238 }