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