add API to make life easier

Original commit message from CVS:
add API to make life easier
This commit is contained in:
Benjamin Otte 2002-01-28 00:51:39 +00:00
parent 780213e23a
commit 9d34e82b9a
4 changed files with 249 additions and 0 deletions

View file

@ -697,6 +697,175 @@ gst_element_request_pad_by_name (GstElement *element, const gchar *name)
return pad;
}
/**
* gst_element_get_compatible_pad_filtered:
* @element: the element in which the pad should be found
* @pad: the pad to find a compatible one for
* @filtercaps: the caps to use as a filter
*
* Looks for an unconnected pad to which the given pad can connect to.
* It is not guaranteed that connecting the pads will work, though
* it should work in most cases.
*
* Returns: the pad to which a connection can be made
*/
GstPad*
gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad, GstCaps *filtercaps)
{
GList *pads;
GstPadTemplate *templ;
GstCaps *intersection;
GstPad *foundpad = NULL;
/* checks */
g_return_val_if_fail (element != NULL, NULL);
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
/* let's use the real pad */
pad = (GstPad *) GST_PAD_REALIZE (pad);
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_RPAD_PEER (pad) == NULL, NULL);
/* try to get an existing unconnected pad */
pads = gst_element_get_pad_list (element);
while (pads)
{
GstPad *current = GST_PAD (pads->data);
if ((GST_PAD_PEER (GST_PAD_REALIZE (current)) == NULL) &&
gst_pad_can_connect_filtered (pad, current, filtercaps))
{
return current;
}
pads = g_list_next (pads);
}
/* try to create a new one */
/* requesting is a little crazy, we need a template. Let's create one */
if (filtercaps != NULL)
{
filtercaps = gst_caps_intersect (filtercaps, (GstCaps *) GST_RPAD_CAPS (pad));
if (filtercaps == NULL)
return NULL;
}
templ = gst_padtemplate_new ((gchar *) GST_PAD_NAME (pad), GST_RPAD_DIRECTION (pad),
GST_PAD_ALWAYS, filtercaps);
foundpad = gst_element_request_compatible_pad (element, templ);
gst_object_unref (GST_OBJECT (templ));
if (filtercaps != NULL)
gst_caps_unref (filtercaps);
return foundpad;
}
/**
* gst_element_get_compatible_pad:
* @element: the element in which the pad should be found
* @pad: the pad to find a compatible one for
*
* Looks for an unconnected pad to which the given pad can connect to.
* It is not guaranteed that connecting the pads will work, though
* it should work in most cases.
*
* Returns: the pad to which a connection can be made
*/
GstPad*
gst_element_get_compatible_pad (GstElement *element, GstPad *pad)
{
return gst_element_get_compatible_pad_filtered (element, pad, NULL);
}
/**
* gst_element_connect_elements:
* @src: the element containing source pad
* @dest: the element containing destination pad
* @filtercaps: the caps to use as filter
*
* Connect the source to the destination element using the filtercaps.
* The connection must be from source to destination, the other
* direction will not be tried.
* The functions looks for existing pads that aren't connected yet.
+ It will use request pads if possible. But both pads will not be requested.
* If multiple connections are possible, only one is established.
*
* Return: TRUE if the elements could be connected.
*/
gboolean
gst_element_connect_elements_filtered (GstElement *src, GstElement *dest,
GstCaps *filtercaps)
{
GList *srcpads, *destpads;
GstPad *srcpad, *destpad;
/* checks */
g_return_val_if_fail (src != NULL, FALSE);
g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
g_return_val_if_fail (dest != NULL, FALSE);
g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
GST_DEBUG (GST_CAT_ELEMENT_PADS, "attempting to connect element %s to element %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
/* loop through the existing pads in the source */
srcpads = gst_element_get_pad_list (src);
while (srcpads)
{
srcpad = (GstPad *) GST_PAD_REALIZE (srcpads->data);
if ((GST_RPAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
(GST_PAD_PEER (srcpad) == NULL))
{
destpad = gst_element_get_compatible_pad_filtered (dest, srcpad, filtercaps);
if (destpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps))
{
GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
return TRUE;
}
}
srcpads = g_list_next (srcpads);
}
/* loop through the existing pads in the destination */
destpads = gst_element_get_pad_list (dest);
while (destpads)
{
destpad = (GstPad *) GST_PAD_REALIZE (destpads->data);
if ((GST_RPAD_DIRECTION (destpad) == GST_PAD_SINK) &&
(GST_PAD_PEER (destpad) == NULL))
{
srcpad = gst_element_get_compatible_pad_filtered (src, destpad, filtercaps);
if (srcpad && gst_pad_connect_filtered (srcpad, destpad, filtercaps))
{
GST_DEBUG (GST_CAT_ELEMENT_PADS, "connected pad %s:%s to pad %s:%s\n", GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
return TRUE;
}
}
destpads = g_list_next (destpads);
}
GST_DEBUG (GST_CAT_ELEMENT_PADS, "no connection possible from %s to %s\n", GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
return FALSE;
}
/**
* gst_element_connect_elements:
* @src: element containing source pad
* @dest: element containing destination pad
*
* Connect the source to the destination element.
* The connection must be from source to destination, the other
* direction will not be tried.
* The functions looks for existing pads and request pads that aren't
* connected yet. If multiple connections are possible, only one is
* established.
*
* Return: TRUE if the elements could be connected.
*/
gboolean
gst_element_connect_elements (GstElement *src, GstElement *dest)
{
return gst_element_connect_elements_filtered (src, dest, NULL);
}
/**
* gst_element_connect_filtered:
* @src: element containing source pad

View file

@ -199,7 +199,14 @@ void gst_element_remove_ghost_pad (GstElement *element, GstPad *pad);
GstPad* gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ);
GstPad* gst_element_request_pad_by_name (GstElement *element, const gchar *name);
GstPad* gst_element_get_compatible_pad_filtered (GstElement *element, GstPad *pad,
GstCaps *filtercaps);
GstPad* gst_element_get_compatible_pad (GstElement *element, GstPad *pad);
/* these functions should probably have another name, but gst_element_connect is already used */
gboolean gst_element_connect_elements (GstElement *src, GstElement *dest);
gboolean gst_element_connect_elements_filtered (GstElement *src, GstElement *dest,
GstCaps *filtercaps);
gboolean gst_element_connect (GstElement *src, const gchar *srcpadname,
GstElement *dest, const gchar *destpadname);
gboolean gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,

View file

@ -573,6 +573,76 @@ gst_pad_disconnect (GstPad *srcpad,
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
}
/**
* gst_pad_can_connect_filtered:
* @srcpad: the source pad to connect
* @sinkpad: the sink pad to connect
* @filtercaps: the filter caps.
*
* Checks if the source pad and the sink pad can be connected.
* The filter indicates the media type that should flow trought this connection.
*
* Returns: TRUE if the pad can be connected, FALSE otherwise
*/
gboolean
gst_pad_can_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
{
gint num_decoupled = 0;
GstRealPad *realsrc, *realsink;
/* generic checks */
g_return_val_if_fail (srcpad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
g_return_val_if_fail (sinkpad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
/* now we need to deal with the real/ghost stuff */
realsrc = GST_PAD_REALIZE (srcpad);
realsink = GST_PAD_REALIZE (sinkpad);
g_return_val_if_fail (GST_RPAD_PEER (realsrc) == NULL, FALSE);
g_return_val_if_fail (GST_RPAD_PEER (realsink) == NULL, FALSE);
g_return_val_if_fail (GST_PAD_PARENT (realsrc) != NULL, FALSE);
g_return_val_if_fail (GST_PAD_PARENT (realsink) != NULL, FALSE);
if (realsrc->sched && realsink->sched) {
if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsrc), GST_ELEMENT_DECOUPLED))
num_decoupled++;
if (GST_FLAG_IS_SET (GST_PAD_PARENT (realsink), GST_ELEMENT_DECOUPLED))
num_decoupled++;
if (realsrc->sched != realsink->sched && num_decoupled != 1) {
g_warning ("connecting pads with different scheds requires exactly one decoupled element (queue)\n");
return FALSE;
}
}
/* check if the directions are compatible */
if (!(((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SINK) &&
(GST_RPAD_DIRECTION (realsink) == GST_PAD_SRC)) ||
((GST_RPAD_DIRECTION (realsrc) == GST_PAD_SRC) &&
(GST_RPAD_DIRECTION (realsink) == GST_PAD_SINK))))
{
return FALSE;
}
return TRUE;
}
/**
* gst_pad_can_connect:
* @srcpad: the source pad to connect
* @sinkpad: the sink pad to connect
*
* Checks if the source pad can be connected to the sink pad.
*
* Returns: TRUE if the pads can be connected, FALSE otherwise
*/
gboolean
gst_pad_can_connect (GstPad *srcpad, GstPad *sinkpad)
{
return gst_pad_can_connect_filtered (srcpad, sinkpad, NULL);
}
/**
* gst_pad_connect_filtered:
* @srcpad: the source pad to connect

View file

@ -385,6 +385,9 @@ GstPad* gst_pad_get_peer (GstPad *pad);
GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
gboolean gst_pad_can_connect (GstPad *srcpad, GstPad *sinkpad);
gboolean gst_pad_can_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
gboolean gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);