--- a/gstreamer_core/gst/gstutils.c Tue Aug 31 15:30:33 2010 +0300
+++ b/gstreamer_core/gst/gstutils.c Wed Sep 01 12:16:41 2010 +0100
@@ -3,7 +3,7 @@
* 2000 Wim Taymans <wtay@chello.be>
* 2002 Thomas Vander Stichele <thomas@apestaart.org>
*
- * gstutils.c: Utility functions
+ * gstutils.c: Utility functions: gtk_get_property stuff, etc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -37,16 +37,8 @@
#include "gsterror.h"
#include "gstinfo.h"
#include "gstparse.h"
-#include "gstvalue.h"
#include "gst-i18n-lib.h"
-/**
- * gst_util_dump_mem:
- * @mem: a pointer to the memory to dump
- * @size: the size of the memory block to dump
- *
- * Dumps the memory block into a hex representation. Useful for debugging.
- */
#ifdef __SYMBIAN32__
#include <glib_global.h>
#include <gobject_global.h>
@@ -103,9 +95,6 @@
*
* Converts the string to the type of the value and
* sets the value with it.
- *
- * Note that this function is dangerous as it does not return any indication
- * if the conversion worked or not.
*/
#ifdef __SYMBIAN32__
EXPORT_C
@@ -114,7 +103,7 @@
void
gst_util_set_value_from_string (GValue * value, const gchar * value_str)
{
- gboolean res;
+ gint sscanf_ret;
g_return_if_fail (value != NULL);
g_return_if_fail (value_str != NULL);
@@ -122,13 +111,86 @@
GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
g_type_name (G_VALUE_TYPE (value)));
- res = gst_value_deserialize (value, value_str);
- if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
- /* backwards compat, all booleans that fail to parse are false */
- g_value_set_boolean (value, FALSE);
- res = TRUE;
+ switch (G_VALUE_TYPE (value)) {
+ case G_TYPE_STRING:
+ g_value_set_string (value, value_str);
+ break;
+ case G_TYPE_ENUM:
+ case G_TYPE_INT:{
+ gint i;
+
+ sscanf_ret = sscanf (value_str, "%d", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_int (value, i);
+ break;
+ }
+ case G_TYPE_UINT:{
+ guint i;
+
+ sscanf_ret = sscanf (value_str, "%u", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_uint (value, i);
+ break;
+ }
+ case G_TYPE_LONG:{
+ glong i;
+
+ sscanf_ret = sscanf (value_str, "%ld", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_long (value, i);
+ break;
+ }
+ case G_TYPE_ULONG:{
+ gulong i;
+
+ sscanf_ret = sscanf (value_str, "%lu", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_ulong (value, i);
+ break;
+ }
+ case G_TYPE_BOOLEAN:{
+ gboolean i = FALSE;
+
+ if (!g_ascii_strncasecmp ("true", value_str, 4))
+ i = TRUE;
+ g_value_set_boolean (value, i);
+ break;
+ }
+ case G_TYPE_CHAR:{
+ gchar i;
+
+ sscanf_ret = sscanf (value_str, "%c", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_char (value, i);
+ break;
+ }
+ case G_TYPE_UCHAR:{
+ guchar i;
+
+ sscanf_ret = sscanf (value_str, "%c", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_uchar (value, i);
+ break;
+ }
+ case G_TYPE_FLOAT:{
+ gfloat i;
+
+ sscanf_ret = sscanf (value_str, "%f", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_float (value, i);
+ break;
+ }
+ case G_TYPE_DOUBLE:{
+ gfloat i;
+
+ sscanf_ret = sscanf (value_str, "%g", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_value_set_double (value, (gdouble) i);
+ break;
+ }
+ default:
+ break;
}
- g_return_if_fail (res);
}
/**
@@ -139,9 +201,6 @@
*
* Convertes the string value to the type of the objects argument and
* sets the argument with it.
- *
- * Note that this function silently returns if @object has no property named
- * @name or when @value cannot be converted to the type of the property.
*/
#ifdef __SYMBIAN32__
EXPORT_C
@@ -151,41 +210,111 @@
gst_util_set_object_arg (GObject * object, const gchar * name,
const gchar * value)
{
- GParamSpec *pspec;
- GType value_type;
- GValue v = { 0, };
-
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (name != NULL);
- g_return_if_fail (value != NULL);
-
- pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
- if (!pspec)
- return;
-
- value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
-
- GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s",
- pspec->flags, g_type_name (value_type));
-
- if (!(pspec->flags & G_PARAM_WRITABLE))
- return;
-
- g_value_init (&v, value_type);
-
- /* special case for element <-> xml (de)serialisation */
- if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) {
- g_value_set_boxed (&v, NULL);
- goto done;
+ gboolean sscanf_ret;
+
+ if (name && value) {
+ GParamSpec *paramspec;
+
+ paramspec =
+ g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
+
+ if (!paramspec) {
+ return;
+ }
+
+ GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d",
+ paramspec->flags, (gint) paramspec->value_type);
+
+ if (paramspec->flags & G_PARAM_WRITABLE) {
+ switch (paramspec->value_type) {
+ case G_TYPE_STRING:
+ g_object_set (G_OBJECT (object), name, value, NULL);
+ break;
+ case G_TYPE_ENUM:
+ case G_TYPE_INT:{
+ gint i;
+
+ sscanf_ret = sscanf (value, "%d", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_UINT:{
+ guint i;
+
+ sscanf_ret = sscanf (value, "%u", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_LONG:{
+ glong i;
+
+ sscanf_ret = sscanf (value, "%ld", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_ULONG:{
+ gulong i;
+
+ sscanf_ret = sscanf (value, "%lu", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_BOOLEAN:{
+ gboolean i = FALSE;
+
+ if (!g_ascii_strncasecmp ("true", value, 4))
+ i = TRUE;
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_CHAR:{
+ gchar i;
+
+ sscanf_ret = sscanf (value, "%c", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_UCHAR:{
+ guchar i;
+
+ sscanf_ret = sscanf (value, "%c", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_FLOAT:{
+ gfloat i;
+
+ sscanf_ret = sscanf (value, "%f", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ break;
+ }
+ case G_TYPE_DOUBLE:{
+ gfloat i;
+
+ sscanf_ret = sscanf (value, "%g", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, (gdouble) i, NULL);
+ break;
+ }
+ default:
+ if (G_IS_PARAM_SPEC_ENUM (paramspec)) {
+ gint i;
+
+ sscanf_ret = sscanf (value, "%d", &i);
+ g_return_if_fail (sscanf_ret == 1);
+ g_object_set (G_OBJECT (object), name, i, NULL);
+ }
+ break;
+ }
+ }
}
-
- if (!gst_value_deserialize (&v, value))
- return;
-
-done:
-
- g_object_set_property (object, pspec->name, &v);
- g_value_unset (&v);
}
/* work around error C2520: conversion from unsigned __int64 to double
@@ -306,7 +435,7 @@
}
static guint64
-gst_util_uint64_scale_int64_unchecked (guint64 val, guint64 num, guint64 denom)
+gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
{
GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
GstUInt64 v, n;
@@ -338,7 +467,7 @@
c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
/* if high bits bigger than denom, we overflow */
- if (G_UNLIKELY (c1.ll >= denom))
+ if (c1.ll >= denom)
goto overflow;
/* shortcut for division by 1, c1.ll should be 0 because of the
@@ -368,36 +497,6 @@
}
}
-static inline guint64
-gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom)
-{
- GstUInt64 result;
- GstUInt64 low, high;
-
- /* do 96 bits mult/div */
- low.ll = val;
- result.ll = ((guint64) low.l.low) * num;
- high.ll = ((guint64) low.l.high) * num + (result.l.high);
-
- low.ll = high.ll / denom;
- result.l.high = high.ll % denom;
- result.ll /= denom;
-
- /* avoid overflow */
- if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32))
- goto overflow;
-
- result.l.high += low.l.low;
-
- return result.ll;
-
-overflow:
- {
- return G_MAXUINT64;
- }
-}
-
-
/**
* gst_util_uint64_scale:
* @val: the number to scale
@@ -420,33 +519,33 @@
{
g_return_val_if_fail (denom != 0, G_MAXUINT64);
- if (G_UNLIKELY (num == 0))
+ if (num == 0)
return 0;
- if (G_UNLIKELY (num == denom))
+ if (num == 1 && denom == 1)
return val;
/* if the denom is high, we need to do a 64 muldiv */
- if (G_UNLIKELY (denom > G_MAXINT32))
+ if (denom > G_MAXINT32)
goto do_int64;
/* if num and denom are low we can do a 32 bit muldiv */
- if (G_LIKELY (num <= G_MAXINT32))
+ if (num <= G_MAXINT32)
goto do_int32;
/* val and num are high, we need 64 muldiv */
- if (G_UNLIKELY (val > G_MAXINT32))
+ if (val > G_MAXINT32)
goto do_int64;
/* val is low and num is high, we can swap them and do 32 muldiv */
- return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom);
+ return gst_util_uint64_scale_int (num, (gint) val, (gint) denom);
do_int32:
- return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom);
+ return gst_util_uint64_scale_int (val, (gint) num, (gint) denom);
do_int64:
/* to the more heavy implementations... */
- return gst_util_uint64_scale_int64_unchecked (val, num, denom);
+ return gst_util_uint64_scale_int64 (val, num, denom);
}
/**
@@ -470,71 +569,43 @@
guint64
gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
{
+ GstUInt64 result;
+ GstUInt64 low, high;
+
g_return_val_if_fail (denom > 0, G_MAXUINT64);
g_return_val_if_fail (num >= 0, G_MAXUINT64);
- if (G_UNLIKELY (num == 0))
+ if (num == 0)
return 0;
- if (G_UNLIKELY (num == denom))
+ if (num == 1 && denom == 1)
return val;
if (val <= G_MAXUINT32)
/* simple case */
return val * num / denom;
- return gst_util_uint64_scale_int_unchecked (val, num, denom);
-}
-
-/**
- * gst_util_seqnum_next:
- *
- * Return a constantly incrementing sequence number.
- *
- * This function is used internally to GStreamer to be able to determine which
- * events and messages are "the same". For example, elements may set the seqnum
- * on a segment-done message to be the same as that of the last seek event, to
- * indicate that event and the message correspond to the same segment.
- *
- * Returns: A constantly incrementing 32-bit unsigned integer, which might
- * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure
- * you handle wraparound correctly.
- *
- * Since: 0.10.22
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-guint32
-gst_util_seqnum_next (void)
-{
- static gint counter = 0;
- return g_atomic_int_exchange_and_add (&counter, 1);
-}
-
-/**
- * gst_util_seqnum_compare:
- * @s1: A sequence number.
- * @s2: Another sequence number.
- *
- * Compare two sequence numbers, handling wraparound.
- *
- * The current implementation just returns (gint32)(@s1 - @s2).
- *
- * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a
- * positive number if @s1 is after @s2.
- *
- * Since: 0.10.22
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gint32
-gst_util_seqnum_compare (guint32 s1, guint32 s2)
-{
- return (gint32) (s1 - s2);
+ /* do 96 bits mult/div */
+ low.ll = val;
+ result.ll = ((guint64) low.l.low) * num;
+ high.ll = ((guint64) low.l.high) * num + (result.l.high);
+
+ low.ll = high.ll / denom;
+ result.l.high = high.ll % denom;
+ result.ll /= denom;
+
+ /* avoid overflow */
+ if (low.ll + result.l.high > G_MAXUINT32)
+ goto overflow;
+
+ result.l.high += low.l.low;
+
+ return result.ll;
+
+overflow:
+ {
+ return G_MAXUINT64;
+ }
}
/* -----------------------------------------------------
@@ -857,60 +928,6 @@
return pad;
}
-/*
- * Checks if the source pad and the sink pad can be linked.
- * Both @srcpad and @sinkpad must be unlinked and have a parent.
- */
-static gboolean
-gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad)
-{
- /* FIXME This function is gross. It's almost a direct copy of
- * gst_pad_link_filtered(). Any decent programmer would attempt
- * to merge the two functions, which I will do some day. --ds
- */
-
- /* generic checks */
- g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
- g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
-
- GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-
- /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
- if (GST_PAD_PEER (srcpad) != NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
- GST_DEBUG_PAD_NAME (srcpad));
- return FALSE;
- }
- if (GST_PAD_PEER (sinkpad) != NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
- GST_DEBUG_PAD_NAME (sinkpad));
- return FALSE;
- }
- if (!GST_PAD_IS_SRC (srcpad)) {
- GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
- GST_DEBUG_PAD_NAME (srcpad));
- return FALSE;
- }
- if (!GST_PAD_IS_SINK (sinkpad)) {
- GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
- GST_DEBUG_PAD_NAME (sinkpad));
- return FALSE;
- }
- if (GST_PAD_PARENT (srcpad) == NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
- GST_DEBUG_PAD_NAME (srcpad));
- return FALSE;
- }
- if (GST_PAD_PARENT (sinkpad) == NULL) {
- GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
- GST_DEBUG_PAD_NAME (srcpad));
- return FALSE;
- }
-
- return TRUE;
-}
-
/**
* gst_element_get_compatible_pad:
* @element: a #GstElement in which the pad should be found.
@@ -938,6 +955,8 @@
GstPad *foundpad = NULL;
gboolean done;
+ /* FIXME check for caps compatibility */
+
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
@@ -966,47 +985,22 @@
peer = gst_pad_get_peer (current);
- if (peer == NULL && gst_pad_check_link (pad, current)) {
- GstCaps *temp, *temp2, *intersection;
-
- /* Now check if the two pads' caps are compatible */
- temp = gst_pad_get_caps (pad);
- if (caps) {
- intersection = gst_caps_intersect (temp, caps);
- gst_caps_unref (temp);
- } else {
- intersection = temp;
- }
-
- temp = gst_pad_get_caps (current);
- temp2 = gst_caps_intersect (temp, intersection);
- gst_caps_unref (temp);
- gst_caps_unref (intersection);
-
- intersection = temp2;
-
- if (!gst_caps_is_empty (intersection)) {
- gst_caps_unref (intersection);
-
- GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
- "found existing unlinked compatible pad %s:%s",
- GST_DEBUG_PAD_NAME (current));
- gst_iterator_free (pads);
-
- return current;
- } else {
- GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads");
- }
- gst_caps_unref (intersection);
+ if (peer == NULL && gst_pad_can_link (pad, current)) {
+
+ GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
+ "found existing unlinked pad %s:%s",
+ GST_DEBUG_PAD_NAME (current));
+
+ gst_iterator_free (pads);
+
+ return current;
} else {
- GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
- "already linked or cannot be linked (peer = %p)", peer);
+ GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
+
+ gst_object_unref (current);
+ if (peer)
+ gst_object_unref (peer);
}
- GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
-
- gst_object_unref (current);
- if (peer)
- gst_object_unref (peer);
break;
}
case GST_ITERATOR_DONE:
@@ -1022,18 +1016,12 @@
}
gst_iterator_free (pads);
- GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
- "Could not find a compatible unlinked always pad to link to %s:%s, now checking request pads",
- GST_DEBUG_PAD_NAME (pad));
-
/* try to create a new one */
/* requesting is a little crazy, we need a template. Let's create one */
- /* FIXME: why not gst_pad_get_pad_template (pad); */
templcaps = gst_pad_get_caps (pad);
templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
-
foundpad = gst_element_request_compatible_pad (element, templ);
gst_object_unref (templ);
@@ -1172,8 +1160,8 @@
GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
if (template->direction == GST_PAD_SRC) {
- if (gst_caps_is_always_compatible (gst_static_caps_get
- (&template->static_caps), caps))
+ if (gst_caps_is_always_compatible (gst_static_caps_get (&template->
+ static_caps), caps))
return TRUE;
}
templates = g_list_next (templates);
@@ -1449,8 +1437,7 @@
/* get a src pad */
if (srcpadname) {
/* name specified, look it up */
- if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
- srcpad = gst_element_get_request_pad (src, srcpadname);
+ srcpad = gst_element_get_pad (src, srcpadname);
if (!srcpad) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
GST_ELEMENT_NAME (src), srcpadname);
@@ -1483,8 +1470,7 @@
/* get a destination pad */
if (destpadname) {
/* name specified, look it up */
- if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
- destpad = gst_element_get_request_pad (dest, destpadname);
+ destpad = gst_element_get_pad (dest, destpadname);
if (!destpad) {
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
GST_ELEMENT_NAME (dest), destpadname);
@@ -1789,7 +1775,6 @@
gboolean
gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
{
- gboolean res = TRUE;
va_list args;
g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
@@ -1798,10 +1783,8 @@
va_start (args, element_2);
while (element_2) {
- if (!gst_element_link (element_1, element_2)) {
- res = FALSE;
- break;
- }
+ if (!gst_element_link (element_1, element_2))
+ return FALSE;
element_1 = element_2;
element_2 = va_arg (args, GstElement *);
@@ -1809,7 +1792,7 @@
va_end (args);
- return res;
+ return TRUE;
}
/**
@@ -1858,9 +1841,6 @@
GstElement * dest, const gchar * destpadname)
{
GstPad *srcpad, *destpad;
- gboolean srcrequest, destrequest;
-
- srcrequest = destrequest = FALSE;
g_return_if_fail (src != NULL);
g_return_if_fail (GST_IS_ELEMENT (src));
@@ -1870,33 +1850,23 @@
g_return_if_fail (destpadname != NULL);
/* obtain the pads requested */
- if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
- if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
- srcrequest = TRUE;
+ srcpad = gst_element_get_pad (src, srcpadname);
if (srcpad == NULL) {
GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
return;
}
- if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
- if ((destpad = gst_element_get_request_pad (dest, destpadname)))
- destrequest = TRUE;
+ destpad = gst_element_get_pad (dest, destpadname);
if (destpad == NULL) {
GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
destpadname);
- goto free_src;
+ gst_object_unref (srcpad);
+ return;
}
/* we're satisified they can be unlinked, let's do it */
gst_pad_unlink (srcpad, destpad);
-
- if (destrequest)
- gst_element_release_request_pad (dest, destpad);
+ gst_object_unref (srcpad);
gst_object_unref (destpad);
-
-free_src:
- if (srcrequest)
- gst_element_release_request_pad (src, srcpad);
- gst_object_unref (srcpad);
}
/**
@@ -1970,7 +1940,8 @@
if (GST_PAD_IS_SRC (pad)) {
GstPad *peerpad = gst_pad_get_peer (pad);
- /* see if the pad is linked and is really a pad of dest */
+ /* see if the pad is connected and is really a pad
+ * of dest */
if (peerpad) {
GstElement *peerelem;
@@ -2164,6 +2135,70 @@
}
/**
+ * gst_pad_can_link:
+ * @srcpad: the source #GstPad to link.
+ * @sinkpad: the sink #GstPad to link.
+ *
+ * Checks if the source pad and the sink pad can be linked.
+ * Both @srcpad and @sinkpad must be unlinked.
+ *
+ * Returns: TRUE if the pads can be linked, FALSE otherwise.
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+gboolean
+gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
+{
+ /* FIXME This function is gross. It's almost a direct copy of
+ * gst_pad_link_filtered(). Any decent programmer would attempt
+ * to merge the two functions, which I will do some day. --ds
+ */
+
+ /* generic checks */
+ g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
+ g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
+
+ GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+
+ /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
+ if (GST_PAD_PEER (srcpad) != NULL) {
+ GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
+ GST_DEBUG_PAD_NAME (srcpad));
+ return FALSE;
+ }
+ if (GST_PAD_PEER (sinkpad) != NULL) {
+ GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
+ GST_DEBUG_PAD_NAME (sinkpad));
+ return FALSE;
+ }
+ if (!GST_PAD_IS_SRC (srcpad)) {
+ GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
+ GST_DEBUG_PAD_NAME (srcpad));
+ return FALSE;
+ }
+ if (!GST_PAD_IS_SINK (sinkpad)) {
+ GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
+ GST_DEBUG_PAD_NAME (sinkpad));
+ return FALSE;
+ }
+ if (GST_PAD_PARENT (srcpad) == NULL) {
+ GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
+ GST_DEBUG_PAD_NAME (srcpad));
+ return FALSE;
+ }
+ if (GST_PAD_PARENT (sinkpad) == NULL) {
+ GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
+ GST_DEBUG_PAD_NAME (srcpad));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* gst_pad_use_fixed_caps:
* @pad: the pad to use
*
@@ -2214,7 +2249,9 @@
"using pad caps %p %" GST_PTR_FORMAT, result, result);
result = gst_caps_ref (result);
- } else if (GST_PAD_PAD_TEMPLATE (pad)) {
+ goto done;
+ }
+ if (GST_PAD_PAD_TEMPLATE (pad)) {
GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
result = GST_PAD_TEMPLATE_CAPS (templ);
@@ -2223,10 +2260,12 @@
result);
result = gst_caps_ref (result);
- } else {
- GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
- result = gst_caps_new_empty ();
+ goto done;
}
+ GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
+ result = gst_caps_new_empty ();
+
+done:
GST_OBJECT_UNLOCK (pad);
return result;
@@ -2520,11 +2559,6 @@
* If the buffers point to contiguous areas of memory, the buffer
* is created without copying the data.
*
- * This is a convenience function for C programmers. See also
- * gst_buffer_merge(), which does the same thing without
- * unreffing the input parameters. Language bindings without
- * explicit reference counting should not wrap this function.
- *
* Returns: the new #GstBuffer which is the concatenation of the source buffers.
*/
#ifdef __SYMBIAN32__
@@ -2572,7 +2606,6 @@
static gboolean
intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
{
- /* skip the pad, the request came from */
if (pad != orig) {
GstCaps *peercaps, *existing;
@@ -2616,8 +2649,7 @@
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s",
- GST_DEBUG_PAD_NAME (pad));
+ GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent_element (pad);
if (element == NULL)
@@ -2725,8 +2757,7 @@
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (caps != NULL, FALSE);
- GST_CAT_DEBUG (GST_CAT_PADS, "proxying pad link for %s:%s",
- GST_DEBUG_PAD_NAME (pad));
+ GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent_element (pad);
if (element == NULL)
@@ -2926,6 +2957,7 @@
gboolean ret;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+ g_return_val_if_fail (src_val >= 0, FALSE);
g_return_val_if_fail (dest_format != NULL, FALSE);
g_return_val_if_fail (dest_val != NULL, FALSE);
@@ -2992,11 +3024,7 @@
* @value: value to set
*
* Unconditionally sets the atomic integer to @value.
- *
- * Deprecated: Use g_atomic_int_set().
- *
*/
-#ifndef GST_REMOVE_DEPRECATED
#ifdef __SYMBIAN32__
EXPORT_C
#endif
@@ -3004,9 +3032,12 @@
void
gst_atomic_int_set (gint * atomic_int, gint value)
{
- g_atomic_int_set (atomic_int, value);
+ int ignore;
+
+ *atomic_int = value;
+ /* read acts as a memory barrier */
+ ignore = g_atomic_int_get (atomic_int);
}
-#endif
/**
* gst_pad_add_data_probe:
@@ -3045,68 +3076,17 @@
gulong
gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
{
- return gst_pad_add_data_probe_full (pad, handler, data, NULL);
-}
-
-/**
- * gst_pad_add_data_probe_full:
- * @pad: pad to add the data probe handler to
- * @handler: function to call when data is passed over pad
- * @data: data to pass along with the handler
- * @notify: function to call when the probe is disconnected, or NULL
- *
- * Adds a "data probe" to a pad. This function will be called whenever data
- * passes through a pad. In this case data means both events and buffers. The
- * probe will be called with the data as an argument, meaning @handler should
- * have the same callback signature as the #GstPad::have-data signal.
- * Note that the data will have a reference count greater than 1, so it will
- * be immutable -- you must not change it.
- *
- * For source pads, the probe will be called after the blocking function, if any
- * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
- * to. For sink pads, the probe function will be called before configuring the
- * sink with new caps, if any, and before calling the pad's chain function.
- *
- * Your data probe should return TRUE to let the data continue to flow, or FALSE
- * to drop it. Dropping data is rarely useful, but occasionally comes in handy
- * with events.
- *
- * Although probes are implemented internally by connecting @handler to the
- * have-data signal on the pad, if you want to remove a probe it is insufficient
- * to only call g_signal_handler_disconnect on the returned handler id. To
- * remove a probe, use the appropriate function, such as
- * gst_pad_remove_data_probe().
- *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
- *
- * Returns: The handler id.
- *
- * Since: 0.10.20
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gulong
-gst_pad_add_data_probe_full (GstPad * pad, GCallback handler,
- gpointer data, GDestroyNotify notify)
-{
gulong sigid;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
GST_OBJECT_LOCK (pad);
-
- /* we only expose a GDestroyNotify in our API because that's less confusing */
- sigid = g_signal_connect_data (pad, "have-data", handler, data,
- (GClosureNotify) notify, 0);
-
+ sigid = g_signal_connect (pad, "have-data", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++;
GST_PAD_DO_BUFFER_SIGNALS (pad)++;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "adding data probe, now %d data, %d event probes",
+ GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes",
+ GST_DEBUG_PAD_NAME (pad),
GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
@@ -3131,48 +3111,16 @@
gulong
gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
{
- return gst_pad_add_event_probe_full (pad, handler, data, NULL);
-}
-
-/**
- * gst_pad_add_event_probe_full:
- * @pad: pad to add the event probe handler to
- * @handler: function to call when events are passed over pad
- * @data: data to pass along with the handler, or NULL
- * @notify: function to call when probe is disconnected, or NULL
- *
- * Adds a probe that will be called for all events passing through a pad. See
- * gst_pad_add_data_probe() for more information.
- *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
- *
- * Returns: The handler id
- *
- * Since: 0.10.20
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gulong
-gst_pad_add_event_probe_full (GstPad * pad, GCallback handler,
- gpointer data, GDestroyNotify notify)
-{
gulong sigid;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
GST_OBJECT_LOCK (pad);
-
- /* we only expose a GDestroyNotify in our API because that's less confusing */
- sigid = g_signal_connect_data (pad, "have-data::event", handler, data,
- (GClosureNotify) notify, 0);
-
+ sigid = g_signal_connect (pad, "have-data::event", handler, data);
GST_PAD_DO_EVENT_SIGNALS (pad)++;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes",
- GST_PAD_DO_EVENT_SIGNALS (pad));
+ GST_DEBUG ("adding event probe to pad %s:%s, now %d probes",
+ GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
return sigid;
@@ -3196,48 +3144,16 @@
gulong
gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
{
- return gst_pad_add_buffer_probe_full (pad, handler, data, NULL);
-}
-
-/**
- * gst_pad_add_buffer_probe_full:
- * @pad: pad to add the buffer probe handler to
- * @handler: function to call when buffer are passed over pad
- * @data: data to pass along with the handler
- * @notify: function to call when the probe is disconnected, or NULL
- *
- * Adds a probe that will be called for all buffers passing through a pad. See
- * gst_pad_add_data_probe() for more information.
- *
- * The @notify function is called when the probe is disconnected and usually
- * used to free @data.
- *
- * Returns: The handler id
- *
- * Since: 0.10.20
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gulong
-gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler,
- gpointer data, GDestroyNotify notify)
-{
gulong sigid;
g_return_val_if_fail (GST_IS_PAD (pad), 0);
g_return_val_if_fail (handler != NULL, 0);
GST_OBJECT_LOCK (pad);
-
- /* we only expose a GDestroyNotify in our API because that's less confusing */
- sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data,
- (GClosureNotify) notify, 0);
-
+ sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
GST_PAD_DO_BUFFER_SIGNALS (pad)++;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes",
- GST_PAD_DO_BUFFER_SIGNALS (pad));
+ GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes",
+ GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
return sigid;
@@ -3264,9 +3180,10 @@
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--;
GST_PAD_DO_EVENT_SIGNALS (pad)--;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "removed data probe, now %d event, %d buffer probes",
- GST_PAD_DO_EVENT_SIGNALS (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
+ GST_DEBUG
+ ("removed data probe from pad %s:%s, now %d event, %d buffer probes",
+ GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
+ GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
}
@@ -3291,9 +3208,8 @@
GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_EVENT_SIGNALS (pad)--;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "removed event probe, now %d event probes",
- GST_PAD_DO_EVENT_SIGNALS (pad));
+ GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
+ GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
}
@@ -3317,9 +3233,8 @@
GST_OBJECT_LOCK (pad);
g_signal_handler_disconnect (pad, handler_id);
GST_PAD_DO_BUFFER_SIGNALS (pad)--;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "removed buffer probe, now %d buffer probes",
- GST_PAD_DO_BUFFER_SIGNALS (pad));
+ GST_DEBUG ("removed buffer probe from pad %s:%s, now %d buffer probes",
+ GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
GST_OBJECT_UNLOCK (pad);
}
@@ -3349,9 +3264,8 @@
g_return_if_fail (list != NULL);
gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
- /* FIXME 0.11: Set the pad as source. */
gst_element_post_message (element,
- gst_message_new_tag_full (GST_OBJECT (element), pad, list));
+ gst_message_new_tag (GST_OBJECT (element), list));
}
static void
@@ -3397,10 +3311,10 @@
}
static GstPad *
-element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
+element_find_unconnected_pad (GstElement * element, GstPadDirection direction)
{
GstIterator *iter;
- GstPad *unlinked_pad = NULL;
+ GstPad *unconnected_pad = NULL;
gboolean done;
switch (direction) {
@@ -3427,11 +3341,11 @@
peer = gst_pad_get_peer (GST_PAD (pad));
if (peer == NULL) {
- unlinked_pad = pad;
+ unconnected_pad = pad;
done = TRUE;
GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
"found existing unlinked pad %s:%s",
- GST_DEBUG_PAD_NAME (unlinked_pad));
+ GST_DEBUG_PAD_NAME (unconnected_pad));
} else {
gst_object_unref (pad);
gst_object_unref (peer);
@@ -3452,30 +3366,30 @@
gst_iterator_free (iter);
- return unlinked_pad;
+ return unconnected_pad;
}
/**
- * gst_bin_find_unlinked_pad:
- * @bin: bin in which to look for elements with unlinked pads
- * @direction: whether to look for an unlinked source or sink pad
+ * gst_bin_find_unconnected_pad:
+ * @bin: bin in which to look for elements with unconnected pads
+ * @direction: whether to look for an unconnected source or sink pad
*
- * Recursively looks for elements with an unlinked pad of the given
- * direction within the specified bin and returns an unlinked pad
+ * Recursively looks for elements with an unconnected pad of the given
+ * direction within the specified bin and returns an unconnected pad
* if one is found, or NULL otherwise. If a pad is found, the caller
* owns a reference to it and should use gst_object_unref() on the
* pad when it is not needed any longer.
*
- * Returns: unlinked pad of the given direction, or NULL.
+ * Returns: unconnected pad of the given direction, or NULL.
*
- * Since: 0.10.20
+ * Since: 0.10.3
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
GstPad *
-gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
+gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
{
GstIterator *iter;
gboolean done;
@@ -3491,7 +3405,7 @@
switch (gst_iterator_next (iter, &element)) {
case GST_ITERATOR_OK:
- pad = element_find_unlinked_pad (GST_ELEMENT (element), direction);
+ pad = element_find_unconnected_pad (GST_ELEMENT (element), direction);
gst_object_unref (element);
if (pad != NULL)
done = TRUE;
@@ -3514,48 +3428,20 @@
}
/**
- * gst_bin_find_unconnected_pad:
- * @bin: bin in which to look for elements with unlinked pads
- * @direction: whether to look for an unlinked source or sink pad
- *
- * Recursively looks for elements with an unlinked pad of the given
- * direction within the specified bin and returns an unlinked pad
- * if one is found, or NULL otherwise. If a pad is found, the caller
- * owns a reference to it and should use gst_object_unref() on the
- * pad when it is not needed any longer.
- *
- * Returns: unlinked pad of the given direction, or NULL.
- *
- * Since: 0.10.3
- *
- * Deprecated: use gst_bin_find_unlinked_pad() instead.
- */
-#ifndef GST_REMOVE_DEPRECATED
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-GstPad *
-gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
-{
- return gst_bin_find_unlinked_pad (bin, direction);
-}
-#endif
-
-/**
* gst_parse_bin_from_description:
* @bin_description: command line describing the bin
- * @ghost_unlinked_pads: whether to automatically create ghost pads
- * for unlinked source or sink pads within the bin
+ * @ghost_unconnected_pads: whether to automatically create ghost pads
+ * for unconnected source or sink pads within
+ * the bin
* @err: where to store the error message in case of an error, or NULL
*
* This is a convenience wrapper around gst_parse_launch() to create a
* #GstBin from a gst-launch-style pipeline description. See
* gst_parse_launch() and the gst-launch man page for details about the
- * syntax. Ghost pads on the bin for unlinked source or sink pads
+ * syntax. Ghost pads on the bin for unconnected source or sink pads
* within the bin can automatically be created (but only a maximum of
* one ghost pad for each direction will be created; if you expect
- * multiple unlinked source pads or multiple unlinked sink pads
+ * multiple unconnected source pads or multiple unconnected sink pads
* and want them all ghosted, you will have to create the ghost pads
* yourself).
*
@@ -3569,43 +3455,7 @@
GstElement *
gst_parse_bin_from_description (const gchar * bin_description,
- gboolean ghost_unlinked_pads, GError ** err)
-{
- return gst_parse_bin_from_description_full (bin_description,
- ghost_unlinked_pads, NULL, 0, err);
-}
-
-/**
- * gst_parse_bin_from_description_full:
- * @bin_description: command line describing the bin
- * @ghost_unlinked_pads: whether to automatically create ghost pads
- * for unlinked source or sink pads within the bin
- * @context: a parse context allocated with gst_parse_context_new(), or %NULL
- * @flags: parsing options, or #GST_PARSE_FLAG_NONE
- * @err: where to store the error message in case of an error, or NULL
- *
- * This is a convenience wrapper around gst_parse_launch() to create a
- * #GstBin from a gst-launch-style pipeline description. See
- * gst_parse_launch() and the gst-launch man page for details about the
- * syntax. Ghost pads on the bin for unlinked source or sink pads
- * within the bin can automatically be created (but only a maximum of
- * one ghost pad for each direction will be created; if you expect
- * multiple unlinked source pads or multiple unlinked sink pads
- * and want them all ghosted, you will have to create the ghost pads
- * yourself).
- *
- * Returns: a newly-created bin, or NULL if an error occurred.
- *
- * Since: 0.10.20
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstElement *
-gst_parse_bin_from_description_full (const gchar * bin_description,
- gboolean ghost_unlinked_pads, GstParseContext * context,
- GstParseFlags flags, GError ** err)
+ gboolean ghost_unconnected_pads, GError ** err)
{
#ifndef GST_DISABLE_PARSE
GstPad *pad = NULL;
@@ -3619,7 +3469,7 @@
/* parse the pipeline to a bin */
desc = g_strdup_printf ("bin.( %s )", bin_description);
- bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err);
+ bin = (GstBin *) gst_parse_launch (desc, err);
g_free (desc);
if (bin == NULL || (err && *err != NULL)) {
@@ -3629,12 +3479,12 @@
}
/* find pads and ghost them if necessary */
- if (ghost_unlinked_pads) {
- if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) {
+ if (ghost_unconnected_pads) {
+ if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) {
gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
gst_object_unref (pad);
}
- if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) {
+ if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) {
gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
gst_object_unref (pad);
}
@@ -3644,7 +3494,7 @@
#else
gchar *msg;
- GST_WARNING ("Disabled API called");
+ GST_WARNING ("Disabled API called: gst_parse_bin_from_description()");
msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
@@ -3757,95 +3607,3 @@
return GST_TIMEVAL_TO_TIME (now);
#endif
}
-
-/**
- * gst_util_array_binary_search:
- * @array: the sorted input array
- * @num_elements: number of elements in the array
- * @element_size: size of every element in bytes
- * @search_func: function to compare two elements, @search_data will always be passed as second argument
- * @mode: search mode that should be used
- * @search_data: element that should be found
- * @user_data: data to pass to @search_func
- *
- * Searches inside @array for @search_data by using the comparison function
- * @search_func. @array must be sorted ascending.
- *
- * As @search_data is always passed as second argument to @search_func it's
- * not required that @search_data has the same type as the array elements.
- *
- * The complexity of this search function is O(log (num_elements)).
- *
- * Returns: The address of the found element or %NULL if nothing was found
- *
- * Since: 0.10.23
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gpointer
-gst_util_array_binary_search (gpointer array, guint num_elements,
- gsize element_size, GCompareDataFunc search_func, GstSearchMode mode,
- gconstpointer search_data, gpointer user_data)
-{
- glong left = 0, right = num_elements - 1, m;
- gint ret;
- guint8 *data = (guint8 *) array;
-
- g_return_val_if_fail (array != NULL, NULL);
- g_return_val_if_fail (element_size > 0, NULL);
- g_return_val_if_fail (search_func != NULL, NULL);
-
- /* 0. No elements => return NULL */
- if (num_elements == 0)
- return NULL;
-
- /* 1. If search_data is before the 0th element return the 0th element */
- ret = search_func (data, search_data, user_data);
- if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0)
- return data;
- else if (ret > 0)
- return NULL;
-
- /* 2. If search_data is after the last element return the last element */
- ret =
- search_func (data + (num_elements - 1) * element_size, search_data,
- user_data);
- if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0)
- return data + (num_elements - 1) * element_size;
- else if (ret < 0)
- return NULL;
-
- /* 3. else binary search */
- while (TRUE) {
- m = left + (right - left) / 2;
-
- ret = search_func (data + m * element_size, search_data, user_data);
-
- if (ret == 0) {
- return data + m * element_size;
- } else if (ret < 0) {
- left = m + 1;
- } else {
- right = m - 1;
- }
-
- /* No exact match found */
- if (right < left) {
- if (mode == GST_SEARCH_MODE_EXACT) {
- return NULL;
- } else if (mode == GST_SEARCH_MODE_AFTER) {
- if (ret < 0)
- return (m < num_elements) ? data + (m + 1) * element_size : NULL;
- else
- return data + m * element_size;
- } else {
- if (ret < 0)
- return data + m * element_size;
- else
- return (m > 0) ? data + (m - 1) * element_size : NULL;
- }
- }
- }
-}