gstreamer_core/gst/gstutils.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
     1 /* GStreamer
     1 /* GStreamer
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
     3  *                    2000 Wim Taymans <wtay@chello.be>
     3  *                    2000 Wim Taymans <wtay@chello.be>
     4  *                    2002 Thomas Vander Stichele <thomas@apestaart.org>
     4  *                    2002 Thomas Vander Stichele <thomas@apestaart.org>
     5  *
     5  *
     6  * gstutils.c: Utility functions: gtk_get_property stuff, etc.
     6  * gstutils.c: Utility functions
     7  *
     7  *
     8  * This library is free software; you can redistribute it and/or
     8  * This library is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU Library General Public
     9  * modify it under the terms of the GNU Library General Public
    10  * License as published by the Free Software Foundation; either
    10  * License as published by the Free Software Foundation; either
    11  * version 2 of the License, or (at your option) any later version.
    11  * version 2 of the License, or (at your option) any later version.
    35 #include "gstghostpad.h"
    35 #include "gstghostpad.h"
    36 #include "gstutils.h"
    36 #include "gstutils.h"
    37 #include "gsterror.h"
    37 #include "gsterror.h"
    38 #include "gstinfo.h"
    38 #include "gstinfo.h"
    39 #include "gstparse.h"
    39 #include "gstparse.h"
       
    40 #include "gstvalue.h"
    40 #include "gst-i18n-lib.h"
    41 #include "gst-i18n-lib.h"
    41 
    42 
       
    43 /**
       
    44  * gst_util_dump_mem:
       
    45  * @mem: a pointer to the memory to dump
       
    46  * @size: the size of the memory block to dump
       
    47  *
       
    48  * Dumps the memory block into a hex representation. Useful for debugging.
       
    49  */
    42 #ifdef __SYMBIAN32__
    50 #ifdef __SYMBIAN32__
    43 #include <glib_global.h>
    51 #include <glib_global.h>
    44 #include <gobject_global.h>
    52 #include <gobject_global.h>
    45 #endif
    53 #endif
    46 
    54 
    93  * @value: the value to set
   101  * @value: the value to set
    94  * @value_str: the string to get the value from
   102  * @value_str: the string to get the value from
    95  *
   103  *
    96  * Converts the string to the type of the value and
   104  * Converts the string to the type of the value and
    97  * sets the value with it.
   105  * sets the value with it.
       
   106  *
       
   107  * Note that this function is dangerous as it does not return any indication
       
   108  * if the conversion worked or not.
    98  */
   109  */
    99 #ifdef __SYMBIAN32__
   110 #ifdef __SYMBIAN32__
   100 EXPORT_C
   111 EXPORT_C
   101 #endif
   112 #endif
   102 
   113 
   103 void
   114 void
   104 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
   115 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
   105 {
   116 {
   106   gint sscanf_ret;
   117   gboolean res;
   107 
   118 
   108   g_return_if_fail (value != NULL);
   119   g_return_if_fail (value != NULL);
   109   g_return_if_fail (value_str != NULL);
   120   g_return_if_fail (value_str != NULL);
   110 
   121 
   111   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
   122   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
   112       g_type_name (G_VALUE_TYPE (value)));
   123       g_type_name (G_VALUE_TYPE (value)));
   113 
   124 
   114   switch (G_VALUE_TYPE (value)) {
   125   res = gst_value_deserialize (value, value_str);
   115     case G_TYPE_STRING:
   126   if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
   116       g_value_set_string (value, value_str);
   127     /* backwards compat, all booleans that fail to parse are false */
   117       break;
   128     g_value_set_boolean (value, FALSE);
   118     case G_TYPE_ENUM:
   129     res = TRUE;
   119     case G_TYPE_INT:{
   130   }
   120       gint i;
   131   g_return_if_fail (res);
   121 
       
   122       sscanf_ret = sscanf (value_str, "%d", &i);
       
   123       g_return_if_fail (sscanf_ret == 1);
       
   124       g_value_set_int (value, i);
       
   125       break;
       
   126     }
       
   127     case G_TYPE_UINT:{
       
   128       guint i;
       
   129 
       
   130       sscanf_ret = sscanf (value_str, "%u", &i);
       
   131       g_return_if_fail (sscanf_ret == 1);
       
   132       g_value_set_uint (value, i);
       
   133       break;
       
   134     }
       
   135     case G_TYPE_LONG:{
       
   136       glong i;
       
   137 
       
   138       sscanf_ret = sscanf (value_str, "%ld", &i);
       
   139       g_return_if_fail (sscanf_ret == 1);
       
   140       g_value_set_long (value, i);
       
   141       break;
       
   142     }
       
   143     case G_TYPE_ULONG:{
       
   144       gulong i;
       
   145 
       
   146       sscanf_ret = sscanf (value_str, "%lu", &i);
       
   147       g_return_if_fail (sscanf_ret == 1);
       
   148       g_value_set_ulong (value, i);
       
   149       break;
       
   150     }
       
   151     case G_TYPE_BOOLEAN:{
       
   152       gboolean i = FALSE;
       
   153 
       
   154       if (!g_ascii_strncasecmp ("true", value_str, 4))
       
   155         i = TRUE;
       
   156       g_value_set_boolean (value, i);
       
   157       break;
       
   158     }
       
   159     case G_TYPE_CHAR:{
       
   160       gchar i;
       
   161 
       
   162       sscanf_ret = sscanf (value_str, "%c", &i);
       
   163       g_return_if_fail (sscanf_ret == 1);
       
   164       g_value_set_char (value, i);
       
   165       break;
       
   166     }
       
   167     case G_TYPE_UCHAR:{
       
   168       guchar i;
       
   169 
       
   170       sscanf_ret = sscanf (value_str, "%c", &i);
       
   171       g_return_if_fail (sscanf_ret == 1);
       
   172       g_value_set_uchar (value, i);
       
   173       break;
       
   174     }
       
   175     case G_TYPE_FLOAT:{
       
   176       gfloat i;
       
   177 
       
   178       sscanf_ret = sscanf (value_str, "%f", &i);
       
   179       g_return_if_fail (sscanf_ret == 1);
       
   180       g_value_set_float (value, i);
       
   181       break;
       
   182     }
       
   183     case G_TYPE_DOUBLE:{
       
   184       gfloat i;
       
   185 
       
   186       sscanf_ret = sscanf (value_str, "%g", &i);
       
   187       g_return_if_fail (sscanf_ret == 1);
       
   188       g_value_set_double (value, (gdouble) i);
       
   189       break;
       
   190     }
       
   191     default:
       
   192       break;
       
   193   }
       
   194 }
   132 }
   195 
   133 
   196 /**
   134 /**
   197  * gst_util_set_object_arg:
   135  * gst_util_set_object_arg:
   198  * @object: the object to set the argument of
   136  * @object: the object to set the argument of
   199  * @name: the name of the argument to set
   137  * @name: the name of the argument to set
   200  * @value: the string value to set
   138  * @value: the string value to set
   201  *
   139  *
   202  * Convertes the string value to the type of the objects argument and
   140  * Convertes the string value to the type of the objects argument and
   203  * sets the argument with it.
   141  * sets the argument with it.
       
   142  *
       
   143  * Note that this function silently returns if @object has no property named
       
   144  * @name or when @value cannot be converted to the type of the property.
   204  */
   145  */
   205 #ifdef __SYMBIAN32__
   146 #ifdef __SYMBIAN32__
   206 EXPORT_C
   147 EXPORT_C
   207 #endif
   148 #endif
   208 
   149 
   209 void
   150 void
   210 gst_util_set_object_arg (GObject * object, const gchar * name,
   151 gst_util_set_object_arg (GObject * object, const gchar * name,
   211     const gchar * value)
   152     const gchar * value)
   212 {
   153 {
   213   gboolean sscanf_ret;
   154   GParamSpec *pspec;
   214 
   155   GType value_type;
   215   if (name && value) {
   156   GValue v = { 0, };
   216     GParamSpec *paramspec;
   157 
   217 
   158   g_return_if_fail (G_IS_OBJECT (object));
   218     paramspec =
   159   g_return_if_fail (name != NULL);
   219         g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
   160   g_return_if_fail (value != NULL);
   220 
   161 
   221     if (!paramspec) {
   162   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
   222       return;
   163   if (!pspec)
   223     }
   164     return;
   224 
   165 
   225     GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d",
   166   value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
   226         paramspec->flags, (gint) paramspec->value_type);
   167 
   227 
   168   GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s",
   228     if (paramspec->flags & G_PARAM_WRITABLE) {
   169       pspec->flags, g_type_name (value_type));
   229       switch (paramspec->value_type) {
   170 
   230         case G_TYPE_STRING:
   171   if (!(pspec->flags & G_PARAM_WRITABLE))
   231           g_object_set (G_OBJECT (object), name, value, NULL);
   172     return;
   232           break;
   173 
   233         case G_TYPE_ENUM:
   174   g_value_init (&v, value_type);
   234         case G_TYPE_INT:{
   175 
   235           gint i;
   176   /* special case for element <-> xml (de)serialisation */
   236 
   177   if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) {
   237           sscanf_ret = sscanf (value, "%d", &i);
   178     g_value_set_boxed (&v, NULL);
   238           g_return_if_fail (sscanf_ret == 1);
   179     goto done;
   239           g_object_set (G_OBJECT (object), name, i, NULL);
   180   }
   240           break;
   181 
   241         }
   182   if (!gst_value_deserialize (&v, value))
   242         case G_TYPE_UINT:{
   183     return;
   243           guint i;
   184 
   244 
   185 done:
   245           sscanf_ret = sscanf (value, "%u", &i);
   186 
   246           g_return_if_fail (sscanf_ret == 1);
   187   g_object_set_property (object, pspec->name, &v);
   247           g_object_set (G_OBJECT (object), name, i, NULL);
   188   g_value_unset (&v);
   248           break;
       
   249         }
       
   250         case G_TYPE_LONG:{
       
   251           glong i;
       
   252 
       
   253           sscanf_ret = sscanf (value, "%ld", &i);
       
   254           g_return_if_fail (sscanf_ret == 1);
       
   255           g_object_set (G_OBJECT (object), name, i, NULL);
       
   256           break;
       
   257         }
       
   258         case G_TYPE_ULONG:{
       
   259           gulong i;
       
   260 
       
   261           sscanf_ret = sscanf (value, "%lu", &i);
       
   262           g_return_if_fail (sscanf_ret == 1);
       
   263           g_object_set (G_OBJECT (object), name, i, NULL);
       
   264           break;
       
   265         }
       
   266         case G_TYPE_BOOLEAN:{
       
   267           gboolean i = FALSE;
       
   268 
       
   269           if (!g_ascii_strncasecmp ("true", value, 4))
       
   270             i = TRUE;
       
   271           g_object_set (G_OBJECT (object), name, i, NULL);
       
   272           break;
       
   273         }
       
   274         case G_TYPE_CHAR:{
       
   275           gchar i;
       
   276 
       
   277           sscanf_ret = sscanf (value, "%c", &i);
       
   278           g_return_if_fail (sscanf_ret == 1);
       
   279           g_object_set (G_OBJECT (object), name, i, NULL);
       
   280           break;
       
   281         }
       
   282         case G_TYPE_UCHAR:{
       
   283           guchar i;
       
   284 
       
   285           sscanf_ret = sscanf (value, "%c", &i);
       
   286           g_return_if_fail (sscanf_ret == 1);
       
   287           g_object_set (G_OBJECT (object), name, i, NULL);
       
   288           break;
       
   289         }
       
   290         case G_TYPE_FLOAT:{
       
   291           gfloat i;
       
   292 
       
   293           sscanf_ret = sscanf (value, "%f", &i);
       
   294           g_return_if_fail (sscanf_ret == 1);
       
   295           g_object_set (G_OBJECT (object), name, i, NULL);
       
   296           break;
       
   297         }
       
   298         case G_TYPE_DOUBLE:{
       
   299           gfloat i;
       
   300 
       
   301           sscanf_ret = sscanf (value, "%g", &i);
       
   302           g_return_if_fail (sscanf_ret == 1);
       
   303           g_object_set (G_OBJECT (object), name, (gdouble) i, NULL);
       
   304           break;
       
   305         }
       
   306         default:
       
   307           if (G_IS_PARAM_SPEC_ENUM (paramspec)) {
       
   308             gint i;
       
   309 
       
   310             sscanf_ret = sscanf (value, "%d", &i);
       
   311             g_return_if_fail (sscanf_ret == 1);
       
   312             g_object_set (G_OBJECT (object), name, i, NULL);
       
   313           }
       
   314           break;
       
   315       }
       
   316     }
       
   317   }
       
   318 }
   189 }
   319 
   190 
   320 /* work around error C2520: conversion from unsigned __int64 to double
   191 /* work around error C2520: conversion from unsigned __int64 to double
   321  * not implemented, use signed __int64
   192  * not implemented, use signed __int64
   322  *
   193  *
   433 
   304 
   434   return q0.ll;
   305   return q0.ll;
   435 }
   306 }
   436 
   307 
   437 static guint64
   308 static guint64
   438 gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
   309 gst_util_uint64_scale_int64_unchecked (guint64 val, guint64 num, guint64 denom)
   439 {
   310 {
   440   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
   311   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
   441   GstUInt64 v, n;
   312   GstUInt64 v, n;
   442 
   313 
   443   /* prepare input */
   314   /* prepare input */
   465   ct.ll = (guint64) a0.l.high + a1.l.low + b0.l.low;
   336   ct.ll = (guint64) a0.l.high + a1.l.low + b0.l.low;
   466   c0.l.high = ct.l.low;
   337   c0.l.high = ct.l.low;
   467   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
   338   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
   468 
   339 
   469   /* if high bits bigger than denom, we overflow */
   340   /* if high bits bigger than denom, we overflow */
   470   if (c1.ll >= denom)
   341   if (G_UNLIKELY (c1.ll >= denom))
   471     goto overflow;
   342     goto overflow;
   472 
   343 
   473   /* shortcut for division by 1, c1.ll should be 0 because of the
   344   /* shortcut for division by 1, c1.ll should be 0 because of the
   474    * overflow check above. */
   345    * overflow check above. */
   475   if (denom == 1)
   346   if (denom == 1)
   495   {
   366   {
   496     return G_MAXUINT64;
   367     return G_MAXUINT64;
   497   }
   368   }
   498 }
   369 }
   499 
   370 
       
   371 static inline guint64
       
   372 gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom)
       
   373 {
       
   374   GstUInt64 result;
       
   375   GstUInt64 low, high;
       
   376 
       
   377   /* do 96 bits mult/div */
       
   378   low.ll = val;
       
   379   result.ll = ((guint64) low.l.low) * num;
       
   380   high.ll = ((guint64) low.l.high) * num + (result.l.high);
       
   381 
       
   382   low.ll = high.ll / denom;
       
   383   result.l.high = high.ll % denom;
       
   384   result.ll /= denom;
       
   385 
       
   386   /* avoid overflow */
       
   387   if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32))
       
   388     goto overflow;
       
   389 
       
   390   result.l.high += low.l.low;
       
   391 
       
   392   return result.ll;
       
   393 
       
   394 overflow:
       
   395   {
       
   396     return G_MAXUINT64;
       
   397   }
       
   398 }
       
   399 
       
   400 
   500 /**
   401 /**
   501  * gst_util_uint64_scale:
   402  * gst_util_uint64_scale:
   502  * @val: the number to scale
   403  * @val: the number to scale
   503  * @num: the numerator of the scale ratio
   404  * @num: the numerator of the scale ratio
   504  * @denom: the denominator of the scale ratio
   405  * @denom: the denominator of the scale ratio
   517 guint64
   418 guint64
   518 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
   419 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
   519 {
   420 {
   520   g_return_val_if_fail (denom != 0, G_MAXUINT64);
   421   g_return_val_if_fail (denom != 0, G_MAXUINT64);
   521 
   422 
   522   if (num == 0)
   423   if (G_UNLIKELY (num == 0))
   523     return 0;
   424     return 0;
   524 
   425 
   525   if (num == 1 && denom == 1)
   426   if (G_UNLIKELY (num == denom))
   526     return val;
   427     return val;
   527 
   428 
   528   /* if the denom is high, we need to do a 64 muldiv */
   429   /* if the denom is high, we need to do a 64 muldiv */
   529   if (denom > G_MAXINT32)
   430   if (G_UNLIKELY (denom > G_MAXINT32))
   530     goto do_int64;
   431     goto do_int64;
   531 
   432 
   532   /* if num and denom are low we can do a 32 bit muldiv */
   433   /* if num and denom are low we can do a 32 bit muldiv */
   533   if (num <= G_MAXINT32)
   434   if (G_LIKELY (num <= G_MAXINT32))
   534     goto do_int32;
   435     goto do_int32;
   535 
   436 
   536   /* val and num are high, we need 64 muldiv */
   437   /* val and num are high, we need 64 muldiv */
   537   if (val > G_MAXINT32)
   438   if (G_UNLIKELY (val > G_MAXINT32))
   538     goto do_int64;
   439     goto do_int64;
   539 
   440 
   540   /* val is low and num is high, we can swap them and do 32 muldiv */
   441   /* val is low and num is high, we can swap them and do 32 muldiv */
   541   return gst_util_uint64_scale_int (num, (gint) val, (gint) denom);
   442   return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom);
   542 
   443 
   543 do_int32:
   444 do_int32:
   544   return gst_util_uint64_scale_int (val, (gint) num, (gint) denom);
   445   return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom);
   545 
   446 
   546 do_int64:
   447 do_int64:
   547   /* to the more heavy implementations... */
   448   /* to the more heavy implementations... */
   548   return gst_util_uint64_scale_int64 (val, num, denom);
   449   return gst_util_uint64_scale_int64_unchecked (val, num, denom);
   549 }
   450 }
   550 
   451 
   551 /**
   452 /**
   552  * gst_util_uint64_scale_int:
   453  * gst_util_uint64_scale_int:
   553  * @val: guint64 (such as a #GstClockTime) to scale.
   454  * @val: guint64 (such as a #GstClockTime) to scale.
   567 #endif
   468 #endif
   568 
   469 
   569 guint64
   470 guint64
   570 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
   471 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
   571 {
   472 {
   572   GstUInt64 result;
       
   573   GstUInt64 low, high;
       
   574 
       
   575   g_return_val_if_fail (denom > 0, G_MAXUINT64);
   473   g_return_val_if_fail (denom > 0, G_MAXUINT64);
   576   g_return_val_if_fail (num >= 0, G_MAXUINT64);
   474   g_return_val_if_fail (num >= 0, G_MAXUINT64);
   577 
   475 
   578   if (num == 0)
   476   if (G_UNLIKELY (num == 0))
   579     return 0;
   477     return 0;
   580 
   478 
   581   if (num == 1 && denom == 1)
   479   if (G_UNLIKELY (num == denom))
   582     return val;
   480     return val;
   583 
   481 
   584   if (val <= G_MAXUINT32)
   482   if (val <= G_MAXUINT32)
   585     /* simple case */
   483     /* simple case */
   586     return val * num / denom;
   484     return val * num / denom;
   587 
   485 
   588   /* do 96 bits mult/div */
   486   return gst_util_uint64_scale_int_unchecked (val, num, denom);
   589   low.ll = val;
   487 }
   590   result.ll = ((guint64) low.l.low) * num;
   488 
   591   high.ll = ((guint64) low.l.high) * num + (result.l.high);
   489 /**
   592 
   490  * gst_util_seqnum_next:
   593   low.ll = high.ll / denom;
   491  *
   594   result.l.high = high.ll % denom;
   492  * Return a constantly incrementing sequence number.
   595   result.ll /= denom;
   493  *
   596 
   494  * This function is used internally to GStreamer to be able to determine which
   597   /* avoid overflow */
   495  * events and messages are "the same". For example, elements may set the seqnum
   598   if (low.ll + result.l.high > G_MAXUINT32)
   496  * on a segment-done message to be the same as that of the last seek event, to
   599     goto overflow;
   497  * indicate that event and the message correspond to the same segment.
   600 
   498  *
   601   result.l.high += low.l.low;
   499  * Returns: A constantly incrementing 32-bit unsigned integer, which might
   602 
   500  * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure
   603   return result.ll;
   501  * you handle wraparound correctly.
   604 
   502  *
   605 overflow:
   503  * Since: 0.10.22
   606   {
   504  */
   607     return G_MAXUINT64;
   505 #ifdef __SYMBIAN32__
   608   }
   506 EXPORT_C
       
   507 #endif
       
   508 
       
   509 guint32
       
   510 gst_util_seqnum_next (void)
       
   511 {
       
   512   static gint counter = 0;
       
   513   return g_atomic_int_exchange_and_add (&counter, 1);
       
   514 }
       
   515 
       
   516 /**
       
   517  * gst_util_seqnum_compare:
       
   518  * @s1: A sequence number.
       
   519  * @s2: Another sequence number.
       
   520  *
       
   521  * Compare two sequence numbers, handling wraparound.
       
   522  * 
       
   523  * The current implementation just returns (gint32)(@s1 - @s2).
       
   524  *
       
   525  * Returns: A negative number if @s1 is before @s2, 0 if they are equal, or a
       
   526  * positive number if @s1 is after @s2.
       
   527  *
       
   528  * Since: 0.10.22
       
   529  */
       
   530 #ifdef __SYMBIAN32__
       
   531 EXPORT_C
       
   532 #endif
       
   533 
       
   534 gint32
       
   535 gst_util_seqnum_compare (guint32 s1, guint32 s2)
       
   536 {
       
   537   return (gint32) (s1 - s2);
   609 }
   538 }
   610 
   539 
   611 /* -----------------------------------------------------
   540 /* -----------------------------------------------------
   612  *
   541  *
   613  *  The following code will be moved out of the main
   542  *  The following code will be moved out of the main
   926     pad = NULL;
   855     pad = NULL;
   927 
   856 
   928   return pad;
   857   return pad;
   929 }
   858 }
   930 
   859 
       
   860 /*
       
   861  * Checks if the source pad and the sink pad can be linked.
       
   862  * Both @srcpad and @sinkpad must be unlinked and have a parent.
       
   863  */
       
   864 static gboolean
       
   865 gst_pad_check_link (GstPad * srcpad, GstPad * sinkpad)
       
   866 {
       
   867   /* FIXME This function is gross.  It's almost a direct copy of
       
   868    * gst_pad_link_filtered().  Any decent programmer would attempt
       
   869    * to merge the two functions, which I will do some day. --ds
       
   870    */
       
   871 
       
   872   /* generic checks */
       
   873   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
       
   874   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
       
   875 
       
   876   GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
       
   877       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
       
   878 
       
   879   /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
       
   880   if (GST_PAD_PEER (srcpad) != NULL) {
       
   881     GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
       
   882         GST_DEBUG_PAD_NAME (srcpad));
       
   883     return FALSE;
       
   884   }
       
   885   if (GST_PAD_PEER (sinkpad) != NULL) {
       
   886     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
       
   887         GST_DEBUG_PAD_NAME (sinkpad));
       
   888     return FALSE;
       
   889   }
       
   890   if (!GST_PAD_IS_SRC (srcpad)) {
       
   891     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
       
   892         GST_DEBUG_PAD_NAME (srcpad));
       
   893     return FALSE;
       
   894   }
       
   895   if (!GST_PAD_IS_SINK (sinkpad)) {
       
   896     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
       
   897         GST_DEBUG_PAD_NAME (sinkpad));
       
   898     return FALSE;
       
   899   }
       
   900   if (GST_PAD_PARENT (srcpad) == NULL) {
       
   901     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
       
   902         GST_DEBUG_PAD_NAME (srcpad));
       
   903     return FALSE;
       
   904   }
       
   905   if (GST_PAD_PARENT (sinkpad) == NULL) {
       
   906     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
       
   907         GST_DEBUG_PAD_NAME (srcpad));
       
   908     return FALSE;
       
   909   }
       
   910 
       
   911   return TRUE;
       
   912 }
       
   913 
   931 /**
   914 /**
   932  * gst_element_get_compatible_pad:
   915  * gst_element_get_compatible_pad:
   933  * @element: a #GstElement in which the pad should be found.
   916  * @element: a #GstElement in which the pad should be found.
   934  * @pad: the #GstPad to find a compatible one for.
   917  * @pad: the #GstPad to find a compatible one for.
   935  * @caps: the #GstCaps to use as a filter.
   918  * @caps: the #GstCaps to use as a filter.
   953   GstPadTemplate *templ;
   936   GstPadTemplate *templ;
   954   GstCaps *templcaps;
   937   GstCaps *templcaps;
   955   GstPad *foundpad = NULL;
   938   GstPad *foundpad = NULL;
   956   gboolean done;
   939   gboolean done;
   957 
   940 
   958   /* FIXME check for caps compatibility */
       
   959 
       
   960   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   941   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   961   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
   942   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
   962 
   943 
   963   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   944   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   964       "finding pad in %s compatible with %s:%s",
   945       "finding pad in %s compatible with %s:%s",
   983         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
   964         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
   984             GST_DEBUG_PAD_NAME (current));
   965             GST_DEBUG_PAD_NAME (current));
   985 
   966 
   986         peer = gst_pad_get_peer (current);
   967         peer = gst_pad_get_peer (current);
   987 
   968 
   988         if (peer == NULL && gst_pad_can_link (pad, current)) {
   969         if (peer == NULL && gst_pad_check_link (pad, current)) {
   989 
   970           GstCaps *temp, *temp2, *intersection;
       
   971 
       
   972           /* Now check if the two pads' caps are compatible */
       
   973           temp = gst_pad_get_caps (pad);
       
   974           if (caps) {
       
   975             intersection = gst_caps_intersect (temp, caps);
       
   976             gst_caps_unref (temp);
       
   977           } else {
       
   978             intersection = temp;
       
   979           }
       
   980 
       
   981           temp = gst_pad_get_caps (current);
       
   982           temp2 = gst_caps_intersect (temp, intersection);
       
   983           gst_caps_unref (temp);
       
   984           gst_caps_unref (intersection);
       
   985 
       
   986           intersection = temp2;
       
   987 
       
   988           if (!gst_caps_is_empty (intersection)) {
       
   989             gst_caps_unref (intersection);
       
   990 
       
   991             GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
   992                 "found existing unlinked compatible pad %s:%s",
       
   993                 GST_DEBUG_PAD_NAME (current));
       
   994             gst_iterator_free (pads);
       
   995 
       
   996             return current;
       
   997           } else {
       
   998             GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "incompatible pads");
       
   999           }
       
  1000           gst_caps_unref (intersection);
       
  1001         } else {
   990           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  1002           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   991               "found existing unlinked pad %s:%s",
  1003               "already linked or cannot be linked (peer = %p)", peer);
   992               GST_DEBUG_PAD_NAME (current));
       
   993 
       
   994           gst_iterator_free (pads);
       
   995 
       
   996           return current;
       
   997         } else {
       
   998           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
       
   999 
       
  1000           gst_object_unref (current);
       
  1001           if (peer)
       
  1002             gst_object_unref (peer);
       
  1003         }
  1004         }
       
  1005         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
       
  1006 
       
  1007         gst_object_unref (current);
       
  1008         if (peer)
       
  1009           gst_object_unref (peer);
  1004         break;
  1010         break;
  1005       }
  1011       }
  1006       case GST_ITERATOR_DONE:
  1012       case GST_ITERATOR_DONE:
  1007         done = TRUE;
  1013         done = TRUE;
  1008         break;
  1014         break;
  1014         break;
  1020         break;
  1015     }
  1021     }
  1016   }
  1022   }
  1017   gst_iterator_free (pads);
  1023   gst_iterator_free (pads);
  1018 
  1024 
       
  1025   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
       
  1026       "Could not find a compatible unlinked always pad to link to %s:%s, now checking request pads",
       
  1027       GST_DEBUG_PAD_NAME (pad));
       
  1028 
  1019   /* try to create a new one */
  1029   /* try to create a new one */
  1020   /* requesting is a little crazy, we need a template. Let's create one */
  1030   /* requesting is a little crazy, we need a template. Let's create one */
       
  1031   /* FIXME: why not gst_pad_get_pad_template (pad); */
  1021   templcaps = gst_pad_get_caps (pad);
  1032   templcaps = gst_pad_get_caps (pad);
  1022 
  1033 
  1023   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
  1034   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
  1024       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
  1035       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
       
  1036 
  1025   foundpad = gst_element_request_compatible_pad (element, templ);
  1037   foundpad = gst_element_request_compatible_pad (element, templ);
  1026   gst_object_unref (templ);
  1038   gst_object_unref (templ);
  1027 
  1039 
  1028   if (foundpad) {
  1040   if (foundpad) {
  1029     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  1041     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  1158 
  1170 
  1159   while (templates) {
  1171   while (templates) {
  1160     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
  1172     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
  1161 
  1173 
  1162     if (template->direction == GST_PAD_SRC) {
  1174     if (template->direction == GST_PAD_SRC) {
  1163       if (gst_caps_is_always_compatible (gst_static_caps_get (&template->
  1175       if (gst_caps_is_always_compatible (gst_static_caps_get
  1164                   static_caps), caps))
  1176               (&template->static_caps), caps))
  1165         return TRUE;
  1177         return TRUE;
  1166     }
  1178     }
  1167     templates = g_list_next (templates);
  1179     templates = g_list_next (templates);
  1168   }
  1180   }
  1169 
  1181 
  1435       destpadname ? destpadname : "(any)");
  1447       destpadname ? destpadname : "(any)");
  1436 
  1448 
  1437   /* get a src pad */
  1449   /* get a src pad */
  1438   if (srcpadname) {
  1450   if (srcpadname) {
  1439     /* name specified, look it up */
  1451     /* name specified, look it up */
  1440     srcpad = gst_element_get_pad (src, srcpadname);
  1452     if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
       
  1453       srcpad = gst_element_get_request_pad (src, srcpadname);
  1441     if (!srcpad) {
  1454     if (!srcpad) {
  1442       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1455       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1443           GST_ELEMENT_NAME (src), srcpadname);
  1456           GST_ELEMENT_NAME (src), srcpadname);
  1444       return FALSE;
  1457       return FALSE;
  1445     } else {
  1458     } else {
  1468   }
  1481   }
  1469 
  1482 
  1470   /* get a destination pad */
  1483   /* get a destination pad */
  1471   if (destpadname) {
  1484   if (destpadname) {
  1472     /* name specified, look it up */
  1485     /* name specified, look it up */
  1473     destpad = gst_element_get_pad (dest, destpadname);
  1486     if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
       
  1487       destpad = gst_element_get_request_pad (dest, destpadname);
  1474     if (!destpad) {
  1488     if (!destpad) {
  1475       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1489       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1476           GST_ELEMENT_NAME (dest), destpadname);
  1490           GST_ELEMENT_NAME (dest), destpadname);
  1477       return FALSE;
  1491       return FALSE;
  1478     } else {
  1492     } else {
  1773 #endif
  1787 #endif
  1774 
  1788 
  1775 gboolean
  1789 gboolean
  1776 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
  1790 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
  1777 {
  1791 {
       
  1792   gboolean res = TRUE;
  1778   va_list args;
  1793   va_list args;
  1779 
  1794 
  1780   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
  1795   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
  1781   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
  1796   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
  1782 
  1797 
  1783   va_start (args, element_2);
  1798   va_start (args, element_2);
  1784 
  1799 
  1785   while (element_2) {
  1800   while (element_2) {
  1786     if (!gst_element_link (element_1, element_2))
  1801     if (!gst_element_link (element_1, element_2)) {
  1787       return FALSE;
  1802       res = FALSE;
       
  1803       break;
       
  1804     }
  1788 
  1805 
  1789     element_1 = element_2;
  1806     element_1 = element_2;
  1790     element_2 = va_arg (args, GstElement *);
  1807     element_2 = va_arg (args, GstElement *);
  1791   }
  1808   }
  1792 
  1809 
  1793   va_end (args);
  1810   va_end (args);
  1794 
  1811 
  1795   return TRUE;
  1812   return res;
  1796 }
  1813 }
  1797 
  1814 
  1798 /**
  1815 /**
  1799  * gst_element_link_filtered:
  1816  * gst_element_link_filtered:
  1800  * @src: a #GstElement containing the source pad.
  1817  * @src: a #GstElement containing the source pad.
  1839 void
  1856 void
  1840 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
  1857 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
  1841     GstElement * dest, const gchar * destpadname)
  1858     GstElement * dest, const gchar * destpadname)
  1842 {
  1859 {
  1843   GstPad *srcpad, *destpad;
  1860   GstPad *srcpad, *destpad;
       
  1861   gboolean srcrequest, destrequest;
       
  1862 
       
  1863   srcrequest = destrequest = FALSE;
  1844 
  1864 
  1845   g_return_if_fail (src != NULL);
  1865   g_return_if_fail (src != NULL);
  1846   g_return_if_fail (GST_IS_ELEMENT (src));
  1866   g_return_if_fail (GST_IS_ELEMENT (src));
  1847   g_return_if_fail (srcpadname != NULL);
  1867   g_return_if_fail (srcpadname != NULL);
  1848   g_return_if_fail (dest != NULL);
  1868   g_return_if_fail (dest != NULL);
  1849   g_return_if_fail (GST_IS_ELEMENT (dest));
  1869   g_return_if_fail (GST_IS_ELEMENT (dest));
  1850   g_return_if_fail (destpadname != NULL);
  1870   g_return_if_fail (destpadname != NULL);
  1851 
  1871 
  1852   /* obtain the pads requested */
  1872   /* obtain the pads requested */
  1853   srcpad = gst_element_get_pad (src, srcpadname);
  1873   if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
       
  1874     if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
       
  1875       srcrequest = TRUE;
  1854   if (srcpad == NULL) {
  1876   if (srcpad == NULL) {
  1855     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
  1877     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
  1856     return;
  1878     return;
  1857   }
  1879   }
  1858   destpad = gst_element_get_pad (dest, destpadname);
  1880   if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
       
  1881     if ((destpad = gst_element_get_request_pad (dest, destpadname)))
       
  1882       destrequest = TRUE;
  1859   if (destpad == NULL) {
  1883   if (destpad == NULL) {
  1860     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
  1884     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
  1861         destpadname);
  1885         destpadname);
  1862     gst_object_unref (srcpad);
  1886     goto free_src;
  1863     return;
       
  1864   }
  1887   }
  1865 
  1888 
  1866   /* we're satisified they can be unlinked, let's do it */
  1889   /* we're satisified they can be unlinked, let's do it */
  1867   gst_pad_unlink (srcpad, destpad);
  1890   gst_pad_unlink (srcpad, destpad);
       
  1891 
       
  1892   if (destrequest)
       
  1893     gst_element_release_request_pad (dest, destpad);
       
  1894   gst_object_unref (destpad);
       
  1895 
       
  1896 free_src:
       
  1897   if (srcrequest)
       
  1898     gst_element_release_request_pad (src, srcpad);
  1868   gst_object_unref (srcpad);
  1899   gst_object_unref (srcpad);
  1869   gst_object_unref (destpad);
       
  1870 }
  1900 }
  1871 
  1901 
  1872 /**
  1902 /**
  1873  * gst_element_unlink_many:
  1903  * gst_element_unlink_many:
  1874  * @element_1: the first #GstElement in the link chain.
  1904  * @element_1: the first #GstElement in the link chain.
  1938         GstPad *pad = GST_PAD_CAST (data);
  1968         GstPad *pad = GST_PAD_CAST (data);
  1939 
  1969 
  1940         if (GST_PAD_IS_SRC (pad)) {
  1970         if (GST_PAD_IS_SRC (pad)) {
  1941           GstPad *peerpad = gst_pad_get_peer (pad);
  1971           GstPad *peerpad = gst_pad_get_peer (pad);
  1942 
  1972 
  1943           /* see if the pad is connected and is really a pad
  1973           /* see if the pad is linked and is really a pad of dest */
  1944            * of dest */
       
  1945           if (peerpad) {
  1974           if (peerpad) {
  1946             GstElement *peerelem;
  1975             GstElement *peerelem;
  1947 
  1976 
  1948             peerelem = gst_pad_get_parent_element (peerpad);
  1977             peerelem = gst_pad_get_parent_element (peerpad);
  1949 
  1978 
  2133   return gst_element_seek (element, 1.0, format, seek_flags,
  2162   return gst_element_seek (element, 1.0, format, seek_flags,
  2134       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0);
  2163       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0);
  2135 }
  2164 }
  2136 
  2165 
  2137 /**
  2166 /**
  2138  * gst_pad_can_link:
       
  2139  * @srcpad: the source #GstPad to link.
       
  2140  * @sinkpad: the sink #GstPad to link.
       
  2141  *
       
  2142  * Checks if the source pad and the sink pad can be linked.
       
  2143  * Both @srcpad and @sinkpad must be unlinked.
       
  2144  *
       
  2145  * Returns: TRUE if the pads can be linked, FALSE otherwise.
       
  2146  */
       
  2147 #ifdef __SYMBIAN32__
       
  2148 EXPORT_C
       
  2149 #endif
       
  2150 
       
  2151 gboolean
       
  2152 gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
       
  2153 {
       
  2154   /* FIXME This function is gross.  It's almost a direct copy of
       
  2155    * gst_pad_link_filtered().  Any decent programmer would attempt
       
  2156    * to merge the two functions, which I will do some day. --ds
       
  2157    */
       
  2158 
       
  2159   /* generic checks */
       
  2160   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
       
  2161   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
       
  2162 
       
  2163   GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
       
  2164       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
       
  2165 
       
  2166   /* FIXME: shouldn't we convert this to g_return_val_if_fail? */
       
  2167   if (GST_PAD_PEER (srcpad) != NULL) {
       
  2168     GST_CAT_INFO (GST_CAT_PADS, "Source pad %s:%s has a peer, failed",
       
  2169         GST_DEBUG_PAD_NAME (srcpad));
       
  2170     return FALSE;
       
  2171   }
       
  2172   if (GST_PAD_PEER (sinkpad) != NULL) {
       
  2173     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has a peer, failed",
       
  2174         GST_DEBUG_PAD_NAME (sinkpad));
       
  2175     return FALSE;
       
  2176   }
       
  2177   if (!GST_PAD_IS_SRC (srcpad)) {
       
  2178     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s is not source pad, failed",
       
  2179         GST_DEBUG_PAD_NAME (srcpad));
       
  2180     return FALSE;
       
  2181   }
       
  2182   if (!GST_PAD_IS_SINK (sinkpad)) {
       
  2183     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s is not sink pad, failed",
       
  2184         GST_DEBUG_PAD_NAME (sinkpad));
       
  2185     return FALSE;
       
  2186   }
       
  2187   if (GST_PAD_PARENT (srcpad) == NULL) {
       
  2188     GST_CAT_INFO (GST_CAT_PADS, "Src pad %s:%s has no parent, failed",
       
  2189         GST_DEBUG_PAD_NAME (srcpad));
       
  2190     return FALSE;
       
  2191   }
       
  2192   if (GST_PAD_PARENT (sinkpad) == NULL) {
       
  2193     GST_CAT_INFO (GST_CAT_PADS, "Sink pad %s:%s has no parent, failed",
       
  2194         GST_DEBUG_PAD_NAME (srcpad));
       
  2195     return FALSE;
       
  2196   }
       
  2197 
       
  2198   return TRUE;
       
  2199 }
       
  2200 
       
  2201 /**
       
  2202  * gst_pad_use_fixed_caps:
  2167  * gst_pad_use_fixed_caps:
  2203  * @pad: the pad to use
  2168  * @pad: the pad to use
  2204  *
  2169  *
  2205  * A helper function you can use that sets the
  2170  * A helper function you can use that sets the
  2206  * @gst_pad_get_fixed_caps_func as the getcaps function for the
  2171  * @gst_pad_get_fixed_caps_func as the getcaps function for the
  2247 
  2212 
  2248     GST_CAT_DEBUG (GST_CAT_CAPS,
  2213     GST_CAT_DEBUG (GST_CAT_CAPS,
  2249         "using pad caps %p %" GST_PTR_FORMAT, result, result);
  2214         "using pad caps %p %" GST_PTR_FORMAT, result, result);
  2250 
  2215 
  2251     result = gst_caps_ref (result);
  2216     result = gst_caps_ref (result);
  2252     goto done;
  2217   } else if (GST_PAD_PAD_TEMPLATE (pad)) {
  2253   }
       
  2254   if (GST_PAD_PAD_TEMPLATE (pad)) {
       
  2255     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
  2218     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
  2256 
  2219 
  2257     result = GST_PAD_TEMPLATE_CAPS (templ);
  2220     result = GST_PAD_TEMPLATE_CAPS (templ);
  2258     GST_CAT_DEBUG (GST_CAT_CAPS,
  2221     GST_CAT_DEBUG (GST_CAT_CAPS,
  2259         "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
  2222         "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
  2260         result);
  2223         result);
  2261 
  2224 
  2262     result = gst_caps_ref (result);
  2225     result = gst_caps_ref (result);
  2263     goto done;
  2226   } else {
  2264   }
  2227     GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
  2265   GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
  2228     result = gst_caps_new_empty ();
  2266   result = gst_caps_new_empty ();
  2229   }
  2267 
       
  2268 done:
       
  2269   GST_OBJECT_UNLOCK (pad);
  2230   GST_OBJECT_UNLOCK (pad);
  2270 
  2231 
  2271   return result;
  2232   return result;
  2272 }
  2233 }
  2273 
  2234 
  2557  * buffers, and unrefs the original source buffers.
  2518  * buffers, and unrefs the original source buffers.
  2558  *
  2519  *
  2559  * If the buffers point to contiguous areas of memory, the buffer
  2520  * If the buffers point to contiguous areas of memory, the buffer
  2560  * is created without copying the data.
  2521  * is created without copying the data.
  2561  *
  2522  *
       
  2523  * This is a convenience function for C programmers. See also 
       
  2524  * gst_buffer_merge(), which does the same thing without 
       
  2525  * unreffing the input parameters. Language bindings without 
       
  2526  * explicit reference counting should not wrap this function.
       
  2527  *
  2562  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
  2528  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
  2563  */
  2529  */
  2564 #ifdef __SYMBIAN32__
  2530 #ifdef __SYMBIAN32__
  2565 EXPORT_C
  2531 EXPORT_C
  2566 #endif
  2532 #endif
  2604 #endif /* GST_REMOVE_DEPRECATED */
  2570 #endif /* GST_REMOVE_DEPRECATED */
  2605 
  2571 
  2606 static gboolean
  2572 static gboolean
  2607 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
  2573 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
  2608 {
  2574 {
       
  2575   /* skip the pad, the request came from */
  2609   if (pad != orig) {
  2576   if (pad != orig) {
  2610     GstCaps *peercaps, *existing;
  2577     GstCaps *peercaps, *existing;
  2611 
  2578 
  2612     existing = g_value_get_pointer (ret);
  2579     existing = g_value_get_pointer (ret);
  2613     peercaps = gst_pad_peer_get_caps (pad);
  2580     peercaps = gst_pad_peer_get_caps (pad);
  2647   GstIteratorResult res;
  2614   GstIteratorResult res;
  2648   GValue ret = { 0, };
  2615   GValue ret = { 0, };
  2649 
  2616 
  2650   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
  2617   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
  2651 
  2618 
  2652   GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
  2619   GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s",
       
  2620       GST_DEBUG_PAD_NAME (pad));
  2653 
  2621 
  2654   element = gst_pad_get_parent_element (pad);
  2622   element = gst_pad_get_parent_element (pad);
  2655   if (element == NULL)
  2623   if (element == NULL)
  2656     return NULL;
  2624     return NULL;
  2657 
  2625 
  2755   LinkData data;
  2723   LinkData data;
  2756 
  2724 
  2757   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2725   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2758   g_return_val_if_fail (caps != NULL, FALSE);
  2726   g_return_val_if_fail (caps != NULL, FALSE);
  2759 
  2727 
  2760   GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
  2728   GST_CAT_DEBUG (GST_CAT_PADS, "proxying pad link for %s:%s",
       
  2729       GST_DEBUG_PAD_NAME (pad));
  2761 
  2730 
  2762   element = gst_pad_get_parent_element (pad);
  2731   element = gst_pad_get_parent_element (pad);
  2763   if (element == NULL)
  2732   if (element == NULL)
  2764     return FALSE;
  2733     return FALSE;
  2765 
  2734 
  2955 {
  2924 {
  2956   GstQuery *query;
  2925   GstQuery *query;
  2957   gboolean ret;
  2926   gboolean ret;
  2958 
  2927 
  2959   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2928   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2960   g_return_val_if_fail (src_val >= 0, FALSE);
       
  2961   g_return_val_if_fail (dest_format != NULL, FALSE);
  2929   g_return_val_if_fail (dest_format != NULL, FALSE);
  2962   g_return_val_if_fail (dest_val != NULL, FALSE);
  2930   g_return_val_if_fail (dest_val != NULL, FALSE);
  2963 
  2931 
  2964   if (*dest_format == src_format) {
  2932   if (*dest_format == src_format) {
  2965     *dest_val = src_val;
  2933     *dest_val = src_val;
  3022  * gst_atomic_int_set:
  2990  * gst_atomic_int_set:
  3023  * @atomic_int: pointer to an atomic integer
  2991  * @atomic_int: pointer to an atomic integer
  3024  * @value: value to set
  2992  * @value: value to set
  3025  *
  2993  *
  3026  * Unconditionally sets the atomic integer to @value.
  2994  * Unconditionally sets the atomic integer to @value.
  3027  */
  2995  * 
       
  2996  * Deprecated: Use g_atomic_int_set().
       
  2997  *
       
  2998  */
       
  2999 #ifndef GST_REMOVE_DEPRECATED
  3028 #ifdef __SYMBIAN32__
  3000 #ifdef __SYMBIAN32__
  3029 EXPORT_C
  3001 EXPORT_C
  3030 #endif
  3002 #endif
  3031 
  3003 
  3032 void
  3004 void
  3033 gst_atomic_int_set (gint * atomic_int, gint value)
  3005 gst_atomic_int_set (gint * atomic_int, gint value)
  3034 {
  3006 {
  3035   int ignore;
  3007   g_atomic_int_set (atomic_int, value);
  3036 
  3008 }
  3037   *atomic_int = value;
  3009 #endif
  3038   /* read acts as a memory barrier */
       
  3039   ignore = g_atomic_int_get (atomic_int);
       
  3040 }
       
  3041 
  3010 
  3042 /**
  3011 /**
  3043  * gst_pad_add_data_probe:
  3012  * gst_pad_add_data_probe:
  3044  * @pad: pad to add the data probe handler to
  3013  * @pad: pad to add the data probe handler to
  3045  * @handler: function to call when data is passed over pad
  3014  * @handler: function to call when data is passed over pad
  3074 #endif
  3043 #endif
  3075 
  3044 
  3076 gulong
  3045 gulong
  3077 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
  3046 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
  3078 {
  3047 {
       
  3048   return gst_pad_add_data_probe_full (pad, handler, data, NULL);
       
  3049 }
       
  3050 
       
  3051 /**
       
  3052  * gst_pad_add_data_probe_full:
       
  3053  * @pad: pad to add the data probe handler to
       
  3054  * @handler: function to call when data is passed over pad
       
  3055  * @data: data to pass along with the handler
       
  3056  * @notify: function to call when the probe is disconnected, or NULL
       
  3057  *
       
  3058  * Adds a "data probe" to a pad. This function will be called whenever data
       
  3059  * passes through a pad. In this case data means both events and buffers. The
       
  3060  * probe will be called with the data as an argument, meaning @handler should
       
  3061  * have the same callback signature as the #GstPad::have-data signal.
       
  3062  * Note that the data will have a reference count greater than 1, so it will
       
  3063  * be immutable -- you must not change it.
       
  3064  *
       
  3065  * For source pads, the probe will be called after the blocking function, if any
       
  3066  * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
       
  3067  * to. For sink pads, the probe function will be called before configuring the
       
  3068  * sink with new caps, if any, and before calling the pad's chain function.
       
  3069  *
       
  3070  * Your data probe should return TRUE to let the data continue to flow, or FALSE
       
  3071  * to drop it. Dropping data is rarely useful, but occasionally comes in handy
       
  3072  * with events.
       
  3073  *
       
  3074  * Although probes are implemented internally by connecting @handler to the
       
  3075  * have-data signal on the pad, if you want to remove a probe it is insufficient
       
  3076  * to only call g_signal_handler_disconnect on the returned handler id. To
       
  3077  * remove a probe, use the appropriate function, such as
       
  3078  * gst_pad_remove_data_probe().
       
  3079  *
       
  3080  * The @notify function is called when the probe is disconnected and usually
       
  3081  * used to free @data.
       
  3082  *
       
  3083  * Returns: The handler id.
       
  3084  *
       
  3085  * Since: 0.10.20
       
  3086  */
       
  3087 #ifdef __SYMBIAN32__
       
  3088 EXPORT_C
       
  3089 #endif
       
  3090 
       
  3091 gulong
       
  3092 gst_pad_add_data_probe_full (GstPad * pad, GCallback handler,
       
  3093     gpointer data, GDestroyNotify notify)
       
  3094 {
  3079   gulong sigid;
  3095   gulong sigid;
  3080 
  3096 
  3081   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3097   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3082   g_return_val_if_fail (handler != NULL, 0);
  3098   g_return_val_if_fail (handler != NULL, 0);
  3083 
  3099 
  3084   GST_OBJECT_LOCK (pad);
  3100   GST_OBJECT_LOCK (pad);
  3085   sigid = g_signal_connect (pad, "have-data", handler, data);
  3101 
       
  3102   /* we only expose a GDestroyNotify in our API because that's less confusing */
       
  3103   sigid = g_signal_connect_data (pad, "have-data", handler, data,
       
  3104       (GClosureNotify) notify, 0);
       
  3105 
  3086   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3106   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3087   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3107   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3088   GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes",
  3108   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3089       GST_DEBUG_PAD_NAME (pad),
  3109       "adding data probe, now %d data, %d event probes",
  3090       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3110       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3091   GST_OBJECT_UNLOCK (pad);
  3111   GST_OBJECT_UNLOCK (pad);
  3092 
  3112 
  3093   return sigid;
  3113   return sigid;
  3094 }
  3114 }
  3109 #endif
  3129 #endif
  3110 
  3130 
  3111 gulong
  3131 gulong
  3112 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
  3132 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
  3113 {
  3133 {
       
  3134   return gst_pad_add_event_probe_full (pad, handler, data, NULL);
       
  3135 }
       
  3136 
       
  3137 /**
       
  3138  * gst_pad_add_event_probe_full:
       
  3139  * @pad: pad to add the event probe handler to
       
  3140  * @handler: function to call when events are passed over pad
       
  3141  * @data: data to pass along with the handler, or NULL
       
  3142  * @notify: function to call when probe is disconnected, or NULL
       
  3143  *
       
  3144  * Adds a probe that will be called for all events passing through a pad. See
       
  3145  * gst_pad_add_data_probe() for more information.
       
  3146  *
       
  3147  * The @notify function is called when the probe is disconnected and usually
       
  3148  * used to free @data.
       
  3149  *
       
  3150  * Returns: The handler id
       
  3151  *
       
  3152  * Since: 0.10.20
       
  3153  */
       
  3154 #ifdef __SYMBIAN32__
       
  3155 EXPORT_C
       
  3156 #endif
       
  3157 
       
  3158 gulong
       
  3159 gst_pad_add_event_probe_full (GstPad * pad, GCallback handler,
       
  3160     gpointer data, GDestroyNotify notify)
       
  3161 {
  3114   gulong sigid;
  3162   gulong sigid;
  3115 
  3163 
  3116   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3164   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3117   g_return_val_if_fail (handler != NULL, 0);
  3165   g_return_val_if_fail (handler != NULL, 0);
  3118 
  3166 
  3119   GST_OBJECT_LOCK (pad);
  3167   GST_OBJECT_LOCK (pad);
  3120   sigid = g_signal_connect (pad, "have-data::event", handler, data);
  3168 
       
  3169   /* we only expose a GDestroyNotify in our API because that's less confusing */
       
  3170   sigid = g_signal_connect_data (pad, "have-data::event", handler, data,
       
  3171       (GClosureNotify) notify, 0);
       
  3172 
  3121   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3173   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3122   GST_DEBUG ("adding event probe to pad %s:%s, now %d probes",
  3174   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes",
  3123       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3175       GST_PAD_DO_EVENT_SIGNALS (pad));
  3124   GST_OBJECT_UNLOCK (pad);
  3176   GST_OBJECT_UNLOCK (pad);
  3125 
  3177 
  3126   return sigid;
  3178   return sigid;
  3127 }
  3179 }
  3128 
  3180 
  3142 #endif
  3194 #endif
  3143 
  3195 
  3144 gulong
  3196 gulong
  3145 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
  3197 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
  3146 {
  3198 {
       
  3199   return gst_pad_add_buffer_probe_full (pad, handler, data, NULL);
       
  3200 }
       
  3201 
       
  3202 /**
       
  3203  * gst_pad_add_buffer_probe_full:
       
  3204  * @pad: pad to add the buffer probe handler to
       
  3205  * @handler: function to call when buffer are passed over pad
       
  3206  * @data: data to pass along with the handler
       
  3207  * @notify: function to call when the probe is disconnected, or NULL
       
  3208  *
       
  3209  * Adds a probe that will be called for all buffers passing through a pad. See
       
  3210  * gst_pad_add_data_probe() for more information.
       
  3211  *
       
  3212  * The @notify function is called when the probe is disconnected and usually
       
  3213  * used to free @data.
       
  3214  *
       
  3215  * Returns: The handler id
       
  3216  *
       
  3217  * Since: 0.10.20
       
  3218  */
       
  3219 #ifdef __SYMBIAN32__
       
  3220 EXPORT_C
       
  3221 #endif
       
  3222 
       
  3223 gulong
       
  3224 gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler,
       
  3225     gpointer data, GDestroyNotify notify)
       
  3226 {
  3147   gulong sigid;
  3227   gulong sigid;
  3148 
  3228 
  3149   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3229   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3150   g_return_val_if_fail (handler != NULL, 0);
  3230   g_return_val_if_fail (handler != NULL, 0);
  3151 
  3231 
  3152   GST_OBJECT_LOCK (pad);
  3232   GST_OBJECT_LOCK (pad);
  3153   sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
  3233 
       
  3234   /* we only expose a GDestroyNotify in our API because that's less confusing */
       
  3235   sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data,
       
  3236       (GClosureNotify) notify, 0);
       
  3237 
  3154   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3238   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3155   GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes",
  3239   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes",
  3156       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3240       GST_PAD_DO_BUFFER_SIGNALS (pad));
  3157   GST_OBJECT_UNLOCK (pad);
  3241   GST_OBJECT_UNLOCK (pad);
  3158 
  3242 
  3159   return sigid;
  3243   return sigid;
  3160 }
  3244 }
  3161 
  3245 
  3178 
  3262 
  3179   GST_OBJECT_LOCK (pad);
  3263   GST_OBJECT_LOCK (pad);
  3180   g_signal_handler_disconnect (pad, handler_id);
  3264   g_signal_handler_disconnect (pad, handler_id);
  3181   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3265   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3182   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3266   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3183   GST_DEBUG
  3267   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3184       ("removed data probe from pad %s:%s, now %d event, %d buffer probes",
  3268       "removed data probe, now %d event, %d buffer probes",
  3185       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
  3269       GST_PAD_DO_EVENT_SIGNALS (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3186       GST_PAD_DO_BUFFER_SIGNALS (pad));
       
  3187   GST_OBJECT_UNLOCK (pad);
  3270   GST_OBJECT_UNLOCK (pad);
  3188 
  3271 
  3189 }
  3272 }
  3190 
  3273 
  3191 /**
  3274 /**
  3206   g_return_if_fail (handler_id > 0);
  3289   g_return_if_fail (handler_id > 0);
  3207 
  3290 
  3208   GST_OBJECT_LOCK (pad);
  3291   GST_OBJECT_LOCK (pad);
  3209   g_signal_handler_disconnect (pad, handler_id);
  3292   g_signal_handler_disconnect (pad, handler_id);
  3210   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3293   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3211   GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
  3294   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3212       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3295       "removed event probe, now %d event probes",
       
  3296       GST_PAD_DO_EVENT_SIGNALS (pad));
  3213   GST_OBJECT_UNLOCK (pad);
  3297   GST_OBJECT_UNLOCK (pad);
  3214 }
  3298 }
  3215 
  3299 
  3216 /**
  3300 /**
  3217  * gst_pad_remove_buffer_probe:
  3301  * gst_pad_remove_buffer_probe:
  3231   g_return_if_fail (handler_id > 0);
  3315   g_return_if_fail (handler_id > 0);
  3232 
  3316 
  3233   GST_OBJECT_LOCK (pad);
  3317   GST_OBJECT_LOCK (pad);
  3234   g_signal_handler_disconnect (pad, handler_id);
  3318   g_signal_handler_disconnect (pad, handler_id);
  3235   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3319   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3236   GST_DEBUG ("removed buffer probe from pad %s:%s, now %d buffer probes",
  3320   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3237       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3321       "removed buffer probe, now %d buffer probes",
       
  3322       GST_PAD_DO_BUFFER_SIGNALS (pad));
  3238   GST_OBJECT_UNLOCK (pad);
  3323   GST_OBJECT_UNLOCK (pad);
  3239 
  3324 
  3240 }
  3325 }
  3241 
  3326 
  3242 /**
  3327 /**
  3262   g_return_if_fail (element != NULL);
  3347   g_return_if_fail (element != NULL);
  3263   g_return_if_fail (pad != NULL);
  3348   g_return_if_fail (pad != NULL);
  3264   g_return_if_fail (list != NULL);
  3349   g_return_if_fail (list != NULL);
  3265 
  3350 
  3266   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
  3351   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
       
  3352   /* FIXME 0.11: Set the pad as source. */
  3267   gst_element_post_message (element,
  3353   gst_element_post_message (element,
  3268       gst_message_new_tag (GST_OBJECT (element), list));
  3354       gst_message_new_tag_full (GST_OBJECT (element), pad, list));
  3269 }
  3355 }
  3270 
  3356 
  3271 static void
  3357 static void
  3272 push_and_ref (GstPad * pad, GstEvent * event)
  3358 push_and_ref (GstPad * pad, GstEvent * event)
  3273 {
  3359 {
  3309   gst_element_post_message (element,
  3395   gst_element_post_message (element,
  3310       gst_message_new_tag (GST_OBJECT (element), list));
  3396       gst_message_new_tag (GST_OBJECT (element), list));
  3311 }
  3397 }
  3312 
  3398 
  3313 static GstPad *
  3399 static GstPad *
  3314 element_find_unconnected_pad (GstElement * element, GstPadDirection direction)
  3400 element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
  3315 {
  3401 {
  3316   GstIterator *iter;
  3402   GstIterator *iter;
  3317   GstPad *unconnected_pad = NULL;
  3403   GstPad *unlinked_pad = NULL;
  3318   gboolean done;
  3404   gboolean done;
  3319 
  3405 
  3320   switch (direction) {
  3406   switch (direction) {
  3321     case GST_PAD_SRC:
  3407     case GST_PAD_SRC:
  3322       iter = gst_element_iterate_src_pads (element);
  3408       iter = gst_element_iterate_src_pads (element);
  3339         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
  3425         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
  3340             GST_DEBUG_PAD_NAME (pad));
  3426             GST_DEBUG_PAD_NAME (pad));
  3341 
  3427 
  3342         peer = gst_pad_get_peer (GST_PAD (pad));
  3428         peer = gst_pad_get_peer (GST_PAD (pad));
  3343         if (peer == NULL) {
  3429         if (peer == NULL) {
  3344           unconnected_pad = pad;
  3430           unlinked_pad = pad;
  3345           done = TRUE;
  3431           done = TRUE;
  3346           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  3432           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  3347               "found existing unlinked pad %s:%s",
  3433               "found existing unlinked pad %s:%s",
  3348               GST_DEBUG_PAD_NAME (unconnected_pad));
  3434               GST_DEBUG_PAD_NAME (unlinked_pad));
  3349         } else {
  3435         } else {
  3350           gst_object_unref (pad);
  3436           gst_object_unref (pad);
  3351           gst_object_unref (peer);
  3437           gst_object_unref (peer);
  3352         }
  3438         }
  3353         break;
  3439         break;
  3364     }
  3450     }
  3365   }
  3451   }
  3366 
  3452 
  3367   gst_iterator_free (iter);
  3453   gst_iterator_free (iter);
  3368 
  3454 
  3369   return unconnected_pad;
  3455   return unlinked_pad;
  3370 }
  3456 }
  3371 
  3457 
  3372 /**
  3458 /**
  3373  * gst_bin_find_unconnected_pad:
  3459  * gst_bin_find_unlinked_pad:
  3374  * @bin: bin in which to look for elements with unconnected pads
  3460  * @bin: bin in which to look for elements with unlinked pads
  3375  * @direction: whether to look for an unconnected source or sink pad
  3461  * @direction: whether to look for an unlinked source or sink pad
  3376  *
  3462  *
  3377  * Recursively looks for elements with an unconnected pad of the given
  3463  * Recursively looks for elements with an unlinked pad of the given
  3378  * direction within the specified bin and returns an unconnected pad
  3464  * direction within the specified bin and returns an unlinked pad
  3379  * if one is found, or NULL otherwise. If a pad is found, the caller
  3465  * if one is found, or NULL otherwise. If a pad is found, the caller
  3380  * owns a reference to it and should use gst_object_unref() on the
  3466  * owns a reference to it and should use gst_object_unref() on the
  3381  * pad when it is not needed any longer.
  3467  * pad when it is not needed any longer.
  3382  *
  3468  *
  3383  * Returns: unconnected pad of the given direction, or NULL.
  3469  * Returns: unlinked pad of the given direction, or NULL.
  3384  *
  3470  *
  3385  * Since: 0.10.3
  3471  * Since: 0.10.20
  3386  */
  3472  */
  3387 #ifdef __SYMBIAN32__
  3473 #ifdef __SYMBIAN32__
  3388 EXPORT_C
  3474 EXPORT_C
  3389 #endif
  3475 #endif
  3390 
  3476 
  3391 GstPad *
  3477 GstPad *
  3392 gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
  3478 gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
  3393 {
  3479 {
  3394   GstIterator *iter;
  3480   GstIterator *iter;
  3395   gboolean done;
  3481   gboolean done;
  3396   GstPad *pad = NULL;
  3482   GstPad *pad = NULL;
  3397 
  3483 
  3403   while (!done) {
  3489   while (!done) {
  3404     gpointer element;
  3490     gpointer element;
  3405 
  3491 
  3406     switch (gst_iterator_next (iter, &element)) {
  3492     switch (gst_iterator_next (iter, &element)) {
  3407       case GST_ITERATOR_OK:
  3493       case GST_ITERATOR_OK:
  3408         pad = element_find_unconnected_pad (GST_ELEMENT (element), direction);
  3494         pad = element_find_unlinked_pad (GST_ELEMENT (element), direction);
  3409         gst_object_unref (element);
  3495         gst_object_unref (element);
  3410         if (pad != NULL)
  3496         if (pad != NULL)
  3411           done = TRUE;
  3497           done = TRUE;
  3412         break;
  3498         break;
  3413       case GST_ITERATOR_DONE:
  3499       case GST_ITERATOR_DONE:
  3426 
  3512 
  3427   return pad;
  3513   return pad;
  3428 }
  3514 }
  3429 
  3515 
  3430 /**
  3516 /**
       
  3517  * gst_bin_find_unconnected_pad:
       
  3518  * @bin: bin in which to look for elements with unlinked pads
       
  3519  * @direction: whether to look for an unlinked source or sink pad
       
  3520  *
       
  3521  * Recursively looks for elements with an unlinked pad of the given
       
  3522  * direction within the specified bin and returns an unlinked pad
       
  3523  * if one is found, or NULL otherwise. If a pad is found, the caller
       
  3524  * owns a reference to it and should use gst_object_unref() on the
       
  3525  * pad when it is not needed any longer.
       
  3526  *
       
  3527  * Returns: unlinked pad of the given direction, or NULL.
       
  3528  *
       
  3529  * Since: 0.10.3
       
  3530  *
       
  3531  * Deprecated: use gst_bin_find_unlinked_pad() instead.
       
  3532  */
       
  3533 #ifndef GST_REMOVE_DEPRECATED
       
  3534 
       
  3535 #ifdef __SYMBIAN32__
       
  3536 EXPORT_C
       
  3537 #endif
       
  3538 GstPad *
       
  3539 gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
       
  3540 {
       
  3541   return gst_bin_find_unlinked_pad (bin, direction);
       
  3542 }
       
  3543 #endif
       
  3544 
       
  3545 /**
  3431  * gst_parse_bin_from_description:
  3546  * gst_parse_bin_from_description:
  3432  * @bin_description: command line describing the bin
  3547  * @bin_description: command line describing the bin
  3433  * @ghost_unconnected_pads: whether to automatically create ghost pads
  3548  * @ghost_unlinked_pads: whether to automatically create ghost pads
  3434  *                          for unconnected source or sink pads within
  3549  *     for unlinked source or sink pads within the bin
  3435  *                          the bin
       
  3436  * @err: where to store the error message in case of an error, or NULL
  3550  * @err: where to store the error message in case of an error, or NULL
  3437  *
  3551  *
  3438  * This is a convenience wrapper around gst_parse_launch() to create a
  3552  * This is a convenience wrapper around gst_parse_launch() to create a
  3439  * #GstBin from a gst-launch-style pipeline description. See
  3553  * #GstBin from a gst-launch-style pipeline description. See
  3440  * gst_parse_launch() and the gst-launch man page for details about the
  3554  * gst_parse_launch() and the gst-launch man page for details about the
  3441  * syntax. Ghost pads on the bin for unconnected source or sink pads
  3555  * syntax. Ghost pads on the bin for unlinked source or sink pads
  3442  * within the bin can automatically be created (but only a maximum of
  3556  * within the bin can automatically be created (but only a maximum of
  3443  * one ghost pad for each direction will be created; if you expect
  3557  * one ghost pad for each direction will be created; if you expect
  3444  * multiple unconnected source pads or multiple unconnected sink pads
  3558  * multiple unlinked source pads or multiple unlinked sink pads
  3445  * and want them all ghosted, you will have to create the ghost pads
  3559  * and want them all ghosted, you will have to create the ghost pads
  3446  * yourself).
  3560  * yourself).
  3447  *
  3561  *
  3448  * Returns: a newly-created bin, or NULL if an error occurred.
  3562  * Returns: a newly-created bin, or NULL if an error occurred.
  3449  *
  3563  *
  3453 EXPORT_C
  3567 EXPORT_C
  3454 #endif
  3568 #endif
  3455 
  3569 
  3456 GstElement *
  3570 GstElement *
  3457 gst_parse_bin_from_description (const gchar * bin_description,
  3571 gst_parse_bin_from_description (const gchar * bin_description,
  3458     gboolean ghost_unconnected_pads, GError ** err)
  3572     gboolean ghost_unlinked_pads, GError ** err)
       
  3573 {
       
  3574   return gst_parse_bin_from_description_full (bin_description,
       
  3575       ghost_unlinked_pads, NULL, 0, err);
       
  3576 }
       
  3577 
       
  3578 /**
       
  3579  * gst_parse_bin_from_description_full:
       
  3580  * @bin_description: command line describing the bin
       
  3581  * @ghost_unlinked_pads: whether to automatically create ghost pads
       
  3582  *     for unlinked source or sink pads within the bin
       
  3583  * @context: a parse context allocated with gst_parse_context_new(), or %NULL
       
  3584  * @flags: parsing options, or #GST_PARSE_FLAG_NONE
       
  3585  * @err: where to store the error message in case of an error, or NULL
       
  3586  *
       
  3587  * This is a convenience wrapper around gst_parse_launch() to create a
       
  3588  * #GstBin from a gst-launch-style pipeline description. See
       
  3589  * gst_parse_launch() and the gst-launch man page for details about the
       
  3590  * syntax. Ghost pads on the bin for unlinked source or sink pads
       
  3591  * within the bin can automatically be created (but only a maximum of
       
  3592  * one ghost pad for each direction will be created; if you expect
       
  3593  * multiple unlinked source pads or multiple unlinked sink pads
       
  3594  * and want them all ghosted, you will have to create the ghost pads
       
  3595  * yourself).
       
  3596  *
       
  3597  * Returns: a newly-created bin, or NULL if an error occurred.
       
  3598  *
       
  3599  * Since: 0.10.20
       
  3600  */
       
  3601 #ifdef __SYMBIAN32__
       
  3602 EXPORT_C
       
  3603 #endif
       
  3604 
       
  3605 GstElement *
       
  3606 gst_parse_bin_from_description_full (const gchar * bin_description,
       
  3607     gboolean ghost_unlinked_pads, GstParseContext * context,
       
  3608     GstParseFlags flags, GError ** err)
  3459 {
  3609 {
  3460 #ifndef GST_DISABLE_PARSE
  3610 #ifndef GST_DISABLE_PARSE
  3461   GstPad *pad = NULL;
  3611   GstPad *pad = NULL;
  3462   GstBin *bin;
  3612   GstBin *bin;
  3463   gchar *desc;
  3613   gchar *desc;
  3467 
  3617 
  3468   GST_DEBUG ("Making bin from description '%s'", bin_description);
  3618   GST_DEBUG ("Making bin from description '%s'", bin_description);
  3469 
  3619 
  3470   /* parse the pipeline to a bin */
  3620   /* parse the pipeline to a bin */
  3471   desc = g_strdup_printf ("bin.( %s )", bin_description);
  3621   desc = g_strdup_printf ("bin.( %s )", bin_description);
  3472   bin = (GstBin *) gst_parse_launch (desc, err);
  3622   bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err);
  3473   g_free (desc);
  3623   g_free (desc);
  3474 
  3624 
  3475   if (bin == NULL || (err && *err != NULL)) {
  3625   if (bin == NULL || (err && *err != NULL)) {
  3476     if (bin)
  3626     if (bin)
  3477       gst_object_unref (bin);
  3627       gst_object_unref (bin);
  3478     return NULL;
  3628     return NULL;
  3479   }
  3629   }
  3480 
  3630 
  3481   /* find pads and ghost them if necessary */
  3631   /* find pads and ghost them if necessary */
  3482   if (ghost_unconnected_pads) {
  3632   if (ghost_unlinked_pads) {
  3483     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) {
  3633     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) {
  3484       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
  3634       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
  3485       gst_object_unref (pad);
  3635       gst_object_unref (pad);
  3486     }
  3636     }
  3487     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) {
  3637     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) {
  3488       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
  3638       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
  3489       gst_object_unref (pad);
  3639       gst_object_unref (pad);
  3490     }
  3640     }
  3491   }
  3641   }
  3492 
  3642 
  3493   return GST_ELEMENT (bin);
  3643   return GST_ELEMENT (bin);
  3494 #else
  3644 #else
  3495   gchar *msg;
  3645   gchar *msg;
  3496 
  3646 
  3497   GST_WARNING ("Disabled API called: gst_parse_bin_from_description()");
  3647   GST_WARNING ("Disabled API called");
  3498 
  3648 
  3499   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
  3649   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
  3500   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
  3650   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
  3501   g_free (msg);
  3651   g_free (msg);
  3502 
  3652 
  3605 
  3755 
  3606   g_get_current_time (&now);
  3756   g_get_current_time (&now);
  3607   return GST_TIMEVAL_TO_TIME (now);
  3757   return GST_TIMEVAL_TO_TIME (now);
  3608 #endif
  3758 #endif
  3609 }
  3759 }
       
  3760 
       
  3761 /**
       
  3762  * gst_util_array_binary_search:
       
  3763  * @array: the sorted input array
       
  3764  * @num_elements: number of elements in the array
       
  3765  * @element_size: size of every element in bytes
       
  3766  * @search_func: function to compare two elements, @search_data will always be passed as second argument
       
  3767  * @mode: search mode that should be used
       
  3768  * @search_data: element that should be found
       
  3769  * @user_data: data to pass to @search_func
       
  3770  *
       
  3771  * Searches inside @array for @search_data by using the comparison function
       
  3772  * @search_func. @array must be sorted ascending.
       
  3773  *
       
  3774  * As @search_data is always passed as second argument to @search_func it's
       
  3775  * not required that @search_data has the same type as the array elements.
       
  3776  *
       
  3777  * The complexity of this search function is O(log (num_elements)).
       
  3778  *
       
  3779  * Returns: The address of the found element or %NULL if nothing was found
       
  3780  *
       
  3781  * Since: 0.10.23
       
  3782  */
       
  3783 #ifdef __SYMBIAN32__
       
  3784 EXPORT_C
       
  3785 #endif
       
  3786 
       
  3787 gpointer
       
  3788 gst_util_array_binary_search (gpointer array, guint num_elements,
       
  3789     gsize element_size, GCompareDataFunc search_func, GstSearchMode mode,
       
  3790     gconstpointer search_data, gpointer user_data)
       
  3791 {
       
  3792   glong left = 0, right = num_elements - 1, m;
       
  3793   gint ret;
       
  3794   guint8 *data = (guint8 *) array;
       
  3795 
       
  3796   g_return_val_if_fail (array != NULL, NULL);
       
  3797   g_return_val_if_fail (element_size > 0, NULL);
       
  3798   g_return_val_if_fail (search_func != NULL, NULL);
       
  3799 
       
  3800   /* 0. No elements => return NULL */
       
  3801   if (num_elements == 0)
       
  3802     return NULL;
       
  3803 
       
  3804   /* 1. If search_data is before the 0th element return the 0th element */
       
  3805   ret = search_func (data, search_data, user_data);
       
  3806   if ((ret >= 0 && mode == GST_SEARCH_MODE_AFTER) || ret == 0)
       
  3807     return data;
       
  3808   else if (ret > 0)
       
  3809     return NULL;
       
  3810 
       
  3811   /* 2. If search_data is after the last element return the last element */
       
  3812   ret =
       
  3813       search_func (data + (num_elements - 1) * element_size, search_data,
       
  3814       user_data);
       
  3815   if ((ret <= 0 && mode == GST_SEARCH_MODE_BEFORE) || ret == 0)
       
  3816     return data + (num_elements - 1) * element_size;
       
  3817   else if (ret < 0)
       
  3818     return NULL;
       
  3819 
       
  3820   /* 3. else binary search */
       
  3821   while (TRUE) {
       
  3822     m = left + (right - left) / 2;
       
  3823 
       
  3824     ret = search_func (data + m * element_size, search_data, user_data);
       
  3825 
       
  3826     if (ret == 0) {
       
  3827       return data + m * element_size;
       
  3828     } else if (ret < 0) {
       
  3829       left = m + 1;
       
  3830     } else {
       
  3831       right = m - 1;
       
  3832     }
       
  3833 
       
  3834     /* No exact match found */
       
  3835     if (right < left) {
       
  3836       if (mode == GST_SEARCH_MODE_EXACT) {
       
  3837         return NULL;
       
  3838       } else if (mode == GST_SEARCH_MODE_AFTER) {
       
  3839         if (ret < 0)
       
  3840           return (m < num_elements) ? data + (m + 1) * element_size : NULL;
       
  3841         else
       
  3842           return data + m * element_size;
       
  3843       } else {
       
  3844         if (ret < 0)
       
  3845           return data + m * element_size;
       
  3846         else
       
  3847           return (m > 0) ? data + (m - 1) * element_size : NULL;
       
  3848       }
       
  3849     }
       
  3850   }
       
  3851 }