gstreamer_core/gst/gstutils.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     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
     6  * gstutils.c: Utility functions: gtk_get_property stuff, etc.
     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"
       
    41 #include "gst-i18n-lib.h"
    40 #include "gst-i18n-lib.h"
    42 
    41 
    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  */
       
    50 #ifdef __SYMBIAN32__
    42 #ifdef __SYMBIAN32__
    51 #include <glib_global.h>
    43 #include <glib_global.h>
    52 #include <gobject_global.h>
    44 #include <gobject_global.h>
    53 #endif
    45 #endif
    54 
    46 
   101  * @value: the value to set
    93  * @value: the value to set
   102  * @value_str: the string to get the value from
    94  * @value_str: the string to get the value from
   103  *
    95  *
   104  * Converts the string to the type of the value and
    96  * Converts the string to the type of the value and
   105  * sets the value with it.
    97  * 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.
       
   109  */
    98  */
   110 #ifdef __SYMBIAN32__
    99 #ifdef __SYMBIAN32__
   111 EXPORT_C
   100 EXPORT_C
   112 #endif
   101 #endif
   113 
   102 
   114 void
   103 void
   115 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
   104 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
   116 {
   105 {
   117   gboolean res;
   106   gint sscanf_ret;
   118 
   107 
   119   g_return_if_fail (value != NULL);
   108   g_return_if_fail (value != NULL);
   120   g_return_if_fail (value_str != NULL);
   109   g_return_if_fail (value_str != NULL);
   121 
   110 
   122   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
   111   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
   123       g_type_name (G_VALUE_TYPE (value)));
   112       g_type_name (G_VALUE_TYPE (value)));
   124 
   113 
   125   res = gst_value_deserialize (value, value_str);
   114   switch (G_VALUE_TYPE (value)) {
   126   if (!res && G_VALUE_TYPE (value) == G_TYPE_BOOLEAN) {
   115     case G_TYPE_STRING:
   127     /* backwards compat, all booleans that fail to parse are false */
   116       g_value_set_string (value, value_str);
   128     g_value_set_boolean (value, FALSE);
   117       break;
   129     res = TRUE;
   118     case G_TYPE_ENUM:
   130   }
   119     case G_TYPE_INT:{
   131   g_return_if_fail (res);
   120       gint i;
       
   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   }
   132 }
   194 }
   133 
   195 
   134 /**
   196 /**
   135  * gst_util_set_object_arg:
   197  * gst_util_set_object_arg:
   136  * @object: the object to set the argument of
   198  * @object: the object to set the argument of
   137  * @name: the name of the argument to set
   199  * @name: the name of the argument to set
   138  * @value: the string value to set
   200  * @value: the string value to set
   139  *
   201  *
   140  * Convertes the string value to the type of the objects argument and
   202  * Convertes the string value to the type of the objects argument and
   141  * sets the argument with it.
   203  * 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.
       
   145  */
   204  */
   146 #ifdef __SYMBIAN32__
   205 #ifdef __SYMBIAN32__
   147 EXPORT_C
   206 EXPORT_C
   148 #endif
   207 #endif
   149 
   208 
   150 void
   209 void
   151 gst_util_set_object_arg (GObject * object, const gchar * name,
   210 gst_util_set_object_arg (GObject * object, const gchar * name,
   152     const gchar * value)
   211     const gchar * value)
   153 {
   212 {
   154   GParamSpec *pspec;
   213   gboolean sscanf_ret;
   155   GType value_type;
   214 
   156   GValue v = { 0, };
   215   if (name && value) {
   157 
   216     GParamSpec *paramspec;
   158   g_return_if_fail (G_IS_OBJECT (object));
   217 
   159   g_return_if_fail (name != NULL);
   218     paramspec =
   160   g_return_if_fail (value != NULL);
   219         g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
   161 
   220 
   162   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
   221     if (!paramspec) {
   163   if (!pspec)
   222       return;
   164     return;
   223     }
   165 
   224 
   166   value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
   225     GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d",
   167 
   226         paramspec->flags, (gint) paramspec->value_type);
   168   GST_DEBUG ("pspec->flags is %d, pspec->value_type is %s",
   227 
   169       pspec->flags, g_type_name (value_type));
   228     if (paramspec->flags & G_PARAM_WRITABLE) {
   170 
   229       switch (paramspec->value_type) {
   171   if (!(pspec->flags & G_PARAM_WRITABLE))
   230         case G_TYPE_STRING:
   172     return;
   231           g_object_set (G_OBJECT (object), name, value, NULL);
   173 
   232           break;
   174   g_value_init (&v, value_type);
   233         case G_TYPE_ENUM:
   175 
   234         case G_TYPE_INT:{
   176   /* special case for element <-> xml (de)serialisation */
   235           gint i;
   177   if (GST_VALUE_HOLDS_STRUCTURE (&v) && strcmp (value, "NULL") == 0) {
   236 
   178     g_value_set_boxed (&v, NULL);
   237           sscanf_ret = sscanf (value, "%d", &i);
   179     goto done;
   238           g_return_if_fail (sscanf_ret == 1);
   180   }
   239           g_object_set (G_OBJECT (object), name, i, NULL);
   181 
   240           break;
   182   if (!gst_value_deserialize (&v, value))
   241         }
   183     return;
   242         case G_TYPE_UINT:{
   184 
   243           guint i;
   185 done:
   244 
   186 
   245           sscanf_ret = sscanf (value, "%u", &i);
   187   g_object_set_property (object, pspec->name, &v);
   246           g_return_if_fail (sscanf_ret == 1);
   188   g_value_unset (&v);
   247           g_object_set (G_OBJECT (object), name, i, NULL);
       
   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   }
   189 }
   318 }
   190 
   319 
   191 /* work around error C2520: conversion from unsigned __int64 to double
   320 /* work around error C2520: conversion from unsigned __int64 to double
   192  * not implemented, use signed __int64
   321  * not implemented, use signed __int64
   193  *
   322  *
   304 
   433 
   305   return q0.ll;
   434   return q0.ll;
   306 }
   435 }
   307 
   436 
   308 static guint64
   437 static guint64
   309 gst_util_uint64_scale_int64_unchecked (guint64 val, guint64 num, guint64 denom)
   438 gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
   310 {
   439 {
   311   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
   440   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
   312   GstUInt64 v, n;
   441   GstUInt64 v, n;
   313 
   442 
   314   /* prepare input */
   443   /* prepare input */
   336   ct.ll = (guint64) a0.l.high + a1.l.low + b0.l.low;
   465   ct.ll = (guint64) a0.l.high + a1.l.low + b0.l.low;
   337   c0.l.high = ct.l.low;
   466   c0.l.high = ct.l.low;
   338   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
   467   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
   339 
   468 
   340   /* if high bits bigger than denom, we overflow */
   469   /* if high bits bigger than denom, we overflow */
   341   if (G_UNLIKELY (c1.ll >= denom))
   470   if (c1.ll >= denom)
   342     goto overflow;
   471     goto overflow;
   343 
   472 
   344   /* shortcut for division by 1, c1.ll should be 0 because of the
   473   /* shortcut for division by 1, c1.ll should be 0 because of the
   345    * overflow check above. */
   474    * overflow check above. */
   346   if (denom == 1)
   475   if (denom == 1)
   366   {
   495   {
   367     return G_MAXUINT64;
   496     return G_MAXUINT64;
   368   }
   497   }
   369 }
   498 }
   370 
   499 
   371 static inline guint64
   500 /**
   372 gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom)
   501  * gst_util_uint64_scale:
       
   502  * @val: the number to scale
       
   503  * @num: the numerator of the scale ratio
       
   504  * @denom: the denominator of the scale ratio
       
   505  *
       
   506  * Scale @val by @num / @denom, trying to avoid overflows.
       
   507  *
       
   508  * This function can potentially be very slow if denom > G_MAXUINT32.
       
   509  *
       
   510  * Returns: @val * @num / @denom, trying to avoid overflows.
       
   511  * In the case of an overflow, this function returns G_MAXUINT64.
       
   512  */
       
   513 #ifdef __SYMBIAN32__
       
   514 EXPORT_C
       
   515 #endif
       
   516 
       
   517 guint64
       
   518 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
       
   519 {
       
   520   g_return_val_if_fail (denom != 0, G_MAXUINT64);
       
   521 
       
   522   if (num == 0)
       
   523     return 0;
       
   524 
       
   525   if (num == 1 && denom == 1)
       
   526     return val;
       
   527 
       
   528   /* if the denom is high, we need to do a 64 muldiv */
       
   529   if (denom > G_MAXINT32)
       
   530     goto do_int64;
       
   531 
       
   532   /* if num and denom are low we can do a 32 bit muldiv */
       
   533   if (num <= G_MAXINT32)
       
   534     goto do_int32;
       
   535 
       
   536   /* val and num are high, we need 64 muldiv */
       
   537   if (val > G_MAXINT32)
       
   538     goto do_int64;
       
   539 
       
   540   /* 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);
       
   542 
       
   543 do_int32:
       
   544   return gst_util_uint64_scale_int (val, (gint) num, (gint) denom);
       
   545 
       
   546 do_int64:
       
   547   /* to the more heavy implementations... */
       
   548   return gst_util_uint64_scale_int64 (val, num, denom);
       
   549 }
       
   550 
       
   551 /**
       
   552  * gst_util_uint64_scale_int:
       
   553  * @val: guint64 (such as a #GstClockTime) to scale.
       
   554  * @num: numerator of the scale factor.
       
   555  * @denom: denominator of the scale factor.
       
   556  *
       
   557  * Scale a guint64 by a factor expressed as a fraction (num/denom), avoiding
       
   558  * overflows and loss of precision.
       
   559  *
       
   560  * @num and @denom must be positive integers. @denom cannot be 0.
       
   561  *
       
   562  * Returns: @val * @num / @denom, avoiding overflow and loss of precision.
       
   563  * In the case of an overflow, this function returns G_MAXUINT64.
       
   564  */
       
   565 #ifdef __SYMBIAN32__
       
   566 EXPORT_C
       
   567 #endif
       
   568 
       
   569 guint64
       
   570 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
   373 {
   571 {
   374   GstUInt64 result;
   572   GstUInt64 result;
   375   GstUInt64 low, high;
   573   GstUInt64 low, high;
       
   574 
       
   575   g_return_val_if_fail (denom > 0, G_MAXUINT64);
       
   576   g_return_val_if_fail (num >= 0, G_MAXUINT64);
       
   577 
       
   578   if (num == 0)
       
   579     return 0;
       
   580 
       
   581   if (num == 1 && denom == 1)
       
   582     return val;
       
   583 
       
   584   if (val <= G_MAXUINT32)
       
   585     /* simple case */
       
   586     return val * num / denom;
   376 
   587 
   377   /* do 96 bits mult/div */
   588   /* do 96 bits mult/div */
   378   low.ll = val;
   589   low.ll = val;
   379   result.ll = ((guint64) low.l.low) * num;
   590   result.ll = ((guint64) low.l.low) * num;
   380   high.ll = ((guint64) low.l.high) * num + (result.l.high);
   591   high.ll = ((guint64) low.l.high) * num + (result.l.high);
   382   low.ll = high.ll / denom;
   593   low.ll = high.ll / denom;
   383   result.l.high = high.ll % denom;
   594   result.l.high = high.ll % denom;
   384   result.ll /= denom;
   595   result.ll /= denom;
   385 
   596 
   386   /* avoid overflow */
   597   /* avoid overflow */
   387   if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32))
   598   if (low.ll + result.l.high > G_MAXUINT32)
   388     goto overflow;
   599     goto overflow;
   389 
   600 
   390   result.l.high += low.l.low;
   601   result.l.high += low.l.low;
   391 
   602 
   392   return result.ll;
   603   return result.ll;
   393 
   604 
   394 overflow:
   605 overflow:
   395   {
   606   {
   396     return G_MAXUINT64;
   607     return G_MAXUINT64;
   397   }
   608   }
   398 }
       
   399 
       
   400 
       
   401 /**
       
   402  * gst_util_uint64_scale:
       
   403  * @val: the number to scale
       
   404  * @num: the numerator of the scale ratio
       
   405  * @denom: the denominator of the scale ratio
       
   406  *
       
   407  * Scale @val by @num / @denom, trying to avoid overflows.
       
   408  *
       
   409  * This function can potentially be very slow if denom > G_MAXUINT32.
       
   410  *
       
   411  * Returns: @val * @num / @denom, trying to avoid overflows.
       
   412  * In the case of an overflow, this function returns G_MAXUINT64.
       
   413  */
       
   414 #ifdef __SYMBIAN32__
       
   415 EXPORT_C
       
   416 #endif
       
   417 
       
   418 guint64
       
   419 gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
       
   420 {
       
   421   g_return_val_if_fail (denom != 0, G_MAXUINT64);
       
   422 
       
   423   if (G_UNLIKELY (num == 0))
       
   424     return 0;
       
   425 
       
   426   if (G_UNLIKELY (num == denom))
       
   427     return val;
       
   428 
       
   429   /* if the denom is high, we need to do a 64 muldiv */
       
   430   if (G_UNLIKELY (denom > G_MAXINT32))
       
   431     goto do_int64;
       
   432 
       
   433   /* if num and denom are low we can do a 32 bit muldiv */
       
   434   if (G_LIKELY (num <= G_MAXINT32))
       
   435     goto do_int32;
       
   436 
       
   437   /* val and num are high, we need 64 muldiv */
       
   438   if (G_UNLIKELY (val > G_MAXINT32))
       
   439     goto do_int64;
       
   440 
       
   441   /* val is low and num is high, we can swap them and do 32 muldiv */
       
   442   return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom);
       
   443 
       
   444 do_int32:
       
   445   return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom);
       
   446 
       
   447 do_int64:
       
   448   /* to the more heavy implementations... */
       
   449   return gst_util_uint64_scale_int64_unchecked (val, num, denom);
       
   450 }
       
   451 
       
   452 /**
       
   453  * gst_util_uint64_scale_int:
       
   454  * @val: guint64 (such as a #GstClockTime) to scale.
       
   455  * @num: numerator of the scale factor.
       
   456  * @denom: denominator of the scale factor.
       
   457  *
       
   458  * Scale a guint64 by a factor expressed as a fraction (num/denom), avoiding
       
   459  * overflows and loss of precision.
       
   460  *
       
   461  * @num and @denom must be positive integers. @denom cannot be 0.
       
   462  *
       
   463  * Returns: @val * @num / @denom, avoiding overflow and loss of precision.
       
   464  * In the case of an overflow, this function returns G_MAXUINT64.
       
   465  */
       
   466 #ifdef __SYMBIAN32__
       
   467 EXPORT_C
       
   468 #endif
       
   469 
       
   470 guint64
       
   471 gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
       
   472 {
       
   473   g_return_val_if_fail (denom > 0, G_MAXUINT64);
       
   474   g_return_val_if_fail (num >= 0, G_MAXUINT64);
       
   475 
       
   476   if (G_UNLIKELY (num == 0))
       
   477     return 0;
       
   478 
       
   479   if (G_UNLIKELY (num == denom))
       
   480     return val;
       
   481 
       
   482   if (val <= G_MAXUINT32)
       
   483     /* simple case */
       
   484     return val * num / denom;
       
   485 
       
   486   return gst_util_uint64_scale_int_unchecked (val, num, denom);
       
   487 }
       
   488 
       
   489 /**
       
   490  * gst_util_seqnum_next:
       
   491  *
       
   492  * Return a constantly incrementing sequence number.
       
   493  *
       
   494  * This function is used internally to GStreamer to be able to determine which
       
   495  * events and messages are "the same". For example, elements may set the seqnum
       
   496  * on a segment-done message to be the same as that of the last seek event, to
       
   497  * indicate that event and the message correspond to the same segment.
       
   498  *
       
   499  * Returns: A constantly incrementing 32-bit unsigned integer, which might
       
   500  * overflow back to 0 at some point. Use gst_util_seqnum_compare() to make sure
       
   501  * you handle wraparound correctly.
       
   502  *
       
   503  * Since: 0.10.22
       
   504  */
       
   505 #ifdef __SYMBIAN32__
       
   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);
       
   538 }
   609 }
   539 
   610 
   540 /* -----------------------------------------------------
   611 /* -----------------------------------------------------
   541  *
   612  *
   542  *  The following code will be moved out of the main
   613  *  The following code will be moved out of the main
   855     pad = NULL;
   926     pad = NULL;
   856 
   927 
   857   return pad;
   928   return pad;
   858 }
   929 }
   859 
   930 
   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 
       
   914 /**
   931 /**
   915  * gst_element_get_compatible_pad:
   932  * gst_element_get_compatible_pad:
   916  * @element: a #GstElement in which the pad should be found.
   933  * @element: a #GstElement in which the pad should be found.
   917  * @pad: the #GstPad to find a compatible one for.
   934  * @pad: the #GstPad to find a compatible one for.
   918  * @caps: the #GstCaps to use as a filter.
   935  * @caps: the #GstCaps to use as a filter.
   936   GstPadTemplate *templ;
   953   GstPadTemplate *templ;
   937   GstCaps *templcaps;
   954   GstCaps *templcaps;
   938   GstPad *foundpad = NULL;
   955   GstPad *foundpad = NULL;
   939   gboolean done;
   956   gboolean done;
   940 
   957 
       
   958   /* FIXME check for caps compatibility */
       
   959 
   941   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   960   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
   942   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
   961   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
   943 
   962 
   944   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   963   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   945       "finding pad in %s compatible with %s:%s",
   964       "finding pad in %s compatible with %s:%s",
   964         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
   983         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
   965             GST_DEBUG_PAD_NAME (current));
   984             GST_DEBUG_PAD_NAME (current));
   966 
   985 
   967         peer = gst_pad_get_peer (current);
   986         peer = gst_pad_get_peer (current);
   968 
   987 
   969         if (peer == NULL && gst_pad_check_link (pad, current)) {
   988         if (peer == NULL && gst_pad_can_link (pad, current)) {
   970           GstCaps *temp, *temp2, *intersection;
   989 
   971 
   990           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   972           /* Now check if the two pads' caps are compatible */
   991               "found existing unlinked pad %s:%s",
   973           temp = gst_pad_get_caps (pad);
   992               GST_DEBUG_PAD_NAME (current));
   974           if (caps) {
   993 
   975             intersection = gst_caps_intersect (temp, caps);
   994           gst_iterator_free (pads);
   976             gst_caps_unref (temp);
   995 
   977           } else {
   996           return current;
   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 {
   997         } else {
  1002           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
   998           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
  1003               "already linked or cannot be linked (peer = %p)", peer);
   999 
       
  1000           gst_object_unref (current);
       
  1001           if (peer)
       
  1002             gst_object_unref (peer);
  1004         }
  1003         }
  1005         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unreffing pads");
       
  1006 
       
  1007         gst_object_unref (current);
       
  1008         if (peer)
       
  1009           gst_object_unref (peer);
       
  1010         break;
  1004         break;
  1011       }
  1005       }
  1012       case GST_ITERATOR_DONE:
  1006       case GST_ITERATOR_DONE:
  1013         done = TRUE;
  1007         done = TRUE;
  1014         break;
  1008         break;
  1020         break;
  1014         break;
  1021     }
  1015     }
  1022   }
  1016   }
  1023   gst_iterator_free (pads);
  1017   gst_iterator_free (pads);
  1024 
  1018 
  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 
       
  1029   /* try to create a new one */
  1019   /* try to create a new one */
  1030   /* requesting is a little crazy, we need a template. Let's create one */
  1020   /* requesting is a little crazy, we need a template. Let's create one */
  1031   /* FIXME: why not gst_pad_get_pad_template (pad); */
       
  1032   templcaps = gst_pad_get_caps (pad);
  1021   templcaps = gst_pad_get_caps (pad);
  1033 
  1022 
  1034   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
  1023   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
  1035       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
  1024       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
  1036 
       
  1037   foundpad = gst_element_request_compatible_pad (element, templ);
  1025   foundpad = gst_element_request_compatible_pad (element, templ);
  1038   gst_object_unref (templ);
  1026   gst_object_unref (templ);
  1039 
  1027 
  1040   if (foundpad) {
  1028   if (foundpad) {
  1041     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  1029     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  1170 
  1158 
  1171   while (templates) {
  1159   while (templates) {
  1172     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
  1160     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
  1173 
  1161 
  1174     if (template->direction == GST_PAD_SRC) {
  1162     if (template->direction == GST_PAD_SRC) {
  1175       if (gst_caps_is_always_compatible (gst_static_caps_get
  1163       if (gst_caps_is_always_compatible (gst_static_caps_get (&template->
  1176               (&template->static_caps), caps))
  1164                   static_caps), caps))
  1177         return TRUE;
  1165         return TRUE;
  1178     }
  1166     }
  1179     templates = g_list_next (templates);
  1167     templates = g_list_next (templates);
  1180   }
  1168   }
  1181 
  1169 
  1447       destpadname ? destpadname : "(any)");
  1435       destpadname ? destpadname : "(any)");
  1448 
  1436 
  1449   /* get a src pad */
  1437   /* get a src pad */
  1450   if (srcpadname) {
  1438   if (srcpadname) {
  1451     /* name specified, look it up */
  1439     /* name specified, look it up */
  1452     if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
  1440     srcpad = gst_element_get_pad (src, srcpadname);
  1453       srcpad = gst_element_get_request_pad (src, srcpadname);
       
  1454     if (!srcpad) {
  1441     if (!srcpad) {
  1455       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1442       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1456           GST_ELEMENT_NAME (src), srcpadname);
  1443           GST_ELEMENT_NAME (src), srcpadname);
  1457       return FALSE;
  1444       return FALSE;
  1458     } else {
  1445     } else {
  1481   }
  1468   }
  1482 
  1469 
  1483   /* get a destination pad */
  1470   /* get a destination pad */
  1484   if (destpadname) {
  1471   if (destpadname) {
  1485     /* name specified, look it up */
  1472     /* name specified, look it up */
  1486     if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
  1473     destpad = gst_element_get_pad (dest, destpadname);
  1487       destpad = gst_element_get_request_pad (dest, destpadname);
       
  1488     if (!destpad) {
  1474     if (!destpad) {
  1489       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1475       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
  1490           GST_ELEMENT_NAME (dest), destpadname);
  1476           GST_ELEMENT_NAME (dest), destpadname);
  1491       return FALSE;
  1477       return FALSE;
  1492     } else {
  1478     } else {
  1787 #endif
  1773 #endif
  1788 
  1774 
  1789 gboolean
  1775 gboolean
  1790 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
  1776 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
  1791 {
  1777 {
  1792   gboolean res = TRUE;
       
  1793   va_list args;
  1778   va_list args;
  1794 
  1779 
  1795   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
  1780   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
  1796   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
  1781   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
  1797 
  1782 
  1798   va_start (args, element_2);
  1783   va_start (args, element_2);
  1799 
  1784 
  1800   while (element_2) {
  1785   while (element_2) {
  1801     if (!gst_element_link (element_1, element_2)) {
  1786     if (!gst_element_link (element_1, element_2))
  1802       res = FALSE;
  1787       return FALSE;
  1803       break;
       
  1804     }
       
  1805 
  1788 
  1806     element_1 = element_2;
  1789     element_1 = element_2;
  1807     element_2 = va_arg (args, GstElement *);
  1790     element_2 = va_arg (args, GstElement *);
  1808   }
  1791   }
  1809 
  1792 
  1810   va_end (args);
  1793   va_end (args);
  1811 
  1794 
  1812   return res;
  1795   return TRUE;
  1813 }
  1796 }
  1814 
  1797 
  1815 /**
  1798 /**
  1816  * gst_element_link_filtered:
  1799  * gst_element_link_filtered:
  1817  * @src: a #GstElement containing the source pad.
  1800  * @src: a #GstElement containing the source pad.
  1856 void
  1839 void
  1857 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
  1840 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
  1858     GstElement * dest, const gchar * destpadname)
  1841     GstElement * dest, const gchar * destpadname)
  1859 {
  1842 {
  1860   GstPad *srcpad, *destpad;
  1843   GstPad *srcpad, *destpad;
  1861   gboolean srcrequest, destrequest;
       
  1862 
       
  1863   srcrequest = destrequest = FALSE;
       
  1864 
  1844 
  1865   g_return_if_fail (src != NULL);
  1845   g_return_if_fail (src != NULL);
  1866   g_return_if_fail (GST_IS_ELEMENT (src));
  1846   g_return_if_fail (GST_IS_ELEMENT (src));
  1867   g_return_if_fail (srcpadname != NULL);
  1847   g_return_if_fail (srcpadname != NULL);
  1868   g_return_if_fail (dest != NULL);
  1848   g_return_if_fail (dest != NULL);
  1869   g_return_if_fail (GST_IS_ELEMENT (dest));
  1849   g_return_if_fail (GST_IS_ELEMENT (dest));
  1870   g_return_if_fail (destpadname != NULL);
  1850   g_return_if_fail (destpadname != NULL);
  1871 
  1851 
  1872   /* obtain the pads requested */
  1852   /* obtain the pads requested */
  1873   if (!(srcpad = gst_element_get_static_pad (src, srcpadname)))
  1853   srcpad = gst_element_get_pad (src, srcpadname);
  1874     if ((srcpad = gst_element_get_request_pad (src, srcpadname)))
       
  1875       srcrequest = TRUE;
       
  1876   if (srcpad == NULL) {
  1854   if (srcpad == NULL) {
  1877     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
  1855     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
  1878     return;
  1856     return;
  1879   }
  1857   }
  1880   if (!(destpad = gst_element_get_static_pad (dest, destpadname)))
  1858   destpad = gst_element_get_pad (dest, destpadname);
  1881     if ((destpad = gst_element_get_request_pad (dest, destpadname)))
       
  1882       destrequest = TRUE;
       
  1883   if (destpad == NULL) {
  1859   if (destpad == NULL) {
  1884     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
  1860     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
  1885         destpadname);
  1861         destpadname);
  1886     goto free_src;
  1862     gst_object_unref (srcpad);
       
  1863     return;
  1887   }
  1864   }
  1888 
  1865 
  1889   /* we're satisified they can be unlinked, let's do it */
  1866   /* we're satisified they can be unlinked, let's do it */
  1890   gst_pad_unlink (srcpad, destpad);
  1867   gst_pad_unlink (srcpad, destpad);
  1891 
  1868   gst_object_unref (srcpad);
  1892   if (destrequest)
       
  1893     gst_element_release_request_pad (dest, destpad);
       
  1894   gst_object_unref (destpad);
  1869   gst_object_unref (destpad);
  1895 
       
  1896 free_src:
       
  1897   if (srcrequest)
       
  1898     gst_element_release_request_pad (src, srcpad);
       
  1899   gst_object_unref (srcpad);
       
  1900 }
  1870 }
  1901 
  1871 
  1902 /**
  1872 /**
  1903  * gst_element_unlink_many:
  1873  * gst_element_unlink_many:
  1904  * @element_1: the first #GstElement in the link chain.
  1874  * @element_1: the first #GstElement in the link chain.
  1968         GstPad *pad = GST_PAD_CAST (data);
  1938         GstPad *pad = GST_PAD_CAST (data);
  1969 
  1939 
  1970         if (GST_PAD_IS_SRC (pad)) {
  1940         if (GST_PAD_IS_SRC (pad)) {
  1971           GstPad *peerpad = gst_pad_get_peer (pad);
  1941           GstPad *peerpad = gst_pad_get_peer (pad);
  1972 
  1942 
  1973           /* see if the pad is linked and is really a pad of dest */
  1943           /* see if the pad is connected and is really a pad
       
  1944            * of dest */
  1974           if (peerpad) {
  1945           if (peerpad) {
  1975             GstElement *peerelem;
  1946             GstElement *peerelem;
  1976 
  1947 
  1977             peerelem = gst_pad_get_parent_element (peerpad);
  1948             peerelem = gst_pad_get_parent_element (peerpad);
  1978 
  1949 
  2162   return gst_element_seek (element, 1.0, format, seek_flags,
  2133   return gst_element_seek (element, 1.0, format, seek_flags,
  2163       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0);
  2134       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0);
  2164 }
  2135 }
  2165 
  2136 
  2166 /**
  2137 /**
       
  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 /**
  2167  * gst_pad_use_fixed_caps:
  2202  * gst_pad_use_fixed_caps:
  2168  * @pad: the pad to use
  2203  * @pad: the pad to use
  2169  *
  2204  *
  2170  * A helper function you can use that sets the
  2205  * A helper function you can use that sets the
  2171  * @gst_pad_get_fixed_caps_func as the getcaps function for the
  2206  * @gst_pad_get_fixed_caps_func as the getcaps function for the
  2212 
  2247 
  2213     GST_CAT_DEBUG (GST_CAT_CAPS,
  2248     GST_CAT_DEBUG (GST_CAT_CAPS,
  2214         "using pad caps %p %" GST_PTR_FORMAT, result, result);
  2249         "using pad caps %p %" GST_PTR_FORMAT, result, result);
  2215 
  2250 
  2216     result = gst_caps_ref (result);
  2251     result = gst_caps_ref (result);
  2217   } else if (GST_PAD_PAD_TEMPLATE (pad)) {
  2252     goto done;
       
  2253   }
       
  2254   if (GST_PAD_PAD_TEMPLATE (pad)) {
  2218     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
  2255     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
  2219 
  2256 
  2220     result = GST_PAD_TEMPLATE_CAPS (templ);
  2257     result = GST_PAD_TEMPLATE_CAPS (templ);
  2221     GST_CAT_DEBUG (GST_CAT_CAPS,
  2258     GST_CAT_DEBUG (GST_CAT_CAPS,
  2222         "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
  2259         "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
  2223         result);
  2260         result);
  2224 
  2261 
  2225     result = gst_caps_ref (result);
  2262     result = gst_caps_ref (result);
  2226   } else {
  2263     goto done;
  2227     GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
  2264   }
  2228     result = gst_caps_new_empty ();
  2265   GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
  2229   }
  2266   result = gst_caps_new_empty ();
       
  2267 
       
  2268 done:
  2230   GST_OBJECT_UNLOCK (pad);
  2269   GST_OBJECT_UNLOCK (pad);
  2231 
  2270 
  2232   return result;
  2271   return result;
  2233 }
  2272 }
  2234 
  2273 
  2518  * buffers, and unrefs the original source buffers.
  2557  * buffers, and unrefs the original source buffers.
  2519  *
  2558  *
  2520  * If the buffers point to contiguous areas of memory, the buffer
  2559  * If the buffers point to contiguous areas of memory, the buffer
  2521  * is created without copying the data.
  2560  * is created without copying the data.
  2522  *
  2561  *
  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  *
       
  2528  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
  2562  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
  2529  */
  2563  */
  2530 #ifdef __SYMBIAN32__
  2564 #ifdef __SYMBIAN32__
  2531 EXPORT_C
  2565 EXPORT_C
  2532 #endif
  2566 #endif
  2570 #endif /* GST_REMOVE_DEPRECATED */
  2604 #endif /* GST_REMOVE_DEPRECATED */
  2571 
  2605 
  2572 static gboolean
  2606 static gboolean
  2573 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
  2607 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
  2574 {
  2608 {
  2575   /* skip the pad, the request came from */
       
  2576   if (pad != orig) {
  2609   if (pad != orig) {
  2577     GstCaps *peercaps, *existing;
  2610     GstCaps *peercaps, *existing;
  2578 
  2611 
  2579     existing = g_value_get_pointer (ret);
  2612     existing = g_value_get_pointer (ret);
  2580     peercaps = gst_pad_peer_get_caps (pad);
  2613     peercaps = gst_pad_peer_get_caps (pad);
  2614   GstIteratorResult res;
  2647   GstIteratorResult res;
  2615   GValue ret = { 0, };
  2648   GValue ret = { 0, };
  2616 
  2649 
  2617   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
  2650   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
  2618 
  2651 
  2619   GST_CAT_DEBUG (GST_CAT_PADS, "proxying getcaps for %s:%s",
  2652   GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
  2620       GST_DEBUG_PAD_NAME (pad));
       
  2621 
  2653 
  2622   element = gst_pad_get_parent_element (pad);
  2654   element = gst_pad_get_parent_element (pad);
  2623   if (element == NULL)
  2655   if (element == NULL)
  2624     return NULL;
  2656     return NULL;
  2625 
  2657 
  2723   LinkData data;
  2755   LinkData data;
  2724 
  2756 
  2725   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2757   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2726   g_return_val_if_fail (caps != NULL, FALSE);
  2758   g_return_val_if_fail (caps != NULL, FALSE);
  2727 
  2759 
  2728   GST_CAT_DEBUG (GST_CAT_PADS, "proxying pad link for %s:%s",
  2760   GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
  2729       GST_DEBUG_PAD_NAME (pad));
       
  2730 
  2761 
  2731   element = gst_pad_get_parent_element (pad);
  2762   element = gst_pad_get_parent_element (pad);
  2732   if (element == NULL)
  2763   if (element == NULL)
  2733     return FALSE;
  2764     return FALSE;
  2734 
  2765 
  2924 {
  2955 {
  2925   GstQuery *query;
  2956   GstQuery *query;
  2926   gboolean ret;
  2957   gboolean ret;
  2927 
  2958 
  2928   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
  2959   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2960   g_return_val_if_fail (src_val >= 0, FALSE);
  2929   g_return_val_if_fail (dest_format != NULL, FALSE);
  2961   g_return_val_if_fail (dest_format != NULL, FALSE);
  2930   g_return_val_if_fail (dest_val != NULL, FALSE);
  2962   g_return_val_if_fail (dest_val != NULL, FALSE);
  2931 
  2963 
  2932   if (*dest_format == src_format) {
  2964   if (*dest_format == src_format) {
  2933     *dest_val = src_val;
  2965     *dest_val = src_val;
  2990  * gst_atomic_int_set:
  3022  * gst_atomic_int_set:
  2991  * @atomic_int: pointer to an atomic integer
  3023  * @atomic_int: pointer to an atomic integer
  2992  * @value: value to set
  3024  * @value: value to set
  2993  *
  3025  *
  2994  * Unconditionally sets the atomic integer to @value.
  3026  * Unconditionally sets the atomic integer to @value.
  2995  * 
  3027  */
  2996  * Deprecated: Use g_atomic_int_set().
       
  2997  *
       
  2998  */
       
  2999 #ifndef GST_REMOVE_DEPRECATED
       
  3000 #ifdef __SYMBIAN32__
  3028 #ifdef __SYMBIAN32__
  3001 EXPORT_C
  3029 EXPORT_C
  3002 #endif
  3030 #endif
  3003 
  3031 
  3004 void
  3032 void
  3005 gst_atomic_int_set (gint * atomic_int, gint value)
  3033 gst_atomic_int_set (gint * atomic_int, gint value)
  3006 {
  3034 {
  3007   g_atomic_int_set (atomic_int, value);
  3035   int ignore;
  3008 }
  3036 
  3009 #endif
  3037   *atomic_int = value;
       
  3038   /* read acts as a memory barrier */
       
  3039   ignore = g_atomic_int_get (atomic_int);
       
  3040 }
  3010 
  3041 
  3011 /**
  3042 /**
  3012  * gst_pad_add_data_probe:
  3043  * gst_pad_add_data_probe:
  3013  * @pad: pad to add the data probe handler to
  3044  * @pad: pad to add the data probe handler to
  3014  * @handler: function to call when data is passed over pad
  3045  * @handler: function to call when data is passed over pad
  3043 #endif
  3074 #endif
  3044 
  3075 
  3045 gulong
  3076 gulong
  3046 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
  3077 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
  3047 {
  3078 {
  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 {
       
  3095   gulong sigid;
  3079   gulong sigid;
  3096 
  3080 
  3097   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3081   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3098   g_return_val_if_fail (handler != NULL, 0);
  3082   g_return_val_if_fail (handler != NULL, 0);
  3099 
  3083 
  3100   GST_OBJECT_LOCK (pad);
  3084   GST_OBJECT_LOCK (pad);
  3101 
  3085   sigid = g_signal_connect (pad, "have-data", handler, data);
  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 
       
  3106   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3086   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3107   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3087   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3108   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3088   GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes",
  3109       "adding data probe, now %d data, %d event probes",
  3089       GST_DEBUG_PAD_NAME (pad),
  3110       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3090       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3111   GST_OBJECT_UNLOCK (pad);
  3091   GST_OBJECT_UNLOCK (pad);
  3112 
  3092 
  3113   return sigid;
  3093   return sigid;
  3114 }
  3094 }
  3129 #endif
  3109 #endif
  3130 
  3110 
  3131 gulong
  3111 gulong
  3132 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
  3112 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
  3133 {
  3113 {
  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 {
       
  3162   gulong sigid;
  3114   gulong sigid;
  3163 
  3115 
  3164   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3116   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3165   g_return_val_if_fail (handler != NULL, 0);
  3117   g_return_val_if_fail (handler != NULL, 0);
  3166 
  3118 
  3167   GST_OBJECT_LOCK (pad);
  3119   GST_OBJECT_LOCK (pad);
  3168 
  3120   sigid = g_signal_connect (pad, "have-data::event", handler, data);
  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 
       
  3173   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3121   GST_PAD_DO_EVENT_SIGNALS (pad)++;
  3174   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding event probe, now %d probes",
  3122   GST_DEBUG ("adding event probe to pad %s:%s, now %d probes",
  3175       GST_PAD_DO_EVENT_SIGNALS (pad));
  3123       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3176   GST_OBJECT_UNLOCK (pad);
  3124   GST_OBJECT_UNLOCK (pad);
  3177 
  3125 
  3178   return sigid;
  3126   return sigid;
  3179 }
  3127 }
  3180 
  3128 
  3194 #endif
  3142 #endif
  3195 
  3143 
  3196 gulong
  3144 gulong
  3197 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
  3145 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
  3198 {
  3146 {
  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 {
       
  3227   gulong sigid;
  3147   gulong sigid;
  3228 
  3148 
  3229   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3149   g_return_val_if_fail (GST_IS_PAD (pad), 0);
  3230   g_return_val_if_fail (handler != NULL, 0);
  3150   g_return_val_if_fail (handler != NULL, 0);
  3231 
  3151 
  3232   GST_OBJECT_LOCK (pad);
  3152   GST_OBJECT_LOCK (pad);
  3233 
  3153   sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
  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 
       
  3238   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3154   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
  3239   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "adding buffer probe, now %d probes",
  3155   GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes",
  3240       GST_PAD_DO_BUFFER_SIGNALS (pad));
  3156       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3241   GST_OBJECT_UNLOCK (pad);
  3157   GST_OBJECT_UNLOCK (pad);
  3242 
  3158 
  3243   return sigid;
  3159   return sigid;
  3244 }
  3160 }
  3245 
  3161 
  3262 
  3178 
  3263   GST_OBJECT_LOCK (pad);
  3179   GST_OBJECT_LOCK (pad);
  3264   g_signal_handler_disconnect (pad, handler_id);
  3180   g_signal_handler_disconnect (pad, handler_id);
  3265   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3181   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3266   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3182   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3267   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3183   GST_DEBUG
  3268       "removed data probe, now %d event, %d buffer probes",
  3184       ("removed data probe from pad %s:%s, now %d event, %d buffer probes",
  3269       GST_PAD_DO_EVENT_SIGNALS (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3185       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
       
  3186       GST_PAD_DO_BUFFER_SIGNALS (pad));
  3270   GST_OBJECT_UNLOCK (pad);
  3187   GST_OBJECT_UNLOCK (pad);
  3271 
  3188 
  3272 }
  3189 }
  3273 
  3190 
  3274 /**
  3191 /**
  3289   g_return_if_fail (handler_id > 0);
  3206   g_return_if_fail (handler_id > 0);
  3290 
  3207 
  3291   GST_OBJECT_LOCK (pad);
  3208   GST_OBJECT_LOCK (pad);
  3292   g_signal_handler_disconnect (pad, handler_id);
  3209   g_signal_handler_disconnect (pad, handler_id);
  3293   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3210   GST_PAD_DO_EVENT_SIGNALS (pad)--;
  3294   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3211   GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
  3295       "removed event probe, now %d event probes",
  3212       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
  3296       GST_PAD_DO_EVENT_SIGNALS (pad));
       
  3297   GST_OBJECT_UNLOCK (pad);
  3213   GST_OBJECT_UNLOCK (pad);
  3298 }
  3214 }
  3299 
  3215 
  3300 /**
  3216 /**
  3301  * gst_pad_remove_buffer_probe:
  3217  * gst_pad_remove_buffer_probe:
  3315   g_return_if_fail (handler_id > 0);
  3231   g_return_if_fail (handler_id > 0);
  3316 
  3232 
  3317   GST_OBJECT_LOCK (pad);
  3233   GST_OBJECT_LOCK (pad);
  3318   g_signal_handler_disconnect (pad, handler_id);
  3234   g_signal_handler_disconnect (pad, handler_id);
  3319   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3235   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
  3320   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
  3236   GST_DEBUG ("removed buffer probe from pad %s:%s, now %d buffer probes",
  3321       "removed buffer probe, now %d buffer probes",
  3237       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
  3322       GST_PAD_DO_BUFFER_SIGNALS (pad));
       
  3323   GST_OBJECT_UNLOCK (pad);
  3238   GST_OBJECT_UNLOCK (pad);
  3324 
  3239 
  3325 }
  3240 }
  3326 
  3241 
  3327 /**
  3242 /**
  3347   g_return_if_fail (element != NULL);
  3262   g_return_if_fail (element != NULL);
  3348   g_return_if_fail (pad != NULL);
  3263   g_return_if_fail (pad != NULL);
  3349   g_return_if_fail (list != NULL);
  3264   g_return_if_fail (list != NULL);
  3350 
  3265 
  3351   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
  3266   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
  3352   /* FIXME 0.11: Set the pad as source. */
       
  3353   gst_element_post_message (element,
  3267   gst_element_post_message (element,
  3354       gst_message_new_tag_full (GST_OBJECT (element), pad, list));
  3268       gst_message_new_tag (GST_OBJECT (element), list));
  3355 }
  3269 }
  3356 
  3270 
  3357 static void
  3271 static void
  3358 push_and_ref (GstPad * pad, GstEvent * event)
  3272 push_and_ref (GstPad * pad, GstEvent * event)
  3359 {
  3273 {
  3395   gst_element_post_message (element,
  3309   gst_element_post_message (element,
  3396       gst_message_new_tag (GST_OBJECT (element), list));
  3310       gst_message_new_tag (GST_OBJECT (element), list));
  3397 }
  3311 }
  3398 
  3312 
  3399 static GstPad *
  3313 static GstPad *
  3400 element_find_unlinked_pad (GstElement * element, GstPadDirection direction)
  3314 element_find_unconnected_pad (GstElement * element, GstPadDirection direction)
  3401 {
  3315 {
  3402   GstIterator *iter;
  3316   GstIterator *iter;
  3403   GstPad *unlinked_pad = NULL;
  3317   GstPad *unconnected_pad = NULL;
  3404   gboolean done;
  3318   gboolean done;
  3405 
  3319 
  3406   switch (direction) {
  3320   switch (direction) {
  3407     case GST_PAD_SRC:
  3321     case GST_PAD_SRC:
  3408       iter = gst_element_iterate_src_pads (element);
  3322       iter = gst_element_iterate_src_pads (element);
  3425         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
  3339         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
  3426             GST_DEBUG_PAD_NAME (pad));
  3340             GST_DEBUG_PAD_NAME (pad));
  3427 
  3341 
  3428         peer = gst_pad_get_peer (GST_PAD (pad));
  3342         peer = gst_pad_get_peer (GST_PAD (pad));
  3429         if (peer == NULL) {
  3343         if (peer == NULL) {
  3430           unlinked_pad = pad;
  3344           unconnected_pad = pad;
  3431           done = TRUE;
  3345           done = TRUE;
  3432           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  3346           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
  3433               "found existing unlinked pad %s:%s",
  3347               "found existing unlinked pad %s:%s",
  3434               GST_DEBUG_PAD_NAME (unlinked_pad));
  3348               GST_DEBUG_PAD_NAME (unconnected_pad));
  3435         } else {
  3349         } else {
  3436           gst_object_unref (pad);
  3350           gst_object_unref (pad);
  3437           gst_object_unref (peer);
  3351           gst_object_unref (peer);
  3438         }
  3352         }
  3439         break;
  3353         break;
  3450     }
  3364     }
  3451   }
  3365   }
  3452 
  3366 
  3453   gst_iterator_free (iter);
  3367   gst_iterator_free (iter);
  3454 
  3368 
  3455   return unlinked_pad;
  3369   return unconnected_pad;
  3456 }
  3370 }
  3457 
  3371 
  3458 /**
  3372 /**
  3459  * gst_bin_find_unlinked_pad:
  3373  * gst_bin_find_unconnected_pad:
  3460  * @bin: bin in which to look for elements with unlinked pads
  3374  * @bin: bin in which to look for elements with unconnected pads
  3461  * @direction: whether to look for an unlinked source or sink pad
  3375  * @direction: whether to look for an unconnected source or sink pad
  3462  *
  3376  *
  3463  * Recursively looks for elements with an unlinked pad of the given
  3377  * Recursively looks for elements with an unconnected pad of the given
  3464  * direction within the specified bin and returns an unlinked pad
  3378  * direction within the specified bin and returns an unconnected pad
  3465  * if one is found, or NULL otherwise. If a pad is found, the caller
  3379  * if one is found, or NULL otherwise. If a pad is found, the caller
  3466  * owns a reference to it and should use gst_object_unref() on the
  3380  * owns a reference to it and should use gst_object_unref() on the
  3467  * pad when it is not needed any longer.
  3381  * pad when it is not needed any longer.
  3468  *
  3382  *
  3469  * Returns: unlinked pad of the given direction, or NULL.
  3383  * Returns: unconnected pad of the given direction, or NULL.
  3470  *
  3384  *
  3471  * Since: 0.10.20
  3385  * Since: 0.10.3
  3472  */
  3386  */
  3473 #ifdef __SYMBIAN32__
  3387 #ifdef __SYMBIAN32__
  3474 EXPORT_C
  3388 EXPORT_C
  3475 #endif
  3389 #endif
  3476 
  3390 
  3477 GstPad *
  3391 GstPad *
  3478 gst_bin_find_unlinked_pad (GstBin * bin, GstPadDirection direction)
  3392 gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
  3479 {
  3393 {
  3480   GstIterator *iter;
  3394   GstIterator *iter;
  3481   gboolean done;
  3395   gboolean done;
  3482   GstPad *pad = NULL;
  3396   GstPad *pad = NULL;
  3483 
  3397 
  3489   while (!done) {
  3403   while (!done) {
  3490     gpointer element;
  3404     gpointer element;
  3491 
  3405 
  3492     switch (gst_iterator_next (iter, &element)) {
  3406     switch (gst_iterator_next (iter, &element)) {
  3493       case GST_ITERATOR_OK:
  3407       case GST_ITERATOR_OK:
  3494         pad = element_find_unlinked_pad (GST_ELEMENT (element), direction);
  3408         pad = element_find_unconnected_pad (GST_ELEMENT (element), direction);
  3495         gst_object_unref (element);
  3409         gst_object_unref (element);
  3496         if (pad != NULL)
  3410         if (pad != NULL)
  3497           done = TRUE;
  3411           done = TRUE;
  3498         break;
  3412         break;
  3499       case GST_ITERATOR_DONE:
  3413       case GST_ITERATOR_DONE:
  3512 
  3426 
  3513   return pad;
  3427   return pad;
  3514 }
  3428 }
  3515 
  3429 
  3516 /**
  3430 /**
  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 /**
       
  3546  * gst_parse_bin_from_description:
  3431  * gst_parse_bin_from_description:
  3547  * @bin_description: command line describing the bin
  3432  * @bin_description: command line describing the bin
  3548  * @ghost_unlinked_pads: whether to automatically create ghost pads
  3433  * @ghost_unconnected_pads: whether to automatically create ghost pads
  3549  *     for unlinked source or sink pads within the bin
  3434  *                          for unconnected source or sink pads within
       
  3435  *                          the bin
  3550  * @err: where to store the error message in case of an error, or NULL
  3436  * @err: where to store the error message in case of an error, or NULL
  3551  *
  3437  *
  3552  * This is a convenience wrapper around gst_parse_launch() to create a
  3438  * This is a convenience wrapper around gst_parse_launch() to create a
  3553  * #GstBin from a gst-launch-style pipeline description. See
  3439  * #GstBin from a gst-launch-style pipeline description. See
  3554  * gst_parse_launch() and the gst-launch man page for details about the
  3440  * gst_parse_launch() and the gst-launch man page for details about the
  3555  * syntax. Ghost pads on the bin for unlinked source or sink pads
  3441  * syntax. Ghost pads on the bin for unconnected source or sink pads
  3556  * within the bin can automatically be created (but only a maximum of
  3442  * within the bin can automatically be created (but only a maximum of
  3557  * one ghost pad for each direction will be created; if you expect
  3443  * one ghost pad for each direction will be created; if you expect
  3558  * multiple unlinked source pads or multiple unlinked sink pads
  3444  * multiple unconnected source pads or multiple unconnected sink pads
  3559  * and want them all ghosted, you will have to create the ghost pads
  3445  * and want them all ghosted, you will have to create the ghost pads
  3560  * yourself).
  3446  * yourself).
  3561  *
  3447  *
  3562  * Returns: a newly-created bin, or NULL if an error occurred.
  3448  * Returns: a newly-created bin, or NULL if an error occurred.
  3563  *
  3449  *
  3567 EXPORT_C
  3453 EXPORT_C
  3568 #endif
  3454 #endif
  3569 
  3455 
  3570 GstElement *
  3456 GstElement *
  3571 gst_parse_bin_from_description (const gchar * bin_description,
  3457 gst_parse_bin_from_description (const gchar * bin_description,
  3572     gboolean ghost_unlinked_pads, GError ** err)
  3458     gboolean ghost_unconnected_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)
       
  3609 {
  3459 {
  3610 #ifndef GST_DISABLE_PARSE
  3460 #ifndef GST_DISABLE_PARSE
  3611   GstPad *pad = NULL;
  3461   GstPad *pad = NULL;
  3612   GstBin *bin;
  3462   GstBin *bin;
  3613   gchar *desc;
  3463   gchar *desc;
  3617 
  3467 
  3618   GST_DEBUG ("Making bin from description '%s'", bin_description);
  3468   GST_DEBUG ("Making bin from description '%s'", bin_description);
  3619 
  3469 
  3620   /* parse the pipeline to a bin */
  3470   /* parse the pipeline to a bin */
  3621   desc = g_strdup_printf ("bin.( %s )", bin_description);
  3471   desc = g_strdup_printf ("bin.( %s )", bin_description);
  3622   bin = (GstBin *) gst_parse_launch_full (desc, context, flags, err);
  3472   bin = (GstBin *) gst_parse_launch (desc, err);
  3623   g_free (desc);
  3473   g_free (desc);
  3624 
  3474 
  3625   if (bin == NULL || (err && *err != NULL)) {
  3475   if (bin == NULL || (err && *err != NULL)) {
  3626     if (bin)
  3476     if (bin)
  3627       gst_object_unref (bin);
  3477       gst_object_unref (bin);
  3628     return NULL;
  3478     return NULL;
  3629   }
  3479   }
  3630 
  3480 
  3631   /* find pads and ghost them if necessary */
  3481   /* find pads and ghost them if necessary */
  3632   if (ghost_unlinked_pads) {
  3482   if (ghost_unconnected_pads) {
  3633     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC))) {
  3483     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) {
  3634       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
  3484       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
  3635       gst_object_unref (pad);
  3485       gst_object_unref (pad);
  3636     }
  3486     }
  3637     if ((pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SINK))) {
  3487     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) {
  3638       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
  3488       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
  3639       gst_object_unref (pad);
  3489       gst_object_unref (pad);
  3640     }
  3490     }
  3641   }
  3491   }
  3642 
  3492 
  3643   return GST_ELEMENT (bin);
  3493   return GST_ELEMENT (bin);
  3644 #else
  3494 #else
  3645   gchar *msg;
  3495   gchar *msg;
  3646 
  3496 
  3647   GST_WARNING ("Disabled API called");
  3497   GST_WARNING ("Disabled API called: gst_parse_bin_from_description()");
  3648 
  3498 
  3649   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
  3499   msg = gst_error_get_message (GST_CORE_ERROR, GST_CORE_ERROR_DISABLED);
  3650   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
  3500   g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_DISABLED, "%s", msg);
  3651   g_free (msg);
  3501   g_free (msg);
  3652 
  3502 
  3755 
  3605 
  3756   g_get_current_time (&now);
  3606   g_get_current_time (&now);
  3757   return GST_TIMEVAL_TO_TIME (now);
  3607   return GST_TIMEVAL_TO_TIME (now);
  3758 #endif
  3608 #endif
  3759 }
  3609 }
  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 }