GESTrackObject: Set sane default values
[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   PROP_ACTIVE
60 };
61
62 static gboolean
63 ges_track_object_create_gnl_object_func (GESTrackObject * object);
64
65 static void
66 ges_track_object_get_property (GObject * object, guint property_id,
67     GValue * value, GParamSpec * pspec)
68 {
69   GESTrackObject *tobj = GES_TRACK_OBJECT (object);
70
71   switch (property_id) {
72     case PROP_START:
73       g_value_set_uint64 (value, tobj->start);
74       break;
75     case PROP_INPOINT:
76       g_value_set_uint64 (value, tobj->inpoint);
77       break;
78     case PROP_DURATION:
79       g_value_set_uint64 (value, tobj->duration);
80       break;
81     case PROP_PRIORITY:
82       g_value_set_uint (value, tobj->priority);
83       break;
84     case PROP_ACTIVE:
85       g_value_set_boolean (value, tobj->active);
86       break;
87     default:
88       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
89   }
90 }
91
92 static void
93 ges_track_object_set_property (GObject * object, guint property_id,
94     const GValue * value, GParamSpec * pspec)
95 {
96   GESTrackObject *tobj = GES_TRACK_OBJECT (object);
97
98   switch (property_id) {
99     case PROP_START:
100       ges_track_object_set_start_internal (tobj, g_value_get_uint64 (value));
101       break;
102     case PROP_INPOINT:
103       ges_track_object_set_inpoint_internal (tobj, g_value_get_uint64 (value));
104       break;
105     case PROP_DURATION:
106       ges_track_object_set_duration_internal (tobj, g_value_get_uint64 (value));
107       break;
108     case PROP_PRIORITY:
109       ges_track_object_set_priority_internal (tobj, g_value_get_uint (value));
110       break;
111     case PROP_ACTIVE:
112       ges_track_object_set_active (tobj, g_value_get_boolean (value));
113       break;
114     default:
115       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
116   }
117 }
118
119 static void
120 ges_track_object_dispose (GObject * object)
121 {
122   G_OBJECT_CLASS (ges_track_object_parent_class)->dispose (object);
123 }
124
125 static void
126 ges_track_object_finalize (GObject * object)
127 {
128   G_OBJECT_CLASS (ges_track_object_parent_class)->finalize (object);
129 }
130
131 static void
132 ges_track_object_class_init (GESTrackObjectClass * klass)
133 {
134   GObjectClass *object_class = G_OBJECT_CLASS (klass);
135
136   object_class->get_property = ges_track_object_get_property;
137   object_class->set_property = ges_track_object_set_property;
138   object_class->dispose = ges_track_object_dispose;
139   object_class->finalize = ges_track_object_finalize;
140
141   /**
142    * GESTrackObject:start
143    *
144    * The position of the object in the container #GESTrack (in nanoseconds).
145    */
146   g_object_class_install_property (object_class, PROP_START,
147       g_param_spec_uint64 ("start", "Start",
148           "The position in the container", 0, G_MAXUINT64, 0,
149           G_PARAM_READWRITE));
150
151   /**
152    * GESTrackObject:in-point
153    *
154    * The in-point at which this #GESTrackObject will start outputting data
155    * from its contents (in nanoseconds).
156    *
157    * Ex : an in-point of 5 seconds means that the first outputted buffer will
158    * be the one located 5 seconds in the controlled resource.
159    */
160   g_object_class_install_property (object_class, PROP_INPOINT,
161       g_param_spec_uint64 ("in-point", "In-point", "The in-point", 0,
162           G_MAXUINT64, 0, G_PARAM_READWRITE));
163
164   /**
165    * GESTrackObject:duration
166    *
167    * The duration (in nanoseconds) which will be used in the container #GESTrack
168    * starting from 'in-point'.
169    *
170    */
171   g_object_class_install_property (object_class, PROP_DURATION,
172       g_param_spec_uint64 ("duration", "Duration", "The duration to use",
173           0, G_MAXUINT64, GST_SECOND, G_PARAM_READWRITE));
174
175   /**
176    * GESTrackObject:priority
177    *
178    * The priority of the object within the containing #GESTrack.
179    * If two objects intersect over the same region of time, the @priority
180    * property is used to decide which one takes precedence.
181    *
182    * The highest priority (that supercedes everything) is 0, and then lowering
183    * priorities go in increasing numerical value (with #G_MAXUINT64 being the
184    * lowest priority).
185    */
186   g_object_class_install_property (object_class, PROP_PRIORITY,
187       g_param_spec_uint ("priority", "Priority",
188           "The priority of the object", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
189
190   /**
191    * GESTrackObject:active
192    *
193    * Whether the object should be taken into account in the #GEStrack output.
194    * If #FALSE, then its contents will not be used in the resulting track.
195    */
196   g_object_class_install_property (object_class, PROP_ACTIVE,
197       g_param_spec_boolean ("active", "Active", "Use object in output",
198           TRUE, G_PARAM_READWRITE));
199
200   klass->create_gnl_object = ges_track_object_create_gnl_object_func;
201 }
202
203 static void
204 ges_track_object_init (GESTrackObject * self)
205 {
206   /* Sane default values */
207   self->start = 0;
208   self->inpoint = 0;
209   self->duration = GST_SECOND;
210   self->priority = 1;
211 }
212
213 gboolean
214 ges_track_object_set_start_internal (GESTrackObject * object, guint64 start)
215 {
216   g_return_val_if_fail (object->gnlobject, FALSE);
217
218   GST_DEBUG ("object:%p, start:%" GST_TIME_FORMAT,
219       object, GST_TIME_ARGS (start));
220
221   if (G_UNLIKELY (start == object->start))
222     return FALSE;
223
224   g_object_set (object->gnlobject, "start", start, NULL);
225   return TRUE;
226 };
227
228 gboolean
229 ges_track_object_set_inpoint_internal (GESTrackObject * object, guint64 inpoint)
230 {
231   guint64 dur;
232
233   GST_DEBUG ("object:%p, inpoint:%" GST_TIME_FORMAT,
234       object, GST_TIME_ARGS (inpoint));
235
236   g_return_val_if_fail (object->gnlobject, FALSE);
237
238   if (G_UNLIKELY (inpoint == object->inpoint))
239     return FALSE;
240
241   /* Calculate new media-start/duration/media-duration */
242   dur = object->inpoint - inpoint + object->duration;
243
244   g_object_set (object->gnlobject, "media-start", inpoint, "duration", dur,
245       "media-duration", dur, NULL);
246   return TRUE;
247 }
248
249 gboolean
250 ges_track_object_set_duration_internal (GESTrackObject * object,
251     guint64 duration)
252 {
253   GST_DEBUG ("object:%p, duration:%" GST_TIME_FORMAT,
254       object, GST_TIME_ARGS (duration));
255
256   g_return_val_if_fail (object->gnlobject, FALSE);
257
258   if (G_UNLIKELY (duration == object->duration))
259     return FALSE;
260
261   g_object_set (object->gnlobject, "duration", duration, "media-duration",
262       duration, NULL);
263   return TRUE;
264 }
265
266 gboolean
267 ges_track_object_set_priority_internal (GESTrackObject * object,
268     guint32 priority)
269 {
270   GST_DEBUG ("object:%p, priority:%d", object, priority);
271
272   g_return_val_if_fail (object->gnlobject, FALSE);
273
274   if (G_UNLIKELY (priority == object->priority))
275     return FALSE;
276
277   g_object_set (object->gnlobject, "priority", priority, NULL);
278   return TRUE;
279 }
280
281 gboolean
282 ges_track_object_set_active (GESTrackObject * object, gboolean active)
283 {
284   GST_DEBUG ("object:%p, active:%d", object, active);
285
286   g_return_val_if_fail (object->gnlobject, FALSE);
287
288   if (G_UNLIKELY (active == object->active))
289     return FALSE;
290
291   g_object_set (object->gnlobject, "active", active, NULL);
292   return TRUE;
293 }
294
295 /* default 'create_gnl_object' virtual method implementation */
296 static gboolean
297 ges_track_object_create_gnl_object_func (GESTrackObject * object)
298 {
299
300   return FALSE;
301 }
302
303 static gboolean
304 ensure_gnl_object (GESTrackObject * object)
305 {
306   GESTrackObjectClass *class;
307   gboolean res;
308
309   if (object->gnlobject && object->valid)
310     return TRUE;
311
312   /* 1. Create the GnlObject */
313   GST_DEBUG ("Creating GnlObject");
314
315   class = GES_TRACK_OBJECT_GET_CLASS (object);
316
317   if (G_UNLIKELY (class->create_gnl_object == NULL)) {
318     GST_ERROR ("No 'create_gnl_object' implementation !");
319     return FALSE;
320   }
321
322   GST_DEBUG ("Calling virtual method");
323
324   /* call the create_gnl_object virtual method */
325   res = class->create_gnl_object (object);
326
327   if (G_UNLIKELY (res && (object->gnlobject == NULL))) {
328     GST_ERROR
329         ("'create_gnl_object' implementation returned TRUE but no GnlObject is available");
330     return FALSE;
331   }
332
333   /* 2. Fill in the GnlObject */
334   if (res) {
335     GST_DEBUG ("Got a valid GnlObject, now filling it in");
336
337     res =
338         ges_timeline_object_fill_track_object (object->timelineobj, object,
339         object->gnlobject);
340     if (res) {
341       /* Set some properties on the GnlObject */
342       g_object_set (object->gnlobject, "caps", object->track->caps, NULL);
343     }
344   }
345
346   object->valid = res;
347
348   GST_DEBUG ("Returning res:%d", res);
349
350   return res;
351 }
352
353 gboolean
354 ges_track_object_set_track (GESTrackObject * object, GESTrack * track)
355 {
356   GST_DEBUG ("object:%p, track:%p", object, track);
357
358   object->track = track;
359
360   if (object->track)
361     return ensure_gnl_object (object);
362
363   return TRUE;
364 }
365
366 void
367 ges_track_object_set_timeline_object (GESTrackObject * object,
368     GESTimelineObject * tlobj)
369 {
370   GST_DEBUG ("object:%p, timeline-object:%p", object, tlobj);
371
372   object->timelineobj = tlobj;
373 }