Branch data Line data Source code
1 : : /* GStreamer Editing Services
2 : : * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3 : : * 2009 Nokia Corporation
4 : : *
5 : : * This library is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Library General Public
7 : : * License as published by the Free Software Foundation; either
8 : : * version 2 of the License, or (at your option) any later version.
9 : : *
10 : : * This library is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Library General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Library General Public
16 : : * License along with this library; if not, write to the
17 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 : : * Boston, MA 02111-1307, USA.
19 : : */
20 : :
21 : : /**
22 : : * SECTION:ges-track-object
23 : : * @short_description: Base Class for objects contained in a #GESTrack
24 : : *
25 : : * #GESTrackObject is the Base Class for any object that can be contained in a
26 : : * #GESTrack.
27 : : *
28 : : * It contains the basic information as to the location of the object within
29 : : * its container, like the start position, the in-point, the duration and the
30 : : * priority.
31 : : */
32 : :
33 : : #include "ges-internal.h"
34 : : #include "ges-track-object.h"
35 : : #include "ges-timeline-object.h"
36 : :
37 [ + + ]: 680 : G_DEFINE_ABSTRACT_TYPE (GESTrackObject, ges_track_object,
38 : 680 : G_TYPE_INITIALLY_UNOWNED);
39 : :
40 : : struct _GESTrackObjectPrivate
41 : : {
42 : : /* These fields are only used before the gnlobject is available */
43 : : guint64 pending_start;
44 : : guint64 pending_inpoint;
45 : : guint64 pending_duration;
46 : : guint32 pending_priority;
47 : : gboolean pending_active;
48 : :
49 : : GstElement *gnlobject; /* The GnlObject */
50 : : GstElement *element; /* The element contained in the gnlobject (can be NULL) */
51 : :
52 : : GESTimelineObject *timelineobj;
53 : : GESTrack *track;
54 : :
55 : : gboolean valid;
56 : :
57 : : gboolean locked; /* If TRUE, then moves in sync with its controlling
58 : : * GESTimelineObject */
59 : : };
60 : :
61 : : enum
62 : : {
63 : : PROP_0,
64 : : PROP_START,
65 : : PROP_INPOINT,
66 : : PROP_DURATION,
67 : : PROP_PRIORITY,
68 : : PROP_ACTIVE,
69 : : PROP_LAST
70 : : };
71 : :
72 : : static GParamSpec *properties[PROP_LAST];
73 : :
74 : : static GstElement *ges_track_object_create_gnl_object_func (GESTrackObject *
75 : : object);
76 : :
77 : : static void gnlobject_start_cb (GstElement * gnlobject, GParamSpec * arg
78 : : G_GNUC_UNUSED, GESTrackObject * obj);
79 : :
80 : : static void gnlobject_media_start_cb (GstElement * gnlobject, GParamSpec * arg
81 : : G_GNUC_UNUSED, GESTrackObject * obj);
82 : :
83 : : static void gnlobject_priority_cb (GstElement * gnlobject, GParamSpec * arg
84 : : G_GNUC_UNUSED, GESTrackObject * obj);
85 : :
86 : : static void gnlobject_duration_cb (GstElement * gnlobject, GParamSpec * arg
87 : : G_GNUC_UNUSED, GESTrackObject * obj);
88 : :
89 : : static void gnlobject_active_cb (GstElement * gnlobject, GParamSpec * arg
90 : : G_GNUC_UNUSED, GESTrackObject * obj);
91 : :
92 : : static inline gboolean
93 : : ges_track_object_set_start_internal (GESTrackObject * object, guint64 start);
94 : : static inline gboolean
95 : : ges_track_object_set_inpoint_internal (GESTrackObject * object,
96 : : guint64 inpoint);
97 : : static inline gboolean ges_track_object_set_duration_internal (GESTrackObject *
98 : : object, guint64 duration);
99 : : static inline gboolean ges_track_object_set_priority_internal (GESTrackObject *
100 : : object, guint32 priority);
101 : :
102 : : static void
103 : 0 : ges_track_object_get_property (GObject * object, guint property_id,
104 : : GValue * value, GParamSpec * pspec)
105 : : {
106 : 0 : GESTrackObject *tobj = GES_TRACK_OBJECT (object);
107 : :
108 [ # # # # : 0 : switch (property_id) {
# # ]
109 : : case PROP_START:
110 : 0 : g_value_set_uint64 (value, tobj->start);
111 : 0 : break;
112 : : case PROP_INPOINT:
113 : 0 : g_value_set_uint64 (value, tobj->inpoint);
114 : 0 : break;
115 : : case PROP_DURATION:
116 : 0 : g_value_set_uint64 (value, tobj->duration);
117 : 0 : break;
118 : : case PROP_PRIORITY:
119 : 0 : g_value_set_uint (value, tobj->priority);
120 : 0 : break;
121 : : case PROP_ACTIVE:
122 : 0 : g_value_set_boolean (value, tobj->active);
123 : 0 : break;
124 : : default:
125 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
126 : : }
127 : 0 : }
128 : :
129 : : static void
130 : 2 : ges_track_object_set_property (GObject * object, guint property_id,
131 : : const GValue * value, GParamSpec * pspec)
132 : : {
133 : 2 : GESTrackObject *tobj = GES_TRACK_OBJECT (object);
134 : :
135 [ + - - - : 2 : switch (property_id) {
- - ]
136 : : case PROP_START:
137 : 2 : ges_track_object_set_start_internal (tobj, g_value_get_uint64 (value));
138 : 2 : break;
139 : : case PROP_INPOINT:
140 : 0 : ges_track_object_set_inpoint_internal (tobj, g_value_get_uint64 (value));
141 : 0 : break;
142 : : case PROP_DURATION:
143 : 0 : ges_track_object_set_duration_internal (tobj, g_value_get_uint64 (value));
144 : 0 : break;
145 : : case PROP_PRIORITY:
146 : 0 : ges_track_object_set_priority_internal (tobj, g_value_get_uint (value));
147 : 0 : break;
148 : : case PROP_ACTIVE:
149 : 0 : ges_track_object_set_active (tobj, g_value_get_boolean (value));
150 : 0 : break;
151 : : default:
152 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
153 : : }
154 : 2 : }
155 : :
156 : : static void
157 : 62 : ges_track_object_dispose (GObject * object)
158 : : {
159 : 62 : G_OBJECT_CLASS (ges_track_object_parent_class)->dispose (object);
160 : 62 : }
161 : :
162 : : static void
163 : 62 : ges_track_object_finalize (GObject * object)
164 : : {
165 : 62 : G_OBJECT_CLASS (ges_track_object_parent_class)->finalize (object);
166 : 62 : }
167 : :
168 : : static void
169 : 24 : ges_track_object_class_init (GESTrackObjectClass * klass)
170 : : {
171 : 24 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
172 : :
173 : 24 : g_type_class_add_private (klass, sizeof (GESTrackObjectPrivate));
174 : :
175 : 24 : object_class->get_property = ges_track_object_get_property;
176 : 24 : object_class->set_property = ges_track_object_set_property;
177 : 24 : object_class->dispose = ges_track_object_dispose;
178 : 24 : object_class->finalize = ges_track_object_finalize;
179 : :
180 : : /**
181 : : * GESTrackObject:start
182 : : *
183 : : * The position of the object in the container #GESTrack (in nanoseconds).
184 : : */
185 : 24 : properties[PROP_START] = g_param_spec_uint64 ("start", "Start",
186 : : "The position in the container", 0, G_MAXUINT64, 0, G_PARAM_READWRITE);
187 : 24 : g_object_class_install_property (object_class, PROP_START,
188 : : properties[PROP_START]);
189 : :
190 : : /**
191 : : * GESTrackObject:in-point
192 : : *
193 : : * The in-point at which this #GESTrackObject will start outputting data
194 : : * from its contents (in nanoseconds).
195 : : *
196 : : * Ex : an in-point of 5 seconds means that the first outputted buffer will
197 : : * be the one located 5 seconds in the controlled resource.
198 : : */
199 : 24 : properties[PROP_INPOINT] =
200 : 24 : g_param_spec_uint64 ("in-point", "In-point", "The in-point", 0,
201 : : G_MAXUINT64, 0, G_PARAM_READWRITE);
202 : 24 : g_object_class_install_property (object_class, PROP_INPOINT,
203 : : properties[PROP_INPOINT]);
204 : :
205 : : /**
206 : : * GESTrackObject:duration
207 : : *
208 : : * The duration (in nanoseconds) which will be used in the container #GESTrack
209 : : * starting from 'in-point'.
210 : : *
211 : : */
212 : 24 : properties[PROP_DURATION] =
213 : 24 : g_param_spec_uint64 ("duration", "Duration", "The duration to use", 0,
214 : : G_MAXUINT64, GST_SECOND, G_PARAM_READWRITE);
215 : 24 : g_object_class_install_property (object_class, PROP_DURATION,
216 : : properties[PROP_DURATION]);
217 : :
218 : : /**
219 : : * GESTrackObject:priority
220 : : *
221 : : * The priority of the object within the containing #GESTrack.
222 : : * If two objects intersect over the same region of time, the @priority
223 : : * property is used to decide which one takes precedence.
224 : : *
225 : : * The highest priority (that supercedes everything) is 0, and then lowering
226 : : * priorities go in increasing numerical value (with #G_MAXUINT64 being the
227 : : * lowest priority).
228 : : */
229 : 24 : properties[PROP_PRIORITY] = g_param_spec_uint ("priority", "Priority",
230 : : "The priority of the object", 0, G_MAXUINT, 0, G_PARAM_READWRITE);
231 : 24 : g_object_class_install_property (object_class, PROP_PRIORITY,
232 : : properties[PROP_PRIORITY]);
233 : :
234 : : /**
235 : : * GESTrackObject:active
236 : : *
237 : : * Whether the object should be taken into account in the #GESTrack output.
238 : : * If #FALSE, then its contents will not be used in the resulting track.
239 : : */
240 : 24 : properties[PROP_ACTIVE] =
241 : 24 : g_param_spec_boolean ("active", "Active", "Use object in output", TRUE,
242 : : G_PARAM_READWRITE);
243 : 24 : g_object_class_install_property (object_class, PROP_ACTIVE,
244 : : properties[PROP_ACTIVE]);
245 : :
246 : 24 : klass->create_gnl_object = ges_track_object_create_gnl_object_func;
247 : 24 : }
248 : :
249 : : static void
250 : 74 : ges_track_object_init (GESTrackObject * self)
251 : : {
252 : 74 : self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
253 : : GES_TYPE_TRACK_OBJECT, GESTrackObjectPrivate);
254 : :
255 : : /* Sane default values */
256 : 74 : self->priv->pending_start = 0;
257 : 74 : self->priv->pending_inpoint = 0;
258 : 74 : self->priv->pending_duration = GST_SECOND;
259 : 74 : self->priv->pending_priority = 1;
260 : 74 : self->priv->pending_active = TRUE;
261 : 74 : self->priv->locked = TRUE;
262 : 74 : }
263 : :
264 : : static inline gboolean
265 : 178 : ges_track_object_set_start_internal (GESTrackObject * object, guint64 start)
266 : : {
267 [ - + ][ # # ]: 178 : GST_DEBUG ("object:%p, start:%" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
268 : : object, GST_TIME_ARGS (start));
269 : :
270 [ + + ]: 178 : if (object->priv->gnlobject != NULL) {
271 [ + + ]: 104 : if (G_UNLIKELY (start == object->start))
272 : 1 : return FALSE;
273 : :
274 : 103 : g_object_set (object->priv->gnlobject, "start", start, NULL);
275 : : } else
276 : 74 : object->priv->pending_start = start;
277 : 178 : return TRUE;
278 : : };
279 : :
280 : : /**
281 : : * ges_track_object_set_start:
282 : : * @object: a #GESTrackObject
283 : : * @start: the start position (in #GstClockTime)
284 : : *
285 : : * Sets the position of the object in the container #GESTrack.
286 : : */
287 : : void
288 : 176 : ges_track_object_set_start (GESTrackObject * object, guint64 start)
289 : : {
290 [ + + ]: 176 : if (ges_track_object_set_start_internal (object, start))
291 : : #if GLIB_CHECK_VERSION(2,26,0)
292 : 175 : g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_START]);
293 : : #else
294 : : g_object_notify (G_OBJECT (object), "start");
295 : : #endif
296 : 176 : }
297 : :
298 : : static inline gboolean
299 : 80 : ges_track_object_set_inpoint_internal (GESTrackObject * object, guint64 inpoint)
300 : : {
301 : :
302 [ - + ][ # # ]: 80 : GST_DEBUG ("object:%p, inpoint:%" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
303 : : object, GST_TIME_ARGS (inpoint));
304 : :
305 [ + + ]: 80 : if (object->priv->gnlobject != NULL) {
306 [ - + ]: 6 : if (G_UNLIKELY (inpoint == object->inpoint))
307 : 0 : return FALSE;
308 : :
309 : 6 : g_object_set (object->priv->gnlobject, "media-start", inpoint, NULL);
310 : : } else
311 : 74 : object->priv->pending_inpoint = inpoint;
312 : :
313 : 80 : return TRUE;
314 : : }
315 : :
316 : : /**
317 : : * ges_track_object_set_inpoint:
318 : : * @object: a #GESTrackObject
319 : : * @inpoint: the in-point (in #GstClockTime)
320 : : *
321 : : * Set the offset within the contents of this #GESTrackObject
322 : : */
323 : : void
324 : 80 : ges_track_object_set_inpoint (GESTrackObject * object, guint64 inpoint)
325 : : {
326 [ + - ]: 80 : if (ges_track_object_set_inpoint_internal (object, inpoint))
327 : : #if GLIB_CHECK_VERSION(2,26,0)
328 : 80 : g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_INPOINT]);
329 : : #else
330 : : g_object_notify (G_OBJECT (object), "in-point");
331 : : #endif
332 : 80 : }
333 : :
334 : : static inline gboolean
335 : 81 : ges_track_object_set_duration_internal (GESTrackObject * object,
336 : : guint64 duration)
337 : : {
338 [ - + ][ # # ]: 81 : GST_DEBUG ("object:%p, duration:%" GST_TIME_FORMAT,
[ # # ][ # # ]
[ # # ]
339 : : object, GST_TIME_ARGS (duration));
340 : :
341 [ + + ]: 81 : if (object->priv->gnlobject != NULL) {
342 [ - + ]: 7 : if (G_UNLIKELY (duration == object->duration))
343 : 0 : return FALSE;
344 : :
345 : 7 : g_object_set (object->priv->gnlobject, "duration", duration,
346 : : "media-duration", duration, NULL);
347 : : } else
348 : 74 : object->priv->pending_duration = duration;
349 : 81 : return TRUE;
350 : : }
351 : :
352 : : /**
353 : : * ges_track_object_set_duration:
354 : : * @object: a #GESTrackObject
355 : : * @duration: the duration (in #GstClockTime)
356 : : *
357 : : * Set the duration which will be used in the container #GESTrack
358 : : * starting from the 'in-point'
359 : : */
360 : : void
361 : 81 : ges_track_object_set_duration (GESTrackObject * object, guint64 duration)
362 : : {
363 [ + - ]: 81 : if (ges_track_object_set_duration_internal (object, duration))
364 : : #if GLIB_CHECK_VERSION(2,26,0)
365 : 81 : g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_DURATION]);
366 : : #else
367 : : g_object_notify (G_OBJECT (object), "duration");
368 : : #endif
369 : 81 : }
370 : :
371 : : static inline gboolean
372 : 145 : ges_track_object_set_priority_internal (GESTrackObject * object,
373 : : guint32 priority)
374 : : {
375 [ - + ]: 145 : GST_DEBUG ("object:%p, priority:%" G_GUINT32_FORMAT, object, priority);
376 : :
377 [ + + ]: 145 : if (object->priv->gnlobject != NULL) {
378 [ - + ]: 71 : if (G_UNLIKELY (priority == object->priority))
379 : 0 : return FALSE;
380 : :
381 : 71 : g_object_set (object->priv->gnlobject, "priority", priority, NULL);
382 : : } else
383 : 74 : object->priv->pending_priority = priority;
384 : 145 : return TRUE;
385 : : }
386 : :
387 : : /**
388 : : * ges_track_object_set_priority:
389 : : * @object: a #GESTrackObject
390 : : * @priority: the priority
391 : : *
392 : : * Sets the priority of the object withing the containing #GESTrack.
393 : : * If two objects intersect over the same region of time, the priority
394 : : * property is used to decide which one takes precedence.
395 : : *
396 : : * The highest priority (that supercedes everything) is 0, and then
397 : : * lowering priorities go in increasing numerical value (with G_MAXUINT32
398 : : * being the lowest priority).
399 : : */
400 : : void
401 : 145 : ges_track_object_set_priority (GESTrackObject * object, guint32 priority)
402 : : {
403 [ + - ]: 145 : if (ges_track_object_set_priority_internal (object, priority))
404 : : #if GLIB_CHECK_VERSION(2,26,0)
405 : 145 : g_object_notify_by_pspec (G_OBJECT (object), properties[PROP_PRIORITY]);
406 : : #else
407 : : g_object_notify (G_OBJECT (object), "priority");
408 : : #endif
409 : 145 : }
410 : :
411 : :
412 : : /**
413 : : * ges_track_object_set_active:
414 : : * @object: a #GESTrackObject
415 : : * @active: visibility
416 : : *
417 : : * Sets the usage of the @object. If @active is %TRUE, the object will be used for
418 : : * playback and rendering, else it will be ignored.
419 : : *
420 : : * Returns: %TRUE if the property was toggled, else %FALSE
421 : : */
422 : : gboolean
423 : 6 : ges_track_object_set_active (GESTrackObject * object, gboolean active)
424 : : {
425 [ - + ]: 6 : GST_DEBUG ("object:%p, active:%d", object, active);
426 : :
427 [ + - ]: 6 : if (object->priv->gnlobject != NULL) {
428 [ - + ]: 6 : if (G_UNLIKELY (active == object->active))
429 : 0 : return FALSE;
430 : :
431 : 6 : g_object_set (object->priv->gnlobject, "active", active, NULL);
432 : : } else
433 : 0 : object->priv->pending_active = active;
434 : 6 : return TRUE;
435 : : }
436 : :
437 : : /* Callbacks from the GNonLin object */
438 : : static void
439 : 173 : gnlobject_start_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED,
440 : : GESTrackObject * obj)
441 : : {
442 : : guint64 start;
443 : : GESTrackObjectClass *klass;
444 : :
445 : 173 : klass = GES_TRACK_OBJECT_GET_CLASS (obj);
446 : :
447 : 173 : g_object_get (gnlobject, "start", &start, NULL);
448 : :
449 [ - + ][ # # ]: 173 : GST_DEBUG ("gnlobject start : %" GST_TIME_FORMAT " current : %"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
450 : : GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (obj->start));
451 : :
452 [ + + ]: 173 : if (start != obj->start) {
453 : 147 : obj->start = start;
454 [ - + ]: 147 : if (klass->start_changed)
455 : 0 : klass->start_changed (obj, start);
456 : : }
457 : 173 : }
458 : :
459 : : /* Callbacks from the GNonLin object */
460 : : static void
461 : 76 : gnlobject_media_start_cb (GstElement * gnlobject,
462 : : GParamSpec * arg G_GNUC_UNUSED, GESTrackObject * obj)
463 : : {
464 : : guint64 start;
465 : : GESTrackObjectClass *klass;
466 : :
467 : 76 : klass = GES_TRACK_OBJECT_GET_CLASS (obj);
468 : :
469 : 76 : g_object_get (gnlobject, "media-start", &start, NULL);
470 : :
471 [ - + ][ # # ]: 76 : GST_DEBUG ("gnlobject in-point : %" GST_TIME_FORMAT " current : %"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
472 : : GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (obj->inpoint));
473 : :
474 [ + + ]: 76 : if (start != obj->inpoint) {
475 : 15 : obj->inpoint = start;
476 [ - + ]: 15 : if (klass->media_start_changed)
477 : 0 : klass->media_start_changed (obj, start);
478 : : }
479 : 76 : }
480 : :
481 : : static void
482 : 141 : gnlobject_priority_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED,
483 : : GESTrackObject * obj)
484 : : {
485 : : guint32 priority;
486 : : GESTrackObjectClass *klass;
487 : :
488 : 141 : klass = GES_TRACK_OBJECT_GET_CLASS (obj);
489 : :
490 : 141 : g_object_get (gnlobject, "priority", &priority, NULL);
491 : :
492 [ - + ]: 141 : GST_DEBUG ("gnlobject priority : %d current : %d", priority, obj->priority);
493 : :
494 [ + + ]: 141 : if (priority != obj->priority) {
495 : 90 : obj->priority = priority;
496 [ - + ]: 90 : if (klass->gnl_priority_changed)
497 : 0 : klass->gnl_priority_changed (obj, priority);
498 : : }
499 : 141 : }
500 : :
501 : : static void
502 : 77 : gnlobject_duration_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED,
503 : : GESTrackObject * obj)
504 : : {
505 : : guint64 duration;
506 : : GESTrackObjectClass *klass;
507 : :
508 : 77 : klass = GES_TRACK_OBJECT_GET_CLASS (obj);
509 : :
510 : 77 : g_object_get (gnlobject, "duration", &duration, NULL);
511 : :
512 [ - + ][ # # ]: 77 : GST_DEBUG ("gnlobject duration : %" GST_TIME_FORMAT " current : %"
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
513 : : GST_TIME_FORMAT, GST_TIME_ARGS (duration), GST_TIME_ARGS (obj->duration));
514 : :
515 [ + + ]: 77 : if (duration != obj->duration) {
516 : 76 : obj->duration = duration;
517 [ + + ]: 76 : if (klass->duration_changed)
518 : 16 : klass->duration_changed (obj, duration);
519 : : }
520 : 77 : }
521 : :
522 : : static void
523 : 76 : gnlobject_active_cb (GstElement * gnlobject, GParamSpec * arg G_GNUC_UNUSED,
524 : : GESTrackObject * obj)
525 : : {
526 : : gboolean active;
527 : : GESTrackObjectClass *klass;
528 : :
529 : 76 : klass = GES_TRACK_OBJECT_GET_CLASS (obj);
530 : :
531 : 76 : g_object_get (gnlobject, "active", &active, NULL);
532 : :
533 [ - + ]: 76 : GST_DEBUG ("gnlobject active : %d current : %d", active, obj->active);
534 : :
535 [ + - ]: 76 : if (active != obj->active) {
536 : 76 : obj->active = active;
537 [ - + ]: 76 : if (klass->active_changed)
538 : 0 : klass->active_changed (obj, active);
539 : : }
540 : 76 : }
541 : :
542 : :
543 : : /* default 'create_gnl_object' virtual method implementation */
544 : : static GstElement *
545 : 69 : ges_track_object_create_gnl_object_func (GESTrackObject * self)
546 : : {
547 : 69 : GESTrackObjectClass *klass = NULL;
548 : 69 : GstElement *child = NULL;
549 : : GstElement *gnlobject;
550 : :
551 : 69 : klass = GES_TRACK_OBJECT_GET_CLASS (self);
552 : :
553 [ - + ]: 69 : if (G_UNLIKELY (self->priv->gnlobject != NULL))
554 : 0 : goto already_have_gnlobject;
555 : :
556 [ - + ]: 69 : if (G_UNLIKELY (klass->gnlobject_factorytype == NULL))
557 : 0 : goto no_gnlfactory;
558 : :
559 [ - + ]: 69 : GST_DEBUG ("Creating a supporting gnlobject of type '%s'",
560 : : klass->gnlobject_factorytype);
561 : :
562 : 69 : gnlobject = gst_element_factory_make (klass->gnlobject_factorytype, NULL);
563 : :
564 [ - + ]: 69 : if (G_UNLIKELY (gnlobject == NULL))
565 : 0 : goto no_gnlobject;
566 : :
567 [ + + ]: 69 : if (klass->create_element) {
568 [ - + ]: 44 : GST_DEBUG ("Calling subclass 'create_element' vmethod");
569 : 44 : child = klass->create_element (self);
570 : :
571 [ - + ]: 44 : if (G_UNLIKELY (!child))
572 : 0 : goto child_failure;
573 : :
574 [ - + ]: 44 : if (!gst_bin_add (GST_BIN (gnlobject), child))
575 : 0 : goto add_failure;
576 : :
577 [ - + ]: 44 : GST_DEBUG ("Succesfully got the element to put in the gnlobject");
578 : 44 : self->priv->element = child;
579 : : }
580 : :
581 [ - + ]: 69 : GST_DEBUG ("done");
582 : 69 : return gnlobject;
583 : :
584 : :
585 : : /* ERROR CASES */
586 : :
587 : : already_have_gnlobject:
588 : : {
589 [ # # ]: 0 : GST_ERROR ("Already controlling a GnlObject %s",
590 : : GST_ELEMENT_NAME (self->priv->gnlobject));
591 : 0 : return NULL;
592 : : }
593 : :
594 : : no_gnlfactory:
595 : : {
596 [ # # ]: 0 : GST_ERROR ("No GESTrackObject::gnlobject_factorytype implementation!");
597 : 0 : return NULL;
598 : : }
599 : :
600 : : no_gnlobject:
601 : : {
602 [ # # ]: 0 : GST_ERROR ("Error creating a gnlobject of type '%s'",
603 : : klass->gnlobject_factorytype);
604 : 0 : return NULL;
605 : : }
606 : :
607 : : child_failure:
608 : : {
609 [ # # ]: 0 : GST_ERROR ("create_element returned NULL");
610 : 0 : gst_object_unref (gnlobject);
611 : 0 : return NULL;
612 : : }
613 : :
614 : : add_failure:
615 : : {
616 [ # # ]: 0 : GST_ERROR ("Error adding the contents to the gnlobject");
617 : 0 : gst_object_unref (child);
618 : 0 : gst_object_unref (gnlobject);
619 : 69 : return NULL;
620 : : }
621 : : }
622 : :
623 : : static gboolean
624 : 70 : ensure_gnl_object (GESTrackObject * object)
625 : : {
626 : : GESTrackObjectClass *class;
627 : : GstElement *gnlobject;
628 : 70 : gboolean res = FALSE;
629 : :
630 [ - + ][ # # ]: 70 : if (object->priv->gnlobject && object->priv->valid)
631 : 0 : return FALSE;
632 : :
633 : : /* 1. Create the GnlObject */
634 [ - + ]: 70 : GST_DEBUG ("Creating GnlObject");
635 : :
636 : 70 : class = GES_TRACK_OBJECT_GET_CLASS (object);
637 : :
638 [ - + ]: 70 : if (G_UNLIKELY (class->create_gnl_object == NULL)) {
639 [ # # ]: 0 : GST_ERROR ("No 'create_gnl_object' implementation !");
640 : 0 : goto done;
641 : : }
642 : :
643 [ - + ]: 70 : GST_DEBUG ("Calling virtual method");
644 : :
645 : : /* call the create_gnl_object virtual method */
646 : 70 : gnlobject = class->create_gnl_object (object);
647 : :
648 [ - + ]: 70 : if (G_UNLIKELY (gnlobject == NULL)) {
649 [ # # ]: 0 : GST_ERROR
650 : : ("'create_gnl_object' implementation returned TRUE but no GnlObject is available");
651 : 0 : goto done;
652 : : }
653 : :
654 : 70 : object->priv->gnlobject = gnlobject;
655 : :
656 : : /* 2. Fill in the GnlObject */
657 [ + - ]: 70 : if (gnlobject) {
658 [ - + ]: 70 : GST_DEBUG ("Got a valid GnlObject, now filling it in");
659 : :
660 : 70 : res =
661 : 70 : ges_timeline_object_fill_track_object (object->priv->timelineobj,
662 : 70 : object, object->priv->gnlobject);
663 [ + - ]: 70 : if (res) {
664 : : /* Connect to property notifications */
665 : : /* FIXME : remember the signalids so we can remove them later on !!! */
666 : 70 : g_signal_connect (G_OBJECT (object->priv->gnlobject), "notify::start",
667 : : G_CALLBACK (gnlobject_start_cb), object);
668 : 70 : g_signal_connect (G_OBJECT (object->priv->gnlobject),
669 : : "notify::media-start", G_CALLBACK (gnlobject_media_start_cb), object);
670 : 70 : g_signal_connect (G_OBJECT (object->priv->gnlobject), "notify::duration",
671 : : G_CALLBACK (gnlobject_duration_cb), object);
672 : 70 : g_signal_connect (G_OBJECT (object->priv->gnlobject), "notify::priority",
673 : : G_CALLBACK (gnlobject_priority_cb), object);
674 : 70 : g_signal_connect (G_OBJECT (object->priv->gnlobject), "notify::active",
675 : : G_CALLBACK (gnlobject_active_cb), object);
676 : :
677 : : /* Set some properties on the GnlObject */
678 : 70 : g_object_set (object->priv->gnlobject,
679 : 70 : "caps", ges_track_get_caps (object->priv->track),
680 : 70 : "duration", object->priv->pending_duration,
681 : 70 : "media-duration", object->priv->pending_duration,
682 : 70 : "start", object->priv->pending_start,
683 : 70 : "media-start", object->priv->pending_inpoint,
684 : 70 : "priority", object->priv->pending_priority,
685 : 70 : "active", object->priv->pending_active, NULL);
686 : :
687 : : }
688 : : }
689 : :
690 : : done:
691 : 70 : object->priv->valid = res;
692 : :
693 [ - + ]: 70 : GST_DEBUG ("Returning res:%d", res);
694 : :
695 : 70 : return res;
696 : : }
697 : :
698 : : /* INTERNAL USAGE */
699 : : gboolean
700 : 132 : ges_track_object_set_track (GESTrackObject * object, GESTrack * track)
701 : : {
702 [ - + ]: 132 : GST_DEBUG ("object:%p, track:%p", object, track);
703 : :
704 : 132 : object->priv->track = track;
705 : :
706 [ + + ]: 132 : if (object->priv->track)
707 : 70 : return ensure_gnl_object (object);
708 : :
709 : 132 : return TRUE;
710 : : }
711 : :
712 : : /**
713 : : * ges_track_object_get_track:
714 : : * @object: a #GESTrackObject
715 : : *
716 : : * Get the #GESTrack to which this object belongs.
717 : : *
718 : : * Returns: (transfer none): The #GESTrack to which this object belongs. Can be %NULL if it
719 : : * is not in any track
720 : : */
721 : : GESTrack *
722 : 261 : ges_track_object_get_track (GESTrackObject * object)
723 : : {
724 [ - + ][ + - ]: 261 : g_return_val_if_fail (GES_IS_TRACK_OBJECT (object), NULL);
[ - + ][ - + ]
725 : :
726 : 261 : return object->priv->track;
727 : : }
728 : :
729 : :
730 : : void
731 : 148 : ges_track_object_set_timeline_object (GESTrackObject * object,
732 : : GESTimelineObject * tlobj)
733 : : {
734 [ - + ]: 148 : GST_DEBUG ("object:%p, timeline-object:%p", object, tlobj);
735 : :
736 : 148 : object->priv->timelineobj = tlobj;
737 : 148 : }
738 : :
739 : : /**
740 : : * ges_track_object_get_timeline_object:
741 : : * @object: a #GESTrackObject
742 : : *
743 : : * Get the #GESTimelineObject which is controlling this track object
744 : : *
745 : : * Returns: (transfer none): the #GESTimelineObject which is controlling
746 : : * this track object
747 : : */
748 : : GESTimelineObject *
749 : 3 : ges_track_object_get_timeline_object (GESTrackObject * object)
750 : : {
751 [ - + ][ + - ]: 3 : g_return_val_if_fail (GES_IS_TRACK_OBJECT (object), NULL);
[ - + ][ - + ]
752 : :
753 : 3 : return object->priv->timelineobj;
754 : : }
755 : :
756 : : /**
757 : : * ges_track_object_get_gnlobject:
758 : : * @object: a #GESTrackObject
759 : : *
760 : : * Get the GNonLin object this object is controlling.
761 : : *
762 : : * Returns: (transfer none): the GNonLin object this object is controlling.
763 : : */
764 : : GstElement *
765 : 228 : ges_track_object_get_gnlobject (GESTrackObject * object)
766 : : {
767 : 228 : return object->priv->gnlobject;
768 : : }
769 : :
770 : : /**
771 : : * ges_track_object_get_element:
772 : : * @object: a #GESTrackObject
773 : : *
774 : : * Get the #GstElement this track object is controlling within GNonLin.
775 : : *
776 : : * Returns: (transfer none): the #GstElement this track object is controlling
777 : : * within GNonLin.
778 : : */
779 : : GstElement *
780 : 32 : ges_track_object_get_element (GESTrackObject * object)
781 : : {
782 : 32 : return object->priv->element;
783 : : }
784 : :
785 : : /**
786 : : * ges_track_object_set_locked:
787 : : * @object: a #GESTrackObject
788 : : * @locked: whether the object is lock to its parent
789 : : *
790 : : * Set the locking status of the @object in relationship to its controlling
791 : : * #GESTimelineObject. If @locked is %TRUE, then this object will move synchronously
792 : : * with its controlling #GESTimelineObject.
793 : : */
794 : : void
795 : 1 : ges_track_object_set_locked (GESTrackObject * object, gboolean locked)
796 : : {
797 : 1 : object->priv->locked = locked;
798 : 1 : }
799 : :
800 : : /**
801 : : * ges_track_object_is_locked:
802 : : * @object: a #GESTrackObject
803 : : *
804 : : * Let you know if object us locked or not (moving synchronously).
805 : : *
806 : : * Returns: %TRUE if the object is moving synchronously to its controlling
807 : : * #GESTimelineObject, else %FALSE.
808 : : */
809 : : gboolean
810 : 191 : ges_track_object_is_locked (GESTrackObject * object)
811 : : {
812 : 191 : return object->priv->locked;
813 : : }
|