More documentation. Coverage now at 25%
[platform/upstream/gstreamer.git] / ges / ges-timeline-layer.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /**
21  * SECTION:ges-timeline-layer
22  * @short_description: Non-overlaping sequence of #GESTimelineObject
23  *
24  * Responsible for the ordering of the various contained TimelineObject(s)
25  */
26
27 #include "ges-internal.h"
28 #include "gesmarshal.h"
29 #include "ges-timeline-layer.h"
30 #include "ges.h"
31
32 G_DEFINE_TYPE (GESTimelineLayer, ges_timeline_layer, G_TYPE_OBJECT);
33
34 enum
35 {
36   OBJECT_ADDED,
37   OBJECT_REMOVED,
38   LAST_SIGNAL
39 };
40
41 static guint ges_timeline_layer_signals[LAST_SIGNAL] = { 0 };
42
43 static void
44 ges_timeline_layer_get_property (GObject * object, guint property_id,
45     GValue * value, GParamSpec * pspec)
46 {
47   switch (property_id) {
48     default:
49       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
50   }
51 }
52
53 static void
54 ges_timeline_layer_set_property (GObject * object, guint property_id,
55     const GValue * value, GParamSpec * pspec)
56 {
57   switch (property_id) {
58     default:
59       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
60   }
61 }
62
63 static void
64 ges_timeline_layer_dispose (GObject * object)
65 {
66   G_OBJECT_CLASS (ges_timeline_layer_parent_class)->dispose (object);
67 }
68
69 static void
70 ges_timeline_layer_finalize (GObject * object)
71 {
72   G_OBJECT_CLASS (ges_timeline_layer_parent_class)->finalize (object);
73 }
74
75 static void
76 ges_timeline_layer_class_init (GESTimelineLayerClass * klass)
77 {
78   GObjectClass *object_class = G_OBJECT_CLASS (klass);
79
80   object_class->get_property = ges_timeline_layer_get_property;
81   object_class->set_property = ges_timeline_layer_set_property;
82   object_class->dispose = ges_timeline_layer_dispose;
83   object_class->finalize = ges_timeline_layer_finalize;
84
85   ges_timeline_layer_signals[OBJECT_ADDED] =
86       g_signal_new ("object-added", G_TYPE_FROM_CLASS (klass),
87       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineLayerClass, object_added),
88       NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
89       GES_TYPE_TIMELINE_OBJECT);
90
91   ges_timeline_layer_signals[OBJECT_REMOVED] =
92       g_signal_new ("object-removed", G_TYPE_FROM_CLASS (klass),
93       G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GESTimelineLayerClass,
94           object_removed), NULL, NULL, ges_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
95       GES_TYPE_TIMELINE_OBJECT);
96
97 }
98
99 static void
100 ges_timeline_layer_init (GESTimelineLayer * self)
101 {
102 }
103
104 GESTimelineLayer *
105 ges_timeline_layer_new (void)
106 {
107   return g_object_new (GES_TYPE_TIMELINE_LAYER, NULL);
108 }
109
110 void
111 ges_timeline_layer_set_timeline (GESTimelineLayer * layer,
112     GESTimeline * timeline)
113 {
114   GST_DEBUG ("layer:%p, timeline:%p", layer, timeline);
115
116   layer->timeline = timeline;
117 }
118
119 static gint
120 objects_start_compare (GESTimelineObject * a, GESTimelineObject * b)
121 {
122   if (a->start == b->start) {
123     if (a->priority < b->priority)
124       return -1;
125     if (a->priority > b->priority)
126       return 1;
127     return 0;
128   }
129   if (a->start < b->start)
130     return -1;
131   if (a->start > b->start)
132     return 1;
133   return 0;
134 }
135
136 gboolean
137 ges_timeline_layer_add_object (GESTimelineLayer * layer,
138     GESTimelineObject * object)
139 {
140   GST_DEBUG ("layer:%p, object:%p", layer, object);
141
142   if (G_UNLIKELY (object->layer)) {
143     GST_WARNING ("TimelineObject %p already belongs to another layer");
144     return FALSE;
145   }
146
147   /* Take a reference to the object and store it stored by start/priority */
148   layer->objects_start =
149       g_slist_insert_sorted (layer->objects_start, g_object_ref (object),
150       (GCompareFunc) objects_start_compare);
151
152   /* Inform the object it's now in this layer */
153   ges_timeline_object_set_layer (object, layer);
154
155   /* emit 'object-added' */
156   g_signal_emit (layer, ges_timeline_layer_signals[OBJECT_ADDED], 0, object);
157
158   return TRUE;
159 }
160
161 gboolean
162 ges_timeline_layer_remove_object (GESTimelineLayer * layer,
163     GESTimelineObject * object)
164 {
165   GST_DEBUG ("layer:%p, object:%p", layer, object);
166
167   if (G_UNLIKELY (object->layer != layer)) {
168     GST_WARNING ("TimelineObject doesn't belong to this layer");
169     return FALSE;
170   }
171
172   /* emit 'object-removed' */
173   g_signal_emit (layer, ges_timeline_layer_signals[OBJECT_REMOVED], 0, object);
174
175   /* inform the object it's no longer in a layer */
176   ges_timeline_object_set_layer (object, NULL);
177
178   /* Remove it from our list of controlled objects */
179   layer->objects_start = g_slist_remove (layer->objects_start, object);
180
181   /* Remove our reference to the object */
182   g_object_unref (object);
183
184   return TRUE;
185 }