gstreamer_core/gst/gstutils.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *                    2000 Wim Taymans <wtay@chello.be>
       
     4  *                    2002 Thomas Vander Stichele <thomas@apestaart.org>
       
     5  *
       
     6  * gstutils.c: Utility functions: gtk_get_property stuff, etc.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Library General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Library General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Library General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /**
       
    25  * SECTION:gstutils
       
    26  * @short_description: Various utility functions
       
    27  *
       
    28  * When defining own plugins, use the GST_BOILERPLATE ease gobject creation.
       
    29  */
       
    30 
       
    31 #include "gst_private.h"
       
    32 #include <stdio.h>
       
    33 #include <string.h>
       
    34 
       
    35 #include "gstghostpad.h"
       
    36 #include "gstutils.h"
       
    37 #include "gsterror.h"
       
    38 #include "gstinfo.h"
       
    39 #include "gstparse.h"
       
    40 #include "gst-i18n-lib.h"
       
    41 
       
    42 #ifdef __SYMBIAN32__
       
    43 #include <glib_global.h>
       
    44 #include <gobject_global.h>
       
    45 #endif
       
    46 
       
    47 
       
    48 /**
       
    49  * gst_util_dump_mem:
       
    50  * @mem: a pointer to the memory to dump
       
    51  * @size: the size of the memory block to dump
       
    52  *
       
    53  * Dumps the memory block into a hex representation. Useful for debugging.
       
    54  */
       
    55 #ifdef __SYMBIAN32__
       
    56 EXPORT_C
       
    57 #endif
       
    58 
       
    59 void
       
    60 gst_util_dump_mem (const guchar * mem, guint size)
       
    61 {
       
    62   guint i, j;
       
    63   GString *string = g_string_sized_new (50);
       
    64   GString *chars = g_string_sized_new (18);
       
    65 
       
    66   i = j = 0;
       
    67   while (i < size) {
       
    68     if (g_ascii_isprint (mem[i]))
       
    69       g_string_append_c (chars, mem[i]);
       
    70     else
       
    71       g_string_append_c (chars, '.');
       
    72 
       
    73     g_string_append_printf (string, "%02x ", mem[i]);
       
    74 
       
    75     j++;
       
    76     i++;
       
    77 
       
    78     if (j == 16 || i == size) {
       
    79       g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j, mem + i - j,
       
    80           string->str, chars->str);
       
    81       g_string_set_size (string, 0);
       
    82       g_string_set_size (chars, 0);
       
    83       j = 0;
       
    84     }
       
    85   }
       
    86   g_string_free (string, TRUE);
       
    87   g_string_free (chars, TRUE);
       
    88 }
       
    89 
       
    90 
       
    91 /**
       
    92  * gst_util_set_value_from_string:
       
    93  * @value: the value to set
       
    94  * @value_str: the string to get the value from
       
    95  *
       
    96  * Converts the string to the type of the value and
       
    97  * sets the value with it.
       
    98  */
       
    99 #ifdef __SYMBIAN32__
       
   100 EXPORT_C
       
   101 #endif
       
   102 
       
   103 void
       
   104 gst_util_set_value_from_string (GValue * value, const gchar * value_str)
       
   105 {
       
   106   gint sscanf_ret;
       
   107 
       
   108   g_return_if_fail (value != NULL);
       
   109   g_return_if_fail (value_str != NULL);
       
   110 
       
   111   GST_CAT_DEBUG (GST_CAT_PARAMS, "parsing '%s' to type %s", value_str,
       
   112       g_type_name (G_VALUE_TYPE (value)));
       
   113 
       
   114   switch (G_VALUE_TYPE (value)) {
       
   115     case G_TYPE_STRING:
       
   116       g_value_set_string (value, value_str);
       
   117       break;
       
   118     case G_TYPE_ENUM:
       
   119     case G_TYPE_INT:{
       
   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   }
       
   194 }
       
   195 
       
   196 /**
       
   197  * gst_util_set_object_arg:
       
   198  * @object: the object to set the argument of
       
   199  * @name: the name of the argument to set
       
   200  * @value: the string value to set
       
   201  *
       
   202  * Convertes the string value to the type of the objects argument and
       
   203  * sets the argument with it.
       
   204  */
       
   205 #ifdef __SYMBIAN32__
       
   206 EXPORT_C
       
   207 #endif
       
   208 
       
   209 void
       
   210 gst_util_set_object_arg (GObject * object, const gchar * name,
       
   211     const gchar * value)
       
   212 {
       
   213   gboolean sscanf_ret;
       
   214 
       
   215   if (name && value) {
       
   216     GParamSpec *paramspec;
       
   217 
       
   218     paramspec =
       
   219         g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
       
   220 
       
   221     if (!paramspec) {
       
   222       return;
       
   223     }
       
   224 
       
   225     GST_DEBUG ("paramspec->flags is %d, paramspec->value_type is %d",
       
   226         paramspec->flags, (gint) paramspec->value_type);
       
   227 
       
   228     if (paramspec->flags & G_PARAM_WRITABLE) {
       
   229       switch (paramspec->value_type) {
       
   230         case G_TYPE_STRING:
       
   231           g_object_set (G_OBJECT (object), name, value, NULL);
       
   232           break;
       
   233         case G_TYPE_ENUM:
       
   234         case G_TYPE_INT:{
       
   235           gint i;
       
   236 
       
   237           sscanf_ret = sscanf (value, "%d", &i);
       
   238           g_return_if_fail (sscanf_ret == 1);
       
   239           g_object_set (G_OBJECT (object), name, i, NULL);
       
   240           break;
       
   241         }
       
   242         case G_TYPE_UINT:{
       
   243           guint i;
       
   244 
       
   245           sscanf_ret = sscanf (value, "%u", &i);
       
   246           g_return_if_fail (sscanf_ret == 1);
       
   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   }
       
   318 }
       
   319 
       
   320 /* work around error C2520: conversion from unsigned __int64 to double
       
   321  * not implemented, use signed __int64
       
   322  *
       
   323  * These are implemented as functions because on some platforms a 64bit int to
       
   324  * double conversion is not defined/implemented.
       
   325  */
       
   326 #ifdef __SYMBIAN32__
       
   327 EXPORT_C
       
   328 #endif
       
   329 
       
   330 
       
   331 gdouble
       
   332 gst_util_guint64_to_gdouble (guint64 value)
       
   333 {
       
   334   if (value & G_GINT64_CONSTANT (0x8000000000000000))
       
   335     return (gdouble) ((gint64) value) + (gdouble) 18446744073709551616.;
       
   336   else
       
   337     return (gdouble) ((gint64) value);
       
   338 }
       
   339 #ifdef __SYMBIAN32__
       
   340 EXPORT_C
       
   341 #endif
       
   342 
       
   343 
       
   344 guint64
       
   345 gst_util_gdouble_to_guint64 (gdouble value)
       
   346 {
       
   347   if (value < (gdouble) 9223372036854775808.)   /* 1 << 63 */
       
   348     return ((guint64) ((gint64) value));
       
   349 
       
   350   value -= (gdouble) 18446744073709551616.;
       
   351   return ((guint64) ((gint64) value));
       
   352 }
       
   353 
       
   354 /* convenience struct for getting high and low uint32 parts of
       
   355  * a guint64 */
       
   356 typedef union
       
   357 {
       
   358   guint64 ll;
       
   359   struct
       
   360   {
       
   361 #if G_BYTE_ORDER == G_BIG_ENDIAN
       
   362     guint32 high, low;
       
   363 #else
       
   364     guint32 low, high;
       
   365 #endif
       
   366   } l;
       
   367 } GstUInt64;
       
   368 
       
   369 /* based on Hacker's Delight p152 */
       
   370 static guint64
       
   371 gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
       
   372 {
       
   373   GstUInt64 q1, q0, rhat;
       
   374   GstUInt64 v, cmp1, cmp2;
       
   375   guint s;
       
   376 
       
   377   v.ll = denom;
       
   378 
       
   379   /* count number of leading zeroes, we know they must be in the high
       
   380    * part of denom since denom > G_MAXUINT32. */
       
   381   s = v.l.high | (v.l.high >> 1);
       
   382   s |= (s >> 2);
       
   383   s |= (s >> 4);
       
   384   s |= (s >> 8);
       
   385   s = ~(s | (s >> 16));
       
   386   s = s - ((s >> 1) & 0x55555555);
       
   387   s = (s & 0x33333333) + ((s >> 2) & 0x33333333);
       
   388   s = (s + (s >> 4)) & 0x0f0f0f0f;
       
   389   s += (s >> 8);
       
   390   s = (s + (s >> 16)) & 0x3f;
       
   391 
       
   392   if (s > 0) {
       
   393     /* normalize divisor and dividend */
       
   394     v.ll <<= s;
       
   395     c1.ll = (c1.ll << s) | (c0.l.high >> (32 - s));
       
   396     c0.ll <<= s;
       
   397   }
       
   398 
       
   399   q1.ll = c1.ll / v.l.high;
       
   400   rhat.ll = c1.ll - q1.ll * v.l.high;
       
   401 
       
   402   cmp1.l.high = rhat.l.low;
       
   403   cmp1.l.low = c0.l.high;
       
   404   cmp2.ll = q1.ll * v.l.low;
       
   405 
       
   406   while (q1.l.high || cmp2.ll > cmp1.ll) {
       
   407     q1.ll--;
       
   408     rhat.ll += v.l.high;
       
   409     if (rhat.l.high)
       
   410       break;
       
   411     cmp1.l.high = rhat.l.low;
       
   412     cmp2.ll -= v.l.low;
       
   413   }
       
   414   c1.l.high = c1.l.low;
       
   415   c1.l.low = c0.l.high;
       
   416   c1.ll -= q1.ll * v.ll;
       
   417   q0.ll = c1.ll / v.l.high;
       
   418   rhat.ll = c1.ll - q0.ll * v.l.high;
       
   419 
       
   420   cmp1.l.high = rhat.l.low;
       
   421   cmp1.l.low = c0.l.low;
       
   422   cmp2.ll = q0.ll * v.l.low;
       
   423 
       
   424   while (q0.l.high || cmp2.ll > cmp1.ll) {
       
   425     q0.ll--;
       
   426     rhat.ll += v.l.high;
       
   427     if (rhat.l.high)
       
   428       break;
       
   429     cmp1.l.high = rhat.l.low;
       
   430     cmp2.ll -= v.l.low;
       
   431   }
       
   432   q0.l.high += q1.l.low;
       
   433 
       
   434   return q0.ll;
       
   435 }
       
   436 
       
   437 static guint64
       
   438 gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
       
   439 {
       
   440   GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
       
   441   GstUInt64 v, n;
       
   442 
       
   443   /* prepare input */
       
   444   v.ll = val;
       
   445   n.ll = num;
       
   446 
       
   447   /* do 128 bits multiply
       
   448    *                   nh   nl
       
   449    *                *  vh   vl
       
   450    *                ----------
       
   451    * a0 =              vl * nl
       
   452    * a1 =         vl * nh
       
   453    * b0 =         vh * nl
       
   454    * b1 =  + vh * nh
       
   455    *       -------------------
       
   456    * c1,c0
       
   457    */
       
   458   a0.ll = (guint64) v.l.low * n.l.low;
       
   459   a1.ll = (guint64) v.l.low * n.l.high;
       
   460   b0.ll = (guint64) v.l.high * n.l.low;
       
   461   b1.ll = (guint64) v.l.high * n.l.high;
       
   462 
       
   463   /* and sum together with carry into 128 bits c1, c0 */
       
   464   c0.l.low = a0.l.low;
       
   465   ct.ll = (guint64) a0.l.high + a1.l.low + b0.l.low;
       
   466   c0.l.high = ct.l.low;
       
   467   c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
       
   468 
       
   469   /* if high bits bigger than denom, we overflow */
       
   470   if (c1.ll >= denom)
       
   471     goto overflow;
       
   472 
       
   473   /* shortcut for division by 1, c1.ll should be 0 because of the
       
   474    * overflow check above. */
       
   475   if (denom == 1)
       
   476     return c0.ll;
       
   477 
       
   478   /* and 128/64 bits division, result fits 64 bits */
       
   479   if (denom <= G_MAXUINT32) {
       
   480     guint32 den = (guint32) denom;
       
   481 
       
   482     /* easy case, (c1,c0)128/(den)32 division */
       
   483     c1.l.high %= den;
       
   484     c1.l.high = c1.ll % den;
       
   485     c1.l.low = c0.l.high;
       
   486     c0.l.high = c1.ll % den;
       
   487     result.l.high = c1.ll / den;
       
   488     result.l.low = c0.ll / den;
       
   489   } else {
       
   490     result.ll = gst_util_div128_64 (c1, c0, denom);
       
   491   }
       
   492   return result.ll;
       
   493 
       
   494 overflow:
       
   495   {
       
   496     return G_MAXUINT64;
       
   497   }
       
   498 }
       
   499 
       
   500 /**
       
   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)
       
   571 {
       
   572   GstUInt64 result;
       
   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;
       
   587 
       
   588   /* do 96 bits mult/div */
       
   589   low.ll = val;
       
   590   result.ll = ((guint64) low.l.low) * num;
       
   591   high.ll = ((guint64) low.l.high) * num + (result.l.high);
       
   592 
       
   593   low.ll = high.ll / denom;
       
   594   result.l.high = high.ll % denom;
       
   595   result.ll /= denom;
       
   596 
       
   597   /* avoid overflow */
       
   598   if (low.ll + result.l.high > G_MAXUINT32)
       
   599     goto overflow;
       
   600 
       
   601   result.l.high += low.l.low;
       
   602 
       
   603   return result.ll;
       
   604 
       
   605 overflow:
       
   606   {
       
   607     return G_MAXUINT64;
       
   608   }
       
   609 }
       
   610 
       
   611 /* -----------------------------------------------------
       
   612  *
       
   613  *  The following code will be moved out of the main
       
   614  * gstreamer library someday.
       
   615  */
       
   616 
       
   617 #include "gstpad.h"
       
   618 
       
   619 static void
       
   620 string_append_indent (GString * str, gint count)
       
   621 {
       
   622   gint xx;
       
   623 
       
   624   for (xx = 0; xx < count; xx++)
       
   625     g_string_append_c (str, ' ');
       
   626 }
       
   627 
       
   628 /**
       
   629  * gst_print_pad_caps:
       
   630  * @buf: the buffer to print the caps in
       
   631  * @indent: initial indentation
       
   632  * @pad: the pad to print the caps from
       
   633  *
       
   634  * Write the pad capabilities in a human readable format into
       
   635  * the given GString.
       
   636  */
       
   637 #ifdef __SYMBIAN32__
       
   638 EXPORT_C
       
   639 #endif
       
   640 
       
   641 void
       
   642 gst_print_pad_caps (GString * buf, gint indent, GstPad * pad)
       
   643 {
       
   644   GstCaps *caps;
       
   645 
       
   646   caps = pad->caps;
       
   647 
       
   648   if (!caps) {
       
   649     string_append_indent (buf, indent);
       
   650     g_string_printf (buf, "%s:%s has no capabilities",
       
   651         GST_DEBUG_PAD_NAME (pad));
       
   652   } else {
       
   653     char *s;
       
   654 
       
   655     s = gst_caps_to_string (caps);
       
   656     g_string_append (buf, s);
       
   657     g_free (s);
       
   658   }
       
   659 }
       
   660 
       
   661 /**
       
   662  * gst_print_element_args:
       
   663  * @buf: the buffer to print the args in
       
   664  * @indent: initial indentation
       
   665  * @element: the element to print the args of
       
   666  *
       
   667  * Print the element argument in a human readable format in the given
       
   668  * GString.
       
   669  */
       
   670 #ifdef __SYMBIAN32__
       
   671 EXPORT_C
       
   672 #endif
       
   673 
       
   674 void
       
   675 gst_print_element_args (GString * buf, gint indent, GstElement * element)
       
   676 {
       
   677   guint width;
       
   678   GValue value = { 0, };        /* the important thing is that value.type = 0 */
       
   679   gchar *str = NULL;
       
   680   GParamSpec *spec, **specs, **walk;
       
   681 
       
   682   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (element), NULL);
       
   683 
       
   684   width = 0;
       
   685   for (walk = specs; *walk; walk++) {
       
   686     spec = *walk;
       
   687     if (width < strlen (spec->name))
       
   688       width = strlen (spec->name);
       
   689   }
       
   690 
       
   691   for (walk = specs; *walk; walk++) {
       
   692     spec = *walk;
       
   693 
       
   694     if (spec->flags & G_PARAM_READABLE) {
       
   695       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
       
   696       g_object_get_property (G_OBJECT (element), spec->name, &value);
       
   697       str = g_strdup_value_contents (&value);
       
   698       g_value_unset (&value);
       
   699     } else {
       
   700       str = g_strdup ("Parameter not readable.");
       
   701     }
       
   702 
       
   703     string_append_indent (buf, indent);
       
   704     g_string_append (buf, spec->name);
       
   705     string_append_indent (buf, 2 + width - strlen (spec->name));
       
   706     g_string_append (buf, str);
       
   707     g_string_append_c (buf, '\n');
       
   708 
       
   709     g_free (str);
       
   710   }
       
   711 
       
   712   g_free (specs);
       
   713 }
       
   714 
       
   715 /**
       
   716  * gst_element_create_all_pads:
       
   717  * @element: a #GstElement to create pads for
       
   718  *
       
   719  * Creates a pad for each pad template that is always available.
       
   720  * This function is only useful during object intialization of
       
   721  * subclasses of #GstElement.
       
   722  */
       
   723 #ifdef __SYMBIAN32__
       
   724 EXPORT_C
       
   725 #endif
       
   726 
       
   727 void
       
   728 gst_element_create_all_pads (GstElement * element)
       
   729 {
       
   730   GList *padlist;
       
   731 
       
   732   /* FIXME: lock element */
       
   733 
       
   734   padlist =
       
   735       gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS
       
   736       (G_OBJECT_GET_CLASS (element)));
       
   737 
       
   738   while (padlist) {
       
   739     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
       
   740 
       
   741     if (padtempl->presence == GST_PAD_ALWAYS) {
       
   742       GstPad *pad;
       
   743 
       
   744       pad = gst_pad_new_from_template (padtempl, padtempl->name_template);
       
   745 
       
   746       gst_element_add_pad (element, pad);
       
   747     }
       
   748     padlist = padlist->next;
       
   749   }
       
   750 }
       
   751 
       
   752 /**
       
   753  * gst_element_get_compatible_pad_template:
       
   754  * @element: a #GstElement to get a compatible pad template for.
       
   755  * @compattempl: the #GstPadTemplate to find a compatible template for.
       
   756  *
       
   757  * Retrieves a pad template from @element that is compatible with @compattempl.
       
   758  * Pads from compatible templates can be linked together.
       
   759  *
       
   760  * Returns: a compatible #GstPadTemplate, or NULL if none was found. No
       
   761  * unreferencing is necessary.
       
   762  */
       
   763 #ifdef __SYMBIAN32__
       
   764 EXPORT_C
       
   765 #endif
       
   766 
       
   767 GstPadTemplate *
       
   768 gst_element_get_compatible_pad_template (GstElement * element,
       
   769     GstPadTemplate * compattempl)
       
   770 {
       
   771   GstPadTemplate *newtempl = NULL;
       
   772   GList *padlist;
       
   773   GstElementClass *class;
       
   774 
       
   775   g_return_val_if_fail (element != NULL, NULL);
       
   776   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   777   g_return_val_if_fail (compattempl != NULL, NULL);
       
   778 
       
   779   class = GST_ELEMENT_GET_CLASS (element);
       
   780 
       
   781   padlist = gst_element_class_get_pad_template_list (class);
       
   782 
       
   783   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
   784       "Looking for a suitable pad template in %s out of %d templates...",
       
   785       GST_ELEMENT_NAME (element), g_list_length (padlist));
       
   786 
       
   787   while (padlist) {
       
   788     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
       
   789     GstCaps *intersection;
       
   790 
       
   791     /* Ignore name
       
   792      * Ignore presence
       
   793      * Check direction (must be opposite)
       
   794      * Check caps
       
   795      */
       
   796     GST_CAT_LOG (GST_CAT_CAPS,
       
   797         "checking pad template %s", padtempl->name_template);
       
   798     if (padtempl->direction != compattempl->direction) {
       
   799       GST_CAT_DEBUG (GST_CAT_CAPS,
       
   800           "compatible direction: found %s pad template \"%s\"",
       
   801           padtempl->direction == GST_PAD_SRC ? "src" : "sink",
       
   802           padtempl->name_template);
       
   803 
       
   804       GST_CAT_DEBUG (GST_CAT_CAPS,
       
   805           "intersecting %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (compattempl));
       
   806       GST_CAT_DEBUG (GST_CAT_CAPS,
       
   807           "..and %" GST_PTR_FORMAT, GST_PAD_TEMPLATE_CAPS (padtempl));
       
   808 
       
   809       intersection = gst_caps_intersect (GST_PAD_TEMPLATE_CAPS (compattempl),
       
   810           GST_PAD_TEMPLATE_CAPS (padtempl));
       
   811 
       
   812       GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible %" GST_PTR_FORMAT,
       
   813           (intersection ? "" : "not "), intersection);
       
   814 
       
   815       if (!gst_caps_is_empty (intersection))
       
   816         newtempl = padtempl;
       
   817       gst_caps_unref (intersection);
       
   818       if (newtempl)
       
   819         break;
       
   820     }
       
   821 
       
   822     padlist = g_list_next (padlist);
       
   823   }
       
   824   if (newtempl)
       
   825     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
   826         "Returning new pad template %p", newtempl);
       
   827   else
       
   828     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "No compatible pad template found");
       
   829 
       
   830   return newtempl;
       
   831 }
       
   832 
       
   833 static GstPad *
       
   834 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
       
   835     const gchar * name)
       
   836 {
       
   837   GstPad *newpad = NULL;
       
   838   GstElementClass *oclass;
       
   839 
       
   840   oclass = GST_ELEMENT_GET_CLASS (element);
       
   841 
       
   842   if (oclass->request_new_pad)
       
   843     newpad = (oclass->request_new_pad) (element, templ, name);
       
   844 
       
   845   if (newpad)
       
   846     gst_object_ref (newpad);
       
   847 
       
   848   return newpad;
       
   849 }
       
   850 
       
   851 
       
   852 
       
   853 /**
       
   854  * gst_element_get_pad_from_template:
       
   855  * @element: a #GstElement.
       
   856  * @templ: a #GstPadTemplate belonging to @element.
       
   857  *
       
   858  * Gets a pad from @element described by @templ. If the presence of @templ is
       
   859  * #GST_PAD_REQUEST, requests a new pad. Can return %NULL for #GST_PAD_SOMETIMES
       
   860  * templates.
       
   861  *
       
   862  * Returns: the #GstPad, or NULL if one could not be found or created.
       
   863  */
       
   864 static GstPad *
       
   865 gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ)
       
   866 {
       
   867   GstPad *ret = NULL;
       
   868   GstPadPresence presence;
       
   869 
       
   870   /* If this function is ever exported, we need check the validity of `element'
       
   871    * and `templ', and to make sure the template actually belongs to the
       
   872    * element. */
       
   873 
       
   874   presence = GST_PAD_TEMPLATE_PRESENCE (templ);
       
   875 
       
   876   switch (presence) {
       
   877     case GST_PAD_ALWAYS:
       
   878     case GST_PAD_SOMETIMES:
       
   879       ret = gst_element_get_static_pad (element, templ->name_template);
       
   880       if (!ret && presence == GST_PAD_ALWAYS)
       
   881         g_warning
       
   882             ("Element %s has an ALWAYS template %s, but no pad of the same name",
       
   883             GST_OBJECT_NAME (element), templ->name_template);
       
   884       break;
       
   885 
       
   886     case GST_PAD_REQUEST:
       
   887       ret = gst_element_request_pad (element, templ, NULL);
       
   888       break;
       
   889   }
       
   890 
       
   891   return ret;
       
   892 }
       
   893 
       
   894 /**
       
   895  * gst_element_request_compatible_pad:
       
   896  * @element: a #GstElement.
       
   897  * @templ: the #GstPadTemplate to which the new pad should be able to link.
       
   898  *
       
   899  * Requests a pad from @element. The returned pad should be unlinked and
       
   900  * compatible with @templ. Might return an existing pad, or request a new one.
       
   901  *
       
   902  * Returns: a #GstPad, or %NULL if one could not be found or created.
       
   903  */
       
   904 #ifdef __SYMBIAN32__
       
   905 EXPORT_C
       
   906 #endif
       
   907 
       
   908 GstPad *
       
   909 gst_element_request_compatible_pad (GstElement * element,
       
   910     GstPadTemplate * templ)
       
   911 {
       
   912   GstPadTemplate *templ_new;
       
   913   GstPad *pad = NULL;
       
   914 
       
   915   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   916   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
       
   917 
       
   918   /* FIXME: should really loop through the templates, testing each for
       
   919    *      compatibility and pad availability. */
       
   920   templ_new = gst_element_get_compatible_pad_template (element, templ);
       
   921   if (templ_new)
       
   922     pad = gst_element_get_pad_from_template (element, templ_new);
       
   923 
       
   924   /* This can happen for non-request pads. No need to unref. */
       
   925   if (pad && GST_PAD_PEER (pad))
       
   926     pad = NULL;
       
   927 
       
   928   return pad;
       
   929 }
       
   930 
       
   931 /**
       
   932  * gst_element_get_compatible_pad:
       
   933  * @element: a #GstElement in which the pad should be found.
       
   934  * @pad: the #GstPad to find a compatible one for.
       
   935  * @caps: the #GstCaps to use as a filter.
       
   936  *
       
   937  * Looks for an unlinked pad to which the given pad can link. It is not
       
   938  * guaranteed that linking the pads will work, though it should work in most
       
   939  * cases.
       
   940  *
       
   941  * Returns: the #GstPad to which a link can be made, or %NULL if one cannot be
       
   942  * found. gst_object_unref() after usage.
       
   943  */
       
   944 #ifdef __SYMBIAN32__
       
   945 EXPORT_C
       
   946 #endif
       
   947 
       
   948 GstPad *
       
   949 gst_element_get_compatible_pad (GstElement * element, GstPad * pad,
       
   950     const GstCaps * caps)
       
   951 {
       
   952   GstIterator *pads;
       
   953   GstPadTemplate *templ;
       
   954   GstCaps *templcaps;
       
   955   GstPad *foundpad = NULL;
       
   956   gboolean done;
       
   957 
       
   958   /* FIXME check for caps compatibility */
       
   959 
       
   960   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   961   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
       
   962 
       
   963   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
   964       "finding pad in %s compatible with %s:%s",
       
   965       GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad));
       
   966 
       
   967   g_return_val_if_fail (GST_PAD_PEER (pad) == NULL, NULL);
       
   968 
       
   969   done = FALSE;
       
   970   /* try to get an existing unlinked pad */
       
   971   pads = gst_element_iterate_pads (element);
       
   972   while (!done) {
       
   973     gpointer padptr;
       
   974 
       
   975     switch (gst_iterator_next (pads, &padptr)) {
       
   976       case GST_ITERATOR_OK:
       
   977       {
       
   978         GstPad *peer;
       
   979         GstPad *current;
       
   980 
       
   981         current = GST_PAD (padptr);
       
   982 
       
   983         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
       
   984             GST_DEBUG_PAD_NAME (current));
       
   985 
       
   986         peer = gst_pad_get_peer (current);
       
   987 
       
   988         if (peer == NULL && gst_pad_can_link (pad, current)) {
       
   989 
       
   990           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
   991               "found existing unlinked pad %s:%s",
       
   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         break;
       
  1005       }
       
  1006       case GST_ITERATOR_DONE:
       
  1007         done = TRUE;
       
  1008         break;
       
  1009       case GST_ITERATOR_RESYNC:
       
  1010         gst_iterator_resync (pads);
       
  1011         break;
       
  1012       case GST_ITERATOR_ERROR:
       
  1013         g_assert_not_reached ();
       
  1014         break;
       
  1015     }
       
  1016   }
       
  1017   gst_iterator_free (pads);
       
  1018 
       
  1019   /* try to create a new one */
       
  1020   /* requesting is a little crazy, we need a template. Let's create one */
       
  1021   templcaps = gst_pad_get_caps (pad);
       
  1022 
       
  1023   templ = gst_pad_template_new ((gchar *) GST_PAD_NAME (pad),
       
  1024       GST_PAD_DIRECTION (pad), GST_PAD_ALWAYS, templcaps);
       
  1025   foundpad = gst_element_request_compatible_pad (element, templ);
       
  1026   gst_object_unref (templ);
       
  1027 
       
  1028   if (foundpad) {
       
  1029     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  1030         "found existing request pad %s:%s", GST_DEBUG_PAD_NAME (foundpad));
       
  1031     return foundpad;
       
  1032   }
       
  1033 
       
  1034   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element,
       
  1035       "Could not find a compatible pad to link to %s:%s",
       
  1036       GST_DEBUG_PAD_NAME (pad));
       
  1037   return NULL;
       
  1038 }
       
  1039 
       
  1040 /**
       
  1041  * gst_element_state_get_name:
       
  1042  * @state: a #GstState to get the name of.
       
  1043  *
       
  1044  * Gets a string representing the given state.
       
  1045  *
       
  1046  * Returns: a string with the name of the state.
       
  1047  */
       
  1048 #ifdef __SYMBIAN32__
       
  1049 EXPORT_C
       
  1050 #endif
       
  1051 
       
  1052 G_CONST_RETURN gchar *
       
  1053 gst_element_state_get_name (GstState state)
       
  1054 {
       
  1055   switch (state) {
       
  1056 #ifdef GST_DEBUG_COLOR
       
  1057     case GST_STATE_VOID_PENDING:
       
  1058       return "VOID_PENDING";
       
  1059     case GST_STATE_NULL:
       
  1060       return "\033[01;34mNULL\033[00m";
       
  1061     case GST_STATE_READY:
       
  1062       return "\033[01;31mREADY\033[00m";
       
  1063     case GST_STATE_PLAYING:
       
  1064       return "\033[01;32mPLAYING\033[00m";
       
  1065     case GST_STATE_PAUSED:
       
  1066       return "\033[01;33mPAUSED\033[00m";
       
  1067     default:
       
  1068       /* This is a memory leak */
       
  1069       return g_strdup_printf ("\033[01;35;41mUNKNOWN!\033[00m(%d)", state);
       
  1070 #else
       
  1071     case GST_STATE_VOID_PENDING:
       
  1072       return "VOID_PENDING";
       
  1073     case GST_STATE_NULL:
       
  1074       return "NULL";
       
  1075     case GST_STATE_READY:
       
  1076       return "READY";
       
  1077     case GST_STATE_PLAYING:
       
  1078       return "PLAYING";
       
  1079     case GST_STATE_PAUSED:
       
  1080       return "PAUSED";
       
  1081     default:
       
  1082       /* This is a memory leak */
       
  1083       return g_strdup_printf ("UNKNOWN!(%d)", state);
       
  1084 #endif
       
  1085   }
       
  1086 }
       
  1087 
       
  1088 /**
       
  1089  * gst_element_state_change_return_get_name:
       
  1090  * @state_ret: a #GstStateChangeReturn to get the name of.
       
  1091  *
       
  1092  * Gets a string representing the given state change result.
       
  1093  *
       
  1094  * Returns: a string with the name of the state change result.
       
  1095  *
       
  1096  * Since: 0.10.11
       
  1097  */
       
  1098 #ifdef __SYMBIAN32__
       
  1099 EXPORT_C
       
  1100 #endif
       
  1101 
       
  1102 G_CONST_RETURN gchar *
       
  1103 gst_element_state_change_return_get_name (GstStateChangeReturn state_ret)
       
  1104 {
       
  1105   switch (state_ret) {
       
  1106 #ifdef GST_DEBUG_COLOR
       
  1107     case GST_STATE_CHANGE_FAILURE:
       
  1108       return "\033[01;31mFAILURE\033[00m";
       
  1109     case GST_STATE_CHANGE_SUCCESS:
       
  1110       return "\033[01;32mSUCCESS\033[00m";
       
  1111     case GST_STATE_CHANGE_ASYNC:
       
  1112       return "\033[01;33mASYNC\033[00m";
       
  1113     case GST_STATE_CHANGE_NO_PREROLL:
       
  1114       return "\033[01;34mNO_PREROLL\033[00m";
       
  1115     default:
       
  1116       /* This is a memory leak */
       
  1117       return g_strdup_printf ("\033[01;35;41mUNKNOWN!\033[00m(%d)", state_ret);
       
  1118 #else
       
  1119     case GST_STATE_CHANGE_FAILURE:
       
  1120       return "FAILURE";
       
  1121     case GST_STATE_CHANGE_SUCCESS:
       
  1122       return "SUCCESS";
       
  1123     case GST_STATE_CHANGE_ASYNC:
       
  1124       return "ASYNC";
       
  1125     case GST_STATE_CHANGE_NO_PREROLL:
       
  1126       return "NO PREROLL";
       
  1127     default:
       
  1128       /* This is a memory leak */
       
  1129       return g_strdup_printf ("UNKNOWN!(%d)", state_ret);
       
  1130 #endif
       
  1131   }
       
  1132 }
       
  1133 
       
  1134 
       
  1135 /**
       
  1136  * gst_element_factory_can_src_caps :
       
  1137  * @factory: factory to query
       
  1138  * @caps: the caps to check
       
  1139  *
       
  1140  * Checks if the factory can source the given capability.
       
  1141  *
       
  1142  * Returns: true if it can src the capabilities
       
  1143  */
       
  1144 #ifdef __SYMBIAN32__
       
  1145 EXPORT_C
       
  1146 #endif
       
  1147 
       
  1148 gboolean
       
  1149 gst_element_factory_can_src_caps (GstElementFactory * factory,
       
  1150     const GstCaps * caps)
       
  1151 {
       
  1152   GList *templates;
       
  1153 
       
  1154   g_return_val_if_fail (factory != NULL, FALSE);
       
  1155   g_return_val_if_fail (caps != NULL, FALSE);
       
  1156 
       
  1157   templates = factory->staticpadtemplates;
       
  1158 
       
  1159   while (templates) {
       
  1160     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
       
  1161 
       
  1162     if (template->direction == GST_PAD_SRC) {
       
  1163       if (gst_caps_is_always_compatible (gst_static_caps_get (&template->
       
  1164                   static_caps), caps))
       
  1165         return TRUE;
       
  1166     }
       
  1167     templates = g_list_next (templates);
       
  1168   }
       
  1169 
       
  1170   return FALSE;
       
  1171 }
       
  1172 
       
  1173 /**
       
  1174  * gst_element_factory_can_sink_caps :
       
  1175  * @factory: factory to query
       
  1176  * @caps: the caps to check
       
  1177  *
       
  1178  * Checks if the factory can sink the given capability.
       
  1179  *
       
  1180  * Returns: true if it can sink the capabilities
       
  1181  */
       
  1182 #ifdef __SYMBIAN32__
       
  1183 EXPORT_C
       
  1184 #endif
       
  1185 
       
  1186 gboolean
       
  1187 gst_element_factory_can_sink_caps (GstElementFactory * factory,
       
  1188     const GstCaps * caps)
       
  1189 {
       
  1190   GList *templates;
       
  1191 
       
  1192   g_return_val_if_fail (factory != NULL, FALSE);
       
  1193   g_return_val_if_fail (caps != NULL, FALSE);
       
  1194 
       
  1195   templates = factory->staticpadtemplates;
       
  1196 
       
  1197   while (templates) {
       
  1198     GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
       
  1199 
       
  1200     if (template->direction == GST_PAD_SINK) {
       
  1201       if (gst_caps_is_always_compatible (caps,
       
  1202               gst_static_caps_get (&template->static_caps)))
       
  1203         return TRUE;
       
  1204     }
       
  1205     templates = g_list_next (templates);
       
  1206   }
       
  1207 
       
  1208   return FALSE;
       
  1209 }
       
  1210 
       
  1211 
       
  1212 /* if return val is true, *direct_child is a caller-owned ref on the direct
       
  1213  * child of ancestor that is part of object's ancestry */
       
  1214 static gboolean
       
  1215 object_has_ancestor (GstObject * object, GstObject * ancestor,
       
  1216     GstObject ** direct_child)
       
  1217 {
       
  1218   GstObject *child, *parent;
       
  1219 
       
  1220   if (direct_child)
       
  1221     *direct_child = NULL;
       
  1222 
       
  1223   child = gst_object_ref (object);
       
  1224   parent = gst_object_get_parent (object);
       
  1225 
       
  1226   while (parent) {
       
  1227     if (ancestor == parent) {
       
  1228       if (direct_child)
       
  1229         *direct_child = child;
       
  1230       else
       
  1231         gst_object_unref (child);
       
  1232       gst_object_unref (parent);
       
  1233       return TRUE;
       
  1234     }
       
  1235 
       
  1236     gst_object_unref (child);
       
  1237     child = parent;
       
  1238     parent = gst_object_get_parent (parent);
       
  1239   }
       
  1240 
       
  1241   gst_object_unref (child);
       
  1242 
       
  1243   return FALSE;
       
  1244 }
       
  1245 
       
  1246 /* caller owns return */
       
  1247 static GstObject *
       
  1248 find_common_root (GstObject * o1, GstObject * o2)
       
  1249 {
       
  1250   GstObject *top = o1;
       
  1251   GstObject *kid1, *kid2;
       
  1252   GstObject *root = NULL;
       
  1253 
       
  1254   while (GST_OBJECT_PARENT (top))
       
  1255     top = GST_OBJECT_PARENT (top);
       
  1256 
       
  1257   /* the itsy-bitsy spider... */
       
  1258 
       
  1259   if (!object_has_ancestor (o2, top, &kid2))
       
  1260     return NULL;
       
  1261 
       
  1262   root = gst_object_ref (top);
       
  1263   while (TRUE) {
       
  1264     if (!object_has_ancestor (o1, kid2, &kid1)) {
       
  1265       gst_object_unref (kid2);
       
  1266       return root;
       
  1267     }
       
  1268     root = kid2;
       
  1269     if (!object_has_ancestor (o2, kid1, &kid2)) {
       
  1270       gst_object_unref (kid1);
       
  1271       return root;
       
  1272     }
       
  1273     root = kid1;
       
  1274   }
       
  1275 }
       
  1276 
       
  1277 /* caller does not own return */
       
  1278 static GstPad *
       
  1279 ghost_up (GstElement * e, GstPad * pad)
       
  1280 {
       
  1281   static gint ghost_pad_index = 0;
       
  1282   GstPad *gpad;
       
  1283   gchar *name;
       
  1284   GstObject *parent = GST_OBJECT_PARENT (e);
       
  1285 
       
  1286   name = g_strdup_printf ("ghost%d", ghost_pad_index++);
       
  1287   gpad = gst_ghost_pad_new (name, pad);
       
  1288   g_free (name);
       
  1289 
       
  1290   if (!gst_element_add_pad ((GstElement *) parent, gpad)) {
       
  1291     g_warning ("Pad named %s already exists in element %s\n",
       
  1292         GST_OBJECT_NAME (gpad), GST_OBJECT_NAME (parent));
       
  1293     gst_object_unref ((GstObject *) gpad);
       
  1294     return NULL;
       
  1295   }
       
  1296 
       
  1297   return gpad;
       
  1298 }
       
  1299 
       
  1300 static void
       
  1301 remove_pad (gpointer ppad, gpointer unused)
       
  1302 {
       
  1303   GstPad *pad = ppad;
       
  1304 
       
  1305   if (!gst_element_remove_pad ((GstElement *) GST_OBJECT_PARENT (pad), pad))
       
  1306     g_warning ("Couldn't remove pad %s from element %s",
       
  1307         GST_OBJECT_NAME (pad), GST_OBJECT_NAME (GST_OBJECT_PARENT (pad)));
       
  1308 }
       
  1309 
       
  1310 static gboolean
       
  1311 prepare_link_maybe_ghosting (GstPad ** src, GstPad ** sink,
       
  1312     GSList ** pads_created)
       
  1313 {
       
  1314   GstObject *root;
       
  1315   GstObject *e1, *e2;
       
  1316   GSList *pads_created_local = NULL;
       
  1317 
       
  1318   g_assert (pads_created);
       
  1319 
       
  1320   e1 = GST_OBJECT_PARENT (*src);
       
  1321   e2 = GST_OBJECT_PARENT (*sink);
       
  1322 
       
  1323   if (G_UNLIKELY (e1 == NULL)) {
       
  1324     GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %"
       
  1325         GST_PTR_FORMAT, *src);
       
  1326     return FALSE;
       
  1327   }
       
  1328   if (G_UNLIKELY (e2 == NULL)) {
       
  1329     GST_WARNING ("Trying to ghost a pad that doesn't have a parent: %"
       
  1330         GST_PTR_FORMAT, *sink);
       
  1331     return FALSE;
       
  1332   }
       
  1333 
       
  1334   if (GST_OBJECT_PARENT (e1) == GST_OBJECT_PARENT (e2)) {
       
  1335     GST_CAT_INFO (GST_CAT_PADS, "%s and %s in same bin, no need for ghost pads",
       
  1336         GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
       
  1337     return TRUE;
       
  1338   }
       
  1339 
       
  1340   GST_CAT_INFO (GST_CAT_PADS, "%s and %s not in same bin, making ghost pads",
       
  1341       GST_OBJECT_NAME (e1), GST_OBJECT_NAME (e2));
       
  1342 
       
  1343   /* we need to setup some ghost pads */
       
  1344   root = find_common_root (e1, e2);
       
  1345   if (!root) {
       
  1346     g_warning ("Trying to connect elements that don't share a common "
       
  1347         "ancestor: %s and %s", GST_ELEMENT_NAME (e1), GST_ELEMENT_NAME (e2));
       
  1348     return FALSE;
       
  1349   }
       
  1350 
       
  1351   while (GST_OBJECT_PARENT (e1) != root) {
       
  1352     *src = ghost_up ((GstElement *) e1, *src);
       
  1353     if (!*src)
       
  1354       goto cleanup_fail;
       
  1355     e1 = GST_OBJECT_PARENT (*src);
       
  1356     pads_created_local = g_slist_prepend (pads_created_local, *src);
       
  1357   }
       
  1358   while (GST_OBJECT_PARENT (e2) != root) {
       
  1359     *sink = ghost_up ((GstElement *) e2, *sink);
       
  1360     if (!*sink)
       
  1361       goto cleanup_fail;
       
  1362     e2 = GST_OBJECT_PARENT (*sink);
       
  1363     pads_created_local = g_slist_prepend (pads_created_local, *sink);
       
  1364   }
       
  1365 
       
  1366   gst_object_unref (root);
       
  1367   *pads_created = g_slist_concat (*pads_created, pads_created_local);
       
  1368   return TRUE;
       
  1369 
       
  1370 cleanup_fail:
       
  1371   gst_object_unref (root);
       
  1372   g_slist_foreach (pads_created_local, remove_pad, NULL);
       
  1373   g_slist_free (pads_created_local);
       
  1374   return FALSE;
       
  1375 }
       
  1376 
       
  1377 static gboolean
       
  1378 pad_link_maybe_ghosting (GstPad * src, GstPad * sink)
       
  1379 {
       
  1380   GSList *pads_created = NULL;
       
  1381   gboolean ret;
       
  1382 
       
  1383   if (!prepare_link_maybe_ghosting (&src, &sink, &pads_created)) {
       
  1384     ret = FALSE;
       
  1385   } else {
       
  1386     ret = (gst_pad_link (src, sink) == GST_PAD_LINK_OK);
       
  1387   }
       
  1388 
       
  1389   if (!ret) {
       
  1390     g_slist_foreach (pads_created, remove_pad, NULL);
       
  1391   }
       
  1392   g_slist_free (pads_created);
       
  1393 
       
  1394   return ret;
       
  1395 }
       
  1396 
       
  1397 /**
       
  1398  * gst_element_link_pads:
       
  1399  * @src: a #GstElement containing the source pad.
       
  1400  * @srcpadname: the name of the #GstPad in source element or NULL for any pad.
       
  1401  * @dest: the #GstElement containing the destination pad.
       
  1402  * @destpadname: the name of the #GstPad in destination element,
       
  1403  * or NULL for any pad.
       
  1404  *
       
  1405  * Links the two named pads of the source and destination elements.
       
  1406  * Side effect is that if one of the pads has no parent, it becomes a
       
  1407  * child of the parent of the other element.  If they have different
       
  1408  * parents, the link fails.
       
  1409  *
       
  1410  * Returns: TRUE if the pads could be linked, FALSE otherwise.
       
  1411  */
       
  1412 #ifdef __SYMBIAN32__
       
  1413 EXPORT_C
       
  1414 #endif
       
  1415 
       
  1416 gboolean
       
  1417 gst_element_link_pads (GstElement * src, const gchar * srcpadname,
       
  1418     GstElement * dest, const gchar * destpadname)
       
  1419 {
       
  1420   const GList *srcpads, *destpads, *srctempls, *desttempls, *l;
       
  1421   GstPad *srcpad, *destpad;
       
  1422   GstPadTemplate *srctempl, *desttempl;
       
  1423   GstElementClass *srcclass, *destclass;
       
  1424 
       
  1425   /* checks */
       
  1426   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
       
  1427   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
       
  1428 
       
  1429   srcclass = GST_ELEMENT_GET_CLASS (src);
       
  1430   destclass = GST_ELEMENT_GET_CLASS (dest);
       
  1431 
       
  1432   GST_CAT_INFO (GST_CAT_ELEMENT_PADS,
       
  1433       "trying to link element %s:%s to element %s:%s", GST_ELEMENT_NAME (src),
       
  1434       srcpadname ? srcpadname : "(any)", GST_ELEMENT_NAME (dest),
       
  1435       destpadname ? destpadname : "(any)");
       
  1436 
       
  1437   /* get a src pad */
       
  1438   if (srcpadname) {
       
  1439     /* name specified, look it up */
       
  1440     srcpad = gst_element_get_pad (src, srcpadname);
       
  1441     if (!srcpad) {
       
  1442       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
       
  1443           GST_ELEMENT_NAME (src), srcpadname);
       
  1444       return FALSE;
       
  1445     } else {
       
  1446       if (!(GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC)) {
       
  1447         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no src pad",
       
  1448             GST_DEBUG_PAD_NAME (srcpad));
       
  1449         gst_object_unref (srcpad);
       
  1450         return FALSE;
       
  1451       }
       
  1452       if (GST_PAD_PEER (srcpad) != NULL) {
       
  1453         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
       
  1454             GST_DEBUG_PAD_NAME (srcpad));
       
  1455         gst_object_unref (srcpad);
       
  1456         return FALSE;
       
  1457       }
       
  1458     }
       
  1459     srcpads = NULL;
       
  1460   } else {
       
  1461     /* no name given, get the first available pad */
       
  1462     GST_OBJECT_LOCK (src);
       
  1463     srcpads = GST_ELEMENT_PADS (src);
       
  1464     srcpad = srcpads ? GST_PAD_CAST (srcpads->data) : NULL;
       
  1465     if (srcpad)
       
  1466       gst_object_ref (srcpad);
       
  1467     GST_OBJECT_UNLOCK (src);
       
  1468   }
       
  1469 
       
  1470   /* get a destination pad */
       
  1471   if (destpadname) {
       
  1472     /* name specified, look it up */
       
  1473     destpad = gst_element_get_pad (dest, destpadname);
       
  1474     if (!destpad) {
       
  1475       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no pad %s:%s",
       
  1476           GST_ELEMENT_NAME (dest), destpadname);
       
  1477       return FALSE;
       
  1478     } else {
       
  1479       if (!(GST_PAD_DIRECTION (destpad) == GST_PAD_SINK)) {
       
  1480         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is no sink pad",
       
  1481             GST_DEBUG_PAD_NAME (destpad));
       
  1482         gst_object_unref (destpad);
       
  1483         return FALSE;
       
  1484       }
       
  1485       if (GST_PAD_PEER (destpad) != NULL) {
       
  1486         GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is already linked",
       
  1487             GST_DEBUG_PAD_NAME (destpad));
       
  1488         gst_object_unref (destpad);
       
  1489         return FALSE;
       
  1490       }
       
  1491     }
       
  1492     destpads = NULL;
       
  1493   } else {
       
  1494     /* no name given, get the first available pad */
       
  1495     GST_OBJECT_LOCK (dest);
       
  1496     destpads = GST_ELEMENT_PADS (dest);
       
  1497     destpad = destpads ? GST_PAD_CAST (destpads->data) : NULL;
       
  1498     if (destpad)
       
  1499       gst_object_ref (destpad);
       
  1500     GST_OBJECT_UNLOCK (dest);
       
  1501   }
       
  1502 
       
  1503   if (srcpadname && destpadname) {
       
  1504     gboolean result;
       
  1505 
       
  1506     /* two explicitly specified pads */
       
  1507     result = pad_link_maybe_ghosting (srcpad, destpad);
       
  1508 
       
  1509     gst_object_unref (srcpad);
       
  1510     gst_object_unref (destpad);
       
  1511 
       
  1512     return result;
       
  1513   }
       
  1514 
       
  1515   if (srcpad) {
       
  1516     /* loop through the allowed pads in the source, trying to find a
       
  1517      * compatible destination pad */
       
  1518     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  1519         "looping through allowed src and dest pads");
       
  1520     do {
       
  1521       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying src pad %s:%s",
       
  1522           GST_DEBUG_PAD_NAME (srcpad));
       
  1523       if ((GST_PAD_DIRECTION (srcpad) == GST_PAD_SRC) &&
       
  1524           (GST_PAD_PEER (srcpad) == NULL)) {
       
  1525         GstPad *temp;
       
  1526 
       
  1527         if (destpadname) {
       
  1528           temp = destpad;
       
  1529           gst_object_ref (temp);
       
  1530         } else {
       
  1531           temp = gst_element_get_compatible_pad (dest, srcpad, NULL);
       
  1532         }
       
  1533 
       
  1534         if (temp && pad_link_maybe_ghosting (srcpad, temp)) {
       
  1535           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
       
  1536               GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (temp));
       
  1537           if (destpad)
       
  1538             gst_object_unref (destpad);
       
  1539           gst_object_unref (srcpad);
       
  1540           gst_object_unref (temp);
       
  1541           return TRUE;
       
  1542         }
       
  1543 
       
  1544         if (temp) {
       
  1545           gst_object_unref (temp);
       
  1546         }
       
  1547       }
       
  1548       /* find a better way for this mess */
       
  1549       if (srcpads) {
       
  1550         srcpads = g_list_next (srcpads);
       
  1551         if (srcpads) {
       
  1552           gst_object_unref (srcpad);
       
  1553           srcpad = GST_PAD_CAST (srcpads->data);
       
  1554           gst_object_ref (srcpad);
       
  1555         }
       
  1556       }
       
  1557     } while (srcpads);
       
  1558   }
       
  1559   if (srcpadname) {
       
  1560     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s:%s to %s",
       
  1561         GST_DEBUG_PAD_NAME (srcpad), GST_ELEMENT_NAME (dest));
       
  1562     if (destpad)
       
  1563       gst_object_unref (destpad);
       
  1564     destpad = NULL;
       
  1565   }
       
  1566   if (srcpad)
       
  1567     gst_object_unref (srcpad);
       
  1568   srcpad = NULL;
       
  1569 
       
  1570   if (destpad) {
       
  1571     /* loop through the existing pads in the destination */
       
  1572     do {
       
  1573       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "trying dest pad %s:%s",
       
  1574           GST_DEBUG_PAD_NAME (destpad));
       
  1575       if ((GST_PAD_DIRECTION (destpad) == GST_PAD_SINK) &&
       
  1576           (GST_PAD_PEER (destpad) == NULL)) {
       
  1577         GstPad *temp = gst_element_get_compatible_pad (src, destpad, NULL);
       
  1578 
       
  1579         if (temp && pad_link_maybe_ghosting (temp, destpad)) {
       
  1580           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "linked pad %s:%s to pad %s:%s",
       
  1581               GST_DEBUG_PAD_NAME (temp), GST_DEBUG_PAD_NAME (destpad));
       
  1582           gst_object_unref (temp);
       
  1583           gst_object_unref (destpad);
       
  1584           return TRUE;
       
  1585         }
       
  1586         if (temp) {
       
  1587           gst_object_unref (temp);
       
  1588         }
       
  1589       }
       
  1590       if (destpads) {
       
  1591         destpads = g_list_next (destpads);
       
  1592         if (destpads) {
       
  1593           gst_object_unref (destpad);
       
  1594           destpad = GST_PAD_CAST (destpads->data);
       
  1595           gst_object_ref (destpad);
       
  1596         }
       
  1597       }
       
  1598     } while (destpads);
       
  1599   }
       
  1600 
       
  1601   if (destpadname) {
       
  1602     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s:%s",
       
  1603         GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME (destpad));
       
  1604     gst_object_unref (destpad);
       
  1605     return FALSE;
       
  1606   } else {
       
  1607     if (destpad)
       
  1608       gst_object_unref (destpad);
       
  1609     destpad = NULL;
       
  1610   }
       
  1611 
       
  1612   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  1613       "we might have request pads on both sides, checking...");
       
  1614   srctempls = gst_element_class_get_pad_template_list (srcclass);
       
  1615   desttempls = gst_element_class_get_pad_template_list (destclass);
       
  1616 
       
  1617   if (srctempls && desttempls) {
       
  1618     while (srctempls) {
       
  1619       srctempl = (GstPadTemplate *) srctempls->data;
       
  1620       if (srctempl->presence == GST_PAD_REQUEST) {
       
  1621         for (l = desttempls; l; l = l->next) {
       
  1622           desttempl = (GstPadTemplate *) l->data;
       
  1623           if (desttempl->presence == GST_PAD_REQUEST &&
       
  1624               desttempl->direction != srctempl->direction) {
       
  1625             if (gst_caps_is_always_compatible (gst_pad_template_get_caps
       
  1626                     (srctempl), gst_pad_template_get_caps (desttempl))) {
       
  1627               srcpad =
       
  1628                   gst_element_get_request_pad (src, srctempl->name_template);
       
  1629               destpad =
       
  1630                   gst_element_get_request_pad (dest, desttempl->name_template);
       
  1631               if (srcpad && destpad
       
  1632                   && pad_link_maybe_ghosting (srcpad, destpad)) {
       
  1633                 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  1634                     "linked pad %s:%s to pad %s:%s",
       
  1635                     GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad));
       
  1636                 gst_object_unref (srcpad);
       
  1637                 gst_object_unref (destpad);
       
  1638                 return TRUE;
       
  1639               }
       
  1640               /* it failed, so we release the request pads */
       
  1641               if (srcpad)
       
  1642                 gst_element_release_request_pad (src, srcpad);
       
  1643               if (destpad)
       
  1644                 gst_element_release_request_pad (dest, destpad);
       
  1645             }
       
  1646           }
       
  1647         }
       
  1648       }
       
  1649       srctempls = srctempls->next;
       
  1650     }
       
  1651   }
       
  1652 
       
  1653   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "no link possible from %s to %s",
       
  1654       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
       
  1655   return FALSE;
       
  1656 }
       
  1657 
       
  1658 /**
       
  1659  * gst_element_link_pads_filtered:
       
  1660  * @src: a #GstElement containing the source pad.
       
  1661  * @srcpadname: the name of the #GstPad in source element or NULL for any pad.
       
  1662  * @dest: the #GstElement containing the destination pad.
       
  1663  * @destpadname: the name of the #GstPad in destination element or NULL for any pad.
       
  1664  * @filter: the #GstCaps to filter the link, or #NULL for no filter.
       
  1665  *
       
  1666  * Links the two named pads of the source and destination elements. Side effect
       
  1667  * is that if one of the pads has no parent, it becomes a child of the parent of
       
  1668  * the other element. If they have different parents, the link fails. If @caps
       
  1669  * is not #NULL, makes sure that the caps of the link is a subset of @caps.
       
  1670  *
       
  1671  * Returns: TRUE if the pads could be linked, FALSE otherwise.
       
  1672  */
       
  1673 #ifdef __SYMBIAN32__
       
  1674 EXPORT_C
       
  1675 #endif
       
  1676 
       
  1677 gboolean
       
  1678 gst_element_link_pads_filtered (GstElement * src, const gchar * srcpadname,
       
  1679     GstElement * dest, const gchar * destpadname, GstCaps * filter)
       
  1680 {
       
  1681   /* checks */
       
  1682   g_return_val_if_fail (GST_IS_ELEMENT (src), FALSE);
       
  1683   g_return_val_if_fail (GST_IS_ELEMENT (dest), FALSE);
       
  1684   g_return_val_if_fail (filter == NULL || GST_IS_CAPS (filter), FALSE);
       
  1685 
       
  1686   if (filter) {
       
  1687     GstElement *capsfilter;
       
  1688     GstObject *parent;
       
  1689     GstState state, pending;
       
  1690 
       
  1691     capsfilter = gst_element_factory_make ("capsfilter", NULL);
       
  1692     if (!capsfilter) {
       
  1693       GST_ERROR ("Could not make a capsfilter");
       
  1694       return FALSE;
       
  1695     }
       
  1696 
       
  1697     parent = gst_object_get_parent (GST_OBJECT (src));
       
  1698     g_return_val_if_fail (GST_IS_BIN (parent), FALSE);
       
  1699 
       
  1700     gst_element_get_state (GST_ELEMENT_CAST (parent), &state, &pending, 0);
       
  1701 
       
  1702     if (!gst_bin_add (GST_BIN (parent), capsfilter)) {
       
  1703       GST_ERROR ("Could not add capsfilter");
       
  1704       gst_object_unref (capsfilter);
       
  1705       gst_object_unref (parent);
       
  1706       return FALSE;
       
  1707     }
       
  1708 
       
  1709     if (pending != GST_STATE_VOID_PENDING)
       
  1710       state = pending;
       
  1711 
       
  1712     gst_element_set_state (capsfilter, state);
       
  1713 
       
  1714     gst_object_unref (parent);
       
  1715 
       
  1716     g_object_set (capsfilter, "caps", filter, NULL);
       
  1717 
       
  1718     if (gst_element_link_pads (src, srcpadname, capsfilter, "sink")
       
  1719         && gst_element_link_pads (capsfilter, "src", dest, destpadname)) {
       
  1720       return TRUE;
       
  1721     } else {
       
  1722       GST_INFO ("Could not link elements");
       
  1723       gst_element_set_state (capsfilter, GST_STATE_NULL);
       
  1724       /* this will unlink and unref as appropriate */
       
  1725       gst_bin_remove (GST_BIN (GST_OBJECT_PARENT (capsfilter)), capsfilter);
       
  1726       return FALSE;
       
  1727     }
       
  1728   } else {
       
  1729     return gst_element_link_pads (src, srcpadname, dest, destpadname);
       
  1730   }
       
  1731 }
       
  1732 
       
  1733 /**
       
  1734  * gst_element_link:
       
  1735  * @src: a #GstElement containing the source pad.
       
  1736  * @dest: the #GstElement containing the destination pad.
       
  1737  *
       
  1738  * Links @src to @dest. The link must be from source to
       
  1739  * destination; the other direction will not be tried. The function looks for
       
  1740  * existing pads that aren't linked yet. It will request new pads if necessary.
       
  1741  * Such pads need to be released manualy when unlinking.
       
  1742  * If multiple links are possible, only one is established.
       
  1743  *
       
  1744  * Make sure you have added your elements to a bin or pipeline with
       
  1745  * gst_bin_add() before trying to link them.
       
  1746  *
       
  1747  * Returns: TRUE if the elements could be linked, FALSE otherwise.
       
  1748  */
       
  1749 #ifdef __SYMBIAN32__
       
  1750 EXPORT_C
       
  1751 #endif
       
  1752 
       
  1753 gboolean
       
  1754 gst_element_link (GstElement * src, GstElement * dest)
       
  1755 {
       
  1756   return gst_element_link_pads_filtered (src, NULL, dest, NULL, NULL);
       
  1757 }
       
  1758 
       
  1759 /**
       
  1760  * gst_element_link_many:
       
  1761  * @element_1: the first #GstElement in the link chain.
       
  1762  * @element_2: the second #GstElement in the link chain.
       
  1763  * @...: the NULL-terminated list of elements to link in order.
       
  1764  *
       
  1765  * Chain together a series of elements. Uses gst_element_link().
       
  1766  * Make sure you have added your elements to a bin or pipeline with
       
  1767  * gst_bin_add() before trying to link them.
       
  1768  *
       
  1769  * Returns: TRUE on success, FALSE otherwise.
       
  1770  */
       
  1771 #ifdef __SYMBIAN32__
       
  1772 EXPORT_C
       
  1773 #endif
       
  1774 
       
  1775 gboolean
       
  1776 gst_element_link_many (GstElement * element_1, GstElement * element_2, ...)
       
  1777 {
       
  1778   va_list args;
       
  1779 
       
  1780   g_return_val_if_fail (GST_IS_ELEMENT (element_1), FALSE);
       
  1781   g_return_val_if_fail (GST_IS_ELEMENT (element_2), FALSE);
       
  1782 
       
  1783   va_start (args, element_2);
       
  1784 
       
  1785   while (element_2) {
       
  1786     if (!gst_element_link (element_1, element_2))
       
  1787       return FALSE;
       
  1788 
       
  1789     element_1 = element_2;
       
  1790     element_2 = va_arg (args, GstElement *);
       
  1791   }
       
  1792 
       
  1793   va_end (args);
       
  1794 
       
  1795   return TRUE;
       
  1796 }
       
  1797 
       
  1798 /**
       
  1799  * gst_element_link_filtered:
       
  1800  * @src: a #GstElement containing the source pad.
       
  1801  * @dest: the #GstElement containing the destination pad.
       
  1802  * @filter: the #GstCaps to filter the link, or #NULL for no filter.
       
  1803  *
       
  1804  * Links @src to @dest using the given caps as filtercaps.
       
  1805  * The link must be from source to
       
  1806  * destination; the other direction will not be tried. The function looks for
       
  1807  * existing pads that aren't linked yet. It will request new pads if necessary.
       
  1808  * If multiple links are possible, only one is established.
       
  1809  *
       
  1810  * Make sure you have added your elements to a bin or pipeline with
       
  1811  * gst_bin_add() before trying to link them.
       
  1812  *
       
  1813  * Returns: TRUE if the pads could be linked, FALSE otherwise.
       
  1814  */
       
  1815 #ifdef __SYMBIAN32__
       
  1816 EXPORT_C
       
  1817 #endif
       
  1818 
       
  1819 gboolean
       
  1820 gst_element_link_filtered (GstElement * src, GstElement * dest,
       
  1821     GstCaps * filter)
       
  1822 {
       
  1823   return gst_element_link_pads_filtered (src, NULL, dest, NULL, filter);
       
  1824 }
       
  1825 
       
  1826 /**
       
  1827  * gst_element_unlink_pads:
       
  1828  * @src: a #GstElement containing the source pad.
       
  1829  * @srcpadname: the name of the #GstPad in source element.
       
  1830  * @dest: a #GstElement containing the destination pad.
       
  1831  * @destpadname: the name of the #GstPad in destination element.
       
  1832  *
       
  1833  * Unlinks the two named pads of the source and destination elements.
       
  1834  */
       
  1835 #ifdef __SYMBIAN32__
       
  1836 EXPORT_C
       
  1837 #endif
       
  1838 
       
  1839 void
       
  1840 gst_element_unlink_pads (GstElement * src, const gchar * srcpadname,
       
  1841     GstElement * dest, const gchar * destpadname)
       
  1842 {
       
  1843   GstPad *srcpad, *destpad;
       
  1844 
       
  1845   g_return_if_fail (src != NULL);
       
  1846   g_return_if_fail (GST_IS_ELEMENT (src));
       
  1847   g_return_if_fail (srcpadname != NULL);
       
  1848   g_return_if_fail (dest != NULL);
       
  1849   g_return_if_fail (GST_IS_ELEMENT (dest));
       
  1850   g_return_if_fail (destpadname != NULL);
       
  1851 
       
  1852   /* obtain the pads requested */
       
  1853   srcpad = gst_element_get_pad (src, srcpadname);
       
  1854   if (srcpad == NULL) {
       
  1855     GST_WARNING_OBJECT (src, "source element has no pad \"%s\"", srcpadname);
       
  1856     return;
       
  1857   }
       
  1858   destpad = gst_element_get_pad (dest, destpadname);
       
  1859   if (destpad == NULL) {
       
  1860     GST_WARNING_OBJECT (dest, "destination element has no pad \"%s\"",
       
  1861         destpadname);
       
  1862     gst_object_unref (srcpad);
       
  1863     return;
       
  1864   }
       
  1865 
       
  1866   /* we're satisified they can be unlinked, let's do it */
       
  1867   gst_pad_unlink (srcpad, destpad);
       
  1868   gst_object_unref (srcpad);
       
  1869   gst_object_unref (destpad);
       
  1870 }
       
  1871 
       
  1872 /**
       
  1873  * gst_element_unlink_many:
       
  1874  * @element_1: the first #GstElement in the link chain.
       
  1875  * @element_2: the second #GstElement in the link chain.
       
  1876  * @...: the NULL-terminated list of elements to unlink in order.
       
  1877  *
       
  1878  * Unlinks a series of elements. Uses gst_element_unlink().
       
  1879  */
       
  1880 #ifdef __SYMBIAN32__
       
  1881 EXPORT_C
       
  1882 #endif
       
  1883 
       
  1884 void
       
  1885 gst_element_unlink_many (GstElement * element_1, GstElement * element_2, ...)
       
  1886 {
       
  1887   va_list args;
       
  1888 
       
  1889   g_return_if_fail (element_1 != NULL && element_2 != NULL);
       
  1890   g_return_if_fail (GST_IS_ELEMENT (element_1) && GST_IS_ELEMENT (element_2));
       
  1891 
       
  1892   va_start (args, element_2);
       
  1893 
       
  1894   while (element_2) {
       
  1895     gst_element_unlink (element_1, element_2);
       
  1896 
       
  1897     element_1 = element_2;
       
  1898     element_2 = va_arg (args, GstElement *);
       
  1899   }
       
  1900 
       
  1901   va_end (args);
       
  1902 }
       
  1903 
       
  1904 /**
       
  1905  * gst_element_unlink:
       
  1906  * @src: the source #GstElement to unlink.
       
  1907  * @dest: the sink #GstElement to unlink.
       
  1908  *
       
  1909  * Unlinks all source pads of the source element with all sink pads
       
  1910  * of the sink element to which they are linked.
       
  1911  *
       
  1912  * If the link has been made using gst_element_link(), it could have created an
       
  1913  * requestpad, which has to be released using gst_element_release_request_pad().
       
  1914  */
       
  1915 #ifdef __SYMBIAN32__
       
  1916 EXPORT_C
       
  1917 #endif
       
  1918 
       
  1919 void
       
  1920 gst_element_unlink (GstElement * src, GstElement * dest)
       
  1921 {
       
  1922   GstIterator *pads;
       
  1923   gboolean done = FALSE;
       
  1924 
       
  1925   g_return_if_fail (GST_IS_ELEMENT (src));
       
  1926   g_return_if_fail (GST_IS_ELEMENT (dest));
       
  1927 
       
  1928   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "unlinking \"%s\" and \"%s\"",
       
  1929       GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (dest));
       
  1930 
       
  1931   pads = gst_element_iterate_pads (src);
       
  1932   while (!done) {
       
  1933     gpointer data;
       
  1934 
       
  1935     switch (gst_iterator_next (pads, &data)) {
       
  1936       case GST_ITERATOR_OK:
       
  1937       {
       
  1938         GstPad *pad = GST_PAD_CAST (data);
       
  1939 
       
  1940         if (GST_PAD_IS_SRC (pad)) {
       
  1941           GstPad *peerpad = gst_pad_get_peer (pad);
       
  1942 
       
  1943           /* see if the pad is connected and is really a pad
       
  1944            * of dest */
       
  1945           if (peerpad) {
       
  1946             GstElement *peerelem;
       
  1947 
       
  1948             peerelem = gst_pad_get_parent_element (peerpad);
       
  1949 
       
  1950             if (peerelem == dest) {
       
  1951               gst_pad_unlink (pad, peerpad);
       
  1952             }
       
  1953             if (peerelem)
       
  1954               gst_object_unref (peerelem);
       
  1955 
       
  1956             gst_object_unref (peerpad);
       
  1957           }
       
  1958         }
       
  1959         gst_object_unref (pad);
       
  1960         break;
       
  1961       }
       
  1962       case GST_ITERATOR_RESYNC:
       
  1963         gst_iterator_resync (pads);
       
  1964         break;
       
  1965       case GST_ITERATOR_DONE:
       
  1966         done = TRUE;
       
  1967         break;
       
  1968       default:
       
  1969         g_assert_not_reached ();
       
  1970         break;
       
  1971     }
       
  1972   }
       
  1973   gst_iterator_free (pads);
       
  1974 }
       
  1975 
       
  1976 /**
       
  1977  * gst_element_query_position:
       
  1978  * @element: a #GstElement to invoke the position query on.
       
  1979  * @format: a pointer to the #GstFormat asked for.
       
  1980  *          On return contains the #GstFormat used.
       
  1981  * @cur: A location in which to store the current position, or NULL.
       
  1982  *
       
  1983  * Queries an element for the stream position.
       
  1984  *
       
  1985  * Returns: TRUE if the query could be performed.
       
  1986  */
       
  1987 #ifdef __SYMBIAN32__
       
  1988 EXPORT_C
       
  1989 #endif
       
  1990 
       
  1991 gboolean
       
  1992 gst_element_query_position (GstElement * element, GstFormat * format,
       
  1993     gint64 * cur)
       
  1994 {
       
  1995   GstQuery *query;
       
  1996   gboolean ret;
       
  1997 
       
  1998   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1999   g_return_val_if_fail (format != NULL, FALSE);
       
  2000 
       
  2001   query = gst_query_new_position (*format);
       
  2002   ret = gst_element_query (element, query);
       
  2003 
       
  2004   if (ret)
       
  2005     gst_query_parse_position (query, format, cur);
       
  2006 
       
  2007   gst_query_unref (query);
       
  2008 
       
  2009   return ret;
       
  2010 }
       
  2011 
       
  2012 /**
       
  2013  * gst_element_query_duration:
       
  2014  * @element: a #GstElement to invoke the duration query on.
       
  2015  * @format: a pointer to the #GstFormat asked for.
       
  2016  *          On return contains the #GstFormat used.
       
  2017  * @duration: A location in which to store the total duration, or NULL.
       
  2018  *
       
  2019  * Queries an element for the total stream duration.
       
  2020  *
       
  2021  * Returns: TRUE if the query could be performed.
       
  2022  */
       
  2023 #ifdef __SYMBIAN32__
       
  2024 EXPORT_C
       
  2025 #endif
       
  2026 
       
  2027 gboolean
       
  2028 gst_element_query_duration (GstElement * element, GstFormat * format,
       
  2029     gint64 * duration)
       
  2030 {
       
  2031   GstQuery *query;
       
  2032   gboolean ret;
       
  2033 
       
  2034   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  2035   g_return_val_if_fail (format != NULL, FALSE);
       
  2036 
       
  2037   query = gst_query_new_duration (*format);
       
  2038   ret = gst_element_query (element, query);
       
  2039 
       
  2040   if (ret)
       
  2041     gst_query_parse_duration (query, format, duration);
       
  2042 
       
  2043   gst_query_unref (query);
       
  2044 
       
  2045   return ret;
       
  2046 }
       
  2047 
       
  2048 /**
       
  2049  * gst_element_query_convert:
       
  2050  * @element: a #GstElement to invoke the convert query on.
       
  2051  * @src_format: a #GstFormat to convert from.
       
  2052  * @src_val: a value to convert.
       
  2053  * @dest_format: a pointer to the #GstFormat to convert to.
       
  2054  * @dest_val: a pointer to the result.
       
  2055  *
       
  2056  * Queries an element to convert @src_val in @src_format to @dest_format.
       
  2057  *
       
  2058  * Returns: TRUE if the query could be performed.
       
  2059  */
       
  2060 #ifdef __SYMBIAN32__
       
  2061 EXPORT_C
       
  2062 #endif
       
  2063 
       
  2064 gboolean
       
  2065 gst_element_query_convert (GstElement * element, GstFormat src_format,
       
  2066     gint64 src_val, GstFormat * dest_format, gint64 * dest_val)
       
  2067 {
       
  2068   GstQuery *query;
       
  2069   gboolean ret;
       
  2070 
       
  2071   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  2072   g_return_val_if_fail (dest_format != NULL, FALSE);
       
  2073   g_return_val_if_fail (dest_val != NULL, FALSE);
       
  2074 
       
  2075   if (*dest_format == src_format) {
       
  2076     *dest_val = src_val;
       
  2077     return TRUE;
       
  2078   }
       
  2079 
       
  2080   query = gst_query_new_convert (src_format, src_val, *dest_format);
       
  2081   ret = gst_element_query (element, query);
       
  2082 
       
  2083   if (ret)
       
  2084     gst_query_parse_convert (query, NULL, NULL, dest_format, dest_val);
       
  2085 
       
  2086   gst_query_unref (query);
       
  2087 
       
  2088   return ret;
       
  2089 }
       
  2090 
       
  2091 /**
       
  2092  * gst_element_seek_simple
       
  2093  * @element: a #GstElement to seek on
       
  2094  * @format: a #GstFormat to execute the seek in, such as #GST_FORMAT_TIME
       
  2095  * @seek_flags: seek options; playback applications will usually want to use
       
  2096  *            GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here
       
  2097  * @seek_pos: position to seek to (relative to the start); if you are doing
       
  2098  *            a seek in #GST_FORMAT_TIME this value is in nanoseconds -
       
  2099  *            multiply with #GST_SECOND to convert seconds to nanoseconds or
       
  2100  *            with #GST_MSECOND to convert milliseconds to nanoseconds.
       
  2101  *
       
  2102  * Simple API to perform a seek on the given element, meaning it just seeks
       
  2103  * to the given position relative to the start of the stream. For more complex
       
  2104  * operations like segment seeks (e.g. for looping) or changing the playback
       
  2105  * rate or seeking relative to the last configured playback segment you should
       
  2106  * use gst_element_seek().
       
  2107  *
       
  2108  * In a completely prerolled PAUSED or PLAYING pipeline, seeking is always
       
  2109  * guaranteed to return %TRUE on a seekable media type or %FALSE when the media
       
  2110  * type is certainly not seekable (such as a live stream).
       
  2111  *
       
  2112  * Some elements allow for seeking in the READY state, in this
       
  2113  * case they will store the seek event and execute it when they are put to
       
  2114  * PAUSED. If the element supports seek in READY, it will always return %TRUE when
       
  2115  * it receives the event in the READY state.
       
  2116  *
       
  2117  * Returns: %TRUE if the seek operation succeeded (the seek might not always be
       
  2118  * executed instantly though)
       
  2119  *
       
  2120  * Since: 0.10.7
       
  2121  */
       
  2122 #ifdef __SYMBIAN32__
       
  2123 EXPORT_C
       
  2124 #endif
       
  2125 
       
  2126 gboolean
       
  2127 gst_element_seek_simple (GstElement * element, GstFormat format,
       
  2128     GstSeekFlags seek_flags, gint64 seek_pos)
       
  2129 {
       
  2130   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  2131   g_return_val_if_fail (seek_pos >= 0, FALSE);
       
  2132 
       
  2133   return gst_element_seek (element, 1.0, format, seek_flags,
       
  2134       GST_SEEK_TYPE_SET, seek_pos, GST_SEEK_TYPE_NONE, 0);
       
  2135 }
       
  2136 
       
  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 /**
       
  2202  * gst_pad_use_fixed_caps:
       
  2203  * @pad: the pad to use
       
  2204  *
       
  2205  * A helper function you can use that sets the
       
  2206  * @gst_pad_get_fixed_caps_func as the getcaps function for the
       
  2207  * pad. This way the function will always return the negotiated caps
       
  2208  * or in case the pad is not negotiated, the padtemplate caps.
       
  2209  *
       
  2210  * Use this function on a pad that, once _set_caps() has been called
       
  2211  * on it, cannot be renegotiated to something else.
       
  2212  */
       
  2213 #ifdef __SYMBIAN32__
       
  2214 EXPORT_C
       
  2215 #endif
       
  2216 
       
  2217 void
       
  2218 gst_pad_use_fixed_caps (GstPad * pad)
       
  2219 {
       
  2220   gst_pad_set_getcaps_function (pad, gst_pad_get_fixed_caps_func);
       
  2221 }
       
  2222 
       
  2223 /**
       
  2224  * gst_pad_get_fixed_caps_func:
       
  2225  * @pad: the pad to use
       
  2226  *
       
  2227  * A helper function you can use as a GetCaps function that
       
  2228  * will return the currently negotiated caps or the padtemplate
       
  2229  * when NULL.
       
  2230  *
       
  2231  * Returns: The currently negotiated caps or the padtemplate.
       
  2232  */
       
  2233 #ifdef __SYMBIAN32__
       
  2234 EXPORT_C
       
  2235 #endif
       
  2236 
       
  2237 GstCaps *
       
  2238 gst_pad_get_fixed_caps_func (GstPad * pad)
       
  2239 {
       
  2240   GstCaps *result;
       
  2241 
       
  2242   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
       
  2243 
       
  2244   GST_OBJECT_LOCK (pad);
       
  2245   if (GST_PAD_CAPS (pad)) {
       
  2246     result = GST_PAD_CAPS (pad);
       
  2247 
       
  2248     GST_CAT_DEBUG (GST_CAT_CAPS,
       
  2249         "using pad caps %p %" GST_PTR_FORMAT, result, result);
       
  2250 
       
  2251     result = gst_caps_ref (result);
       
  2252     goto done;
       
  2253   }
       
  2254   if (GST_PAD_PAD_TEMPLATE (pad)) {
       
  2255     GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
       
  2256 
       
  2257     result = GST_PAD_TEMPLATE_CAPS (templ);
       
  2258     GST_CAT_DEBUG (GST_CAT_CAPS,
       
  2259         "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result,
       
  2260         result);
       
  2261 
       
  2262     result = gst_caps_ref (result);
       
  2263     goto done;
       
  2264   }
       
  2265   GST_CAT_DEBUG (GST_CAT_CAPS, "pad has no caps");
       
  2266   result = gst_caps_new_empty ();
       
  2267 
       
  2268 done:
       
  2269   GST_OBJECT_UNLOCK (pad);
       
  2270 
       
  2271   return result;
       
  2272 }
       
  2273 
       
  2274 /**
       
  2275  * gst_pad_get_parent_element:
       
  2276  * @pad: a pad
       
  2277  *
       
  2278  * Gets the parent of @pad, cast to a #GstElement. If a @pad has no parent or
       
  2279  * its parent is not an element, return NULL.
       
  2280  *
       
  2281  * Returns: The parent of the pad. The caller has a reference on the parent, so
       
  2282  * unref when you're finished with it.
       
  2283  *
       
  2284  * MT safe.
       
  2285  */
       
  2286 #ifdef __SYMBIAN32__
       
  2287 EXPORT_C
       
  2288 #endif
       
  2289 
       
  2290 GstElement *
       
  2291 gst_pad_get_parent_element (GstPad * pad)
       
  2292 {
       
  2293   GstObject *p;
       
  2294 
       
  2295   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
       
  2296 
       
  2297   p = gst_object_get_parent (GST_OBJECT_CAST (pad));
       
  2298 
       
  2299   if (p && !GST_IS_ELEMENT (p)) {
       
  2300     gst_object_unref (p);
       
  2301     p = NULL;
       
  2302   }
       
  2303   return GST_ELEMENT_CAST (p);
       
  2304 }
       
  2305 
       
  2306 /**
       
  2307  * gst_object_default_error:
       
  2308  * @source: the #GstObject that initiated the error.
       
  2309  * @error: the GError.
       
  2310  * @debug: an additional debug information string, or NULL.
       
  2311  *
       
  2312  * A default error function.
       
  2313  *
       
  2314  * The default handler will simply print the error string using g_print.
       
  2315  */
       
  2316 #ifdef __SYMBIAN32__
       
  2317 EXPORT_C
       
  2318 #endif
       
  2319 
       
  2320 void
       
  2321 gst_object_default_error (GstObject * source, GError * error, gchar * debug)
       
  2322 {
       
  2323   gchar *name = gst_object_get_path_string (source);
       
  2324 
       
  2325   g_print (_("ERROR: from element %s: %s\n"), name, error->message);
       
  2326   if (debug)
       
  2327     g_print (_("Additional debug info:\n%s\n"), debug);
       
  2328 
       
  2329   g_free (name);
       
  2330 }
       
  2331 
       
  2332 /**
       
  2333  * gst_bin_add_many:
       
  2334  * @bin: a #GstBin
       
  2335  * @element_1: the #GstElement element to add to the bin
       
  2336  * @...: additional elements to add to the bin
       
  2337  *
       
  2338  * Adds a NULL-terminated list of elements to a bin.  This function is
       
  2339  * equivalent to calling gst_bin_add() for each member of the list. The return
       
  2340  * value of each gst_bin_add() is ignored.
       
  2341  */
       
  2342 #ifdef __SYMBIAN32__
       
  2343 EXPORT_C
       
  2344 #endif
       
  2345 
       
  2346 void
       
  2347 gst_bin_add_many (GstBin * bin, GstElement * element_1, ...)
       
  2348 {
       
  2349   va_list args;
       
  2350 
       
  2351   g_return_if_fail (GST_IS_BIN (bin));
       
  2352   g_return_if_fail (GST_IS_ELEMENT (element_1));
       
  2353 
       
  2354   va_start (args, element_1);
       
  2355 
       
  2356   while (element_1) {
       
  2357     gst_bin_add (bin, element_1);
       
  2358 
       
  2359     element_1 = va_arg (args, GstElement *);
       
  2360   }
       
  2361 
       
  2362   va_end (args);
       
  2363 }
       
  2364 
       
  2365 /**
       
  2366  * gst_bin_remove_many:
       
  2367  * @bin: a #GstBin
       
  2368  * @element_1: the first #GstElement to remove from the bin
       
  2369  * @...: NULL-terminated list of elements to remove from the bin
       
  2370  *
       
  2371  * Remove a list of elements from a bin. This function is equivalent
       
  2372  * to calling gst_bin_remove() with each member of the list.
       
  2373  */
       
  2374 #ifdef __SYMBIAN32__
       
  2375 EXPORT_C
       
  2376 #endif
       
  2377 
       
  2378 void
       
  2379 gst_bin_remove_many (GstBin * bin, GstElement * element_1, ...)
       
  2380 {
       
  2381   va_list args;
       
  2382 
       
  2383   g_return_if_fail (GST_IS_BIN (bin));
       
  2384   g_return_if_fail (GST_IS_ELEMENT (element_1));
       
  2385 
       
  2386   va_start (args, element_1);
       
  2387 
       
  2388   while (element_1) {
       
  2389     gst_bin_remove (bin, element_1);
       
  2390 
       
  2391     element_1 = va_arg (args, GstElement *);
       
  2392   }
       
  2393 
       
  2394   va_end (args);
       
  2395 }
       
  2396 
       
  2397 static void
       
  2398 gst_element_populate_std_props (GObjectClass * klass, const gchar * prop_name,
       
  2399     guint arg_id, GParamFlags flags)
       
  2400 {
       
  2401   GQuark prop_id = g_quark_from_string (prop_name);
       
  2402   GParamSpec *pspec;
       
  2403 
       
  2404   static GQuark fd_id = 0;
       
  2405   static GQuark blocksize_id;
       
  2406   static GQuark bytesperread_id;
       
  2407   static GQuark dump_id;
       
  2408   static GQuark filesize_id;
       
  2409   static GQuark mmapsize_id;
       
  2410   static GQuark location_id;
       
  2411   static GQuark offset_id;
       
  2412   static GQuark silent_id;
       
  2413   static GQuark touch_id;
       
  2414 
       
  2415   if (!fd_id) {
       
  2416     fd_id = g_quark_from_static_string ("fd");
       
  2417     blocksize_id = g_quark_from_static_string ("blocksize");
       
  2418     bytesperread_id = g_quark_from_static_string ("bytesperread");
       
  2419     dump_id = g_quark_from_static_string ("dump");
       
  2420     filesize_id = g_quark_from_static_string ("filesize");
       
  2421     mmapsize_id = g_quark_from_static_string ("mmapsize");
       
  2422     location_id = g_quark_from_static_string ("location");
       
  2423     offset_id = g_quark_from_static_string ("offset");
       
  2424     silent_id = g_quark_from_static_string ("silent");
       
  2425     touch_id = g_quark_from_static_string ("touch");
       
  2426   }
       
  2427 
       
  2428   if (prop_id == fd_id) {
       
  2429     pspec = g_param_spec_int ("fd", "File-descriptor",
       
  2430         "File-descriptor for the file being read", 0, G_MAXINT, 0, flags);
       
  2431   } else if (prop_id == blocksize_id) {
       
  2432     pspec = g_param_spec_ulong ("blocksize", "Block Size",
       
  2433         "Block size to read per buffer", 0, G_MAXULONG, 4096, flags);
       
  2434 
       
  2435   } else if (prop_id == bytesperread_id) {
       
  2436     pspec = g_param_spec_int ("bytesperread", "Bytes per read",
       
  2437         "Number of bytes to read per buffer", G_MININT, G_MAXINT, 0, flags);
       
  2438 
       
  2439   } else if (prop_id == dump_id) {
       
  2440     pspec = g_param_spec_boolean ("dump", "Dump",
       
  2441         "Dump bytes to stdout", FALSE, flags);
       
  2442 
       
  2443   } else if (prop_id == filesize_id) {
       
  2444     pspec = g_param_spec_int64 ("filesize", "File Size",
       
  2445         "Size of the file being read", 0, G_MAXINT64, 0, flags);
       
  2446 
       
  2447   } else if (prop_id == mmapsize_id) {
       
  2448     pspec = g_param_spec_ulong ("mmapsize", "mmap() Block Size",
       
  2449         "Size in bytes of mmap()d regions", 0, G_MAXULONG, 4 * 1048576, flags);
       
  2450 
       
  2451   } else if (prop_id == location_id) {
       
  2452     pspec = g_param_spec_string ("location", "File Location",
       
  2453         "Location of the file to read", NULL, flags);
       
  2454 
       
  2455   } else if (prop_id == offset_id) {
       
  2456     pspec = g_param_spec_int64 ("offset", "File Offset",
       
  2457         "Byte offset of current read pointer", 0, G_MAXINT64, 0, flags);
       
  2458 
       
  2459   } else if (prop_id == silent_id) {
       
  2460     pspec = g_param_spec_boolean ("silent", "Silent", "Don't produce events",
       
  2461         FALSE, flags);
       
  2462 
       
  2463   } else if (prop_id == touch_id) {
       
  2464     pspec = g_param_spec_boolean ("touch", "Touch read data",
       
  2465         "Touch data to force disk read before " "push ()", TRUE, flags);
       
  2466   } else {
       
  2467     g_warning ("Unknown - 'standard' property '%s' id %d from klass %s",
       
  2468         prop_name, arg_id, g_type_name (G_OBJECT_CLASS_TYPE (klass)));
       
  2469     pspec = NULL;
       
  2470   }
       
  2471 
       
  2472   if (pspec) {
       
  2473     g_object_class_install_property (klass, arg_id, pspec);
       
  2474   }
       
  2475 }
       
  2476 
       
  2477 /**
       
  2478  * gst_element_class_install_std_props:
       
  2479  * @klass: the #GstElementClass to add the properties to.
       
  2480  * @first_name: the name of the first property.
       
  2481  * in a NULL terminated
       
  2482  * @...: the id and flags of the first property, followed by
       
  2483  * further 'name', 'id', 'flags' triplets and terminated by NULL.
       
  2484  *
       
  2485  * Adds a list of standardized properties with types to the @klass.
       
  2486  * the id is for the property switch in your get_prop method, and
       
  2487  * the flags determine readability / writeability.
       
  2488  **/
       
  2489 #ifdef __SYMBIAN32__
       
  2490 EXPORT_C
       
  2491 #endif
       
  2492 
       
  2493 void
       
  2494 gst_element_class_install_std_props (GstElementClass * klass,
       
  2495     const gchar * first_name, ...)
       
  2496 {
       
  2497   const char *name;
       
  2498 
       
  2499   va_list args;
       
  2500 
       
  2501   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
       
  2502 
       
  2503   va_start (args, first_name);
       
  2504 
       
  2505   name = first_name;
       
  2506 
       
  2507   while (name) {
       
  2508     int arg_id = va_arg (args, int);
       
  2509     int flags = va_arg (args, int);
       
  2510 
       
  2511     gst_element_populate_std_props ((GObjectClass *) klass, name, arg_id,
       
  2512         flags);
       
  2513 
       
  2514     name = va_arg (args, char *);
       
  2515   }
       
  2516 
       
  2517   va_end (args);
       
  2518 }
       
  2519 
       
  2520 
       
  2521 /**
       
  2522  * gst_buffer_merge:
       
  2523  * @buf1: the first source #GstBuffer to merge.
       
  2524  * @buf2: the second source #GstBuffer to merge.
       
  2525  *
       
  2526  * Create a new buffer that is the concatenation of the two source
       
  2527  * buffers.  The original source buffers will not be modified or
       
  2528  * unref'd.  Make sure you unref the source buffers if they are not used
       
  2529  * anymore afterwards.
       
  2530  *
       
  2531  * If the buffers point to contiguous areas of memory, the buffer
       
  2532  * is created without copying the data.
       
  2533  *
       
  2534  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
       
  2535  */
       
  2536 #ifdef __SYMBIAN32__
       
  2537 EXPORT_C
       
  2538 #endif
       
  2539 
       
  2540 GstBuffer *
       
  2541 gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2)
       
  2542 {
       
  2543   GstBuffer *result;
       
  2544 
       
  2545   /* we're just a specific case of the more general gst_buffer_span() */
       
  2546   result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
       
  2547 
       
  2548   return result;
       
  2549 }
       
  2550 
       
  2551 /**
       
  2552  * gst_buffer_join:
       
  2553  * @buf1: the first source #GstBuffer.
       
  2554  * @buf2: the second source #GstBuffer.
       
  2555  *
       
  2556  * Create a new buffer that is the concatenation of the two source
       
  2557  * buffers, and unrefs the original source buffers.
       
  2558  *
       
  2559  * If the buffers point to contiguous areas of memory, the buffer
       
  2560  * is created without copying the data.
       
  2561  *
       
  2562  * Returns: the new #GstBuffer which is the concatenation of the source buffers.
       
  2563  */
       
  2564 #ifdef __SYMBIAN32__
       
  2565 EXPORT_C
       
  2566 #endif
       
  2567 
       
  2568 GstBuffer *
       
  2569 gst_buffer_join (GstBuffer * buf1, GstBuffer * buf2)
       
  2570 {
       
  2571   GstBuffer *result;
       
  2572 
       
  2573   result = gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
       
  2574   gst_buffer_unref (buf1);
       
  2575   gst_buffer_unref (buf2);
       
  2576 
       
  2577   return result;
       
  2578 }
       
  2579 
       
  2580 
       
  2581 /**
       
  2582  * gst_buffer_stamp:
       
  2583  * @dest: buffer to stamp
       
  2584  * @src: buffer to stamp from
       
  2585  *
       
  2586  * Copies additional information (the timestamp, duration, and offset start
       
  2587  * and end) from one buffer to the other.
       
  2588  *
       
  2589  * This function does not copy any buffer flags or caps and is equivalent to
       
  2590  * gst_buffer_copy_metadata(@dest, @src, GST_BUFFER_COPY_TIMESTAMPS).
       
  2591  *
       
  2592  * Deprecated: use gst_buffer_copy_metadata() instead, it provides more
       
  2593  * control.
       
  2594  */
       
  2595 #ifndef GST_REMOVE_DEPRECATED
       
  2596 #ifdef __SYMBIAN32__
       
  2597 EXPORT_C
       
  2598 #endif
       
  2599 void
       
  2600 gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src)
       
  2601 {
       
  2602   gst_buffer_copy_metadata (dest, src, GST_BUFFER_COPY_TIMESTAMPS);
       
  2603 }
       
  2604 #endif /* GST_REMOVE_DEPRECATED */
       
  2605 
       
  2606 static gboolean
       
  2607 intersect_caps_func (GstPad * pad, GValue * ret, GstPad * orig)
       
  2608 {
       
  2609   if (pad != orig) {
       
  2610     GstCaps *peercaps, *existing;
       
  2611 
       
  2612     existing = g_value_get_pointer (ret);
       
  2613     peercaps = gst_pad_peer_get_caps (pad);
       
  2614     if (peercaps == NULL)
       
  2615       peercaps = gst_caps_new_any ();
       
  2616     g_value_set_pointer (ret, gst_caps_intersect (existing, peercaps));
       
  2617     gst_caps_unref (existing);
       
  2618     gst_caps_unref (peercaps);
       
  2619   }
       
  2620   gst_object_unref (pad);
       
  2621   return TRUE;
       
  2622 }
       
  2623 
       
  2624 /**
       
  2625  * gst_pad_proxy_getcaps:
       
  2626  * @pad: a #GstPad to proxy.
       
  2627  *
       
  2628  * Calls gst_pad_get_allowed_caps() for every other pad belonging to the
       
  2629  * same element as @pad, and returns the intersection of the results.
       
  2630  *
       
  2631  * This function is useful as a default getcaps function for an element
       
  2632  * that can handle any stream format, but requires all its pads to have
       
  2633  * the same caps.  Two such elements are tee and aggregator.
       
  2634  *
       
  2635  * Returns: the intersection of the other pads' allowed caps.
       
  2636  */
       
  2637 #ifdef __SYMBIAN32__
       
  2638 EXPORT_C
       
  2639 #endif
       
  2640 
       
  2641 GstCaps *
       
  2642 gst_pad_proxy_getcaps (GstPad * pad)
       
  2643 {
       
  2644   GstElement *element;
       
  2645   GstCaps *caps, *intersected;
       
  2646   GstIterator *iter;
       
  2647   GstIteratorResult res;
       
  2648   GValue ret = { 0, };
       
  2649 
       
  2650   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
       
  2651 
       
  2652   GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
       
  2653 
       
  2654   element = gst_pad_get_parent_element (pad);
       
  2655   if (element == NULL)
       
  2656     return NULL;
       
  2657 
       
  2658   /* value to hold the return, by default it holds ANY, the ref is taken by
       
  2659    * the GValue. */
       
  2660   g_value_init (&ret, G_TYPE_POINTER);
       
  2661   g_value_set_pointer (&ret, gst_caps_new_any ());
       
  2662 
       
  2663   iter = gst_element_iterate_pads (element);
       
  2664   while (1) {
       
  2665     res =
       
  2666         gst_iterator_fold (iter, (GstIteratorFoldFunction) intersect_caps_func,
       
  2667         &ret, pad);
       
  2668     switch (res) {
       
  2669       case GST_ITERATOR_RESYNC:
       
  2670         /* unref any value stored */
       
  2671         if ((caps = g_value_get_pointer (&ret)))
       
  2672           gst_caps_unref (caps);
       
  2673         /* need to reset the result again to ANY */
       
  2674         g_value_set_pointer (&ret, gst_caps_new_any ());
       
  2675         gst_iterator_resync (iter);
       
  2676         break;
       
  2677       case GST_ITERATOR_DONE:
       
  2678         /* all pads iterated, return collected value */
       
  2679         goto done;
       
  2680       default:
       
  2681         /* iterator returned _ERROR or premature end with _OK,
       
  2682          * mark an error and exit */
       
  2683         if ((caps = g_value_get_pointer (&ret)))
       
  2684           gst_caps_unref (caps);
       
  2685         g_value_set_pointer (&ret, NULL);
       
  2686         goto error;
       
  2687     }
       
  2688   }
       
  2689 done:
       
  2690   gst_iterator_free (iter);
       
  2691 
       
  2692   gst_object_unref (element);
       
  2693 
       
  2694   caps = g_value_get_pointer (&ret);
       
  2695   g_value_unset (&ret);
       
  2696 
       
  2697   intersected = gst_caps_intersect (caps, gst_pad_get_pad_template_caps (pad));
       
  2698   gst_caps_unref (caps);
       
  2699 
       
  2700   return intersected;
       
  2701 
       
  2702   /* ERRORS */
       
  2703 error:
       
  2704   {
       
  2705     g_warning ("Pad list returned error on element %s",
       
  2706         GST_ELEMENT_NAME (element));
       
  2707     gst_iterator_free (iter);
       
  2708     gst_object_unref (element);
       
  2709     return NULL;
       
  2710   }
       
  2711 }
       
  2712 
       
  2713 typedef struct
       
  2714 {
       
  2715   GstPad *orig;
       
  2716   GstCaps *caps;
       
  2717 } LinkData;
       
  2718 
       
  2719 static gboolean
       
  2720 link_fold_func (GstPad * pad, GValue * ret, LinkData * data)
       
  2721 {
       
  2722   gboolean success = TRUE;
       
  2723 
       
  2724   if (pad != data->orig) {
       
  2725     success = gst_pad_set_caps (pad, data->caps);
       
  2726     g_value_set_boolean (ret, success);
       
  2727   }
       
  2728   gst_object_unref (pad);
       
  2729 
       
  2730   return success;
       
  2731 }
       
  2732 
       
  2733 /**
       
  2734  * gst_pad_proxy_setcaps
       
  2735  * @pad: a #GstPad to proxy from
       
  2736  * @caps: the #GstCaps to link with
       
  2737  *
       
  2738  * Calls gst_pad_set_caps() for every other pad belonging to the
       
  2739  * same element as @pad.  If gst_pad_set_caps() fails on any pad,
       
  2740  * the proxy setcaps fails. May be used only during negotiation.
       
  2741  *
       
  2742  * Returns: TRUE if sucessful
       
  2743  */
       
  2744 #ifdef __SYMBIAN32__
       
  2745 EXPORT_C
       
  2746 #endif
       
  2747 
       
  2748 gboolean
       
  2749 gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps)
       
  2750 {
       
  2751   GstElement *element;
       
  2752   GstIterator *iter;
       
  2753   GstIteratorResult res;
       
  2754   GValue ret = { 0, };
       
  2755   LinkData data;
       
  2756 
       
  2757   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2758   g_return_val_if_fail (caps != NULL, FALSE);
       
  2759 
       
  2760   GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
       
  2761 
       
  2762   element = gst_pad_get_parent_element (pad);
       
  2763   if (element == NULL)
       
  2764     return FALSE;
       
  2765 
       
  2766   iter = gst_element_iterate_pads (element);
       
  2767 
       
  2768   g_value_init (&ret, G_TYPE_BOOLEAN);
       
  2769   g_value_set_boolean (&ret, TRUE);
       
  2770   data.orig = pad;
       
  2771   data.caps = caps;
       
  2772 
       
  2773   res = gst_iterator_fold (iter, (GstIteratorFoldFunction) link_fold_func,
       
  2774       &ret, &data);
       
  2775   gst_iterator_free (iter);
       
  2776 
       
  2777   if (res != GST_ITERATOR_DONE)
       
  2778     goto pads_changed;
       
  2779 
       
  2780   gst_object_unref (element);
       
  2781 
       
  2782   /* ok not to unset the gvalue */
       
  2783   return g_value_get_boolean (&ret);
       
  2784 
       
  2785   /* ERRORS */
       
  2786 pads_changed:
       
  2787   {
       
  2788     g_warning ("Pad list changed during proxy_pad_link for element %s",
       
  2789         GST_ELEMENT_NAME (element));
       
  2790     gst_object_unref (element);
       
  2791     return FALSE;
       
  2792   }
       
  2793 }
       
  2794 
       
  2795 /**
       
  2796  * gst_pad_query_position:
       
  2797  * @pad: a #GstPad to invoke the position query on.
       
  2798  * @format: a pointer to the #GstFormat asked for.
       
  2799  *          On return contains the #GstFormat used.
       
  2800  * @cur: A location in which to store the current position, or NULL.
       
  2801  *
       
  2802  * Queries a pad for the stream position.
       
  2803  *
       
  2804  * Returns: TRUE if the query could be performed.
       
  2805  */
       
  2806 #ifdef __SYMBIAN32__
       
  2807 EXPORT_C
       
  2808 #endif
       
  2809 
       
  2810 gboolean
       
  2811 gst_pad_query_position (GstPad * pad, GstFormat * format, gint64 * cur)
       
  2812 {
       
  2813   GstQuery *query;
       
  2814   gboolean ret;
       
  2815 
       
  2816   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2817   g_return_val_if_fail (format != NULL, FALSE);
       
  2818 
       
  2819   query = gst_query_new_position (*format);
       
  2820   ret = gst_pad_query (pad, query);
       
  2821 
       
  2822   if (ret)
       
  2823     gst_query_parse_position (query, format, cur);
       
  2824 
       
  2825   gst_query_unref (query);
       
  2826 
       
  2827   return ret;
       
  2828 }
       
  2829 
       
  2830 /**
       
  2831  * gst_pad_query_peer_position:
       
  2832  * @pad: a #GstPad on whose peer to invoke the position query on.
       
  2833  *       Must be a sink pad.
       
  2834  * @format: a pointer to the #GstFormat asked for.
       
  2835  *          On return contains the #GstFormat used.
       
  2836  * @cur: A location in which to store the current position, or NULL.
       
  2837  *
       
  2838  * Queries the peer of a given sink pad for the stream position.
       
  2839  *
       
  2840  * Returns: TRUE if the query could be performed.
       
  2841  */
       
  2842 #ifdef __SYMBIAN32__
       
  2843 EXPORT_C
       
  2844 #endif
       
  2845 
       
  2846 gboolean
       
  2847 gst_pad_query_peer_position (GstPad * pad, GstFormat * format, gint64 * cur)
       
  2848 {
       
  2849   gboolean ret = FALSE;
       
  2850   GstPad *peer;
       
  2851 
       
  2852   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2853   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
       
  2854   g_return_val_if_fail (format != NULL, FALSE);
       
  2855 
       
  2856   peer = gst_pad_get_peer (pad);
       
  2857   if (peer) {
       
  2858     ret = gst_pad_query_position (peer, format, cur);
       
  2859     gst_object_unref (peer);
       
  2860   }
       
  2861 
       
  2862   return ret;
       
  2863 }
       
  2864 
       
  2865 /**
       
  2866  * gst_pad_query_duration:
       
  2867  * @pad: a #GstPad to invoke the duration query on.
       
  2868  * @format: a pointer to the #GstFormat asked for.
       
  2869  *          On return contains the #GstFormat used.
       
  2870  * @duration: A location in which to store the total duration, or NULL.
       
  2871  *
       
  2872  * Queries a pad for the total stream duration.
       
  2873  *
       
  2874  * Returns: TRUE if the query could be performed.
       
  2875  */
       
  2876 #ifdef __SYMBIAN32__
       
  2877 EXPORT_C
       
  2878 #endif
       
  2879 
       
  2880 gboolean
       
  2881 gst_pad_query_duration (GstPad * pad, GstFormat * format, gint64 * duration)
       
  2882 {
       
  2883   GstQuery *query;
       
  2884   gboolean ret;
       
  2885 
       
  2886   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2887   g_return_val_if_fail (format != NULL, FALSE);
       
  2888 
       
  2889   query = gst_query_new_duration (*format);
       
  2890   ret = gst_pad_query (pad, query);
       
  2891 
       
  2892   if (ret)
       
  2893     gst_query_parse_duration (query, format, duration);
       
  2894 
       
  2895   gst_query_unref (query);
       
  2896 
       
  2897   return ret;
       
  2898 }
       
  2899 
       
  2900 /**
       
  2901  * gst_pad_query_peer_duration:
       
  2902  * @pad: a #GstPad on whose peer pad to invoke the duration query on.
       
  2903  *       Must be a sink pad.
       
  2904  * @format: a pointer to the #GstFormat asked for.
       
  2905  *          On return contains the #GstFormat used.
       
  2906  * @duration: A location in which to store the total duration, or NULL.
       
  2907  *
       
  2908  * Queries the peer pad of a given sink pad for the total stream duration.
       
  2909  *
       
  2910  * Returns: TRUE if the query could be performed.
       
  2911  */
       
  2912 #ifdef __SYMBIAN32__
       
  2913 EXPORT_C
       
  2914 #endif
       
  2915 
       
  2916 gboolean
       
  2917 gst_pad_query_peer_duration (GstPad * pad, GstFormat * format,
       
  2918     gint64 * duration)
       
  2919 {
       
  2920   gboolean ret = FALSE;
       
  2921   GstPad *peer;
       
  2922 
       
  2923   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  2924   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
       
  2925   g_return_val_if_fail (format != NULL, FALSE);
       
  2926 
       
  2927   peer = gst_pad_get_peer (pad);
       
  2928   if (peer) {
       
  2929     ret = gst_pad_query_duration (peer, format, duration);
       
  2930     gst_object_unref (peer);
       
  2931   }
       
  2932 
       
  2933   return ret;
       
  2934 }
       
  2935 
       
  2936 /**
       
  2937  * gst_pad_query_convert:
       
  2938  * @pad: a #GstPad to invoke the convert query on.
       
  2939  * @src_format: a #GstFormat to convert from.
       
  2940  * @src_val: a value to convert.
       
  2941  * @dest_format: a pointer to the #GstFormat to convert to.
       
  2942  * @dest_val: a pointer to the result.
       
  2943  *
       
  2944  * Queries a pad to convert @src_val in @src_format to @dest_format.
       
  2945  *
       
  2946  * Returns: TRUE if the query could be performed.
       
  2947  */
       
  2948 #ifdef __SYMBIAN32__
       
  2949 EXPORT_C
       
  2950 #endif
       
  2951 
       
  2952 gboolean
       
  2953 gst_pad_query_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
       
  2954     GstFormat * dest_format, gint64 * dest_val)
       
  2955 {
       
  2956   GstQuery *query;
       
  2957   gboolean ret;
       
  2958 
       
  2959   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);
       
  2962   g_return_val_if_fail (dest_val != NULL, FALSE);
       
  2963 
       
  2964   if (*dest_format == src_format) {
       
  2965     *dest_val = src_val;
       
  2966     return TRUE;
       
  2967   }
       
  2968 
       
  2969   query = gst_query_new_convert (src_format, src_val, *dest_format);
       
  2970   ret = gst_pad_query (pad, query);
       
  2971 
       
  2972   if (ret)
       
  2973     gst_query_parse_convert (query, NULL, NULL, dest_format, dest_val);
       
  2974 
       
  2975   gst_query_unref (query);
       
  2976 
       
  2977   return ret;
       
  2978 }
       
  2979 
       
  2980 /**
       
  2981  * gst_pad_query_peer_convert:
       
  2982  * @pad: a #GstPad, on whose peer pad to invoke the convert query on.
       
  2983  *       Must be a sink pad.
       
  2984  * @src_format: a #GstFormat to convert from.
       
  2985  * @src_val: a value to convert.
       
  2986  * @dest_format: a pointer to the #GstFormat to convert to.
       
  2987  * @dest_val: a pointer to the result.
       
  2988  *
       
  2989  * Queries the peer pad of a given sink pad to convert @src_val in @src_format
       
  2990  * to @dest_format.
       
  2991  *
       
  2992  * Returns: TRUE if the query could be performed.
       
  2993  */
       
  2994 #ifdef __SYMBIAN32__
       
  2995 EXPORT_C
       
  2996 #endif
       
  2997 
       
  2998 gboolean
       
  2999 gst_pad_query_peer_convert (GstPad * pad, GstFormat src_format, gint64 src_val,
       
  3000     GstFormat * dest_format, gint64 * dest_val)
       
  3001 {
       
  3002   gboolean ret = FALSE;
       
  3003   GstPad *peer;
       
  3004 
       
  3005   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
  3006   g_return_val_if_fail (GST_PAD_IS_SINK (pad), FALSE);
       
  3007   g_return_val_if_fail (src_val >= 0, FALSE);
       
  3008   g_return_val_if_fail (dest_format != NULL, FALSE);
       
  3009   g_return_val_if_fail (dest_val != NULL, FALSE);
       
  3010 
       
  3011   peer = gst_pad_get_peer (pad);
       
  3012   if (peer) {
       
  3013     ret = gst_pad_query_convert (peer, src_format, src_val, dest_format,
       
  3014         dest_val);
       
  3015     gst_object_unref (peer);
       
  3016   }
       
  3017 
       
  3018   return ret;
       
  3019 }
       
  3020 
       
  3021 /**
       
  3022  * gst_atomic_int_set:
       
  3023  * @atomic_int: pointer to an atomic integer
       
  3024  * @value: value to set
       
  3025  *
       
  3026  * Unconditionally sets the atomic integer to @value.
       
  3027  */
       
  3028 #ifdef __SYMBIAN32__
       
  3029 EXPORT_C
       
  3030 #endif
       
  3031 
       
  3032 void
       
  3033 gst_atomic_int_set (gint * atomic_int, gint value)
       
  3034 {
       
  3035   int ignore;
       
  3036 
       
  3037   *atomic_int = value;
       
  3038   /* read acts as a memory barrier */
       
  3039   ignore = g_atomic_int_get (atomic_int);
       
  3040 }
       
  3041 
       
  3042 /**
       
  3043  * gst_pad_add_data_probe:
       
  3044  * @pad: pad to add the data probe handler to
       
  3045  * @handler: function to call when data is passed over pad
       
  3046  * @data: data to pass along with the handler
       
  3047  *
       
  3048  * Adds a "data probe" to a pad. This function will be called whenever data
       
  3049  * passes through a pad. In this case data means both events and buffers. The
       
  3050  * probe will be called with the data as an argument, meaning @handler should
       
  3051  * have the same callback signature as the #GstPad::have-data signal.
       
  3052  * Note that the data will have a reference count greater than 1, so it will
       
  3053  * be immutable -- you must not change it.
       
  3054  *
       
  3055  * For source pads, the probe will be called after the blocking function, if any
       
  3056  * (see gst_pad_set_blocked_async()), but before looking up the peer to chain
       
  3057  * to. For sink pads, the probe function will be called before configuring the
       
  3058  * sink with new caps, if any, and before calling the pad's chain function.
       
  3059  *
       
  3060  * Your data probe should return TRUE to let the data continue to flow, or FALSE
       
  3061  * to drop it. Dropping data is rarely useful, but occasionally comes in handy
       
  3062  * with events.
       
  3063  *
       
  3064  * Although probes are implemented internally by connecting @handler to the
       
  3065  * have-data signal on the pad, if you want to remove a probe it is insufficient
       
  3066  * to only call g_signal_handler_disconnect on the returned handler id. To
       
  3067  * remove a probe, use the appropriate function, such as
       
  3068  * gst_pad_remove_data_probe().
       
  3069  *
       
  3070  * Returns: The handler id.
       
  3071  */
       
  3072 #ifdef __SYMBIAN32__
       
  3073 EXPORT_C
       
  3074 #endif
       
  3075 
       
  3076 gulong
       
  3077 gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
       
  3078 {
       
  3079   gulong sigid;
       
  3080 
       
  3081   g_return_val_if_fail (GST_IS_PAD (pad), 0);
       
  3082   g_return_val_if_fail (handler != NULL, 0);
       
  3083 
       
  3084   GST_OBJECT_LOCK (pad);
       
  3085   sigid = g_signal_connect (pad, "have-data", handler, data);
       
  3086   GST_PAD_DO_EVENT_SIGNALS (pad)++;
       
  3087   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
       
  3088   GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes",
       
  3089       GST_DEBUG_PAD_NAME (pad),
       
  3090       GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
       
  3091   GST_OBJECT_UNLOCK (pad);
       
  3092 
       
  3093   return sigid;
       
  3094 }
       
  3095 
       
  3096 /**
       
  3097  * gst_pad_add_event_probe:
       
  3098  * @pad: pad to add the event probe handler to
       
  3099  * @handler: function to call when events are passed over pad
       
  3100  * @data: data to pass along with the handler
       
  3101  *
       
  3102  * Adds a probe that will be called for all events passing through a pad. See
       
  3103  * gst_pad_add_data_probe() for more information.
       
  3104  *
       
  3105  * Returns: The handler id
       
  3106  */
       
  3107 #ifdef __SYMBIAN32__
       
  3108 EXPORT_C
       
  3109 #endif
       
  3110 
       
  3111 gulong
       
  3112 gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
       
  3113 {
       
  3114   gulong sigid;
       
  3115 
       
  3116   g_return_val_if_fail (GST_IS_PAD (pad), 0);
       
  3117   g_return_val_if_fail (handler != NULL, 0);
       
  3118 
       
  3119   GST_OBJECT_LOCK (pad);
       
  3120   sigid = g_signal_connect (pad, "have-data::event", handler, data);
       
  3121   GST_PAD_DO_EVENT_SIGNALS (pad)++;
       
  3122   GST_DEBUG ("adding event probe to pad %s:%s, now %d probes",
       
  3123       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
       
  3124   GST_OBJECT_UNLOCK (pad);
       
  3125 
       
  3126   return sigid;
       
  3127 }
       
  3128 
       
  3129 /**
       
  3130  * gst_pad_add_buffer_probe:
       
  3131  * @pad: pad to add the buffer probe handler to
       
  3132  * @handler: function to call when buffers are passed over pad
       
  3133  * @data: data to pass along with the handler
       
  3134  *
       
  3135  * Adds a probe that will be called for all buffers passing through a pad. See
       
  3136  * gst_pad_add_data_probe() for more information.
       
  3137  *
       
  3138  * Returns: The handler id
       
  3139  */
       
  3140 #ifdef __SYMBIAN32__
       
  3141 EXPORT_C
       
  3142 #endif
       
  3143 
       
  3144 gulong
       
  3145 gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
       
  3146 {
       
  3147   gulong sigid;
       
  3148 
       
  3149   g_return_val_if_fail (GST_IS_PAD (pad), 0);
       
  3150   g_return_val_if_fail (handler != NULL, 0);
       
  3151 
       
  3152   GST_OBJECT_LOCK (pad);
       
  3153   sigid = g_signal_connect (pad, "have-data::buffer", handler, data);
       
  3154   GST_PAD_DO_BUFFER_SIGNALS (pad)++;
       
  3155   GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes",
       
  3156       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
       
  3157   GST_OBJECT_UNLOCK (pad);
       
  3158 
       
  3159   return sigid;
       
  3160 }
       
  3161 
       
  3162 /**
       
  3163  * gst_pad_remove_data_probe:
       
  3164  * @pad: pad to remove the data probe handler from
       
  3165  * @handler_id: handler id returned from gst_pad_add_data_probe
       
  3166  *
       
  3167  * Removes a data probe from @pad.
       
  3168  */
       
  3169 #ifdef __SYMBIAN32__
       
  3170 EXPORT_C
       
  3171 #endif
       
  3172 
       
  3173 void
       
  3174 gst_pad_remove_data_probe (GstPad * pad, guint handler_id)
       
  3175 {
       
  3176   g_return_if_fail (GST_IS_PAD (pad));
       
  3177   g_return_if_fail (handler_id > 0);
       
  3178 
       
  3179   GST_OBJECT_LOCK (pad);
       
  3180   g_signal_handler_disconnect (pad, handler_id);
       
  3181   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
       
  3182   GST_PAD_DO_EVENT_SIGNALS (pad)--;
       
  3183   GST_DEBUG
       
  3184       ("removed data probe from pad %s:%s, now %d event, %d buffer probes",
       
  3185       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
       
  3186       GST_PAD_DO_BUFFER_SIGNALS (pad));
       
  3187   GST_OBJECT_UNLOCK (pad);
       
  3188 
       
  3189 }
       
  3190 
       
  3191 /**
       
  3192  * gst_pad_remove_event_probe:
       
  3193  * @pad: pad to remove the event probe handler from
       
  3194  * @handler_id: handler id returned from gst_pad_add_event_probe
       
  3195  *
       
  3196  * Removes an event probe from @pad.
       
  3197  */
       
  3198 #ifdef __SYMBIAN32__
       
  3199 EXPORT_C
       
  3200 #endif
       
  3201 
       
  3202 void
       
  3203 gst_pad_remove_event_probe (GstPad * pad, guint handler_id)
       
  3204 {
       
  3205   g_return_if_fail (GST_IS_PAD (pad));
       
  3206   g_return_if_fail (handler_id > 0);
       
  3207 
       
  3208   GST_OBJECT_LOCK (pad);
       
  3209   g_signal_handler_disconnect (pad, handler_id);
       
  3210   GST_PAD_DO_EVENT_SIGNALS (pad)--;
       
  3211   GST_DEBUG ("removed event probe from pad %s:%s, now %d event probes",
       
  3212       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
       
  3213   GST_OBJECT_UNLOCK (pad);
       
  3214 }
       
  3215 
       
  3216 /**
       
  3217  * gst_pad_remove_buffer_probe:
       
  3218  * @pad: pad to remove the buffer probe handler from
       
  3219  * @handler_id: handler id returned from gst_pad_add_buffer_probe
       
  3220  *
       
  3221  * Removes a buffer probe from @pad.
       
  3222  */
       
  3223 #ifdef __SYMBIAN32__
       
  3224 EXPORT_C
       
  3225 #endif
       
  3226 
       
  3227 void
       
  3228 gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id)
       
  3229 {
       
  3230   g_return_if_fail (GST_IS_PAD (pad));
       
  3231   g_return_if_fail (handler_id > 0);
       
  3232 
       
  3233   GST_OBJECT_LOCK (pad);
       
  3234   g_signal_handler_disconnect (pad, handler_id);
       
  3235   GST_PAD_DO_BUFFER_SIGNALS (pad)--;
       
  3236   GST_DEBUG ("removed buffer probe from pad %s:%s, now %d buffer probes",
       
  3237       GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
       
  3238   GST_OBJECT_UNLOCK (pad);
       
  3239 
       
  3240 }
       
  3241 
       
  3242 /**
       
  3243  * gst_element_found_tags_for_pad:
       
  3244  * @element: element for which to post taglist to bus.
       
  3245  * @pad: pad on which to push tag-event.
       
  3246  * @list: the taglist to post on the bus and create event from.
       
  3247  *
       
  3248  * Posts a message to the bus that new tags were found and pushes the
       
  3249  * tags as event. Takes ownership of the @list.
       
  3250  *
       
  3251  * This is a utility method for elements. Applications should use the
       
  3252  * #GstTagSetter interface.
       
  3253  */
       
  3254 #ifdef __SYMBIAN32__
       
  3255 EXPORT_C
       
  3256 #endif
       
  3257 
       
  3258 void
       
  3259 gst_element_found_tags_for_pad (GstElement * element,
       
  3260     GstPad * pad, GstTagList * list)
       
  3261 {
       
  3262   g_return_if_fail (element != NULL);
       
  3263   g_return_if_fail (pad != NULL);
       
  3264   g_return_if_fail (list != NULL);
       
  3265 
       
  3266   gst_pad_push_event (pad, gst_event_new_tag (gst_tag_list_copy (list)));
       
  3267   gst_element_post_message (element,
       
  3268       gst_message_new_tag (GST_OBJECT (element), list));
       
  3269 }
       
  3270 
       
  3271 static void
       
  3272 push_and_ref (GstPad * pad, GstEvent * event)
       
  3273 {
       
  3274   gst_pad_push_event (pad, gst_event_ref (event));
       
  3275   /* iterator refs pad, we unref when we are done with it */
       
  3276   gst_object_unref (pad);
       
  3277 }
       
  3278 
       
  3279 /**
       
  3280  * gst_element_found_tags:
       
  3281  * @element: element for which we found the tags.
       
  3282  * @list: list of tags.
       
  3283  *
       
  3284  * Posts a message to the bus that new tags were found, and pushes an event
       
  3285  * to all sourcepads. Takes ownership of the @list.
       
  3286  *
       
  3287  * This is a utility method for elements. Applications should use the
       
  3288  * #GstTagSetter interface.
       
  3289  */
       
  3290 #ifdef __SYMBIAN32__
       
  3291 EXPORT_C
       
  3292 #endif
       
  3293 
       
  3294 void
       
  3295 gst_element_found_tags (GstElement * element, GstTagList * list)
       
  3296 {
       
  3297   GstIterator *iter;
       
  3298   GstEvent *event;
       
  3299 
       
  3300   g_return_if_fail (element != NULL);
       
  3301   g_return_if_fail (list != NULL);
       
  3302 
       
  3303   iter = gst_element_iterate_src_pads (element);
       
  3304   event = gst_event_new_tag (gst_tag_list_copy (list));
       
  3305   gst_iterator_foreach (iter, (GFunc) push_and_ref, event);
       
  3306   gst_iterator_free (iter);
       
  3307   gst_event_unref (event);
       
  3308 
       
  3309   gst_element_post_message (element,
       
  3310       gst_message_new_tag (GST_OBJECT (element), list));
       
  3311 }
       
  3312 
       
  3313 static GstPad *
       
  3314 element_find_unconnected_pad (GstElement * element, GstPadDirection direction)
       
  3315 {
       
  3316   GstIterator *iter;
       
  3317   GstPad *unconnected_pad = NULL;
       
  3318   gboolean done;
       
  3319 
       
  3320   switch (direction) {
       
  3321     case GST_PAD_SRC:
       
  3322       iter = gst_element_iterate_src_pads (element);
       
  3323       break;
       
  3324     case GST_PAD_SINK:
       
  3325       iter = gst_element_iterate_sink_pads (element);
       
  3326       break;
       
  3327     default:
       
  3328       g_return_val_if_reached (NULL);
       
  3329   }
       
  3330 
       
  3331   done = FALSE;
       
  3332   while (!done) {
       
  3333     gpointer pad;
       
  3334 
       
  3335     switch (gst_iterator_next (iter, &pad)) {
       
  3336       case GST_ITERATOR_OK:{
       
  3337         GstPad *peer;
       
  3338 
       
  3339         GST_CAT_LOG (GST_CAT_ELEMENT_PADS, "examining pad %s:%s",
       
  3340             GST_DEBUG_PAD_NAME (pad));
       
  3341 
       
  3342         peer = gst_pad_get_peer (GST_PAD (pad));
       
  3343         if (peer == NULL) {
       
  3344           unconnected_pad = pad;
       
  3345           done = TRUE;
       
  3346           GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  3347               "found existing unlinked pad %s:%s",
       
  3348               GST_DEBUG_PAD_NAME (unconnected_pad));
       
  3349         } else {
       
  3350           gst_object_unref (pad);
       
  3351           gst_object_unref (peer);
       
  3352         }
       
  3353         break;
       
  3354       }
       
  3355       case GST_ITERATOR_DONE:
       
  3356         done = TRUE;
       
  3357         break;
       
  3358       case GST_ITERATOR_RESYNC:
       
  3359         gst_iterator_resync (iter);
       
  3360         break;
       
  3361       case GST_ITERATOR_ERROR:
       
  3362         g_return_val_if_reached (NULL);
       
  3363         break;
       
  3364     }
       
  3365   }
       
  3366 
       
  3367   gst_iterator_free (iter);
       
  3368 
       
  3369   return unconnected_pad;
       
  3370 }
       
  3371 
       
  3372 /**
       
  3373  * gst_bin_find_unconnected_pad:
       
  3374  * @bin: bin in which to look for elements with unconnected pads
       
  3375  * @direction: whether to look for an unconnected source or sink pad
       
  3376  *
       
  3377  * Recursively looks for elements with an unconnected pad of the given
       
  3378  * direction within the specified bin and returns an unconnected pad
       
  3379  * 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
       
  3381  * pad when it is not needed any longer.
       
  3382  *
       
  3383  * Returns: unconnected pad of the given direction, or NULL.
       
  3384  *
       
  3385  * Since: 0.10.3
       
  3386  */
       
  3387 #ifdef __SYMBIAN32__
       
  3388 EXPORT_C
       
  3389 #endif
       
  3390 
       
  3391 GstPad *
       
  3392 gst_bin_find_unconnected_pad (GstBin * bin, GstPadDirection direction)
       
  3393 {
       
  3394   GstIterator *iter;
       
  3395   gboolean done;
       
  3396   GstPad *pad = NULL;
       
  3397 
       
  3398   g_return_val_if_fail (GST_IS_BIN (bin), NULL);
       
  3399   g_return_val_if_fail (direction != GST_PAD_UNKNOWN, NULL);
       
  3400 
       
  3401   done = FALSE;
       
  3402   iter = gst_bin_iterate_recurse (bin);
       
  3403   while (!done) {
       
  3404     gpointer element;
       
  3405 
       
  3406     switch (gst_iterator_next (iter, &element)) {
       
  3407       case GST_ITERATOR_OK:
       
  3408         pad = element_find_unconnected_pad (GST_ELEMENT (element), direction);
       
  3409         gst_object_unref (element);
       
  3410         if (pad != NULL)
       
  3411           done = TRUE;
       
  3412         break;
       
  3413       case GST_ITERATOR_DONE:
       
  3414         done = TRUE;
       
  3415         break;
       
  3416       case GST_ITERATOR_RESYNC:
       
  3417         gst_iterator_resync (iter);
       
  3418         break;
       
  3419       case GST_ITERATOR_ERROR:
       
  3420         g_return_val_if_reached (NULL);
       
  3421         break;
       
  3422     }
       
  3423   }
       
  3424 
       
  3425   gst_iterator_free (iter);
       
  3426 
       
  3427   return pad;
       
  3428 }
       
  3429 
       
  3430 /**
       
  3431  * gst_parse_bin_from_description:
       
  3432  * @bin_description: command line describing the bin
       
  3433  * @ghost_unconnected_pads: whether to automatically create ghost pads
       
  3434  *                          for unconnected source or sink pads within
       
  3435  *                          the bin
       
  3436  * @err: where to store the error message in case of an error, or NULL
       
  3437  *
       
  3438  * This is a convenience wrapper around gst_parse_launch() to create a
       
  3439  * #GstBin from a gst-launch-style pipeline description. See
       
  3440  * 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
       
  3442  * 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
       
  3444  * multiple unconnected source pads or multiple unconnected sink pads
       
  3445  * and want them all ghosted, you will have to create the ghost pads
       
  3446  * yourself).
       
  3447  *
       
  3448  * Returns: a newly-created bin, or NULL if an error occurred.
       
  3449  *
       
  3450  * Since: 0.10.3
       
  3451  */
       
  3452 #ifdef __SYMBIAN32__
       
  3453 EXPORT_C
       
  3454 #endif
       
  3455 
       
  3456 GstElement *
       
  3457 gst_parse_bin_from_description (const gchar * bin_description,
       
  3458     gboolean ghost_unconnected_pads, GError ** err)
       
  3459 {
       
  3460 #ifndef GST_DISABLE_PARSE
       
  3461   GstPad *pad = NULL;
       
  3462   GstBin *bin;
       
  3463   gchar *desc;
       
  3464 
       
  3465   g_return_val_if_fail (bin_description != NULL, NULL);
       
  3466   g_return_val_if_fail (err == NULL || *err == NULL, NULL);
       
  3467 
       
  3468   GST_DEBUG ("Making bin from description '%s'", bin_description);
       
  3469 
       
  3470   /* parse the pipeline to a bin */
       
  3471   desc = g_strdup_printf ("bin.( %s )", bin_description);
       
  3472   bin = (GstBin *) gst_parse_launch (desc, err);
       
  3473   g_free (desc);
       
  3474 
       
  3475   if (bin == NULL || (err && *err != NULL)) {
       
  3476     if (bin)
       
  3477       gst_object_unref (bin);
       
  3478     return NULL;
       
  3479   }
       
  3480 
       
  3481   /* find pads and ghost them if necessary */
       
  3482   if (ghost_unconnected_pads) {
       
  3483     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC))) {
       
  3484       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", pad));
       
  3485       gst_object_unref (pad);
       
  3486     }
       
  3487     if ((pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SINK))) {
       
  3488       gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
       
  3489       gst_object_unref (pad);
       
  3490     }
       
  3491   }
       
  3492 
       
  3493   return GST_ELEMENT (bin);
       
  3494 #else
       
  3495   gchar *msg;
       
  3496 
       
  3497   GST_WARNING ("Disabled API called: gst_parse_bin_from_description()");
       
  3498 
       
  3499   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);
       
  3501   g_free (msg);
       
  3502 
       
  3503   return NULL;
       
  3504 #endif
       
  3505 }
       
  3506 
       
  3507 /**
       
  3508  * gst_type_register_static_full:
       
  3509  * @parent_type: The GType of the parent type the newly registered type will 
       
  3510  *   derive from
       
  3511  * @type_name: NULL-terminated string used as the name of the new type
       
  3512  * @class_size: Size of the class structure.
       
  3513  * @base_init: Location of the base initialization function (optional).
       
  3514  * @base_finalize: Location of the base finalization function (optional).
       
  3515  * @class_init: Location of the class initialization function for class types 
       
  3516  *   Location of the default vtable inititalization function for interface 
       
  3517  *   types. (optional)
       
  3518  * @class_finalize: Location of the class finalization function for class types.
       
  3519  *   Location of the default vtable finalization function for interface types. 
       
  3520  *   (optional)
       
  3521  * @class_data: User-supplied data passed to the class init/finalize functions.
       
  3522  * @instance_size: Size of the instance (object) structure (required for 
       
  3523  *   instantiatable types only).
       
  3524  * @n_preallocs: The number of pre-allocated (cached) instances to reserve 
       
  3525  *   memory for (0 indicates no caching). Ignored on recent GLib's.
       
  3526  * @instance_init: Location of the instance initialization function (optional, 
       
  3527  *   for instantiatable types only).
       
  3528  * @value_table: A GTypeValueTable function table for generic handling of 
       
  3529  *   GValues of this type (usually only useful for fundamental types). 
       
  3530  * @flags: #GTypeFlags for this GType. E.g: G_TYPE_FLAG_ABSTRACT
       
  3531  *
       
  3532  * Helper function which constructs a #GTypeInfo structure and registers a 
       
  3533  * GType, but which generates less linker overhead than a static const 
       
  3534  * #GTypeInfo structure. For further details of the parameters, please see
       
  3535  * #GTypeInfo in the GLib documentation.
       
  3536  *
       
  3537  * Registers type_name as the name of a new static type derived from 
       
  3538  * parent_type. The value of flags determines the nature (e.g. abstract or 
       
  3539  * not) of the type. It works by filling a GTypeInfo struct and calling 
       
  3540  * g_type_info_register_static().
       
  3541  *
       
  3542  * Returns: A #GType for the newly-registered type.
       
  3543  *
       
  3544  * Since: 0.10.14
       
  3545  */
       
  3546 #ifdef __SYMBIAN32__
       
  3547 EXPORT_C
       
  3548 #endif
       
  3549 
       
  3550 GType
       
  3551 gst_type_register_static_full (GType parent_type,
       
  3552     const gchar * type_name,
       
  3553     guint class_size,
       
  3554     GBaseInitFunc base_init,
       
  3555     GBaseFinalizeFunc base_finalize,
       
  3556     GClassInitFunc class_init,
       
  3557     GClassFinalizeFunc class_finalize,
       
  3558     gconstpointer class_data,
       
  3559     guint instance_size,
       
  3560     guint16 n_preallocs,
       
  3561     GInstanceInitFunc instance_init,
       
  3562     const GTypeValueTable * value_table, GTypeFlags flags)
       
  3563 {
       
  3564   GTypeInfo info;
       
  3565 
       
  3566   info.class_size = class_size;
       
  3567   info.base_init = base_init;
       
  3568   info.base_finalize = base_finalize;
       
  3569   info.class_init = class_init;
       
  3570   info.class_finalize = class_finalize;
       
  3571   info.class_data = class_data;
       
  3572   info.instance_size = instance_size;
       
  3573   info.n_preallocs = n_preallocs;
       
  3574   info.instance_init = instance_init;
       
  3575   info.value_table = value_table;
       
  3576 
       
  3577   return g_type_register_static (parent_type, type_name, &info, flags);
       
  3578 }
       
  3579 
       
  3580 
       
  3581 /**
       
  3582  * gst_util_get_timestamp:
       
  3583  *
       
  3584  * Get a timestamp as GstClockTime to be used for interval meassurements.
       
  3585  * The timestamp should not be interpreted in any other way.
       
  3586  *
       
  3587  * Returns: the timestamp
       
  3588  *
       
  3589  * Since: 0.10.16
       
  3590  */
       
  3591 #ifdef __SYMBIAN32__
       
  3592 EXPORT_C
       
  3593 #endif
       
  3594 
       
  3595 GstClockTime
       
  3596 gst_util_get_timestamp (void)
       
  3597 {
       
  3598 #if defined (HAVE_POSIX_TIMERS) && defined(HAVE_MONOTONIC_CLOCK)
       
  3599   struct timespec now;
       
  3600 
       
  3601   clock_gettime (CLOCK_MONOTONIC, &now);
       
  3602   return GST_TIMESPEC_TO_TIME (now);
       
  3603 #else
       
  3604   GTimeVal now;
       
  3605 
       
  3606   g_get_current_time (&now);
       
  3607   return GST_TIMEVAL_TO_TIME (now);
       
  3608 #endif
       
  3609 }