2 * Copyright (C) <2009> Edward Hervey <bilboed@bilboed.com>
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.
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.
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
26 GST_DEBUG_CATEGORY_STATIC (gnlghostpad);
27 #define GST_CAT_DEFAULT gnlghostpad
29 typedef struct _GnlPadPrivate GnlPadPrivate;
34 GnlPadPrivate *ghostpriv;
36 GstPadEventFunction eventfunc;
37 GstPadQueryFunction queryfunc;
39 GstEvent *pending_seek;
43 gnl_object_translate_incoming_seek (GnlObject * object, GstEvent * event)
49 GstSeekType curtype, stoptype;
55 guint32 seqnum = GST_EVENT_SEQNUM (event);
57 gst_event_parse_seek (event, &rate, &format, &flags,
58 &curtype, &cur, &stoptype, &stop);
60 GST_DEBUG_OBJECT (object,
61 "GOT SEEK rate:%f, format:%d, flags:%d, curtype:%d, stoptype:%d, %"
62 GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, format, flags, curtype,
63 stoptype, GST_TIME_ARGS (cur), GST_TIME_ARGS (stop));
65 if (G_UNLIKELY (format != GST_FORMAT_TIME))
69 ncurtype = GST_SEEK_TYPE_SET;
70 if (G_LIKELY ((curtype == GST_SEEK_TYPE_SET)
71 && (gnl_object_to_media_time (object, cur, &ncur)))) {
72 /* cur is TYPE_SET and value is valid */
73 if (ncur > G_MAXINT64)
74 GST_WARNING_OBJECT (object, "return value too big...");
75 GST_LOG_OBJECT (object, "Setting cur to %" GST_TIME_FORMAT,
76 GST_TIME_ARGS (ncur));
77 } else if ((curtype != GST_SEEK_TYPE_NONE)) {
78 GST_DEBUG_OBJECT (object, "Limiting seek start to inpoint");
79 ncur = object->inpoint;
81 GST_DEBUG_OBJECT (object, "leaving GST_SEEK_TYPE_NONE");
83 ncurtype = GST_SEEK_TYPE_NONE;
86 /* convert stop, we also need to limit it to object->stop */
87 if (G_LIKELY ((stoptype == GST_SEEK_TYPE_SET)
88 && (gnl_object_to_media_time (object, stop, &nstop)))) {
89 if (nstop > G_MAXINT64)
90 GST_WARNING_OBJECT (object, "return value too big...");
91 GST_LOG_OBJECT (object, "Setting stop to %" GST_TIME_FORMAT,
92 GST_TIME_ARGS (nstop));
94 GST_DEBUG_OBJECT (object, "Limiting end of seek to media_stop");
95 gnl_object_to_media_time (object, object->stop, &nstop);
96 if (nstop > G_MAXINT64)
97 GST_WARNING_OBJECT (object, "return value too big...");
98 GST_LOG_OBJECT (object, "Setting stop to %" GST_TIME_FORMAT,
99 GST_TIME_ARGS (nstop));
103 /* add accurate seekflags */
104 if (G_UNLIKELY (!(flags & GST_SEEK_FLAG_ACCURATE))) {
105 GST_DEBUG_OBJECT (object, "Adding GST_SEEK_FLAG_ACCURATE");
106 flags |= GST_SEEK_FLAG_ACCURATE;
108 GST_DEBUG_OBJECT (object,
109 "event already has GST_SEEK_FLAG_ACCURATE : %d", flags);
114 GST_DEBUG_OBJECT (object,
115 "SENDING SEEK rate:%f, format:TIME, flags:%d, curtype:%d, stoptype:SET, %"
116 GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, flags, ncurtype,
117 GST_TIME_ARGS (ncur), GST_TIME_ARGS (nstop));
119 event2 = gst_event_new_seek (rate, GST_FORMAT_TIME, flags,
120 ncurtype, (gint64) ncur, GST_SEEK_TYPE_SET, (gint64) nstop);
121 GST_EVENT_SEQNUM (event2) = seqnum;
128 GST_WARNING ("GNonLin time shifting only works with GST_FORMAT_TIME");
134 translate_outgoing_seek (GnlObject * object, GstEvent * event)
140 GstSeekType curtype, stoptype;
141 GstSeekType ncurtype;
146 guint32 seqnum = GST_EVENT_SEQNUM (event);
148 gst_event_parse_seek (event, &rate, &format, &flags,
149 &curtype, &cur, &stoptype, &stop);
151 GST_DEBUG_OBJECT (object,
152 "GOT SEEK rate:%f, format:%d, flags:%d, curtype:%d, stoptype:%d, %"
153 GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, format, flags, curtype,
154 stoptype, GST_TIME_ARGS (cur), GST_TIME_ARGS (stop));
156 if (G_UNLIKELY (format != GST_FORMAT_TIME))
160 ncurtype = GST_SEEK_TYPE_SET;
161 if (G_LIKELY ((curtype == GST_SEEK_TYPE_SET)
162 && (gnl_media_to_object_time (object, cur, &ncur)))) {
163 /* cur is TYPE_SET and value is valid */
164 if (ncur > G_MAXINT64)
165 GST_WARNING_OBJECT (object, "return value too big...");
166 GST_LOG_OBJECT (object, "Setting cur to %" GST_TIME_FORMAT,
167 GST_TIME_ARGS (ncur));
168 } else if ((curtype != GST_SEEK_TYPE_NONE)) {
169 GST_DEBUG_OBJECT (object, "Limiting seek start to start");
170 ncur = object->start;
172 GST_DEBUG_OBJECT (object, "leaving GST_SEEK_TYPE_NONE");
174 ncurtype = GST_SEEK_TYPE_NONE;
177 /* convert stop, we also need to limit it to object->stop */
178 if (G_LIKELY ((stoptype == GST_SEEK_TYPE_SET)
179 && (gnl_media_to_object_time (object, stop, &nstop)))) {
180 if (nstop > G_MAXINT64)
181 GST_WARNING_OBJECT (object, "return value too big...");
182 GST_LOG_OBJECT (object, "Setting stop to %" GST_TIME_FORMAT,
183 GST_TIME_ARGS (nstop));
185 GST_DEBUG_OBJECT (object, "Limiting end of seek to stop");
186 nstop = object->stop;
187 if (nstop > G_MAXINT64)
188 GST_WARNING_OBJECT (object, "return value too big...");
189 GST_LOG_OBJECT (object, "Setting stop to %" GST_TIME_FORMAT,
190 GST_TIME_ARGS (nstop));
193 GST_DEBUG_OBJECT (object,
194 "SENDING SEEK rate:%f, format:TIME, flags:%d, curtype:%d, stoptype:SET, %"
195 GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, flags, ncurtype,
196 GST_TIME_ARGS (ncur), GST_TIME_ARGS (nstop));
198 event2 = gst_event_new_seek (rate, GST_FORMAT_TIME, flags,
199 ncurtype, (gint64) ncur, GST_SEEK_TYPE_SET, (gint64) nstop);
200 GST_EVENT_SEQNUM (event2) = seqnum;
202 gst_event_unref (event);
209 GST_WARNING ("GNonLin time shifting only works with GST_FORMAT_TIME");
215 translate_outgoing_segment (GnlObject * object, GstEvent * event)
217 const GstSegment *orig;
220 guint32 seqnum = GST_EVENT_SEQNUM (event);
222 /* only modify the streamtime */
223 gst_event_parse_segment (event, &orig);
225 GST_DEBUG_OBJECT (object,
226 "Got SEGMENT %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT " // %"
227 GST_TIME_FORMAT, GST_TIME_ARGS (orig->start), GST_TIME_ARGS (orig->stop),
228 GST_TIME_ARGS (orig->time));
230 if (G_UNLIKELY (orig->format != GST_FORMAT_TIME)) {
231 GST_WARNING_OBJECT (object,
232 "Can't translate segments with format != GST_FORMAT_TIME");
236 gst_segment_copy_into (orig, &segment);
238 gnl_media_to_object_time (object, orig->time, &segment.time);
240 if (G_UNLIKELY (segment.time > G_MAXINT64))
241 GST_WARNING_OBJECT (object, "Return value too big...");
243 GST_DEBUG_OBJECT (object,
244 "Sending SEGMENT %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT " // %"
245 GST_TIME_FORMAT, GST_TIME_ARGS (segment.start),
246 GST_TIME_ARGS (segment.stop), GST_TIME_ARGS (segment.time));
248 event2 = gst_event_new_segment (&segment);
249 GST_EVENT_SEQNUM (event2) = seqnum;
250 gst_event_unref (event);
256 translate_incoming_segment (GnlObject * object, GstEvent * event)
259 const GstSegment *orig;
261 guint32 seqnum = GST_EVENT_SEQNUM (event);
263 /* only modify the streamtime */
264 gst_event_parse_segment (event, &orig);
266 GST_DEBUG_OBJECT (object,
267 "Got SEGMENT %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT " // %"
268 GST_TIME_FORMAT, GST_TIME_ARGS (orig->start), GST_TIME_ARGS (orig->stop),
269 GST_TIME_ARGS (orig->time));
271 if (G_UNLIKELY (orig->format != GST_FORMAT_TIME)) {
272 GST_WARNING_OBJECT (object,
273 "Can't translate segments with format != GST_FORMAT_TIME");
277 gst_segment_copy_into (orig, &segment);
279 if (!gnl_object_to_media_time (object, orig->time, &segment.time)) {
280 GST_DEBUG ("Can't convert media_time, using 0");
284 if (GNL_IS_OPERATION (object)) {
285 segment.base = GNL_OPERATION (object)->next_base_time;
286 GST_INFO_OBJECT (object, "Using operation base time %" GST_TIME_FORMAT,
287 GST_TIME_ARGS (GNL_OPERATION (object)->next_base_time));
290 if (G_UNLIKELY (segment.time > G_MAXINT64))
291 GST_WARNING_OBJECT (object, "Return value too big...");
293 GST_DEBUG_OBJECT (object,
294 "Sending SEGMENT %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT " // %"
295 GST_TIME_FORMAT, GST_TIME_ARGS (segment.start),
296 GST_TIME_ARGS (segment.stop), GST_TIME_ARGS (segment.time));
298 event2 = gst_event_new_segment (&segment);
299 GST_EVENT_SEQNUM (event2) = seqnum;
300 gst_event_unref (event);
302 if (object->seqnum) {
303 gst_event_set_seqnum (event, object->seqnum);
310 internalpad_event_function (GstPad * internal, GstObject * parent,
313 GnlPadPrivate *priv = gst_pad_get_element_private (internal);
314 GnlObject *object = priv->object;
317 GST_DEBUG_OBJECT (internal, "event:%s (seqnum::%d)",
318 GST_EVENT_TYPE_NAME (event), GST_EVENT_SEQNUM (event));
320 if (G_UNLIKELY (!(priv->eventfunc))) {
321 GST_WARNING_OBJECT (internal,
322 "priv->eventfunc == NULL !! What is going on ?");
328 switch (GST_EVENT_TYPE (event)) {
330 object->wanted_seqnum = gst_event_get_seqnum (event);
332 GST_DEBUG_OBJECT (object, "Setting wanted_seqnum to %i",
333 object->wanted_seqnum);
335 case GST_EVENT_SEGMENT:
336 if (object->wanted_seqnum == 0) {
337 g_assert ("All gnlobject should be seeked at one point or another"
338 " and thus we should always have a wanted_seqnum when getting"
339 " a new segment" == NULL);
342 GST_DEBUG_OBJECT (object, "Got segment, seqnum-> %i (wanted %i)",
343 gst_event_get_seqnum (event), object->wanted_seqnum);
345 object->seqnum = object->wanted_seqnum;
346 object->wanted_seqnum = 0;
348 event = translate_outgoing_segment (object, event);
352 gst_event_set_seqnum (event, object->seqnum);
353 GST_INFO_OBJECT (object, "Tweaking seqnum to %i", object->seqnum);
362 switch (GST_EVENT_TYPE (event)) {
364 event = translate_outgoing_seek (object, event);
374 GST_DEBUG_OBJECT (internal, "Calling priv->eventfunc %p", priv->eventfunc);
375 res = priv->eventfunc (internal, parent, event);
381 translate_outgoing_position_query
383 Should only be called:
384 _ if the query is a GST_QUERY_POSITION
385 _ after the query was sent upstream
386 _ if the upstream query returned TRUE
390 translate_incoming_position_query (GnlObject * object, GstQuery * query)
395 gst_query_parse_position (query, &format, &cur);
396 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
397 GST_WARNING_OBJECT (object,
398 "position query is in a format different from time, returning without modifying values");
402 gnl_media_to_object_time (object, (guint64) cur, (guint64 *) & cur2);
404 GST_DEBUG_OBJECT (object,
405 "Adjust position from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
406 GST_TIME_ARGS (cur), GST_TIME_ARGS (cur2));
407 gst_query_set_position (query, GST_FORMAT_TIME, cur2);
414 translate_outgoing_position_query (GnlObject * object, GstQuery * query)
419 gst_query_parse_position (query, &format, &cur);
420 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
421 GST_WARNING_OBJECT (object,
422 "position query is in a format different from time, returning without modifying values");
426 if (G_UNLIKELY (!(gnl_object_to_media_time (object, (guint64) cur,
427 (guint64 *) & cur2)))) {
428 GST_WARNING_OBJECT (object,
429 "Couldn't get media time for %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
433 GST_DEBUG_OBJECT (object,
434 "Adjust position from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
435 GST_TIME_ARGS (cur), GST_TIME_ARGS (cur2));
436 gst_query_set_position (query, GST_FORMAT_TIME, cur2);
443 translate_incoming_duration_query (GnlObject * object, GstQuery * query)
448 gst_query_parse_duration (query, &format, &cur);
449 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
450 GST_WARNING_OBJECT (object,
451 "We can only handle duration queries in GST_FORMAT_TIME");
455 gst_query_set_duration (query, GST_FORMAT_TIME, object->duration);
461 internalpad_query_function (GstPad * internal, GstObject * parent,
464 GnlPadPrivate *priv = gst_pad_get_element_private (internal);
465 GnlObject *object = priv->object;
468 GST_DEBUG_OBJECT (internal, "querytype:%s",
469 gst_query_type_get_name (GST_QUERY_TYPE (query)));
471 if (!(priv->queryfunc)) {
472 GST_WARNING_OBJECT (internal,
473 "priv->queryfunc == NULL !! What is going on ?");
477 if ((ret = priv->queryfunc (internal, parent, query))) {
483 switch (GST_QUERY_TYPE (query)) {
484 case GST_QUERY_POSITION:
485 ret = translate_outgoing_position_query (object, query);
499 ghostpad_event_function (GstPad * ghostpad, GstObject * parent,
504 gboolean ret = FALSE;
506 priv = gst_pad_get_element_private (ghostpad);
507 object = priv->object;
509 GST_DEBUG_OBJECT (ghostpad, "event:%s", GST_EVENT_TYPE_NAME (event));
511 if (G_UNLIKELY (priv->eventfunc == NULL))
517 switch (GST_EVENT_TYPE (event)) {
522 event = gnl_object_translate_incoming_seek (object, event);
523 object->wanted_seqnum = gst_event_get_seqnum (event);
525 if (!(target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghostpad)))) {
526 g_assert ("Seeked a pad with not target SHOULD NOT HAPPEND");
530 gst_object_unref (target);
540 switch (GST_EVENT_TYPE (event)) {
541 case GST_EVENT_SEGMENT:
542 event = translate_incoming_segment (object, event);
554 GST_DEBUG_OBJECT (ghostpad, "Calling priv->eventfunc");
555 ret = priv->eventfunc (ghostpad, parent, event);
556 GST_DEBUG_OBJECT (ghostpad, "Returned from calling priv->eventfunc : %d",
565 GST_WARNING_OBJECT (ghostpad,
566 "priv->eventfunc == NULL !! What's going on ?");
572 ghostpad_query_function (GstPad * ghostpad, GstObject * parent,
575 GnlPadPrivate *priv = gst_pad_get_element_private (ghostpad);
576 GnlObject *object = GNL_OBJECT (parent);
577 gboolean pret = TRUE;
579 GST_DEBUG_OBJECT (ghostpad, "querytype:%s", GST_QUERY_TYPE_NAME (query));
581 switch (GST_QUERY_TYPE (query)) {
582 case GST_QUERY_DURATION:
583 /* skip duration upstream query, we'll fill it in ourselves */
586 pret = priv->queryfunc (ghostpad, parent, query);
590 /* translate result */
591 switch (GST_QUERY_TYPE (query)) {
592 case GST_QUERY_POSITION:
593 pret = translate_incoming_position_query (object, query);
595 case GST_QUERY_DURATION:
596 pret = translate_incoming_duration_query (object, query);
606 /* internal pad going away */
608 internal_pad_finalizing (GnlPadPrivate * priv, GObject * pad G_GNUC_UNUSED)
610 g_slice_free (GnlPadPrivate, priv);
613 static inline GstPad *
614 get_proxy_pad (GstPad * ghostpad)
616 GValue item = { 0, };
620 it = gst_pad_iterate_internal_links (ghostpad);
622 gst_iterator_next (it, &item);
623 ret = g_value_dup_object (&item);
624 g_value_unset (&item);
626 gst_iterator_free (it);
632 control_internal_pad (GstPad * ghostpad, GnlObject * object)
635 GnlPadPrivate *privghost;
639 GST_DEBUG_OBJECT (object, "We don't have a valid ghostpad !");
642 privghost = gst_pad_get_element_private (ghostpad);
644 GST_LOG_OBJECT (ghostpad, "overriding ghostpad's internal pad function");
646 internal = get_proxy_pad (ghostpad);
648 if (G_UNLIKELY (!(priv = gst_pad_get_element_private (internal)))) {
649 GST_DEBUG_OBJECT (internal,
650 "Creating a GnlPadPrivate to put in element_private");
651 priv = g_slice_new0 (GnlPadPrivate);
653 /* Remember existing pad functions */
654 priv->eventfunc = GST_PAD_EVENTFUNC (internal);
655 priv->queryfunc = GST_PAD_QUERYFUNC (internal);
656 gst_pad_set_element_private (internal, priv);
658 g_object_weak_ref ((GObject *) internal,
659 (GWeakNotify) internal_pad_finalizing, priv);
661 /* add query/event function overrides on internal pad */
662 gst_pad_set_event_function (internal,
663 GST_DEBUG_FUNCPTR (internalpad_event_function));
664 gst_pad_set_query_function (internal,
665 GST_DEBUG_FUNCPTR (internalpad_query_function));
668 priv->object = object;
669 priv->ghostpriv = privghost;
670 priv->dir = GST_PAD_DIRECTION (ghostpad);
671 gst_object_unref (internal);
673 GST_DEBUG_OBJECT (ghostpad, "Done with pad %s:%s",
674 GST_DEBUG_PAD_NAME (ghostpad));
679 * gnl_object_ghost_pad:
680 * @object: #GnlObject to add the ghostpad to
681 * @name: Name for the new pad
682 * @target: Target #GstPad to ghost
684 * Adds a #GstGhostPad overridding the correct pad [query|event]_function so
685 * that time shifting is done correctly
686 * The #GstGhostPad is added to the #GnlObject
688 * /!\ This function doesn't check if the existing [src|sink] pad was removed
689 * first, so you might end up with more pads than wanted
691 * Returns: The #GstPad if everything went correctly, else NULL.
694 gnl_object_ghost_pad (GnlObject * object, const gchar * name, GstPad * target)
696 GstPadDirection dir = GST_PAD_DIRECTION (target);
699 GST_DEBUG_OBJECT (object, "name:%s, target:%p", name, target);
701 g_return_val_if_fail (target, FALSE);
702 g_return_val_if_fail ((dir != GST_PAD_UNKNOWN), FALSE);
704 ghost = gnl_object_ghost_pad_no_target (object, name, dir, NULL);
706 GST_WARNING_OBJECT (object, "Couldn't create ghostpad");
710 if (!(gnl_object_ghost_pad_set_target (object, ghost, target))) {
711 GST_WARNING_OBJECT (object,
712 "Couldn't set the target pad... removing ghostpad");
713 gst_object_unref (ghost);
717 GST_DEBUG_OBJECT (object, "activating ghostpad");
719 gst_pad_set_active (ghost, TRUE);
720 /* add it to element */
721 if (!(gst_element_add_pad (GST_ELEMENT (object), ghost))) {
722 GST_WARNING ("couldn't add newly created ghostpad");
730 * gnl_object_ghost_pad_no_target:
731 * /!\ Doesn't add the pad to the GnlObject....
734 gnl_object_ghost_pad_no_target (GnlObject * object, const gchar * name,
735 GstPadDirection dir, GstPadTemplate * template)
740 /* create a no_target ghostpad */
742 ghost = gst_ghost_pad_new_no_target_from_template (name, template);
744 ghost = gst_ghost_pad_new_no_target (name, dir);
749 /* remember the existing ghostpad event/query/link/unlink functions */
750 priv = g_slice_new0 (GnlPadPrivate);
752 priv->object = object;
754 /* grab/replace event/query functions */
755 GST_DEBUG_OBJECT (ghost, "Setting priv->eventfunc to %p",
756 GST_PAD_EVENTFUNC (ghost));
757 priv->eventfunc = GST_PAD_EVENTFUNC (ghost);
758 priv->queryfunc = GST_PAD_QUERYFUNC (ghost);
760 gst_pad_set_event_function (ghost,
761 GST_DEBUG_FUNCPTR (ghostpad_event_function));
762 gst_pad_set_query_function (ghost,
763 GST_DEBUG_FUNCPTR (ghostpad_query_function));
765 gst_pad_set_element_private (ghost, priv);
766 control_internal_pad (ghost, object);
774 gnl_object_remove_ghost_pad (GnlObject * object, GstPad * ghost)
778 GST_DEBUG_OBJECT (object, "ghostpad %s:%s", GST_DEBUG_PAD_NAME (ghost));
780 priv = gst_pad_get_element_private (ghost);
781 gst_ghost_pad_set_target (GST_GHOST_PAD (ghost), NULL);
782 gst_element_remove_pad (GST_ELEMENT (object), ghost);
784 g_slice_free (GnlPadPrivate, priv);
788 gnl_object_ghost_pad_set_target (GnlObject * object, GstPad * ghost,
791 GnlPadPrivate *priv = gst_pad_get_element_private (ghost);
793 g_return_val_if_fail (priv, FALSE);
794 g_return_val_if_fail (GST_IS_PAD (ghost), FALSE);
797 GST_DEBUG_OBJECT (object, "setting target %s:%s on %s:%s",
798 GST_DEBUG_PAD_NAME (target), GST_DEBUG_PAD_NAME (ghost));
800 GST_ERROR_OBJECT (object, "removing target from ghostpad");
801 priv->pending_seek = NULL;
805 if (!(gst_ghost_pad_set_target (GST_GHOST_PAD (ghost), target))) {
806 GST_WARNING_OBJECT (priv->object, "Could not set ghost %s:%s "
807 "target to: %s:%s", GST_DEBUG_PAD_NAME (ghost),
808 GST_DEBUG_PAD_NAME (target));
812 if (target && priv->pending_seek) {
813 gboolean res = gst_pad_send_event (ghost, priv->pending_seek);
815 GST_INFO_OBJECT (object, "Sending our pending seek event: %" GST_PTR_FORMAT
816 " -- Result is %i", priv->pending_seek, res);
818 priv->pending_seek = NULL;
825 gnl_init_ghostpad_category (void)
827 GST_DEBUG_CATEGORY_INIT (gnlghostpad, "gnlghostpad",
828 GST_DEBUG_FG_BLUE | GST_DEBUG_BOLD, "GNonLin GhostPad");