GESTrackObject: Add 'active' property.
[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 }
207
208 gboolean
209 ges_track_object_set_start_internal (GESTrackObject * object, guint64 start)
210 {
211   g_return_val_if_fail (object->gnlobject, FALSE);
212
213   GST_DEBUG ("object:%p, start:%" GST_TIME_FORMAT,
214       object, GST_TIME_ARGS (start));
215
216   if (G_UNLIKELY (start == object->start))
217     return FALSE;
218
219   g_object_set (object->gnlobject, "start", start, NULL);
220   return TRUE;
221 };
222
223 gboolean
224 ges_track_object_set_inpoint_internal (GESTrackObject * object, guint64 inpoint)
225 {
226   guint64 dur;
227
228   GST_DEBUG ("object:%p, inpoint:%" GST_TIME_FORMAT,
229       object, GST_TIME_ARGS (inpoint));
230
231   g_return_val_if_fail (object->gnlobject, FALSE);
232
233   if (G_UNLIKELY (inpoint == object->inpoint))
234     return FALSE;
235
236   /* Calculate new media-start/duration/media-duration */
237   dur = object->inpoint - inpoint + object->duration;
238
239   g_object_set (object->gnlobject, "media-start", inpoint, "duration", dur,
240       "media-duration", dur, NULL);
241   return TRUE;
242 }
243
244 gboolean
245 ges_track_object_set_duration_internal (GESTrackObject * object,
246     guint64 duration)
247 {
248   GST_DEBUG ("object:%p, duration:%" GST_TIME_FORMAT,
249       object, GST_TIME_ARGS (duration));
250
251   g_return_val_if_fail (object->gnlobject, FALSE);
252
253   if (G_UNLIKELY (duration == object->duration))
254     return FALSE;
255
256   g_object_set (object->gnlobject, "duration", duration, "media-duration",
257       duration, NULL);
258   return TRUE;
259 }
260
261 gboolean
262 ges_track_object_set_priority_internal (GESTrackObject * object,
263     guint32 priority)
264 {
265   GST_DEBUG ("object:%p, priority:%d", object, priority);
266
267   g_return_val_if_fail (object->gnlobject, FALSE);
268
269   if (G_UNLIKELY (priority == object->priority))
270     return FALSE;
271
272   g_object_set (object->gnlobject, "priority", priority, NULL);
273   return TRUE;
274 }
275
276 gboolean
277 ges_track_object_set_active (GESTrackObject * object, gboolean active)
278 {
279   GST_DEBUG ("object:%p, active:%d", object, active);
280
281   g_return_val_if_fail (object->gnlobject, FALSE);
282
283   if (G_UNLIKELY (active == object->active))
284     return FALSE;
285
286   g_object_set (object->gnlobject, "active", active, NULL);
287   return TRUE;
288 }
289
290 /* default 'create_gnl_object' virtual method implementation */
291 static gboolean
292 ges_track_object_create_gnl_object_func (GESTrackObject * object)
293 {
294
295   return FALSE;
296 }
297
298 static gboolean
299 ensure_gnl_object (GESTrackObject * object)
300 {
301   GESTrackObjectClass *class;
302   gboolean res;
303
304   if (object->gnlobject && object->valid)
305     return TRUE;
306
307   /* 1. Create the GnlObject */
308   GST_DEBUG ("Creating GnlObject");
309
310   class = GES_TRACK_OBJECT_GET_CLASS (object);
311
312   if (G_UNLIKELY (class->create_gnl_object == NULL)) {
313     GST_ERROR ("No 'create_gnl_object' implementation !");
314     return FALSE;
315   }
316
317   GST_DEBUG ("Calling virtual method");
318
319   /* call the create_gnl_object virtual method */
320   res = class->create_gnl_object (object);
321
322   if (G_UNLIKELY (res && (object->gnlobject == NULL))) {
323     GST_ERROR
324         ("'create_gnl_object' implementation returned TRUE but no GnlObject is available");
325     return FALSE;
326   }
327
328   /* 2. Fill in the GnlObject */
329   if (res) {
330     GST_DEBUG ("Got a valid GnlObject, now filling it in");
331
332     res =
333         ges_timeline_object_fill_track_object (object->timelineobj, object,
334         object->gnlobject);
335     if (res) {
336       /* Set some properties on the GnlObject */
337       g_object_set (object->gnlobject, "caps", object->track->caps, NULL);
338     }
339   }
340
341   object->valid = res;
342
343   GST_DEBUG ("Returning res:%d", res);
344
345   return res;
346 }
347
348 gboolean
349 ges_track_object_set_track (GESTrackObject * object, GESTrack * track)
350 {
351   GST_DEBUG ("object:%p, track:%p", object, track);
352
353   object->track = track;
354
355   if (object->track)
356     return ensure_gnl_object (object);
357
358   return TRUE;
359 }
360
361 void
362 ges_track_object_set_timeline_object (GESTrackObject * object,
363     GESTimelineObject * tlobj)
364 {
365   GST_DEBUG ("object:%p, timeline-object:%p", object, tlobj);
366
367   object->timelineobj = tlobj;
368 }