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"
31 /***** Start with the base GstPad class *****/
32 static void gst_pad_class_init (GstPadClass *klass);
33 static void gst_pad_init (GstPad *pad);
35 static GstObject *pad_parent_class = NULL;
38 gst_pad_get_type(void) {
39 static GtkType pad_type = 0;
42 static const GtkTypeInfo pad_info = {
46 (GtkClassInitFunc)gst_pad_class_init,
47 (GtkObjectInitFunc)gst_pad_init,
50 (GtkClassInitFunc)NULL,
52 pad_type = gtk_type_unique(GST_TYPE_OBJECT,&pad_info);
58 gst_pad_class_init (GstPadClass *klass)
60 pad_parent_class = gtk_type_class(GST_TYPE_OBJECT);
64 gst_pad_init (GstPad *pad)
67 pad->element_private = NULL;
70 pad->padtemplate = NULL;
75 /***** Then do the Real Pad *****/
76 /* Pad signals and args */
90 static void gst_real_pad_class_init (GstRealPadClass *klass);
91 static void gst_real_pad_init (GstRealPad *pad);
93 static void gst_real_pad_set_arg (GtkObject *object,GtkArg *arg,guint id);
94 static void gst_real_pad_get_arg (GtkObject *object,GtkArg *arg,guint id);
96 static void gst_real_pad_destroy (GtkObject *object);
98 static void gst_pad_push_func (GstPad *pad, GstBuffer *buf);
100 static GstPad *real_pad_parent_class = NULL;
101 static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
104 gst_real_pad_get_type(void) {
105 static GtkType pad_type = 0;
108 static const GtkTypeInfo pad_info = {
111 sizeof(GstRealPadClass),
112 (GtkClassInitFunc)gst_real_pad_class_init,
113 (GtkObjectInitFunc)gst_real_pad_init,
116 (GtkClassInitFunc)NULL,
118 pad_type = gtk_type_unique(GST_TYPE_PAD,&pad_info);
124 gst_real_pad_class_init (GstRealPadClass *klass)
126 GtkObjectClass *gtkobject_class;
128 gtkobject_class = (GtkObjectClass*)klass;
130 real_pad_parent_class = gtk_type_class(GST_TYPE_PAD);
132 gst_real_pad_signals[REAL_SET_ACTIVE] =
133 gtk_signal_new ("set_active", GTK_RUN_LAST, gtkobject_class->type,
134 GTK_SIGNAL_OFFSET (GstRealPadClass, set_active),
135 gtk_marshal_NONE__BOOL, GTK_TYPE_NONE, 1,
137 gst_real_pad_signals[REAL_CAPS_CHANGED] =
138 gtk_signal_new ("caps_changed", GTK_RUN_LAST, gtkobject_class->type,
139 GTK_SIGNAL_OFFSET (GstRealPadClass, caps_changed),
140 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
142 gtk_object_class_add_signals (gtkobject_class, gst_real_pad_signals, REAL_LAST_SIGNAL);
144 gtk_object_add_arg_type ("GstRealPad::active", GTK_TYPE_BOOL,
145 GTK_ARG_READWRITE, REAL_ARG_ACTIVE);
147 gtkobject_class->destroy = gst_real_pad_destroy;
148 gtkobject_class->set_arg = gst_real_pad_set_arg;
149 gtkobject_class->get_arg = gst_real_pad_get_arg;
153 gst_real_pad_init (GstRealPad *pad)
155 pad->direction = GST_PAD_UNKNOWN;
158 pad->chainfunc = NULL;
160 pad->getregionfunc = NULL;
162 pad->eosfunc = gst_pad_eos_func;
164 pad->pushfunc = GST_DEBUG_FUNCPTR(gst_pad_push_func);
165 pad->pullfunc = NULL;
166 pad->pullregionfunc = NULL;
168 pad->ghostpads = NULL;
173 gst_real_pad_set_arg (GtkObject *object, GtkArg *arg, guint id)
175 g_return_if_fail(GST_IS_PAD(object));
178 case REAL_ARG_ACTIVE:
179 if (GTK_VALUE_BOOL(*arg)) {
180 gst_info("gstpad: activating pad\n");
181 GST_FLAG_UNSET(object,GST_PAD_DISABLED);
183 gst_info("gstpad: de-activating pad\n");
184 GST_FLAG_SET(object,GST_PAD_DISABLED);
186 gtk_signal_emit(GTK_OBJECT(object), gst_real_pad_signals[REAL_SET_ACTIVE],
187 ! GST_FLAG_IS_SET(object,GST_PAD_DISABLED));
195 gst_real_pad_get_arg (GtkObject *object, GtkArg *arg, guint id)
197 /* it's not null if we got it, but it might not be ours */
198 g_return_if_fail (GST_IS_PAD (object));
201 case REAL_ARG_ACTIVE:
202 GTK_VALUE_BOOL (*arg) = ! GST_FLAG_IS_SET (object, GST_PAD_DISABLED);
212 * @name: name of new pad
213 * @direction: either GST_PAD_SRC or GST_PAD_SINK
215 * Create a new pad with given name.
220 gst_pad_new (gchar *name,
221 GstPadDirection direction)
225 g_return_val_if_fail (name != NULL, NULL);
226 g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
228 pad = gtk_type_new (gst_real_pad_get_type ());
229 GST_PAD_NAME(pad) = g_strdup (name);
230 GST_RPAD_DIRECTION(pad) = direction;
236 * gst_pad_new_from_template:
237 * @templ: the pad template to use
238 * @name: the name of the element
240 * Create a new pad with given name from the given template.
245 gst_pad_new_from_template (GstPadTemplate *templ,
250 g_return_val_if_fail (name != NULL, NULL);
251 g_return_val_if_fail (templ != NULL, NULL);
253 pad = gst_pad_new (name, templ->direction);
254 GST_PAD_CAPS(pad) = templ->caps;
255 GST_PAD_PADTEMPLATE(pad) = templ;
261 * gst_pad_get_direction:
262 * @pad: the Pad to get the direction from
264 * Get the direction of the pad.
266 * Returns: the direction of the pad
269 gst_pad_get_direction (GstPad *pad)
271 g_return_val_if_fail (pad != NULL, GST_PAD_UNKNOWN);
272 g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
274 return GST_PAD_DIRECTION(pad);
279 * @pad: the pad to set the name of
280 * @name: the name of the pad
282 * Set the name of a pad.
285 gst_pad_set_name (GstPad *pad,
288 g_return_if_fail (pad != NULL);
289 g_return_if_fail (GST_IS_PAD (pad));
291 if (pad->name != NULL)
294 pad->name = g_strdup (name);
299 * @pad: the pad to get the name of
301 * Get the name of a pad.
303 * Returns: the name of the pad, don't free.
306 gst_pad_get_name (GstPad *pad)
308 g_return_val_if_fail (pad != NULL, NULL);
309 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
311 return GST_PAD_NAME(pad);
315 * gst_pad_set_chain_function:
316 * @pad: the pad to set the chain function for
317 * @chain: the chain function
319 * Set the given chain function for the pad.
321 void gst_pad_set_chain_function (GstPad *pad,
322 GstPadChainFunction chain)
324 g_return_if_fail (pad != NULL);
325 g_return_if_fail (GST_IS_REAL_PAD (pad));
327 GST_RPAD_CHAINFUNC(pad) = chain;
328 GST_DEBUG (0,"chainfunc for %s:%s(@%p) at %p is set to %p\n",
329 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_CHAINFUNC(pad),chain);
333 * gst_pad_set_get_function:
334 * @pad: the pad to set the get function for
335 * @get: the get function
337 * Set the given get function for the pad.
340 gst_pad_set_get_function (GstPad *pad,
341 GstPadGetFunction get)
343 g_return_if_fail (pad != NULL);
344 g_return_if_fail (GST_IS_REAL_PAD (pad));
346 GST_RPAD_GETFUNC(pad) = get;
347 GST_DEBUG (0,"getfunc for %s:%s(@%p) at %p is set to %p\n",
348 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_GETFUNC(pad),get);
352 * gst_pad_set_getregion_function:
353 * @pad: the pad to set the getregion function for
354 * @getregion: the getregion function
356 * Set the given getregion function for the pad.
359 gst_pad_set_getregion_function (GstPad *pad,
360 GstPadGetRegionFunction getregion)
362 g_return_if_fail (pad != NULL);
363 g_return_if_fail (GST_IS_REAL_PAD (pad));
365 GST_RPAD_GETREGIONFUNC(pad) = getregion;
366 GST_DEBUG (0,"getregionfunc for %s:%s(@%p) at %p is set to %p\n",
367 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_GETREGIONFUNC(pad),getregion);
371 * gst_pad_set_qos_function:
372 * @pad: the pad to set the qos function for
373 * @qos: the qos function
375 * Set the given qos function for the pad.
378 gst_pad_set_qos_function (GstPad *pad,
379 GstPadQoSFunction qos)
381 g_return_if_fail (pad != NULL);
382 g_return_if_fail (GST_IS_REAL_PAD (pad));
384 GST_RPAD_QOSFUNC(pad) = qos;
385 GST_DEBUG (0,"qosfunc for %s:%s(@%p) at %p is set to %p\n",
386 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_QOSFUNC(pad),qos);
390 * gst_pad_set_eos_function:
391 * @pad: the pad to set the eos function for
392 * @eos: the eos function
394 * Set the given EOS function for the pad.
397 gst_pad_set_eos_function (GstPad *pad,
398 GstPadEOSFunction eos)
400 g_return_if_fail (pad != NULL);
401 g_return_if_fail (GST_IS_REAL_PAD (pad));
403 GST_RPAD_EOSFUNC(pad) = eos;
404 GST_DEBUG (0,"eosfunc for %s:%s(@%p) at %p is set to %p\n",
405 GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_EOSFUNC(pad),eos);
411 gst_pad_push_func(GstPad *pad, GstBuffer *buf)
413 if (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)) != NULL) {
414 GST_DEBUG (0,"calling chain function\n");
415 (GST_RPAD_CHAINFUNC(GST_RPAD_PEER(pad)))(pad,buf);
417 GST_DEBUG (0,"got a problem here: default pad_push handler in place, no chain function\n");
423 * gst_pad_handle_qos:
424 * @pad: the pad to handle the QoS message
425 * @qos_message: the QoS message to handle
427 * Pass the qos message downstream.
430 gst_pad_handle_qos(GstPad *pad,
437 GST_DEBUG (0,"gst_pad_handle_qos(\"%s\",%08ld)\n", GST_ELEMENT(pad->parent)->name,qos_message);
439 if (GST_RPAD_QOSFUNC(pad)) {
440 (GST_RPAD_QOSFUNC(pad)) (pad,qos_message);
442 element = GST_ELEMENT (GST_PAD_PARENT(GST_RPAD_PEER(pad)));
444 pads = element->pads;
445 GST_DEBUG (0,"gst_pad_handle_qos recurse(\"%s\",%08ld)\n", element->name, qos_message);
447 target_pad = GST_PAD (pads->data);
448 if (GST_RPAD_DIRECTION(target_pad) == GST_PAD_SINK) {
449 gst_pad_handle_qos (target_pad, qos_message);
451 pads = g_list_next (pads);
459 * gst_pad_disconnect:
460 * @srcpad: the source pad to disconnect
461 * @sinkpad: the sink pad to disconnect
463 * Disconnects the source pad from the sink pad.
466 gst_pad_disconnect (GstPad *srcpad,
469 GstRealPad *realsrc, *realsink;
472 g_return_if_fail (srcpad != NULL);
473 g_return_if_fail (GST_IS_PAD (srcpad));
474 g_return_if_fail (sinkpad != NULL);
475 g_return_if_fail (GST_IS_PAD (sinkpad));
477 // now we need to deal with the real/ghost stuff
478 realsrc = GST_PAD_REALIZE(srcpad);
479 realsink = GST_PAD_REALIZE(sinkpad);
481 g_return_if_fail (GST_RPAD_PEER(realsrc) != NULL);
482 g_return_if_fail (GST_RPAD_PEER(realsink) != NULL);
484 g_return_if_fail ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
485 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
487 /* first clear peers */
488 GST_RPAD_PEER(realsrc) = NULL;
489 GST_RPAD_PEER(realsink) = NULL;
491 GST_INFO (GST_CAT_ELEMENT_PADS, "disconnected %s:%s and %s:%s",
492 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
497 * @srcpad: the source pad to connect
498 * @sinkpad: the sink pad to connect
500 * Connects the source pad to the sink pad.
503 gst_pad_connect (GstPad *srcpad,
506 GstRealPad *realsrc, *realsink;
510 g_return_if_fail(srcpad != NULL);
511 g_return_if_fail(GST_IS_PAD(srcpad));
512 g_return_if_fail(sinkpad != NULL);
513 g_return_if_fail(GST_IS_PAD(sinkpad));
515 // now we need to deal with the real/ghost stuff
516 realsrc = GST_PAD_REALIZE(srcpad);
517 realsink = GST_PAD_REALIZE(sinkpad);
519 g_return_if_fail(GST_RPAD_PEER(realsrc) == NULL);
520 g_return_if_fail(GST_RPAD_PEER(realsink) == NULL);
522 /* check for reversed directions and swap if necessary */
523 if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
524 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SRC)) {
529 g_return_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
530 (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
532 if (!gst_pad_check_compatibility (srcpad, sinkpad)) {
533 g_warning ("gstpad: connecting incompatible pads (%s:%s) and (%s:%s)\n",
534 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
537 GST_DEBUG (0,"gstpad: connecting compatible pads (%s:%s) and (%s:%s)\n",
538 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
541 /* first set peers */
542 GST_RPAD_PEER(realsrc) = realsink;
543 GST_RPAD_PEER(realsink) = realsrc;
545 /* set the connected flag */
546 /* FIXME: set connected flag */
548 GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s",
549 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
553 * gst_pad_set_parent:
554 * @pad: the pad to set the parent
555 * @parent: the object to set the parent to
557 * Sets the parent object of a pad.
560 gst_pad_set_parent (GstPad *pad,
563 g_return_if_fail (pad != NULL);
564 g_return_if_fail (GST_IS_PAD (pad));
565 g_return_if_fail (pad->parent == NULL);
566 g_return_if_fail (parent != NULL);
567 g_return_if_fail (GTK_IS_OBJECT (parent));
568 g_return_if_fail ((gpointer)pad != (gpointer)parent);
570 //g_print("set parent %s\n", gst_element_get_name(parent));
572 GST_PAD_PARENT(pad) = parent;
576 * gst_pad_add_ghost_pad:
577 * @pad: the pad to set the ghost parent
578 * @ghostpad: the ghost pad to add
580 * Add a ghost pad to a pad.
583 gst_pad_add_ghost_pad (GstPad *pad,
588 g_return_if_fail (pad != NULL);
589 g_return_if_fail (GST_IS_PAD (pad));
590 g_return_if_fail (ghostpad != NULL);
591 g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
593 realpad = GST_PAD_REALIZE(pad);
595 realpad->ghostpads = g_list_prepend (realpad->ghostpads, ghostpad);
600 * gst_pad_remove_ghost_parent:
601 * @pad: the pad to remove the ghost parent
602 * @ghostpad: the ghost pad to remove from the pad
604 * Remove a ghost pad from a pad.
607 gst_pad_remove_ghost_parent (GstPad *pad,
612 g_return_if_fail (pad != NULL);
613 g_return_if_fail (GST_IS_PAD (pad));
614 g_return_if_fail (ghostpad != NULL);
615 g_return_if_fail (GST_IS_GHOST_PAD (ghostpad));
617 realpad = GST_PAD_REALIZE (pad);
619 realpad->ghostpads = g_list_remove (realpad->ghostpads, ghostpad);
623 * gst_pad_get_parent:
624 * @pad: the pad to get the parent from
626 * Get the parent object of this pad.
628 * Returns: the parent object
631 gst_pad_get_parent (GstPad *pad)
633 g_return_val_if_fail (pad != NULL, NULL);
634 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
636 return GST_PAD_PARENT(pad);
640 * gst_pad_get_ghost_pad_list:
641 * @pad: the pad to get the ghost parents from
643 * Get the ghost parents of this pad.
645 * Returns: a GList of ghost pads
648 gst_pad_get_ghost_parents (GstPad *pad)
650 g_return_val_if_fail (pad != NULL, NULL);
651 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
653 return GST_PAD_REALIZE(pad)->ghostpads;
657 * gst_pad_set_caps_list:
658 * @pad: the pad to set the caps to
659 * @caps: a GList of the capabilities to attach to this pad
661 * Set the capabilities of this pad.
664 gst_pad_set_caps_list (GstPad *pad,
667 g_return_if_fail (pad != NULL);
668 g_return_if_fail (GST_IS_REAL_PAD (pad)); // NOTE this restriction
670 GST_PAD_CAPS(pad) = caps;
674 * gst_pad_get_caps_list:
675 * @pad: the pad to get the capabilities from
677 * Get the capabilities of this pad.
679 * Returns: a list of the capabilities of this pad
682 gst_pad_get_caps_list (GstPad *pad)
684 g_return_val_if_fail (pad != NULL, NULL);
685 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
687 return GST_PAD_CAPS(pad);
691 * gst_pad_get_caps_by_name:
692 * @pad: the pad to get the capabilities from
693 * @name: the name of the capability to get
695 * Get the capabilities with the given name from this pad.
697 * Returns: a capability or NULL if not found
700 gst_pad_get_caps_by_name (GstPad *pad, gchar *name)
704 g_return_val_if_fail (pad != NULL, NULL);
705 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
707 caps = GST_PAD_CAPS(pad);
710 GstCaps *cap = (GstCaps *)caps->data;
712 if (!strcmp (cap->name, name))
715 caps = g_list_next (caps);
722 * gst_pad_check_compatibility:
723 * @srcpad: the srcpad to check
724 * @sinkpad: the sinkpad to check against
726 * Check if two pads have compatible capabilities.
728 * Returns: TRUE if they are compatible or the capabilities
729 * could not be checked
732 gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
734 GstRealPad *realsrc, *realsink;
736 g_return_val_if_fail (srcpad != NULL, FALSE);
737 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
738 g_return_val_if_fail (sinkpad != NULL, FALSE);
739 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
741 realsrc = GST_PAD_REALIZE(srcpad);
742 realsink = GST_PAD_REALIZE(sinkpad);
744 if (GST_RPAD_CAPS(realsrc) && GST_RPAD_CAPS(realsink)) {
745 if (!gst_caps_list_check_compatibility (GST_RPAD_CAPS(realsrc), GST_RPAD_CAPS(realsink))) {
753 GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s)\n",
754 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
761 * @pad: the pad to get the peer from
763 * Get the peer pad of this pad.
765 * Returns: the peer pad
768 gst_pad_get_peer (GstPad *pad)
770 g_return_val_if_fail (pad != NULL, NULL);
771 g_return_val_if_fail (GST_IS_PAD (pad), NULL);
773 return GST_PAD(GST_PAD_PEER(pad));
776 // FIXME this needs to be rethought soon
778 gst_real_pad_destroy (GtkObject *object)
780 GstPad *pad = GST_PAD (object);
782 // g_print("in gst_pad_real_destroy()\n");
786 g_list_free (GST_REAL_PAD(pad)->ghostpads);
791 * gst_pad_load_and_connect:
792 * @parent: the parent XML node to read the description from
793 * @element: the element that has the source pad
794 * @elements: a hashtable with elements
796 * Read the pad definition from the XML node and connect the given pad
797 * in element to a pad of an element in the hashtable.
800 gst_pad_load_and_connect (xmlNodePtr parent,
802 GHashTable *elements)
804 xmlNodePtr field = parent->childs;
805 GstPad *pad = NULL, *targetpad;
811 if (!strcmp(field->name, "name")) {
812 pad = gst_element_get_pad(GST_ELEMENT(element), xmlNodeGetContent(field));
814 else if (!strcmp(field->name, "peer")) {
815 peer = g_strdup(xmlNodeGetContent(field));
819 g_return_if_fail(pad != NULL);
821 if (peer == NULL) return;
823 split = g_strsplit(peer, ".", 2);
825 g_return_if_fail(split[0] != NULL);
826 g_return_if_fail(split[1] != NULL);
828 target = (GstElement *)g_hash_table_lookup(elements, split[0]);
830 if (target == NULL) goto cleanup;
832 targetpad = gst_element_get_pad(target, split[1]);
834 if (targetpad == NULL) goto cleanup;
836 gst_pad_connect(pad, targetpad);
844 * gst_pad_save_thyself:
845 * @pad: the pad to save
846 * @parent: the parent XML node to save the description in
848 * Saves the pad into an xml representation
850 * Returns: the xml representation of the pad
853 gst_pad_save_thyself (GstPad *pad,
859 g_return_val_if_fail (GST_IS_REAL_PAD (pad), NULL);
861 realpad = GST_REAL_PAD(pad);
863 xmlNewChild(parent,NULL,"name",pad->name);
864 if (GST_RPAD_PEER(realpad) != NULL) {
865 peer = GST_PAD(GST_RPAD_PEER(realpad));
866 // first check to see if the peer's parent's parent is the same
867 //if (pad->parent->parent == peer->parent->parent)
868 // we just save it off
869 xmlNewChild(parent,NULL,"peer",g_strdup_printf("%s.%s",
870 GST_ELEMENT(peer->parent)->name,peer->name));
872 xmlNewChild(parent,NULL,"peer","");
878 * gst_pad_ghost_save_thyself:
879 * @pad: the pad to save
881 * @parent: the parent XML node to save the description in
883 * Saves the ghost pad into an xml representation.
885 * Returns: the xml representation of the pad
888 gst_pad_ghost_save_thyself (GstPad *pad,
894 g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL);
896 self = xmlNewChild(parent,NULL,"ghostpad",NULL);
897 xmlNewChild(self,NULL,"name",pad->name);
898 xmlNewChild(self,NULL,"parent",GST_ELEMENT(pad->parent)->name);
900 // FIXME FIXME FIXME!
906 void gst_pad_push(GstPad *pad,GstBuffer *buf) {
907 GstRealPad *peer = GST_RPAD_PEER(pad);
908 GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
909 if (peer->pushfunc) {
910 GST_DEBUG (0,"calling pushfunc &%s of peer pad %s:%s\n",
911 GST_DEBUG_FUNCPTR_NAME(peer->pushfunc),GST_DEBUG_PAD_NAME(((GstPad*)peer)));
912 (peer->pushfunc)(((GstPad*)peer),buf);
914 GST_DEBUG (0,"no pushfunc\n");
919 GstBuffer *gst_pad_pull(GstPad *pad) {
920 GstRealPad *peer = GST_RPAD_PEER(pad);
921 GST_DEBUG_ENTER("(%s:%s)",GST_DEBUG_PAD_NAME(pad));
922 if (peer->pullfunc) {
923 GST_DEBUG (0,"calling pullfunc &%s (@%p) of peer pad %s:%s\n",
924 GST_DEBUG_FUNCPTR_NAME(peer->pullfunc),&peer->pullfunc,GST_DEBUG_PAD_NAME(((GstPad*)peer)));
925 return (peer->pullfunc)(((GstPad*)peer));
927 GST_DEBUG (0,"no pullfunc for peer pad %s:%s at %p\n",GST_DEBUG_PAD_NAME(((GstPad*)peer)),&peer->pullfunc);
933 #ifndef gst_pad_pullregion
934 GstBuffer *gst_pad_pullregion(GstPad *pad,gulong offset,gulong size) {
935 GstRealPad *peer = GST_RPAD_PEER(pad);
936 GST_DEBUG_ENTER("(%s:%s,%ld,%ld)",GST_DEBUG_PAD_NAME(pad),offset,size);
937 if (peer->pullregionfunc) {
938 GST_DEBUG (0,"calling pullregionfunc &%s of peer pad %s:%s\n",
939 GST_DEBUG_FUNCPTR_NAME(peer->pullregionfunc),GST_DEBUG_PAD_NAME(((GstPad*)peer)));
940 return (peer->pullregionfunc)(((GstPad*)peer),offset,size);
942 GST_DEBUG (0,"no pullregionfunc\n");
948 /************************************************************************
955 * gst_padtemplate_new:
956 * @factory: the padfactory to use
958 * Creates a new padtemplate from the factory.
960 * Returns: the new padtemplate
963 gst_padtemplate_new (GstPadFactory *factory)
966 GstPadFactoryEntry tag;
970 g_return_val_if_fail (factory != NULL, NULL);
972 new = g_new0 (GstPadTemplate, 1);
974 tag = (*factory)[i++];
975 g_return_val_if_fail (tag != NULL, new);
976 new->name_template = g_strdup ((gchar *)tag);
978 tag = (*factory)[i++];
979 new->direction = GPOINTER_TO_UINT (tag);
981 tag = (*factory)[i++];
982 new->presence = GPOINTER_TO_UINT (tag);
984 tag = (*factory)[i++];
986 while (GPOINTER_TO_INT (tag) == 1) {
987 new->caps = g_list_append (new->caps, gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
989 tag = (*factory)[i++];
996 * gst_padtemplate_create:
997 * @name_template: the name template
998 * @direction: the direction for the template
999 * @presence: the presence of the pad
1000 * @caps: a list of capabilities for the template
1002 * Creates a new padtemplate from the given arguments.
1004 * Returns: the new padtemplate
1007 gst_padtemplate_create (gchar *name_template,
1008 GstPadDirection direction, GstPadPresence presence,
1011 GstPadTemplate *new;
1013 new = g_new0 (GstPadTemplate, 1);
1015 new->name_template = name_template;
1016 new->direction = direction;
1017 new->presence = presence;
1025 * gst_padtemplate_save_thyself:
1026 * @templ: the padtemplate to save
1027 * @parent: the parent XML tree
1029 * Saves the padtemplate into XML.
1031 * Returns: the new XML tree
1034 gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
1040 xmlNewChild(parent,NULL,"nametemplate", templ->name_template);
1041 xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src"));
1043 switch (templ->presence) {
1044 case GST_PAD_ALWAYS:
1045 presence = "always";
1047 case GST_PAD_SOMETIMES:
1048 presence = "sometimes";
1050 case GST_PAD_REQUEST:
1051 presence = "request";
1054 presence = "unknown";
1057 xmlNewChild(parent,NULL,"presence", presence);
1061 GstCaps *cap = (GstCaps *)caps->data;
1063 subtree = xmlNewChild (parent, NULL, "caps", NULL);
1064 gst_caps_save_thyself (cap, subtree);
1066 caps = g_list_next (caps);
1073 * gst_padtemplate_load_thyself:
1074 * @parent: the source XML tree
1076 * Loads a padtemplate from the XML tree.
1078 * Returns: the new padtemplate
1081 gst_padtemplate_load_thyself (xmlNodePtr parent)
1083 xmlNodePtr field = parent->childs;
1084 GstPadTemplate *factory = g_new0 (GstPadTemplate, 1);
1087 if (!strcmp(field->name, "nametemplate")) {
1088 factory->name_template = xmlNodeGetContent(field);
1090 if (!strcmp(field->name, "direction")) {
1091 gchar *value = xmlNodeGetContent(field);
1093 factory->direction = GST_PAD_UNKNOWN;
1094 if (!strcmp(value, "sink")) {
1095 factory->direction = GST_PAD_SINK;
1097 else if (!strcmp(value, "src")) {
1098 factory->direction = GST_PAD_SRC;
1102 if (!strcmp(field->name, "presence")) {
1103 gchar *value = xmlNodeGetContent(field);
1105 if (!strcmp(value, "always")) {
1106 factory->presence = GST_PAD_ALWAYS;
1108 else if (!strcmp(value, "sometimes")) {
1109 factory->presence = GST_PAD_SOMETIMES;
1111 else if (!strcmp(value, "request")) {
1112 factory->presence = GST_PAD_REQUEST;
1116 else if (!strcmp(field->name, "caps")) {
1117 factory->caps = g_list_append(factory->caps, gst_caps_load_thyself (field));
1119 field = field->next;
1126 gst_pad_eos_func(GstPad *pad)
1128 GstElement *element;
1131 gboolean result = TRUE, success;
1133 g_return_val_if_fail (pad != NULL, FALSE);
1134 g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
1136 GST_INFO (GST_CAT_PADS,"attempting to set EOS on sink pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1138 element = GST_ELEMENT(gst_pad_get_parent (pad));
1139 // g_return_val_if_fail (element != NULL, FALSE);
1140 // g_return_val_if_fail (GST_IS_ELEMENT(element), FALSE);
1142 pads = gst_element_get_pad_list(element);
1144 srcpad = GST_PAD(pads->data);
1145 pads = g_list_next(pads);
1147 if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) {
1148 result = gst_pad_eos(GST_REAL_PAD(srcpad));
1149 if (result == FALSE) success = FALSE;
1153 if (result == FALSE) return FALSE;
1155 GST_INFO (GST_CAT_PADS,"set EOS on sink pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1156 GST_FLAG_SET (pad, GST_PAD_EOS);
1163 * @pad: the pad to set to eos
1165 * Sets the given pad to the EOS state.
1167 * Returns: TRUE if it succeeded
1170 gst_pad_set_eos(GstPad *pad)
1172 g_return_val_if_fail (pad != NULL, FALSE);
1173 g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
1174 g_return_val_if_fail (GST_PAD_CONNECTED(pad), FALSE);
1176 GST_INFO (GST_CAT_PADS,"attempting to set EOS on src pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1178 if (!gst_pad_eos(GST_REAL_PAD(pad))) {
1182 GST_INFO (GST_CAT_PADS,"set EOS on src pad %s:%s",GST_DEBUG_PAD_NAME(pad));
1183 GST_FLAG_SET (pad, GST_PAD_EOS);
1185 gst_element_signal_eos (GST_ELEMENT (pad->parent));
1192 gst_pad_select(GstPad *nextpad, ...) {
1195 GSList *pads = NULL;
1197 // construct the list of pads
1198 va_start (args, nextpad);
1199 while ((pad = va_arg (args, GstPad*)))
1200 pads = g_slist_prepend (pads, pad);
1203 // now switch to the nextpad
1208 * gst_pad_set_element_private:
1209 * @pad: the pad to set the private data to
1210 * @priv: The private data to attach to the pad
1212 * Set the given private data pointer to the pad. This
1213 * function can only be used by the element that own the
1217 gst_pad_set_element_private (GstPad *pad, gpointer priv)
1219 pad->element_private = priv;
1223 * gst_pad_get_element_private:
1224 * @pad: the pad to get the private data of
1226 * Get the private data of a pad. The private data can
1227 * only be set by the parent element of this pad.
1229 * Returns: a pointer to the private data.
1232 gst_pad_get_element_private (GstPad *pad)
1234 return pad->element_private;
1245 /***** ghost pads *****/
1247 static void gst_ghost_pad_class_init (GstGhostPadClass *klass);
1248 static void gst_ghost_pad_init (GstGhostPad *pad);
1250 static GstPad *ghost_pad_parent_class = NULL;
1251 //static guint gst_ghost_pad_signals[LAST_SIGNAL] = { 0 };
1254 gst_ghost_pad_get_type(void) {
1255 static GtkType pad_type = 0;
1258 static const GtkTypeInfo pad_info = {
1260 sizeof(GstGhostPad),
1261 sizeof(GstGhostPadClass),
1262 (GtkClassInitFunc)gst_ghost_pad_class_init,
1263 (GtkObjectInitFunc)gst_ghost_pad_init,
1264 (GtkArgSetFunc)NULL,
1265 (GtkArgGetFunc)NULL,
1266 (GtkClassInitFunc)NULL,
1268 pad_type = gtk_type_unique(GST_TYPE_PAD,&pad_info);
1274 gst_ghost_pad_class_init (GstGhostPadClass *klass)
1276 GtkObjectClass *gtkobject_class;
1278 gtkobject_class = (GtkObjectClass*)klass;
1280 ghost_pad_parent_class = gtk_type_class(GST_TYPE_PAD);
1284 gst_ghost_pad_init (GstGhostPad *pad)
1286 pad->realpad = NULL;
1290 * gst_ghost_pad_new:
1291 * @name: name of the new ghost pad
1292 * @pad: the pad to create a ghost pad of
1294 * Create a new ghost pad associated with the given pad.
1296 * Returns: new ghost pad
1299 gst_ghost_pad_new (gchar *name,
1302 GstGhostPad *ghostpad;
1304 g_return_val_if_fail (name != NULL, NULL);
1305 g_return_val_if_fail (GST_IS_PAD(pad), NULL);
1307 ghostpad = gtk_type_new (gst_ghost_pad_get_type ());
1308 GST_PAD_NAME(ghostpad) = g_strdup (name);
1309 GST_GPAD_REALPAD(ghostpad) = GST_PAD_REALIZE(pad);
1311 // add ourselves to the real pad's list of ghostpads
1312 gst_pad_add_ghost_pad (pad, GST_PAD(ghostpad));
1314 // FIXME need to ref the real pad here... ?
1316 GST_DEBUG(0,"created ghost pad \"%s\"\n",name);
1318 return GST_PAD(ghostpad);