2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstpad.c: Pads for connecting elements together
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
27 #include "gstelement.h"
32 /***** Start with the base GstPad class *****/
33 static void gst_pad_class_init (GstPadClass *klass);
34 static void gst_pad_init (GstPad *pad);
36 static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
39 static GstObject *pad_parent_class = NULL;
42 gst_pad_get_type(void) {
43 static GtkType pad_type = 0;
46 static const GtkTypeInfo pad_info = {
50 (GtkClassInitFunc)gst_pad_class_init,
51 (GtkObjectInitFunc)gst_pad_init,
54 (GtkClassInitFunc)NULL,
56 pad_type = gtk_type_unique(GST_TYPE_OBJECT,&pad_info);
62 gst_pad_class_init (GstPadClass *klass)
64 pad_parent_class = gtk_type_class(GST_TYPE_OBJECT);
68 gst_pad_init (GstPad *pad)
70 pad->element_private = NULL;
72 pad->padtemplate = NULL;
77 /***** Then do the Real Pad *****/
78 /* Pad signals and args */
92 static void gst_real_pad_class_init (GstRealPadClass *klass);
93 static void gst_real_pad_init (GstRealPad *pad);
95 static void gst_real_pad_set_arg (GtkObject *object,GtkArg *arg,guint id);
96 static void gst_real_pad_get_arg (GtkObject *object,GtkArg *arg,guint id);
98 static void gst_real_pad_destroy (GtkObject *object);
100 static void gst_pad_push_func (GstPad *pad, GstBuffer *buf);
101 static gboolean gst_pad_eos_func (GstPad *pad);
104 static GstPad *real_pad_parent_class = NULL;
105 static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
108 gst_real_pad_get_type(void) {
109 static GtkType pad_type = 0;
112 static const GtkTypeInfo pad_info = {
115 sizeof(GstRealPadClass),
116 (GtkClassInitFunc)gst_real_pad_class_init,
117 (GtkObjectInitFunc)gst_real_pad_init,
120 (GtkClassInitFunc)NULL,
122 pad_type = gtk_type_unique(GST_TYPE_PAD,&pad_info);
128 gst_real_pad_class_init (GstRealPadClass *klass)
130 GtkObjectClass *gtkobject_class;
131 GstObjectClass *gstobject_class;
133 gtkobject_class = (GtkObjectClass*)klass;
134 gstobject_class = (GstObjectClass*)klass;
136 real_pad_parent_class = gtk_type_class(GST_TYPE_PAD);
138 gst_real_pad_signals[REAL_SET_ACTIVE] =
139 gtk_signal_new ("set_active", GTK_RUN_LAST, gtkobject_class->type,
140 GTK_SIGNAL_OFFSET (GstRealPadClass, set_active),
141 gtk_marshal_NONE__BOOL, GTK_TYPE_NONE, 1,
143 gst_real_pad_signals[REAL_CAPS_CHANGED] =
144 gtk_signal_new ("caps_changed", GTK_RUN_LAST, gtkobject_class->type,
145 GTK_SIGNAL_OFFSET (GstRealPadClass, caps_changed),
146 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
148 gtk_object_class_add_signals (gtkobject_class, gst_real_pad_signals, REAL_LAST_SIGNAL);
150 gtk_object_add_arg_type ("GstRealPad::active", GTK_TYPE_BOOL,
151 GTK_ARG_READWRITE, REAL_ARG_ACTIVE);
153 gtkobject_class->destroy = gst_real_pad_destroy;
154 gtkobject_class->set_arg = gst_real_pad_set_arg;
155 gtkobject_class->get_arg = gst_real_pad_get_arg;
157 gstobject_class->save_thyself = gst_pad_save_thyself;
158 gstobject_class->path_string_separator = ".";
162 gst_real_pad_init (GstRealPad *pad)
164 pad->direction = GST_PAD_UNKNOWN;
167 pad->chainfunc = NULL;
169 pad->getregionfunc = NULL;
171 pad->eosfunc = gst_pad_eos_func;
173 pad->pushfunc = GST_DEBUG_FUNCPTR(gst_pad_push_func);
174 pad->pullfunc = NULL;
175 pad->pullregionfunc = NULL;
177 pad->ghostpads = NULL;
182 gst_real_pad_set_arg (GtkObject *object, GtkArg *arg, guint id)
184 g_return_if_fail(GST_IS_PAD(object));
187 case REAL_ARG_ACTIVE:
188 if (GTK_VALUE_BOOL(*arg)) {
189 gst_info("gstpad: activating pad\n");
190 GST_FLAG_UNSET(object,GST_PAD_DISABLED);
192 gst_info("gstpad: de-activating pad\n");
193 GST_FLAG_SET(object,GST_PAD_DISABLED);
195 gtk_signal_emit(GTK_OBJECT(object), gst_real_pad_signals[REAL_SET_ACTIVE],
196 ! GST_FLAG_IS_SET(object,GST_PAD_DISABLED));
204 gst_real_pad_get_arg (GtkObject *object, GtkArg *arg, guint id)
206 /* it's not null if we got it, but it might not be ours */
207 g_return_if_fail (GST_IS_PAD (object));
210 case REAL_ARG_ACTIVE:
211 GTK_VALUE_BOOL (*arg) = ! GST_FLAG_IS_SET (object, GST_PAD_DISABLED);
221 * @name: name of new pad
222 * @direction: either GST_PAD_SRC or GST_PAD_SINK
224 * Create a new pad with given name.
229 gst_pad_new (gchar *name,
230 GstPadDirection direction)
234 g_return_val_if_fail (name != NULL, NULL);
235 g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
237 pad = gtk_type_new (gst_real_pad_get_type ());
238 gst_object_set_name (GST_OBJECT (pad), name);
239 GST_RPAD_DIRECTION(pad) = direction;
245 * gst_pad_new_from_template:
246 * @templ: the pad template to use
247 * @name: the name of the element
249 * Create a new pad with given name from the given template.
254 gst_pad_new_from_template (GstPadTemplate *templ,
259 g_return_val_if_fail (name != NULL, NULL);
260 g_return_val_if_fail (templ != NULL, NULL);
262 pad = gst_pad_new (name, templ->direction);
263 GST_PAD_CAPS(pad) = templ->caps;
264 GST_PAD_PADTEMPLATE(pad) = templ;
270 * gst_pad_get_direction:
271 * @pad: the Pad to get the direction from
273 * Get the direction of the pad.
275 * Returns: the direction of the pad
278 gst_pad_get_direction (GstPad *pad)
280 g_return_val_if_fail (pad != NULL, GST_PAD_UNKNOWN);
281 g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
283 return GST_PAD_DIRECTION(pad);
288 * @pad: the pad to set the name of
289 * @name: the name of the pad
291 * Set the name of a pad.
294 gst_pad_set_name (GstPad *pad,
297 g_return_if_fail (pad != NULL);
298 g_return_if_fail (GST_IS_PAD (pad));
300 gst_object_set_name (GST_OBJECT (pad), name);
305 * @pad: the pad to get the name of
307 * Get the name of a pad.
309 * Returns: the name of the pad, don't free.
312 gst_pad_get_name (GstPad *pad)
314 g_return_val_if_fail (pad != NULL, NULL);
315 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
317 return GST_OBJECT_NAME (pad);
321 * gst_pad_set_chain_function:
322 * @pad: the pad to set the chain function for
323 * @chain: the chain function
325 * Set the given chain function for the pad.
327 void gst_pad_set_chain_function (GstPad *pad,
328 GstPadChainFunction chain)
330 g_return_if_fail (pad != NULL);
331 g_return_if_fail (GST_IS_REAL_PAD (pad));
333 GST_RPAD_CHAINFUNC(pad) = chain;
334 GST_DEBUG (0,"chainfunc for %s:%s(@%p) at %p is set to %p\n",
335 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_CHAINFUNC(pad),chain);
339 * gst_pad_set_get_function:
340 * @pad: the pad to set the get function for
341 * @get: the get function
343 * Set the given get function for the pad.
346 gst_pad_set_get_function (GstPad *pad,
347 GstPadGetFunction get)
349 g_return_if_fail (pad != NULL);
350 g_return_if_fail (GST_IS_REAL_PAD (pad));
352 GST_RPAD_GETFUNC(pad) = get;
353 GST_DEBUG (0,"getfunc for %s:%s(@%p) at %p is set to %p\n",
354 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_GETFUNC(pad),get);
358 * gst_pad_set_getregion_function:
359 * @pad: the pad to set the getregion function for
360 * @getregion: the getregion function
362 * Set the given getregion function for the pad.
365 gst_pad_set_getregion_function (GstPad *pad,
366 GstPadGetRegionFunction getregion)
368 g_return_if_fail (pad != NULL);
369 g_return_if_fail (GST_IS_REAL_PAD (pad));
371 GST_RPAD_GETREGIONFUNC(pad) = getregion;
372 GST_DEBUG (0,"getregionfunc for %s:%s(@%p) at %p is set to %p\n",
373 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_GETREGIONFUNC(pad),getregion);
377 * gst_pad_set_qos_function:
378 * @pad: the pad to set the qos function for
379 * @qos: the qos function
381 * Set the given qos function for the pad.
384 gst_pad_set_qos_function (GstPad *pad,
385 GstPadQoSFunction qos)
387 g_return_if_fail (pad != NULL);
388 g_return_if_fail (GST_IS_REAL_PAD (pad));
390 GST_RPAD_QOSFUNC(pad) = qos;
391 GST_DEBUG (0,"qosfunc for %s:%s(@%p) at %p is set to %p\n",
392 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_QOSFUNC(pad),qos);
396 * gst_pad_set_eos_function:
397 * @pad: the pad to set the eos function for
398 * @eos: the eos function
400 * Set the given EOS function for the pad.
403 gst_pad_set_eos_function (GstPad *pad,
404 GstPadEOSFunction eos)
406 g_return_if_fail (pad != NULL);
407 g_return_if_fail (GST_IS_REAL_PAD (pad));
409 GST_RPAD_EOSFUNC(pad) = eos;
410 GST_DEBUG (0,"eosfunc for %s:%s(@%p) at %p is set to %p\n",
411 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_EOSFUNC(pad),eos);
417 gst_pad_push_func(GstPad *pad, GstBuffer *buf)
419 if (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)) != NULL) {
420 GST_DEBUG (0,"calling chain function\n");
421 (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)))(pad,buf);
423 GST_DEBUG (0,"got a problem here: default pad_push handler in place, no chain function\n");
429 * gst_pad_handle_qos:
430 * @pad: the pad to handle the QoS message
431 * @qos_message: the QoS message to handle
433 * Pass the qos message downstream.
436 gst_pad_handle_qos(GstPad *pad,
443 GST_DEBUG (0,"gst_pad_handle_qos(\"%s\",%08ld)\n", GST_OBJECT_NAME (GST_PAD_PARENT (pad)),qos_message);
445 if (GST_RPAD_QOSFUNC(pad)) {
446 (GST_RPAD_QOSFUNC(pad)) (pad,qos_message);
448 element = GST_ELEMENT (GST_PAD_PARENT(GST_RPAD_PEER(pad)));
450 pads = element->pads;
451 GST_DEBUG (0,"gst_pad_handle_qos recurse(\"%s\",%08ld)\n", GST_ELEMENT_NAME (element), qos_message);
453 target_pad = GST_PAD (pads->data);
454 if (GST_RPAD_DIRECTION(target_pad) == GST_PAD_SINK) {
455 gst_pad_handle_qos (target_pad, qos_message);
457 pads = g_list_next (pads);
465 * gst_pad_disconnect:
466 * @srcpad: the source pad to disconnect
467 * @sinkpad: the sink pad to disconnect
469 * Disconnects the source pad from the sink pad.
472 gst_pad_disconnect (GstPad *srcpad,
475 GstRealPad *realsrc, *realsink;
478 g_return_if_fail (srcpad != NULL);
479 g_return_if_fail (GST_IS_PAD (srcpad));
480 g_return_if_fail (sinkpad != NULL);
481 g_return_if_fail (GST_IS_PAD (sinkpad));
483 // now we need to deal with the real/ghost stuff
484 realsrc = GST_PAD_REALIZE(srcpad);
485 realsink = GST_PAD_REALIZE(sinkpad);
487 g_return_if_fail (GST_RPAD_PEER(realsrc) != NULL);
488 g_return_if_fail (GST_RPAD_PEER(realsink) != NULL);
490 g_return_if_fail ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
491 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
493 /* first clear peers */
494 GST_RPAD_PEER(realsrc) = NULL;
495 GST_RPAD_PEER(realsink) = NULL;
497 GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s",
498 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
503 * @srcpad: the source pad to connect
504 * @sinkpad: the sink pad to connect
506 * Connects the source pad to the sink pad.
509 gst_pad_connect (GstPad *srcpad,
512 GstRealPad *realsrc, *realsink;
516 g_return_if_fail(srcpad != NULL);
517 g_return_if_fail(GST_IS_PAD(srcpad));
518 g_return_if_fail(sinkpad != NULL);
519 g_return_if_fail(GST_IS_PAD(sinkpad));
521 // now we need to deal with the real/ghost stuff
522 realsrc = GST_PAD_REALIZE(srcpad);
523 realsink = GST_PAD_REALIZE(sinkpad);
525 g_return_if_fail(GST_RPAD_PEER(realsrc) == NULL);
526 g_return_if_fail(GST_RPAD_PEER(realsink) == NULL);
528 /* check for reversed directions and swap if necessary */
529 if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
530 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SRC)) {
535 g_return_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
536 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
538 if (!gst_pad_check_compatibility (srcpad, sinkpad)) {
539 g_warning ("gstpad: connecting incompatible pads (%s:%s) and (%s:%s)\n",
540 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
543 GST_DEBUG (0,"gstpad: connecting compatible pads (%s:%s) and (%s:%s)\n",
544 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
547 /* first set peers */
548 GST_RPAD_PEER(realsrc) = realsink;
549 GST_RPAD_PEER(realsink) = realsrc;
551 /* set the connected flag */
552 /* FIXME: set connected flag */
554 GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s",
555 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
559 * gst_pad_set_parent:
560 * @pad: the pad to set the parent
561 * @parent: the object to set the parent to
563 * Sets the parent object of a pad.
566 gst_pad_set_parent (GstPad *pad,
569 g_return_if_fail (pad != NULL);
570 g_return_if_fail (GST_IS_PAD (pad));
571 g_return_if_fail (GST_PAD_PARENT (pad) == NULL);
572 g_return_if_fail (parent != NULL);
573 g_return_if_fail (GTK_IS_OBJECT (parent));
574 g_return_if_fail ((gpointer)pad != (gpointer)parent);
576 gst_object_set_parent (GST_OBJECT (pad), parent);
580 * gst_pad_get_parent:
581 * @pad: the pad to get the parent from
583 * Get the parent object of this pad.
585 * Returns: the parent object
588 gst_pad_get_parent (GstPad *pad)
590 g_return_val_if_fail (pad != NULL, NULL);
591 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
593 return GST_OBJECT_PARENT (pad);
597 * gst_pad_add_ghost_pad:
598 * @pad: the pad to set the ghost parent
599 * @ghostpad: the ghost pad to add
601 * Add a ghost pad to a pad.
604 gst_pad_add_ghost_pad (GstPad *pad,
609 g_return_if_fail (pad != NULL);
610 g_return_if_fail (GST_IS_PAD (pad));
611 g_return_if_fail (ghostpad != NULL);
612 g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
614 realpad = GST_PAD_REALIZE(pad);
616 realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad);
621 * gst_pad_remove_ghost_pad:
622 * @pad: the pad to remove the ghost parent
623 * @ghostpad: the ghost pad to remove from the pad
625 * Remove a ghost pad from a pad.
628 gst_pad_remove_ghost_pad (GstPad *pad,
633 g_return_if_fail (pad != NULL);
634 g_return_if_fail (GST_IS_PAD (pad));
635 g_return_if_fail (ghostpad != NULL);
636 g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
638 realpad = GST_PAD_REALIZE (pad);
640 realpad->ghostpads = g_list_remove (realpad->ghostpads, ghostpad);
644 * gst_pad_get_ghost_pad_list:
645 * @pad: the pad to get the ghost parents from
647 * Get the ghost parents of this pad.
649 * Returns: a GList of ghost pads
652 gst_pad_get_ghost_pad_list (GstPad *pad)
654 g_return_val_if_fail (pad != NULL, NULL);
655 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
657 return GST_PAD_REALIZE(pad)->ghostpads;
661 * gst_pad_set_caps_list:
662 * @pad: the pad to set the caps to
663 * @caps: a GList of the capabilities to attach to this pad
665 * Set the capabilities of this pad.
668 gst_pad_set_caps_list (GstPad *pad,
671 g_return_if_fail (pad != NULL);
672 g_return_if_fail (GST_IS_REAL_PAD (pad)); // NOTE this restriction
674 GST_PAD_CAPS(pad) = caps;
678 * gst_pad_get_caps_list:
679 * @pad: the pad to get the capabilities from
681 * Get the capabilities of this pad.
683 * Returns: a list of the capabilities of this pad
686 gst_pad_get_caps_list (GstPad *pad)
688 g_return_val_if_fail (pad != NULL, NULL);
689 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
691 return GST_PAD_CAPS(pad);
695 * gst_pad_get_caps_by_name:
696 * @pad: the pad to get the capabilities from
697 * @name: the name of the capability to get
699 * Get the capabilities with the given name from this pad.
701 * Returns: a capability or NULL if not found
704 gst_pad_get_caps_by_name (GstPad *pad, gchar *name)
708 g_return_val_if_fail (pad != NULL, NULL);
709 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
711 caps = GST_PAD_CAPS(pad);
714 GstCaps *cap = (GstCaps *)caps->data;
716 if (!strcmp (cap->name, name))
719 caps = g_list_next (caps);
726 * gst_pad_check_compatibility:
727 * @srcpad: the srcpad to check
728 * @sinkpad: the sinkpad to check against
730 * Check if two pads have compatible capabilities.
732 * Returns: TRUE if they are compatible or the capabilities
733 * could not be checked
736 gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
738 GstRealPad *realsrc, *realsink;
740 g_return_val_if_fail (srcpad != NULL, FALSE);
741 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
742 g_return_val_if_fail (sinkpad != NULL, FALSE);
743 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
745 realsrc = GST_PAD_REALIZE(srcpad);
746 realsink = GST_PAD_REALIZE(sinkpad);
748 if (GST_RPAD_CAPS(realsrc) && GST_RPAD_CAPS(realsink)) {
749 if (!gst_caps_list_check_compatibility (GST_RPAD_CAPS(realsrc), GST_RPAD_CAPS(realsink))) {
757 GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s)\n",
758 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
765 * @pad: the pad to get the peer from
767 * Get the peer pad of this pad.
769 * Returns: the peer pad
772 gst_pad_get_peer (GstPad *pad)
774 g_return_val_if_fail (pad != NULL, NULL);
775 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
777 return GST_PAD(GST_PAD_PEER(pad));
780 // FIXME this needs to be rethought soon
782 gst_real_pad_destroy (GtkObject *object)
784 GstPad *pad = GST_PAD (object);
786 // g_print("in gst_pad_real_destroy()\n");
788 g_list_free (GST_REAL_PAD(pad)->ghostpads);
793 * gst_pad_load_and_connect:
794 * @self: the XML node to read the description from
795 * @parent: the element that has the pad
797 * Read the pad definition from the XML node and connect the given pad
798 * in element to a pad of an element up in the hierarchy.
801 gst_pad_load_and_connect (xmlNodePtr self,
804 xmlNodePtr field = self->childs;
805 GstPad *pad = NULL, *targetpad;
809 GstObject *grandparent;
812 if (!strcmp (field->name, "name")) {
813 pad = gst_element_get_pad (GST_ELEMENT (parent), xmlNodeGetContent (field));
815 else if (!strcmp(field->name, "peer")) {
816 peer = g_strdup (xmlNodeGetContent (field));
820 g_return_if_fail (pad != NULL);
822 if (peer == NULL) return;
824 split = g_strsplit (peer, ".", 2);
826 g_return_if_fail (split[0] != NULL);
827 g_return_if_fail (split[1] != NULL);
829 grandparent = gst_object_get_parent (parent);
831 if (grandparent && GST_IS_BIN (grandparent)) {
832 target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]);
837 if (target == NULL) goto cleanup;
839 targetpad = gst_element_get_pad (target, split[1]);
841 if (targetpad == NULL) goto cleanup;
843 gst_pad_connect (pad, targetpad);
851 * gst_pad_save_thyself:
852 * @pad: the pad to save
853 * @parent: the parent XML node to save the description in
855 * Saves the pad into an xml representation
857 * Returns: the xml representation of the pad
860 gst_pad_save_thyself (GstObject *object,
866 g_return_val_if_fail (GST_IS_REAL_PAD (object), NULL);
868 realpad = GST_REAL_PAD(object);
870 xmlNewChild(parent,NULL,"name", GST_PAD_NAME (realpad));
871 if (GST_RPAD_PEER(realpad) != NULL) {
872 peer = GST_PAD(GST_RPAD_PEER(realpad));
873 // first check to see if the peer's parent's parent is the same
874 // we just save it off
875 xmlNewChild(parent,NULL,"peer",g_strdup_printf("%s.%s",
876 GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)));
878 xmlNewChild(parent,NULL,"peer","");
884 * gst_pad_ghost_save_thyself:
885 * @pad: the pad to save
887 * @parent: the parent XML node to save the description in
889 * Saves the ghost pad into an xml representation.
891 * Returns: the xml representation of the pad
894 gst_pad_ghost_save_thyself (GstPad *pad,
900 g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
902 self = xmlNewChild(parent,NULL,"ghostpad",NULL);
903 xmlNewChild(self,NULL,"name", GST_PAD_NAME (pad));
904 xmlNewChild(self,NULL,"parent", GST_OBJECT_NAME (GST_PAD_PARENT (pad)));
906 // FIXME FIXME FIXME!
912 void gst_pad_push(GstPad *pad,GstBuffer *buf) {
913 GstRealPad *peer = GST_RPAD_PEER(pad);
914 GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
915 if (peer->pushfunc) {
916 GST_DEBUG (0,"calling pushfunc &%s of peer pad %s:%s\n",
917 GST_DEBUG_FUNCPTR_NAME(peer->pushfunc),GST_DEBUG_PAD_NAME(((GstPad*)peer)));
918 (peer->pushfunc)(((GstPad*)peer),buf);
920 GST_DEBUG (0,"no pushfunc\n");
925 GstBuffer *gst_pad_pull(GstPad *pad) {
926 GstRealPad *peer = GST_RPAD_PEER(pad);
927 GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
928 if (peer->pullfunc) {
929 GST_DEBUG (0,"calling pullfunc &%s (@%p) of peer pad %s:%s\n",
930 GST_DEBUG_FUNCPTR_NAME(peer->pullfunc),&peer->pullfunc,GST_DEBUG_PAD_NAME(((GstPad*)peer)));
931 return (peer->pullfunc)(((GstPad*)peer));
933 GST_DEBUG (0,"no pullfunc for peer pad %s:%s at %p\n",GST_DEBUG_PAD_NAME(((GstPad*)peer)),&peer->pullfunc);
939 #ifndef gst_pad_pullregion
940 GstBuffer *gst_pad_pullregion(GstPad *pad,gulong offset,gulong size) {
941 GstRealPad *peer = GST_RPAD_PEER(pad);
942 GST_DEBUG_ENTER("(%s:%s,%ld,%ld)",GST_DEBUG_PAD_NAME(pad),offset,size);
943 if (peer->pullregionfunc) {
944 GST_DEBUG (0,"calling pullregionfunc &%s of peer pad %s:%s\n",
945 GST_DEBUG_FUNCPTR_NAME(peer->pullregionfunc),GST_DEBUG_PAD_NAME(((GstPad*)peer)));
946 return (peer->pullregionfunc)(((GstPad*)peer),offset,size);
948 GST_DEBUG (0,"no pullregionfunc\n");
954 /************************************************************************
961 * gst_padtemplate_new:
962 * @factory: the padfactory to use
964 * Creates a new padtemplate from the factory.
966 * Returns: the new padtemplate
969 gst_padtemplate_new (GstPadFactory *factory)
972 GstPadFactoryEntry tag;
976 g_return_val_if_fail (factory != NULL, NULL);
978 new = g_new0 (GstPadTemplate, 1);
980 tag = (*factory)[i++];
981 g_return_val_if_fail (tag != NULL, new);
982 new->name_template = g_strdup ((gchar *)tag);
984 tag = (*factory)[i++];
985 new->direction = GPOINTER_TO_UINT (tag);
987 tag = (*factory)[i++];
988 new->presence = GPOINTER_TO_UINT (tag);
990 tag = (*factory)[i++];
992 while (GPOINTER_TO_INT (tag) == 1) {
993 new->caps = g_list_append (new->caps, gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
995 tag = (*factory)[i++];
1002 * gst_padtemplate_create:
1003 * @name_template: the name template
1004 * @direction: the direction for the template
1005 * @presence: the presence of the pad
1006 * @caps: a list of capabilities for the template
1008 * Creates a new padtemplate from the given arguments.
1010 * Returns: the new padtemplate
1013 gst_padtemplate_create (gchar *name_template,
1014 GstPadDirection direction, GstPadPresence presence,
1017 GstPadTemplate *new;
1019 new = g_new0 (GstPadTemplate, 1);
1021 new->name_template = name_template;
1022 new->direction = direction;
1023 new->presence = presence;
1031 * gst_padtemplate_save_thyself:
1032 * @templ: the padtemplate to save
1033 * @parent: the parent XML tree
1035 * Saves the padtemplate into XML.
1037 * Returns: the new XML tree
1040 gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
1046 xmlNewChild(parent,NULL,"nametemplate", templ->name_template);
1047 xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src"));
1049 switch (templ->presence) {
1050 case GST_PAD_ALWAYS:
1051 presence = "always";
1053 case GST_PAD_SOMETIMES:
1054 presence = "sometimes";
1056 case GST_PAD_REQUEST:
1057 presence = "request";
1060 presence = "unknown";
1063 xmlNewChild(parent,NULL,"presence", presence);
1067 GstCaps *cap = (GstCaps *)caps->data;
1069 subtree = xmlNewChild (parent, NULL, "caps", NULL);
1070 gst_caps_save_thyself (cap, subtree);
1072 caps = g_list_next (caps);
1079 * gst_padtemplate_load_thyself:
1080 * @parent: the source XML tree
1082 * Loads a padtemplate from the XML tree.
1084 * Returns: the new padtemplate
1087 gst_padtemplate_load_thyself (xmlNodePtr parent)
1089 xmlNodePtr field = parent->childs;
1090 GstPadTemplate *factory = g_new0 (GstPadTemplate, 1);
1093 if (!strcmp(field->name, "nametemplate")) {
1094 factory->name_template = xmlNodeGetContent(field);
1096 if (!strcmp(field->name, "direction")) {
1097 gchar *value = xmlNodeGetContent(field);
1099 factory->direction = GST_PAD_UNKNOWN;
1100 if (!strcmp(value, "sink")) {
1101 factory->direction = GST_PAD_SINK;
1103 else if (!strcmp(value, "src")) {
1104 factory->direction = GST_PAD_SRC;
1108 if (!strcmp(field->name, "presence")) {
1109 gchar *value = xmlNodeGetContent(field);
1111 if (!strcmp(value, "always")) {
1112 factory->presence = GST_PAD_ALWAYS;
1114 else if (!strcmp(value, "sometimes")) {
1115 factory->presence = GST_PAD_SOMETIMES;
1117 else if (!strcmp(value, "request")) {
1118 factory->presence = GST_PAD_REQUEST;
1122 else if (!strcmp(field->name, "caps")) {
1123 factory->caps = g_list_append(factory->caps, gst_caps_load_thyself (field));
1125 field = field->next;
1132 gst_pad_eos_func(GstPad *pad)
1134 GstElement *element;
1137 gboolean result = TRUE, success;
1139 g_return_val_if_fail (pad != NULL, FALSE);
1140 g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
1142 GST_INFO (GST_CAT_PADS,"attempting to set EOS on sink pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1144 element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
1145 // g_return_val_if_fail (element != NULL, FALSE);
1146 // g_return_val_if_fail (GST_IS_ELEMENT(element), FALSE);
1148 pads = gst_element_get_pad_list(element);
1150 srcpad = GST_PAD(pads->data);
1151 pads = g_list_next(pads);
1153 if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) {
1154 result = gst_pad_eos(GST_REAL_PAD(srcpad));
1155 if (result == FALSE) success = FALSE;
1159 if (result == FALSE) return FALSE;
1161 GST_INFO (GST_CAT_PADS,"set EOS on sink pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1162 GST_FLAG_SET (pad, GST_PAD_EOS);
1169 * @pad: the pad to set to eos
1171 * Sets the given pad to the EOS state.
1173 * Returns: TRUE if it succeeded
1176 gst_pad_set_eos(GstPad *pad)
1178 g_return_val_if_fail (pad != NULL, FALSE);
1179 g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
1180 g_return_val_if_fail (GST_PAD_CONNECTED(pad), FALSE);
1182 GST_INFO (GST_CAT_PADS,"attempting to set EOS on src pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1184 if (!gst_pad_eos(GST_REAL_PAD(pad))) {
1188 GST_INFO (GST_CAT_PADS,"set EOS on src pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1189 GST_FLAG_SET (pad, GST_PAD_EOS);
1191 gst_element_signal_eos (GST_ELEMENT (GST_PAD_PARENT (pad)));
1198 gst_pad_select(GstPad *nextpad, ...) {
1201 GSList *pads = NULL;
1203 // construct the list of pads
1204 va_start (args, nextpad);
1205 while ((pad = va_arg (args, GstPad*)))
1206 pads = g_slist_prepend (pads, pad);
1209 // now switch to the nextpad
1214 * gst_pad_set_element_private:
1215 * @pad: the pad to set the private data to
1216 * @priv: The private data to attach to the pad
1218 * Set the given private data pointer to the pad. This
1219 * function can only be used by the element that own the
1223 gst_pad_set_element_private (GstPad *pad, gpointer priv)
1225 pad->element_private = priv;
1229 * gst_pad_get_element_private:
1230 * @pad: the pad to get the private data of
1232 * Get the private data of a pad. The private data can
1233 * only be set by the parent element of this pad.
1235 * Returns: a pointer to the private data.
1238 gst_pad_get_element_private (GstPad *pad)
1240 return pad->element_private;
1251 /***** ghost pads *****/
1253 static void gst_ghost_pad_class_init (GstGhostPadClass *klass);
1254 static void gst_ghost_pad_init (GstGhostPad *pad);
1256 static GstPad *ghost_pad_parent_class = NULL;
1257 //static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 };
1260 gst_ghost_pad_get_type(void) {
1261 static GtkType pad_type = 0;
1264 static const GtkTypeInfo pad_info = {
1266 sizeof(GstGhostPad),
1267 sizeof(GstGhostPadClass),
1268 (GtkClassInitFunc)gst_ghost_pad_class_init,
1269 (GtkObjectInitFunc)gst_ghost_pad_init,
1270 (GtkArgSetFunc)NULL,
1271 (GtkArgGetFunc)NULL,
1272 (GtkClassInitFunc)NULL,
1274 pad_type = gtk_type_unique(GST_TYPE_PAD,&pad_info);
1280 gst_ghost_pad_class_init (GstGhostPadClass *klass)
1282 GtkObjectClass *gtkobject_class;
1284 gtkobject_class = (GtkObjectClass*)klass;
1286 ghost_pad_parent_class = gtk_type_class(GST_TYPE_PAD);
1290 gst_ghost_pad_init (GstGhostPad *pad)
1292 pad->realpad = NULL;
1296 * gst_ghost_pad_new:
1297 * @name: name of the new ghost pad
1298 * @pad: the pad to create a ghost pad of
1300 * Create a new ghost pad associated with the given pad.
1302 * Returns: new ghost pad
1305 gst_ghost_pad_new (gchar *name,
1308 GstGhostPad *ghostpad;
1310 g_return_val_if_fail (name != NULL, NULL);
1311 g_return_val_if_fail (GST_IS_PAD(pad), NULL);
1313 ghostpad = gtk_type_new (gst_ghost_pad_get_type ());
1314 gst_pad_set_name (GST_PAD (ghostpad), name);
1315 GST_GPAD_REALPAD(ghostpad) = GST_PAD_REALIZE(pad);
1317 // add ourselves to the real pad's list of ghostpads
1318 gst_pad_add_ghost_pad (pad, GST_PAD(ghostpad));
1320 // FIXME need to ref the real pad here... ?
1322 GST_DEBUG(0,"created ghost pad \"%s\"\n",name);
1324 return GST_PAD(ghostpad);