GESTrackObject: Document some more
[platform/upstream/gstreamer.git] / ges / ges-track-object.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-track-object
22  * @short_description: Base Class for objects contained in a #GESTrack
23  *
24  * #GESTrackObject is the Base Class for any object that can be contained in a
25  * #GESTrack.
26  *
27  * It contains the basic information as to the location of the object within
28  * its container, like the start position, the in-point, the duration and the
29  * priority.
30  */
31
32 #include "ges-internal.h"
33 #include "ges-track-object.h"
34 #include "ges-timeline-object.h"
35
36 static GQuark _start_quark;
37 static GQuark _inpoint_quark;
38 static GQuark _duration_quark;
39 static GQuark _priority_quark;
40
41 #define _do_init \
42 { \
43   _start_quark = g_quark_from_static_string ("start"); \
44   _inpoint_quark = g_quark_from_static_string ("inpoint"); \
45   _duration_quark = g_quark_from_static_string ("duration"); \
46   _priority_quark = g_quark_from_static_string ("priority"); \
47 }
48
49 G_DEFINE_TYPE_WITH_CODE (GESTrackObject, ges_track_object, G_TYPE_OBJECT,
50     _do_init);
51
52 enum
53 {
54   PROP_0,
55   PROP_START,
56   PROP_INPOINT,
57   PROP_DURATION,
58   PROP_PRIORITY,
59 };
60
61 static gboolean
62 ges_track_object_create_gnl_object_func (GESTrackObject * object);
63
64 static void
65 ges_track_object_get_property (GObject * object, guint property_id,
66     GValue * value, GParamSpec * pspec)
67 {
68   GESTrackObject *tobj = GES_TRACK_OBJECT (object);
69
70   switch (property_id) {
71     case PROP_START:
72       g_value_set_uint64 (value, tobj->start);
73       break;
74     case PROP_INPOINT:
75       g_value_set_uint64 (value, tobj->inpoint);
76       break;
77     case PROP_DURATION:
78       g_value_set_uint64 (value, tobj->duration);
79       break;
80     case PROP_PRIORITY:
81       g_value_set_uint (value, tobj->priority);
82       break;
83     default:
84       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
85   }
86 }
87
88 static void
89 ges_track_object_set_property (GObject * object, guint property_id,
90     const GValue * value, GParamSpec * pspec)
91 {
92   GESTrackObject *tobj = GES_TRACK_OBJECT (object);
93
94   switch (property_id) {
95     case PROP_START:
96       ges_track_object_set_start_internal (tobj, g_value_get_uint64 (value));
97       break;
98     case PROP_INPOINT:
99       ges_track_object_set_inpoint_internal (tobj, g_value_get_uint64 (value));
100       break;
101     case PROP_DURATION:
102       ges_track_object_set_duration_internal (tobj, g_value_get_uint64 (value));
103       break;
104     case PROP_PRIORITY:
105       ges_track_object_set_priority_internal (tobj, g_value_get_uint (value));
106       break;
107     default:
108       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
109   }
110 }
111
112 static void
113 ges_track_object_dispose (GObject * object)
114 {
115   G_OBJECT_CLASS (ges_track_object_parent_class)->dispose (object);
116 }
117
118 static void
119 ges_track_object_finalize (GObject * object)
120 {
121   G_OBJECT_CLASS (ges_track_object_parent_class)->finalize (object);
122 }
123
124 static void
125 ges_track_object_class_init (GESTrackObjectClass * klass)
126 {
127   GObjectClass *object_class = G_OBJECT_CLASS (klass);
128
129   object_class->get_property = ges_track_object_get_property;
130   object_class->set_property = ges_track_object_set_property;
131   object_class->dispose = ges_track_object_dispose;
132   object_class->finalize = ges_track_object_finalize;
133
134   /**
135    * GESTrackObject:start
136    *
137    * The position of the object in the container #GESTrack (in nanoseconds).
138    */
139   g_object_class_install_property (object_class, PROP_START,
140       g_param_spec_uint64 ("start", "Start",
141           "The position in the container", 0, G_MAXUINT64, 0,
142           G_PARAM_READWRITE));
143
144   /**
145    * GESTrackObject:in-point
146    *
147    * The in-point at which this #GESTrackObject will start outputting data
148    * from its contents (in nanoseconds).
149    *
150    * Ex : an in-point of 5 seconds means that the first outputted buffer will
151    * be the one located 5 seconds in the controlled resource.
152    */
153   g_object_class_install_property (object_class, PROP_INPOINT,
154       g_param_spec_uint64 ("in-point", "In-point", "The in-point", 0,
155           G_MAXUINT64, 0, G_PARAM_READWRITE));
156
157   /**
158    * GESTrackObject:duration
159    *
160    * The duration (in nanoseconds) which will be used in the container #GESTrack
161    * starting from 'in-point'.
162    *
163    */
164   g_object_class_install_property (object_class, PROP_DURATION,
165       g_param_spec_uint64 ("duration", "Duration", "The duration to use",
166           0, G_MAXUINT64, GST_SECOND, G_PARAM_READWRITE));
167
168   /**
169    * GESTrackObject:priority
170    *
171    * The priority of the object within the containing #GESTrack.
172    * If two objects intersect over the same region of time, the @priority
173    * property is used to decide which one takes precedence.
174    *
175    * The highest priority (that supercedes everything) is 0, and then lowering
176    * priorities go in increasing numerical value (with #G_MAXUINT64 being the
177    * lowest priority).
178    */
179   g_object_class_install_property (object_class, PROP_PRIORITY,
180       g_param_spec_uint ("priority", "Priority",
181           "The priority of the object", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
182
183   klass->create_gnl_object = ges_track_object_create_gnl_object_func;
184 }
185
186 static void
187 ges_track_object_init (GESTrackObject * self)
188 {
189 }
190
191 gboolean
192 ges_track_object_set_start_internal (GESTrackObject * object, guint64 start)
193 {
194   g_return_val_if_fail (object->gnlobject, FALSE);
195
196   GST_DEBUG ("object:%p, start:%" GST_TIME_FORMAT,
197       object, GST_TIME_ARGS (start));
198
199   if (G_UNLIKELY (start == object->start))
200     return FALSE;
201
202   g_object_set (object->gnlobject, "start", start, NULL);
203   return TRUE;
204 };
205
206 gboolean
207 ges_track_object_set_inpoint_internal (GESTrackObject * object, guint64 inpoint)
208 {
209   guint64 dur;
210
211   GST_DEBUG ("object:%p, inpoint:%" GST_TIME_FORMAT,
212       object, GST_TIME_ARGS (inpoint));
213
214   g_return_val_if_fail (object->gnlobject, FALSE);
215
216   if (G_UNLIKELY (inpoint == object->inpoint))
217     return FALSE;
218
219   /* Calculate new media-start/duration/media-duration */
220   dur = object->inpoint - inpoint + object->duration;
221
222   g_object_set (object->gnlobject, "media-start", inpoint, "duration", dur,
223       "media-duration", dur, NULL);
224   return TRUE;
225 }
226
227 gboolean
228 ges_track_object_set_duration_internal (GESTrackObject * object,
229     guint64 duration)
230 {
231   GST_DEBUG ("object:%p, duration:%" GST_TIME_FORMAT,
232       object, GST_TIME_ARGS (duration));
233
234   g_return_val_if_fail (object->gnlobject, FALSE);
235
236   if (G_UNLIKELY (duration == object->duration))
237     return FALSE;
238
239   g_object_set (object->gnlobject, "duration", duration, "media-duration",
240       duration, NULL);
241   return TRUE;
242 }
243
244 gboolean
245 ges_track_object_set_priority_internal (GESTrackObject * object,
246     guint32 priority)
247 {
248   GST_DEBUG ("object:%p, priority:%d", object, priority);
249
250   g_return_val_if_fail (object->gnlobject, FALSE);
251
252   if (G_UNLIKELY (priority == object->priority))
253     return FALSE;
254
255   g_object_set (object->gnlobject, "priority", priority, NULL);
256   return TRUE;
257 }
258
259 /* default 'create_gnl_object' virtual method implementation */
260 static gboolean
261 ges_track_object_create_gnl_object_func (GESTrackObject * object)
262 {
263
264   return FALSE;
265 }
266
267 static gboolean
268 ensure_gnl_object (GESTrackObject * object)
269 {
270   GESTrackObjectClass *class;
271   gboolean res;
272
273   if (object->gnlobject && object->valid)
274     return TRUE;
275
276   /* 1. Create the GnlObject */
277   GST_DEBUG ("Creating GnlObject");
278
279   class = GES_TRACK_OBJECT_GET_CLASS (object);
280
281   if (G_UNLIKELY (class->create_gnl_object == NULL)) {
282     GST_ERROR ("No 'create_gnl_object' implementation !");
283     return FALSE;
284   }
285
286   GST_DEBUG ("Calling virtual method");
287
288   /* call the create_gnl_object virtual method */
289   res = class->create_gnl_object (object);
290
291   if (G_UNLIKELY (res && (object->gnlobject == NULL))) {
292     GST_ERROR
293         ("'create_gnl_object' implementation returned TRUE but no GnlObject is available");
294     return FALSE;
295   }
296
297   /* 2. Fill in the GnlObject */
298   if (res) {
299     GST_DEBUG ("Got a valid GnlObject, now filling it in");
300
301     res =
302         ges_timeline_object_fill_track_object (object->timelineobj, object,
303         object->gnlobject);
304     if (res) {
305       /* Set some properties on the GnlObject */
306       g_object_set (object->gnlobject, "caps", object->track->caps, NULL);
307     }
308   }
309
310   object->valid = res;
311
312   GST_DEBUG ("Returning res:%d", res);
313
314   return res;
315 }
316
317 gboolean
318 ges_track_object_set_track (GESTrackObject * object, GESTrack * track)
319 {
320   GST_DEBUG ("object:%p, track:%p", object, track);
321
322   object->track = track;
323
324   if (object->track)
325     return ensure_gnl_object (object);
326
327   return TRUE;
328 }
329
330 void
331 ges_track_object_set_timeline_object (GESTrackObject * object,
332     GESTimelineObject * tlobj)
333 {
334   GST_DEBUG ("object:%p, timeline-object:%p", object, tlobj);
335
336   object->timelineobj = tlobj;
337 }