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);
349 gst_event_set_seqnum (event, object->seqnum);
353 gst_event_set_seqnum (event, object->seqnum);
354 GST_INFO_OBJECT (object, "Tweaking seqnum to %i", object->seqnum);
363 switch (GST_EVENT_TYPE (event)) {
365 event = translate_outgoing_seek (object, event);
375 GST_DEBUG_OBJECT (internal, "Calling priv->eventfunc %p", priv->eventfunc);
376 res = priv->eventfunc (internal, parent, event);
382 translate_outgoing_position_query
384 Should only be called:
385 _ if the query is a GST_QUERY_POSITION
386 _ after the query was sent upstream
387 _ if the upstream query returned TRUE
391 translate_incoming_position_query (GnlObject * object, GstQuery * query)
396 gst_query_parse_position (query, &format, &cur);
397 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
398 GST_WARNING_OBJECT (object,
399 "position query is in a format different from time, returning without modifying values");
403 gnl_media_to_object_time (object, (guint64) cur, (guint64 *) & cur2);
405 GST_DEBUG_OBJECT (object,
406 "Adjust position from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
407 GST_TIME_ARGS (cur), GST_TIME_ARGS (cur2));
408 gst_query_set_position (query, GST_FORMAT_TIME, cur2);
415 translate_outgoing_position_query (GnlObject * object, GstQuery * query)
420 gst_query_parse_position (query, &format, &cur);
421 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
422 GST_WARNING_OBJECT (object,
423 "position query is in a format different from time, returning without modifying values");
427 if (G_UNLIKELY (!(gnl_object_to_media_time (object, (guint64) cur,
428 (guint64 *) & cur2)))) {
429 GST_WARNING_OBJECT (object,
430 "Couldn't get media time for %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
434 GST_DEBUG_OBJECT (object,
435 "Adjust position from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
436 GST_TIME_ARGS (cur), GST_TIME_ARGS (cur2));
437 gst_query_set_position (query, GST_FORMAT_TIME, cur2);
444 translate_incoming_duration_query (GnlObject * object, GstQuery * query)
449 gst_query_parse_duration (query, &format, &cur);
450 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
451 GST_WARNING_OBJECT (object,
452 "We can only handle duration queries in GST_FORMAT_TIME");
456 gst_query_set_duration (query, GST_FORMAT_TIME, object->duration);
462 internalpad_query_function (GstPad * internal, GstObject * parent,
465 GnlPadPrivate *priv = gst_pad_get_element_private (internal);
466 GnlObject *object = priv->object;
469 GST_DEBUG_OBJECT (internal, "querytype:%s",
470 gst_query_type_get_name (GST_QUERY_TYPE (query)));
472 if (!(priv->queryfunc)) {
473 GST_WARNING_OBJECT (internal,
474 "priv->queryfunc == NULL !! What is going on ?");
478 if ((ret = priv->queryfunc (internal, parent, query))) {
484 switch (GST_QUERY_TYPE (query)) {
485 case GST_QUERY_POSITION:
486 ret = translate_outgoing_position_query (object, query);
500 ghostpad_event_function (GstPad * ghostpad, GstObject * parent,
505 gboolean ret = FALSE;
507 priv = gst_pad_get_element_private (ghostpad);
508 object = priv->object;
510 GST_DEBUG_OBJECT (ghostpad, "event:%s", GST_EVENT_TYPE_NAME (event));
512 if (G_UNLIKELY (priv->eventfunc == NULL))
518 switch (GST_EVENT_TYPE (event)) {
523 event = gnl_object_translate_incoming_seek (object, event);
524 object->wanted_seqnum = gst_event_get_seqnum (event);
526 if (!(target = gst_ghost_pad_get_target (GST_GHOST_PAD (ghostpad)))) {
527 g_assert ("Seeked a pad with not target SHOULD NOT HAPPEND");
531 gst_object_unref (target);
541 switch (GST_EVENT_TYPE (event)) {
542 case GST_EVENT_SEGMENT:
543 event = translate_incoming_segment (object, event);
555 GST_DEBUG_OBJECT (ghostpad, "Calling priv->eventfunc");
556 ret = priv->eventfunc (ghostpad, parent, event);
557 GST_DEBUG_OBJECT (ghostpad, "Returned from calling priv->eventfunc : %d",
566 GST_WARNING_OBJECT (ghostpad,
567 "priv->eventfunc == NULL !! What's going on ?");
573 ghostpad_query_function (GstPad * ghostpad, GstObject * parent,
576 GnlPadPrivate *priv = gst_pad_get_element_private (ghostpad);
577 GnlObject *object = GNL_OBJECT (parent);
578 gboolean pret = TRUE;
580 GST_DEBUG_OBJECT (ghostpad, "querytype:%s", GST_QUERY_TYPE_NAME (query));
582 switch (GST_QUERY_TYPE (query)) {
583 case GST_QUERY_DURATION:
584 /* skip duration upstream query, we'll fill it in ourselves */
587 pret = priv->queryfunc (ghostpad, parent, query);
591 /* translate result */
592 switch (GST_QUERY_TYPE (query)) {
593 case GST_QUERY_POSITION:
594 pret = translate_incoming_position_query (object, query);
596 case GST_QUERY_DURATION:
597 pret = translate_incoming_duration_query (object, query);
607 /* internal pad going away */
609 internal_pad_finalizing (GnlPadPrivate * priv, GObject * pad G_GNUC_UNUSED)
611 g_slice_free (GnlPadPrivate, priv);
614 static inline GstPad *
615 get_proxy_pad (GstPad * ghostpad)
617 GValue item = { 0, };
621 it = gst_pad_iterate_internal_links (ghostpad);
623 gst_iterator_next (it, &item);
624 ret = g_value_dup_object (&item);
625 g_value_unset (&item);
627 gst_iterator_free (it);
633 control_internal_pad (GstPad * ghostpad, GnlObject * object)
636 GnlPadPrivate *privghost;
640 GST_DEBUG_OBJECT (object, "We don't have a valid ghostpad !");
643 privghost = gst_pad_get_element_private (ghostpad);
645 GST_LOG_OBJECT (ghostpad, "overriding ghostpad's internal pad function");
647 internal = get_proxy_pad (ghostpad);
649 if (G_UNLIKELY (!(priv = gst_pad_get_element_private (internal)))) {
650 GST_DEBUG_OBJECT (internal,
651 "Creating a GnlPadPrivate to put in element_private");
652 priv = g_slice_new0 (GnlPadPrivate);
654 /* Remember existing pad functions */
655 priv->eventfunc = GST_PAD_EVENTFUNC (internal);
656 priv->queryfunc = GST_PAD_QUERYFUNC (internal);
657 gst_pad_set_element_private (internal, priv);
659 g_object_weak_ref ((GObject *) internal,
660 (GWeakNotify) internal_pad_finalizing, priv);
662 /* add query/event function overrides on internal pad */
663 gst_pad_set_event_function (internal,
664 GST_DEBUG_FUNCPTR (internalpad_event_function));
665 gst_pad_set_query_function (internal,
666 GST_DEBUG_FUNCPTR (internalpad_query_function));
669 priv->object = object;
670 priv->ghostpriv = privghost;
671 priv->dir = GST_PAD_DIRECTION (ghostpad);
672 gst_object_unref (internal);
674 GST_DEBUG_OBJECT (ghostpad, "Done with pad %s:%s",
675 GST_DEBUG_PAD_NAME (ghostpad));
680 * gnl_object_ghost_pad:
681 * @object: #GnlObject to add the ghostpad to
682 * @name: Name for the new pad
683 * @target: Target #GstPad to ghost
685 * Adds a #GstGhostPad overridding the correct pad [query|event]_function so
686 * that time shifting is done correctly
687 * The #GstGhostPad is added to the #GnlObject
689 * /!\ This function doesn't check if the existing [src|sink] pad was removed
690 * first, so you might end up with more pads than wanted
692 * Returns: The #GstPad if everything went correctly, else NULL.
695 gnl_object_ghost_pad (GnlObject * object, const gchar * name, GstPad * target)
697 GstPadDirection dir = GST_PAD_DIRECTION (target);
700 GST_DEBUG_OBJECT (object, "name:%s, target:%p", name, target);
702 g_return_val_if_fail (target, FALSE);
703 g_return_val_if_fail ((dir != GST_PAD_UNKNOWN), FALSE);
705 ghost = gnl_object_ghost_pad_no_target (object, name, dir, NULL);
707 GST_WARNING_OBJECT (object, "Couldn't create ghostpad");
711 if (!(gnl_object_ghost_pad_set_target (object, ghost, target))) {
712 GST_WARNING_OBJECT (object,
713 "Couldn't set the target pad... removing ghostpad");
714 gst_object_unref (ghost);
718 GST_DEBUG_OBJECT (object, "activating ghostpad");
720 gst_pad_set_active (ghost, TRUE);
721 /* add it to element */
722 if (!(gst_element_add_pad (GST_ELEMENT (object), ghost))) {
723 GST_WARNING ("couldn't add newly created ghostpad");
731 * gnl_object_ghost_pad_no_target:
732 * /!\ Doesn't add the pad to the GnlObject....
735 gnl_object_ghost_pad_no_target (GnlObject * object, const gchar * name,
736 GstPadDirection dir, GstPadTemplate * template)
741 /* create a no_target ghostpad */
743 ghost = gst_ghost_pad_new_no_target_from_template (name, template);
745 ghost = gst_ghost_pad_new_no_target (name, dir);
750 /* remember the existing ghostpad event/query/link/unlink functions */
751 priv = g_slice_new0 (GnlPadPrivate);
753 priv->object = object;
755 /* grab/replace event/query functions */
756 GST_DEBUG_OBJECT (ghost, "Setting priv->eventfunc to %p",
757 GST_PAD_EVENTFUNC (ghost));
758 priv->eventfunc = GST_PAD_EVENTFUNC (ghost);
759 priv->queryfunc = GST_PAD_QUERYFUNC (ghost);
761 gst_pad_set_event_function (ghost,
762 GST_DEBUG_FUNCPTR (ghostpad_event_function));
763 gst_pad_set_query_function (ghost,
764 GST_DEBUG_FUNCPTR (ghostpad_query_function));
766 gst_pad_set_element_private (ghost, priv);
767 control_internal_pad (ghost, object);
775 gnl_object_remove_ghost_pad (GnlObject * object, GstPad * ghost)
779 GST_DEBUG_OBJECT (object, "ghostpad %s:%s", GST_DEBUG_PAD_NAME (ghost));
781 priv = gst_pad_get_element_private (ghost);
782 gst_ghost_pad_set_target (GST_GHOST_PAD (ghost), NULL);
783 gst_element_remove_pad (GST_ELEMENT (object), ghost);
785 g_slice_free (GnlPadPrivate, priv);
789 gnl_object_ghost_pad_set_target (GnlObject * object, GstPad * ghost,
792 GnlPadPrivate *priv = gst_pad_get_element_private (ghost);
794 g_return_val_if_fail (priv, FALSE);
795 g_return_val_if_fail (GST_IS_PAD (ghost), FALSE);
798 GST_DEBUG_OBJECT (object, "setting target %s:%s on %s:%s",
799 GST_DEBUG_PAD_NAME (target), GST_DEBUG_PAD_NAME (ghost));
801 GST_ERROR_OBJECT (object, "removing target from ghostpad");
802 priv->pending_seek = NULL;
806 if (!(gst_ghost_pad_set_target (GST_GHOST_PAD (ghost), target))) {
807 GST_WARNING_OBJECT (priv->object, "Could not set ghost %s:%s "
808 "target to: %s:%s", GST_DEBUG_PAD_NAME (ghost),
809 GST_DEBUG_PAD_NAME (target));
813 if (target && priv->pending_seek) {
814 gboolean res = gst_pad_send_event (ghost, priv->pending_seek);
816 GST_INFO_OBJECT (object, "Sending our pending seek event: %" GST_PTR_FORMAT
817 " -- Result is %i", priv->pending_seek, res);
819 priv->pending_seek = NULL;
826 gnl_init_ghostpad_category (void)
828 GST_DEBUG_CATEGORY_INIT (gnlghostpad, "gnlghostpad",
829 GST_DEBUG_FG_BLUE | GST_DEBUG_BOLD, "GNonLin GhostPad");