gstreamer_core/gst/gstelement.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
child 29 567bb019e3e3
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *                    2004 Wim Taymans <wim@fluendo.com>
       
     4  *
       
     5  * gstelement.c: The base element, all elements derive from this
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Library General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Library General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Library General Public
       
    18  * License along with this library; if not, write to the
       
    19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    20  * Boston, MA 02111-1307, USA.
       
    21  */
       
    22 
       
    23 /**
       
    24  * SECTION:gstelement
       
    25  * @short_description: Abstract base class for all pipeline elements
       
    26  * @see_also: #GstElementFactory, #GstPad
       
    27  *
       
    28  * GstElement is the abstract base class needed to construct an element that
       
    29  * can be used in a GStreamer pipeline. Please refer to the plugin writers
       
    30  * guide for more information on creating #GstElement subclasses.
       
    31  *
       
    32  * The name of a #GstElement can be get with gst_element_get_name() and set with
       
    33  * gst_element_set_name().  For speed, GST_ELEMENT_NAME() can be used in the
       
    34  * core when using the appropriate locking. Do not use this in plug-ins or
       
    35  * applications in order to retain ABI compatibility.
       
    36  *
       
    37  * All elements have pads (of the type #GstPad).  These pads link to pads on
       
    38  * other elements.  #GstBuffer flow between these linked pads.
       
    39  * A #GstElement has a #GList of #GstPad structures for all their input (or sink)
       
    40  * and output (or source) pads.
       
    41  * Core and plug-in writers can add and remove pads with gst_element_add_pad()
       
    42  * and gst_element_remove_pad().
       
    43  *
       
    44  * A pad of an element can be retrieved by name with gst_element_get_pad().
       
    45  * An iterator of all pads can be retrieved with gst_element_iterate_pads().
       
    46  *
       
    47  * Elements can be linked through their pads.
       
    48  * If the link is straightforward, use the gst_element_link()
       
    49  * convenience function to link two elements, or gst_element_link_many()
       
    50  * for more elements in a row.
       
    51  * Use gst_element_link_filtered() to link two elements constrained by
       
    52  * a specified set of #GstCaps.
       
    53  * For finer control, use gst_element_link_pads() and
       
    54  * gst_element_link_pads_filtered() to specify the pads to link on
       
    55  * each element by name.
       
    56  *
       
    57  * Each element has a state (see #GstState).  You can get and set the state
       
    58  * of an element with gst_element_get_state() and gst_element_set_state().
       
    59  * To get a string representation of a #GstState, use
       
    60  * gst_element_state_get_name().
       
    61  *
       
    62  * You can get and set a #GstClock on an element using gst_element_get_clock()
       
    63  * and gst_element_set_clock().
       
    64  * Some elements can provide a clock for the pipeline if
       
    65  * gst_element_provides_clock() returns %TRUE. With the
       
    66  * gst_element_provide_clock() method one can retrieve the clock provided by
       
    67  * such an element.
       
    68  * Not all elements require a clock to operate correctly. If
       
    69  * gst_element_requires_clock() returns %TRUE, a clock should be set on the
       
    70  * element with gst_element_set_clock().
       
    71  *
       
    72  * Note that clock slection and distribution is normally handled by the
       
    73  * toplevel #GstPipeline so the clock functions are only to be used in very
       
    74  * specific situations.
       
    75  *
       
    76  * Last reviewed on 2006-03-12 (0.10.5)
       
    77  */
       
    78 
       
    79 #include "gst_private.h"
       
    80 #include <glib.h>
       
    81 #include <stdarg.h>
       
    82 #include <gobject/gvaluecollector.h>
       
    83 
       
    84 #include "gstelement.h"
       
    85 #include "gstenumtypes.h"
       
    86 #include "gstbus.h"
       
    87 #include "gstmarshal.h"
       
    88 #include "gsterror.h"
       
    89 #include "gstevent.h"
       
    90 #include "gstutils.h"
       
    91 #include "gstinfo.h"
       
    92 #include "gst-i18n-lib.h"
       
    93 
       
    94 #ifdef __SYMBIAN32__
       
    95 #include <glib_global.h>
       
    96 #endif
       
    97 
       
    98 /* Element signals and args */
       
    99 enum
       
   100 {
       
   101   PAD_ADDED,
       
   102   PAD_REMOVED,
       
   103   NO_MORE_PADS,
       
   104   /* add more above */
       
   105   LAST_SIGNAL
       
   106 };
       
   107 
       
   108 enum
       
   109 {
       
   110   ARG_0
       
   111       /* FILL ME */
       
   112 };
       
   113 
       
   114 extern void __gst_element_details_clear (GstElementDetails * dp);
       
   115 extern void __gst_element_details_copy (GstElementDetails * dest,
       
   116     const GstElementDetails * src);
       
   117 
       
   118 static void gst_element_class_init (GstElementClass * klass);
       
   119 static void gst_element_init (GstElement * element);
       
   120 static void gst_element_base_class_init (gpointer g_class);
       
   121 static void gst_element_base_class_finalize (gpointer g_class);
       
   122 
       
   123 static void gst_element_dispose (GObject * object);
       
   124 static void gst_element_finalize (GObject * object);
       
   125 
       
   126 static GstStateChangeReturn gst_element_change_state_func (GstElement * element,
       
   127     GstStateChange transition);
       
   128 static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
       
   129     GstState * state, GstState * pending, GstClockTime timeout);
       
   130 static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
       
   131     GstState state);
       
   132 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
       
   133 
       
   134 static gboolean gst_element_default_send_event (GstElement * element,
       
   135     GstEvent * event);
       
   136 static gboolean gst_element_default_query (GstElement * element,
       
   137     GstQuery * query);
       
   138 
       
   139 static GstPadTemplate
       
   140     * gst_element_class_get_request_pad_template (GstElementClass *
       
   141     element_class, const gchar * name);
       
   142 
       
   143 #ifndef GST_DISABLE_LOADSAVE
       
   144 static xmlNodePtr gst_element_save_thyself (GstObject * object,
       
   145     xmlNodePtr parent);
       
   146 static void gst_element_restore_thyself (GstObject * parent, xmlNodePtr self);
       
   147 #endif
       
   148 
       
   149 static GstObjectClass *parent_class = NULL;
       
   150 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
       
   151 #ifdef __SYMBIAN32__
       
   152 EXPORT_C
       
   153 #endif
       
   154 
       
   155 
       
   156 GType
       
   157 gst_element_get_type (void)
       
   158 {
       
   159   static GType gst_element_type = 0;
       
   160 
       
   161   if (G_UNLIKELY (gst_element_type == 0)) {
       
   162     static const GTypeInfo element_info = {
       
   163       sizeof (GstElementClass),
       
   164       gst_element_base_class_init,
       
   165       gst_element_base_class_finalize,
       
   166       (GClassInitFunc) gst_element_class_init,
       
   167       NULL,
       
   168       NULL,
       
   169       sizeof (GstElement),
       
   170       0,
       
   171       (GInstanceInitFunc) gst_element_init,
       
   172       NULL
       
   173     };
       
   174 
       
   175     gst_element_type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
       
   176         &element_info, G_TYPE_FLAG_ABSTRACT);
       
   177   }
       
   178   return gst_element_type;
       
   179 }
       
   180 
       
   181 static void
       
   182 gst_element_class_init (GstElementClass * klass)
       
   183 {
       
   184   GObjectClass *gobject_class;
       
   185   GstObjectClass *gstobject_class;
       
   186 
       
   187   gobject_class = (GObjectClass *) klass;
       
   188   gstobject_class = (GstObjectClass *) klass;
       
   189 
       
   190   parent_class = g_type_class_peek_parent (klass);
       
   191 
       
   192   /**
       
   193    * GstElement::pad-added:
       
   194    * @gstelement: the object which received the signal
       
   195    * @new_pad: the pad that has been added
       
   196    *
       
   197    * a new #GstPad has been added to the element.
       
   198    */
       
   199   gst_element_signals[PAD_ADDED] =
       
   200       g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       
   201       G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
       
   202       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
       
   203   /**
       
   204    * GstElement::pad-removed:
       
   205    * @gstelement: the object which received the signal
       
   206    * @old_pad: the pad that has been removed
       
   207    *
       
   208    * a #GstPad has been removed from the element
       
   209    */
       
   210   gst_element_signals[PAD_REMOVED] =
       
   211       g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
       
   212       G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
       
   213       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
       
   214   /**
       
   215    * GstElement::no-more-pads:
       
   216    * @gstelement: the object which received the signal
       
   217    *
       
   218    * This signals that the element will not generate more dynamic pads.
       
   219    */
       
   220   gst_element_signals[NO_MORE_PADS] =
       
   221       g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
       
   222       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
       
   223       NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
       
   224 
       
   225   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
       
   226   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
       
   227 
       
   228 #ifndef GST_DISABLE_LOADSAVE
       
   229   gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
       
   230   gstobject_class->restore_thyself =
       
   231       GST_DEBUG_FUNCPTR (gst_element_restore_thyself);
       
   232 #endif
       
   233 
       
   234   klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
       
   235   klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
       
   236   klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
       
   237   klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
       
   238   klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
       
   239   klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
       
   240   klass->numpadtemplates = 0;
       
   241 
       
   242   klass->elementfactory = NULL;
       
   243 }
       
   244 
       
   245 static void
       
   246 gst_element_base_class_init (gpointer g_class)
       
   247 {
       
   248   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
   249 
       
   250   /* FIXME 0.11: Copy the element details and instead of clearing the
       
   251    * pad template list copy the list and increase the refcount of
       
   252    * the pad templates by one.
       
   253    *
       
   254    * This will make it possible to add pad templates and set element
       
   255    * details in the class_init functions and is the real GObject way
       
   256    * of doing things.
       
   257    * See http://bugzilla.gnome.org/show_bug.cgi?id=491501
       
   258    */
       
   259   memset (&element_class->details, 0, sizeof (GstElementDetails));
       
   260   element_class->padtemplates = NULL;
       
   261 }
       
   262 
       
   263 static void
       
   264 gst_element_base_class_finalize (gpointer g_class)
       
   265 {
       
   266   GstElementClass *klass = GST_ELEMENT_CLASS (g_class);
       
   267 
       
   268   g_list_foreach (klass->padtemplates, (GFunc) gst_object_unref, NULL);
       
   269   g_list_free (klass->padtemplates);
       
   270   __gst_element_details_clear (&klass->details);
       
   271 }
       
   272 
       
   273 static void
       
   274 gst_element_init (GstElement * element)
       
   275 {
       
   276   GST_STATE (element) = GST_STATE_NULL;
       
   277   GST_STATE_TARGET (element) = GST_STATE_NULL;
       
   278   GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
       
   279   GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
       
   280   GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
       
   281 
       
   282   element->state_lock = g_new0 (GStaticRecMutex, 1);
       
   283   g_static_rec_mutex_init (element->state_lock);
       
   284   element->state_cond = g_cond_new ();
       
   285 }
       
   286 
       
   287 /**
       
   288  * gst_element_default_error:
       
   289  * @object: a #GObject that signalled the error.
       
   290  * @orig: the #GstObject that initiated the error.
       
   291  * @error: the GError.
       
   292  * @debug: an additional debug information string, or %NULL.
       
   293  *
       
   294  * A default error signal callback to attach to an element.
       
   295  * The user data passed to the g_signal_connect is ignored.
       
   296  *
       
   297  * The default handler will simply print the error string using g_print.
       
   298  *
       
   299  * MT safe.
       
   300  */
       
   301 #ifdef __SYMBIAN32__
       
   302 EXPORT_C
       
   303 #endif
       
   304 
       
   305 void
       
   306 gst_element_default_error (GObject * object, GstObject * source, GError * error,
       
   307     gchar * debug)
       
   308 {
       
   309   gchar *name = gst_object_get_path_string (source);
       
   310 
       
   311   g_print (_("ERROR: from element %s: %s\n"), name, error->message);
       
   312   if (debug)
       
   313     g_print (_("Additional debug info:\n%s\n"), debug);
       
   314 
       
   315   g_free (name);
       
   316 }
       
   317 
       
   318 /**
       
   319  * gst_element_release_request_pad:
       
   320  * @element: a #GstElement to release the request pad of.
       
   321  * @pad: the #GstPad to release.
       
   322  *
       
   323  * Makes the element free the previously requested pad as obtained
       
   324  * with gst_element_get_request_pad().
       
   325  *
       
   326  * MT safe.
       
   327  */
       
   328 #ifdef __SYMBIAN32__
       
   329 EXPORT_C
       
   330 #endif
       
   331 
       
   332 void
       
   333 gst_element_release_request_pad (GstElement * element, GstPad * pad)
       
   334 {
       
   335   GstElementClass *oclass;
       
   336 
       
   337   g_return_if_fail (GST_IS_ELEMENT (element));
       
   338   g_return_if_fail (GST_IS_PAD (pad));
       
   339 
       
   340   oclass = GST_ELEMENT_GET_CLASS (element);
       
   341 
       
   342   /* if the element implements a custom release function we call that, else we
       
   343    * simply remove the pad from the element */
       
   344   if (oclass->release_pad)
       
   345     (oclass->release_pad) (element, pad);
       
   346   else
       
   347     gst_element_remove_pad (element, pad);
       
   348 }
       
   349 
       
   350 /**
       
   351  * gst_element_requires_clock:
       
   352  * @element: a #GstElement to query
       
   353  *
       
   354  * Query if the element requires a clock.
       
   355  *
       
   356  * Returns: %TRUE if the element requires a clock
       
   357  *
       
   358  * MT safe.
       
   359  */
       
   360 #ifdef __SYMBIAN32__
       
   361 EXPORT_C
       
   362 #endif
       
   363 
       
   364 gboolean
       
   365 gst_element_requires_clock (GstElement * element)
       
   366 {
       
   367   gboolean result;
       
   368 
       
   369   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   370 
       
   371   result = (GST_ELEMENT_GET_CLASS (element)->set_clock != NULL);
       
   372 
       
   373   return result;
       
   374 }
       
   375 
       
   376 /**
       
   377  * gst_element_provides_clock:
       
   378  * @element: a #GstElement to query
       
   379  *
       
   380  * Query if the element provides a clock. A #GstClock provided by an
       
   381  * element can be used as the global #GstClock for the pipeline.
       
   382  * An element that can provide a clock is only required to do so in the PAUSED
       
   383  * state, this means when it is fully negotiated and has allocated the resources
       
   384  * to operate the clock.
       
   385  *
       
   386  * Returns: %TRUE if the element provides a clock
       
   387  *
       
   388  * MT safe.
       
   389  */
       
   390 #ifdef __SYMBIAN32__
       
   391 EXPORT_C
       
   392 #endif
       
   393 
       
   394 gboolean
       
   395 gst_element_provides_clock (GstElement * element)
       
   396 {
       
   397   gboolean result;
       
   398 
       
   399   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   400 
       
   401   result = (GST_ELEMENT_GET_CLASS (element)->provide_clock != NULL);
       
   402 
       
   403   return result;
       
   404 }
       
   405 
       
   406 /**
       
   407  * gst_element_provide_clock:
       
   408  * @element: a #GstElement to query
       
   409  *
       
   410  * Get the clock provided by the given element.
       
   411  * <note>An element is only required to provide a clock in the PAUSED
       
   412  * state. Some elements can provide a clock in other states.</note>
       
   413  *
       
   414  * Returns: the GstClock provided by the element or %NULL
       
   415  * if no clock could be provided.  Unref after usage.
       
   416  *
       
   417  * MT safe.
       
   418  */
       
   419 #ifdef __SYMBIAN32__
       
   420 EXPORT_C
       
   421 #endif
       
   422 
       
   423 GstClock *
       
   424 gst_element_provide_clock (GstElement * element)
       
   425 {
       
   426   GstClock *result = NULL;
       
   427   GstElementClass *oclass;
       
   428 
       
   429   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   430 
       
   431   oclass = GST_ELEMENT_GET_CLASS (element);
       
   432 
       
   433   if (oclass->provide_clock)
       
   434     result = oclass->provide_clock (element);
       
   435 
       
   436   return result;
       
   437 }
       
   438 
       
   439 /**
       
   440  * gst_element_set_clock:
       
   441  * @element: a #GstElement to set the clock for.
       
   442  * @clock: the #GstClock to set for the element.
       
   443  *
       
   444  * Sets the clock for the element. This function increases the
       
   445  * refcount on the clock. Any previously set clock on the object
       
   446  * is unreffed.
       
   447  *
       
   448  * Returns: %TRUE if the element accepted the clock. An element can refuse a
       
   449  * clock when it, for example, is not able to slave its internal clock to the
       
   450  * @clock or when it requires a specific clock to operate.
       
   451  *
       
   452  * MT safe.
       
   453  */
       
   454 #ifdef __SYMBIAN32__
       
   455 EXPORT_C
       
   456 #endif
       
   457 
       
   458 gboolean
       
   459 gst_element_set_clock (GstElement * element, GstClock * clock)
       
   460 {
       
   461   GstElementClass *oclass;
       
   462   gboolean res = TRUE;
       
   463   GstClock **clock_p;
       
   464 
       
   465   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   466 
       
   467   oclass = GST_ELEMENT_GET_CLASS (element);
       
   468 
       
   469   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, "setting clock %p", clock);
       
   470 
       
   471   if (oclass->set_clock)
       
   472     res = oclass->set_clock (element, clock);
       
   473 
       
   474   if (res) {
       
   475     /* only update the clock pointer if the element accepted the clock */
       
   476     GST_OBJECT_LOCK (element);
       
   477     clock_p = &element->clock;
       
   478     gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
       
   479     GST_OBJECT_UNLOCK (element);
       
   480   }
       
   481   return res;
       
   482 }
       
   483 
       
   484 /**
       
   485  * gst_element_get_clock:
       
   486  * @element: a #GstElement to get the clock of.
       
   487  *
       
   488  * Gets the currently configured clock of the element. This is the clock as was
       
   489  * last set with gst_element_set_clock().
       
   490  *
       
   491  * Returns: the #GstClock of the element. unref after usage.
       
   492  *
       
   493  * MT safe.
       
   494  */
       
   495 #ifdef __SYMBIAN32__
       
   496 EXPORT_C
       
   497 #endif
       
   498 
       
   499 GstClock *
       
   500 gst_element_get_clock (GstElement * element)
       
   501 {
       
   502   GstClock *result;
       
   503 
       
   504   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   505 
       
   506   GST_OBJECT_LOCK (element);
       
   507   if ((result = element->clock))
       
   508     gst_object_ref (result);
       
   509   GST_OBJECT_UNLOCK (element);
       
   510 
       
   511   return result;
       
   512 }
       
   513 
       
   514 /**
       
   515  * gst_element_set_base_time:
       
   516  * @element: a #GstElement.
       
   517  * @time: the base time to set.
       
   518  *
       
   519  * Set the base time of an element. See gst_element_get_base_time().
       
   520  *
       
   521  * MT safe.
       
   522  */
       
   523 #ifdef __SYMBIAN32__
       
   524 EXPORT_C
       
   525 #endif
       
   526 
       
   527 void
       
   528 gst_element_set_base_time (GstElement * element, GstClockTime time)
       
   529 {
       
   530   GstClockTime old;
       
   531 
       
   532   g_return_if_fail (GST_IS_ELEMENT (element));
       
   533 
       
   534   GST_OBJECT_LOCK (element);
       
   535   old = element->base_time;
       
   536   element->base_time = time;
       
   537   GST_OBJECT_UNLOCK (element);
       
   538 
       
   539   GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element,
       
   540       "set base_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT,
       
   541       GST_TIME_ARGS (time), GST_TIME_ARGS (old));
       
   542 }
       
   543 
       
   544 /**
       
   545  * gst_element_get_base_time:
       
   546  * @element: a #GstElement.
       
   547  *
       
   548  * Returns the base time of the element. The base time is the
       
   549  * absolute time of the clock when this element was last put to
       
   550  * PLAYING. Subtracting the base time from the clock time gives
       
   551  * the stream time of the element.
       
   552  *
       
   553  * Returns: the base time of the element.
       
   554  *
       
   555  * MT safe.
       
   556  */
       
   557 #ifdef __SYMBIAN32__
       
   558 EXPORT_C
       
   559 #endif
       
   560 
       
   561 GstClockTime
       
   562 gst_element_get_base_time (GstElement * element)
       
   563 {
       
   564   GstClockTime result;
       
   565 
       
   566   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
       
   567 
       
   568   GST_OBJECT_LOCK (element);
       
   569   result = element->base_time;
       
   570   GST_OBJECT_UNLOCK (element);
       
   571 
       
   572   return result;
       
   573 }
       
   574 
       
   575 #ifndef GST_DISABLE_INDEX
       
   576 /**
       
   577  * gst_element_is_indexable:
       
   578  * @element: a #GstElement.
       
   579  *
       
   580  * Queries if the element can be indexed.
       
   581  *
       
   582  * Returns: TRUE if the element can be indexed.
       
   583  *
       
   584  * MT safe.
       
   585  */
       
   586 #ifdef __SYMBIAN32__
       
   587 EXPORT_C
       
   588 #endif
       
   589 
       
   590 gboolean
       
   591 gst_element_is_indexable (GstElement * element)
       
   592 {
       
   593   gboolean result;
       
   594 
       
   595   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   596 
       
   597   result = (GST_ELEMENT_GET_CLASS (element)->set_index != NULL);
       
   598 
       
   599   return result;
       
   600 }
       
   601 
       
   602 /**
       
   603  * gst_element_set_index:
       
   604  * @element: a #GstElement.
       
   605  * @index: a #GstIndex.
       
   606  *
       
   607  * Set @index on the element. The refcount of the index
       
   608  * will be increased, any previously set index is unreffed.
       
   609  *
       
   610  * MT safe.
       
   611  */
       
   612 #ifdef __SYMBIAN32__
       
   613 EXPORT_C
       
   614 #endif
       
   615 
       
   616 void
       
   617 gst_element_set_index (GstElement * element, GstIndex * index)
       
   618 {
       
   619   GstElementClass *oclass;
       
   620 
       
   621   g_return_if_fail (GST_IS_ELEMENT (element));
       
   622   g_return_if_fail (GST_IS_INDEX (index));
       
   623 
       
   624   oclass = GST_ELEMENT_GET_CLASS (element);
       
   625 
       
   626   if (oclass->set_index)
       
   627     oclass->set_index (element, index);
       
   628 }
       
   629 
       
   630 /**
       
   631  * gst_element_get_index:
       
   632  * @element: a #GstElement.
       
   633  *
       
   634  * Gets the index from the element.
       
   635  *
       
   636  * Returns: a #GstIndex or %NULL when no index was set on the
       
   637  * element. unref after usage.
       
   638  *
       
   639  * MT safe.
       
   640  */
       
   641 #ifdef __SYMBIAN32__
       
   642 EXPORT_C
       
   643 #endif
       
   644 
       
   645 GstIndex *
       
   646 gst_element_get_index (GstElement * element)
       
   647 {
       
   648   GstElementClass *oclass;
       
   649   GstIndex *result = NULL;
       
   650 
       
   651   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   652 
       
   653   oclass = GST_ELEMENT_GET_CLASS (element);
       
   654 
       
   655   if (oclass->get_index)
       
   656     result = oclass->get_index (element);
       
   657 
       
   658   return result;
       
   659 }
       
   660 #endif
       
   661 
       
   662 /**
       
   663  * gst_element_add_pad:
       
   664  * @element: a #GstElement to add the pad to.
       
   665  * @pad: the #GstPad to add to the element.
       
   666  *
       
   667  * Adds a pad (link point) to @element. @pad's parent will be set to @element;
       
   668 #ifdef __SYMBIAN32__
       
   669 EXPORT_C
       
   670 #endif
       
   671 
       
   672  * see gst_object_set_parent() for refcounting information.
       
   673  *
       
   674  * Pads are not automatically activated so elements should perform the needed
       
   675  * steps to activate the pad in case this pad is added in the PAUSED or PLAYING
       
   676  * state. See gst_pad_set_active() for more information about activating pads.
       
   677  *
       
   678  * The pad and the element should be unlocked when calling this function.
       
   679  *
       
   680  * This function will emit the #GstElement::pad-added signal on the element.
       
   681  *
       
   682  * Returns: %TRUE if the pad could be added. This function can fail when
       
   683  * a pad with the same name already existed or the pad already had another
       
   684  * parent.
       
   685  *
       
   686  * MT safe.
       
   687  */
       
   688 #ifdef __SYMBIAN32__
       
   689 EXPORT_C
       
   690 #endif
       
   691 
       
   692 gboolean
       
   693 gst_element_add_pad (GstElement * element, GstPad * pad)
       
   694 {
       
   695   gchar *pad_name;
       
   696   gboolean flushing;
       
   697 
       
   698   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   699   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
   700 
       
   701   /* locking pad to look at the name */
       
   702   GST_OBJECT_LOCK (pad);
       
   703   pad_name = g_strdup (GST_PAD_NAME (pad));
       
   704   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
       
   705       GST_STR_NULL (pad_name));
       
   706   flushing = GST_PAD_IS_FLUSHING (pad);
       
   707   GST_OBJECT_UNLOCK (pad);
       
   708 
       
   709   /* then check to see if there's already a pad by that name here */
       
   710   GST_OBJECT_LOCK (element);
       
   711   if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
       
   712     goto name_exists;
       
   713 
       
   714   /* try to set the pad's parent */
       
   715   if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
       
   716               GST_OBJECT_CAST (element))))
       
   717     goto had_parent;
       
   718 
       
   719   /* check for flushing pads */
       
   720   if (flushing && (GST_STATE (element) > GST_STATE_READY ||
       
   721           GST_STATE_NEXT (element) == GST_STATE_PAUSED)) {
       
   722     g_warning ("adding flushing pad '%s' to running element '%s'",
       
   723         GST_STR_NULL (pad_name), GST_ELEMENT_NAME (element));
       
   724     /* unset flushing */
       
   725     GST_OBJECT_LOCK (pad);
       
   726     GST_PAD_UNSET_FLUSHING (pad);
       
   727     GST_OBJECT_UNLOCK (pad);
       
   728   }
       
   729 
       
   730   g_free (pad_name);
       
   731 
       
   732   /* add it to the list */
       
   733   switch (gst_pad_get_direction (pad)) {
       
   734     case GST_PAD_SRC:
       
   735       element->srcpads = g_list_prepend (element->srcpads, pad);
       
   736       element->numsrcpads++;
       
   737       break;
       
   738     case GST_PAD_SINK:
       
   739       element->sinkpads = g_list_prepend (element->sinkpads, pad);
       
   740       element->numsinkpads++;
       
   741       break;
       
   742     default:
       
   743       goto no_direction;
       
   744   }
       
   745   element->pads = g_list_prepend (element->pads, pad);
       
   746   element->numpads++;
       
   747   element->pads_cookie++;
       
   748   GST_OBJECT_UNLOCK (element);
       
   749 
       
   750   /* emit the PAD_ADDED signal */
       
   751   g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);
       
   752 
       
   753   return TRUE;
       
   754 
       
   755   /* ERROR cases */
       
   756 name_exists:
       
   757   {
       
   758     g_critical ("Padname %s is not unique in element %s, not adding",
       
   759         pad_name, GST_ELEMENT_NAME (element));
       
   760     GST_OBJECT_UNLOCK (element);
       
   761     g_free (pad_name);
       
   762     return FALSE;
       
   763   }
       
   764 had_parent:
       
   765   {
       
   766     g_critical
       
   767         ("Pad %s already has parent when trying to add to element %s",
       
   768         pad_name, GST_ELEMENT_NAME (element));
       
   769     GST_OBJECT_UNLOCK (element);
       
   770     g_free (pad_name);
       
   771     return FALSE;
       
   772   }
       
   773 no_direction:
       
   774   {
       
   775     GST_OBJECT_LOCK (pad);
       
   776     g_critical
       
   777         ("Trying to add pad %s to element %s, but it has no direction",
       
   778         GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element));
       
   779     GST_OBJECT_UNLOCK (pad);
       
   780     GST_OBJECT_UNLOCK (element);
       
   781     return FALSE;
       
   782   }
       
   783 }
       
   784 
       
   785 /**
       
   786  * gst_element_remove_pad:
       
   787  * @element: a #GstElement to remove pad from.
       
   788  * @pad: the #GstPad to remove from the element.
       
   789  *
       
   790  * Removes @pad from @element. @pad will be destroyed if it has not been
       
   791  * referenced elsewhere using gst_object_unparent().
       
   792  *
       
   793  * This function is used by plugin developers and should not be used
       
   794  * by applications. Pads that were dynamically requested from elements
       
   795  * with gst_element_get_request_pad() should be released with the
       
   796  * gst_element_release_request_pad() function instead.
       
   797  *
       
   798  * Pads are not automatically deactivated so elements should perform the needed
       
   799  * steps to deactivate the pad in case this pad is removed in the PAUSED or
       
   800  * PLAYING state. See gst_pad_set_active() for more information about
       
   801  * deactivating pads.
       
   802  *
       
   803  * The pad and the element should be unlocked when calling this function.
       
   804  *
       
   805  * This function will emit the #GstElement::pad-removed signal on the element.
       
   806  *
       
   807  * Returns: %TRUE if the pad could be removed. Can return %FALSE if the
       
   808  * pad does not belong to the provided element.
       
   809  *
       
   810  * MT safe.
       
   811  */
       
   812 #ifdef __SYMBIAN32__
       
   813 EXPORT_C
       
   814 #endif
       
   815 
       
   816 gboolean
       
   817 gst_element_remove_pad (GstElement * element, GstPad * pad)
       
   818 {
       
   819   GstPad *peer;
       
   820 
       
   821   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
   822   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
       
   823 
       
   824   /* locking pad to look at the name and parent */
       
   825   GST_OBJECT_LOCK (pad);
       
   826   GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
       
   827       GST_STR_NULL (GST_PAD_NAME (pad)));
       
   828 
       
   829   if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
       
   830     goto not_our_pad;
       
   831   GST_OBJECT_UNLOCK (pad);
       
   832 
       
   833   /* unlink */
       
   834   if ((peer = gst_pad_get_peer (pad))) {
       
   835     /* window for MT unsafeness, someone else could unlink here
       
   836      * and then we call unlink with wrong pads. The unlink
       
   837      * function would catch this and safely return failed. */
       
   838     if (GST_PAD_IS_SRC (pad))
       
   839       gst_pad_unlink (pad, peer);
       
   840     else
       
   841       gst_pad_unlink (peer, pad);
       
   842 
       
   843     gst_object_unref (peer);
       
   844   }
       
   845 
       
   846   GST_OBJECT_LOCK (element);
       
   847   /* remove it from the list */
       
   848   switch (gst_pad_get_direction (pad)) {
       
   849     case GST_PAD_SRC:
       
   850       element->srcpads = g_list_remove (element->srcpads, pad);
       
   851       element->numsrcpads--;
       
   852       break;
       
   853     case GST_PAD_SINK:
       
   854       element->sinkpads = g_list_remove (element->sinkpads, pad);
       
   855       element->numsinkpads--;
       
   856       break;
       
   857     default:
       
   858       g_critical ("Removing pad without direction???");
       
   859       break;
       
   860   }
       
   861   element->pads = g_list_remove (element->pads, pad);
       
   862   element->numpads--;
       
   863   element->pads_cookie++;
       
   864   GST_OBJECT_UNLOCK (element);
       
   865 
       
   866   /* emit the PAD_REMOVED signal before unparenting and losing the last ref. */
       
   867   g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad);
       
   868 
       
   869   gst_object_unparent (GST_OBJECT_CAST (pad));
       
   870 
       
   871   return TRUE;
       
   872 
       
   873   /* ERRORS */
       
   874 not_our_pad:
       
   875   {
       
   876     /* FIXME, locking order? */
       
   877     GST_OBJECT_LOCK (element);
       
   878     g_critical ("Padname %s:%s does not belong to element %s when removing",
       
   879         GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
       
   880     GST_OBJECT_UNLOCK (element);
       
   881     GST_OBJECT_UNLOCK (pad);
       
   882     return FALSE;
       
   883   }
       
   884 }
       
   885 
       
   886 /**
       
   887  * gst_element_no_more_pads:
       
   888  * @element: a #GstElement
       
   889  *
       
   890  * Use this function to signal that the element does not expect any more pads
       
   891  * to show up in the current pipeline. This function should be called whenever
       
   892  * pads have been added by the element itself. Elements with #GST_PAD_SOMETIMES
       
   893  * pad templates use this in combination with autopluggers to figure out that
       
   894  * the element is done initializing its pads.
       
   895  *
       
   896  * This function emits the #GstElement::no-more-pads signal.
       
   897  *
       
   898  * MT safe.
       
   899  */
       
   900 #ifdef __SYMBIAN32__
       
   901 EXPORT_C
       
   902 #endif
       
   903 
       
   904 void
       
   905 gst_element_no_more_pads (GstElement * element)
       
   906 {
       
   907   g_return_if_fail (GST_IS_ELEMENT (element));
       
   908 
       
   909   g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
       
   910 }
       
   911 
       
   912 static gint
       
   913 pad_compare_name (GstPad * pad1, const gchar * name)
       
   914 {
       
   915   gint result;
       
   916 
       
   917   GST_OBJECT_LOCK (pad1);
       
   918   result = strcmp (GST_PAD_NAME (pad1), name);
       
   919   GST_OBJECT_UNLOCK (pad1);
       
   920 
       
   921   return result;
       
   922 }
       
   923 
       
   924 /**
       
   925  * gst_element_get_static_pad:
       
   926  * @element: a #GstElement to find a static pad of.
       
   927  * @name: the name of the static #GstPad to retrieve.
       
   928  *
       
   929  * Retrieves a pad from @element by name. This version only retrieves
       
   930  * already-existing (i.e. 'static') pads.
       
   931  *
       
   932  * Returns: the requested #GstPad if found, otherwise %NULL. unref after
       
   933  * usage.
       
   934  *
       
   935  * MT safe.
       
   936  */
       
   937 #ifdef __SYMBIAN32__
       
   938 EXPORT_C
       
   939 #endif
       
   940 
       
   941 GstPad *
       
   942 gst_element_get_static_pad (GstElement * element, const gchar * name)
       
   943 {
       
   944   GList *find;
       
   945   GstPad *result = NULL;
       
   946 
       
   947   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
   948   g_return_val_if_fail (name != NULL, NULL);
       
   949 
       
   950   GST_OBJECT_LOCK (element);
       
   951   find =
       
   952       g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
       
   953   if (find) {
       
   954     result = GST_PAD_CAST (find->data);
       
   955     gst_object_ref (result);
       
   956   }
       
   957 
       
   958   if (result == NULL) {
       
   959     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
       
   960         name, GST_ELEMENT_NAME (element));
       
   961   } else {
       
   962     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
       
   963         GST_ELEMENT_NAME (element), name);
       
   964   }
       
   965   GST_OBJECT_UNLOCK (element);
       
   966 
       
   967   return result;
       
   968 }
       
   969 
       
   970 static GstPad *
       
   971 gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
       
   972     const gchar * name)
       
   973 {
       
   974   GstPad *newpad = NULL;
       
   975   GstElementClass *oclass;
       
   976 
       
   977   oclass = GST_ELEMENT_GET_CLASS (element);
       
   978 
       
   979   if (oclass->request_new_pad)
       
   980     newpad = (oclass->request_new_pad) (element, templ, name);
       
   981 
       
   982   if (newpad)
       
   983     gst_object_ref (newpad);
       
   984 
       
   985   return newpad;
       
   986 }
       
   987 
       
   988 /**
       
   989  * gst_element_get_request_pad:
       
   990  * @element: a #GstElement to find a request pad of.
       
   991  * @name: the name of the request #GstPad to retrieve.
       
   992  *
       
   993  * Retrieves a pad from the element by name. This version only retrieves
       
   994  * request pads. The pad should be released with
       
   995  * gst_element_release_request_pad().
       
   996  *
       
   997  * Returns: requested #GstPad if found, otherwise %NULL. Release after usage.
       
   998  */
       
   999 #ifdef __SYMBIAN32__
       
  1000 EXPORT_C
       
  1001 #endif
       
  1002 
       
  1003 GstPad *
       
  1004 gst_element_get_request_pad (GstElement * element, const gchar * name)
       
  1005 {
       
  1006   GstPadTemplate *templ = NULL;
       
  1007   GstPad *pad;
       
  1008   const gchar *req_name = NULL;
       
  1009   gboolean templ_found = FALSE;
       
  1010   GList *list;
       
  1011   gint n;
       
  1012   const gchar *data;
       
  1013   gchar *str, *endptr = NULL;
       
  1014   GstElementClass *class;
       
  1015 
       
  1016   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1017   g_return_val_if_fail (name != NULL, NULL);
       
  1018 
       
  1019   class = GST_ELEMENT_GET_CLASS (element);
       
  1020 
       
  1021   /* if the name contains a %, we assume it's the complete template name. Get
       
  1022    * the template and try to get a pad */
       
  1023   if (strstr (name, "%")) {
       
  1024     templ = gst_element_class_get_request_pad_template (class, name);
       
  1025     req_name = NULL;
       
  1026     if (templ)
       
  1027       templ_found = TRUE;
       
  1028   } else {
       
  1029     /* there is no % in the name, try to find a matching template */
       
  1030     list = gst_element_class_get_pad_template_list (class);
       
  1031     while (!templ_found && list) {
       
  1032       templ = (GstPadTemplate *) list->data;
       
  1033       if (templ->presence == GST_PAD_REQUEST) {
       
  1034         GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
       
  1035             templ->name_template);
       
  1036         /* see if we find an exact match */
       
  1037         if (strcmp (name, templ->name_template) == 0) {
       
  1038           templ_found = TRUE;
       
  1039           req_name = name;
       
  1040           break;
       
  1041         }
       
  1042         /* Because of sanity checks in gst_pad_template_new(), we know that %s
       
  1043            and %d, occurring at the end of the name_template, are the only
       
  1044            possibilities. */
       
  1045         else if ((str = strchr (templ->name_template, '%'))
       
  1046             && strncmp (templ->name_template, name,
       
  1047                 str - templ->name_template) == 0
       
  1048             && strlen (name) > str - templ->name_template) {
       
  1049           data = name + (str - templ->name_template);
       
  1050           if (*(str + 1) == 'd') {
       
  1051             /* it's an int */
       
  1052             n = (gint) strtol (data, &endptr, 10);
       
  1053             if (endptr && *endptr == '\0') {
       
  1054               templ_found = TRUE;
       
  1055               req_name = name;
       
  1056               break;
       
  1057             }
       
  1058           } else {
       
  1059             /* it's a string */
       
  1060             templ_found = TRUE;
       
  1061             req_name = name;
       
  1062             break;
       
  1063           }
       
  1064         }
       
  1065       }
       
  1066       list = list->next;
       
  1067     }
       
  1068   }
       
  1069 
       
  1070   if (!templ_found)
       
  1071     return NULL;
       
  1072 
       
  1073   pad = gst_element_request_pad (element, templ, req_name);
       
  1074 
       
  1075   return pad;
       
  1076 }
       
  1077 
       
  1078 /**
       
  1079  * gst_element_get_pad:
       
  1080  * @element: a #GstElement.
       
  1081  * @name: the name of the pad to retrieve.
       
  1082  *
       
  1083  * Retrieves a pad from @element by name. Tries gst_element_get_static_pad()
       
  1084  * first, then gst_element_get_request_pad().
       
  1085  *
       
  1086  * <note>Usage of this function is not recommended as it is unclear if the reference
       
  1087  * to the result pad should be released with gst_object_unref() in case of a static pad
       
  1088  * or gst_element_release_request_pad() in case of a request pad.</note>
       
  1089  *
       
  1090  * Returns: the #GstPad if found, otherwise %NULL. Unref or Release after usage,
       
  1091  * depending on the type of the pad.
       
  1092  */
       
  1093 #ifdef __SYMBIAN32__
       
  1094 EXPORT_C
       
  1095 #endif
       
  1096 
       
  1097 GstPad *
       
  1098 gst_element_get_pad (GstElement * element, const gchar * name)
       
  1099 {
       
  1100   GstPad *pad;
       
  1101 
       
  1102   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1103   g_return_val_if_fail (name != NULL, NULL);
       
  1104 
       
  1105   pad = gst_element_get_static_pad (element, name);
       
  1106   if (!pad)
       
  1107     pad = gst_element_get_request_pad (element, name);
       
  1108 
       
  1109   return pad;
       
  1110 }
       
  1111 
       
  1112 static GstIteratorItem
       
  1113 iterate_pad (GstIterator * it, GstPad * pad)
       
  1114 {
       
  1115   gst_object_ref (pad);
       
  1116   return GST_ITERATOR_ITEM_PASS;
       
  1117 }
       
  1118 
       
  1119 static GstIterator *
       
  1120 gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
       
  1121 {
       
  1122   GstIterator *result;
       
  1123 
       
  1124   GST_OBJECT_LOCK (element);
       
  1125   gst_object_ref (element);
       
  1126   result = gst_iterator_new_list (GST_TYPE_PAD,
       
  1127       GST_OBJECT_GET_LOCK (element),
       
  1128       &element->pads_cookie,
       
  1129       padlist,
       
  1130       element,
       
  1131       (GstIteratorItemFunction) iterate_pad,
       
  1132       (GstIteratorDisposeFunction) gst_object_unref);
       
  1133   GST_OBJECT_UNLOCK (element);
       
  1134 
       
  1135   return result;
       
  1136 }
       
  1137 
       
  1138 /**
       
  1139  * gst_element_iterate_pads:
       
  1140  * @element: a #GstElement to iterate pads of.
       
  1141  *
       
  1142  * Retrieves an iterattor of @element's pads. The iterator should
       
  1143  * be freed after usage.
       
  1144  *
       
  1145  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
       
  1146  *
       
  1147  * MT safe.
       
  1148  */
       
  1149 #ifdef __SYMBIAN32__
       
  1150 EXPORT_C
       
  1151 #endif
       
  1152 
       
  1153 GstIterator *
       
  1154 gst_element_iterate_pads (GstElement * element)
       
  1155 {
       
  1156   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1157 
       
  1158   return gst_element_iterate_pad_list (element, &element->pads);
       
  1159 }
       
  1160 
       
  1161 /**
       
  1162  * gst_element_iterate_src_pads:
       
  1163  * @element: a #GstElement.
       
  1164  *
       
  1165  * Retrieves an iterator of @element's source pads.
       
  1166  *
       
  1167  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
       
  1168  *
       
  1169  * MT safe.
       
  1170  */
       
  1171 #ifdef __SYMBIAN32__
       
  1172 EXPORT_C
       
  1173 #endif
       
  1174 
       
  1175 GstIterator *
       
  1176 gst_element_iterate_src_pads (GstElement * element)
       
  1177 {
       
  1178   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1179 
       
  1180   return gst_element_iterate_pad_list (element, &element->srcpads);
       
  1181 }
       
  1182 
       
  1183 /**
       
  1184  * gst_element_iterate_sink_pads:
       
  1185  * @element: a #GstElement.
       
  1186  *
       
  1187  * Retrieves an iterator of @element's sink pads.
       
  1188  *
       
  1189  * Returns: the #GstIterator of #GstPad. Unref each pad after use.
       
  1190  *
       
  1191  * MT safe.
       
  1192  */
       
  1193 #ifdef __SYMBIAN32__
       
  1194 EXPORT_C
       
  1195 #endif
       
  1196 
       
  1197 GstIterator *
       
  1198 gst_element_iterate_sink_pads (GstElement * element)
       
  1199 {
       
  1200   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1201 
       
  1202   return gst_element_iterate_pad_list (element, &element->sinkpads);
       
  1203 }
       
  1204 
       
  1205 /**
       
  1206  * gst_element_class_add_pad_template:
       
  1207  * @klass: the #GstElementClass to add the pad template to.
       
  1208  * @templ: a #GstPadTemplate to add to the element class.
       
  1209  *
       
  1210  * Adds a padtemplate to an element class. This is mainly used in the _base_init
       
  1211  * functions of classes.
       
  1212  */
       
  1213 #ifdef __SYMBIAN32__
       
  1214 EXPORT_C
       
  1215 #endif
       
  1216 
       
  1217 void
       
  1218 gst_element_class_add_pad_template (GstElementClass * klass,
       
  1219     GstPadTemplate * templ)
       
  1220 {
       
  1221   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
       
  1222   g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
       
  1223 
       
  1224   /* FIXME 0.11: allow replacing the pad templates by
       
  1225    * calling this with the same name as an already existing pad
       
  1226    * template. For this we _must_ _not_ ref the added pad template
       
  1227    * a second time and _must_ document that this function takes
       
  1228    * ownership of the pad template. Otherwise we will leak pad templates
       
  1229    * or the caller unref's the pad template and it disappears */
       
  1230   /* avoid registering pad templates with the same name */
       
  1231   g_return_if_fail (gst_element_class_get_pad_template (klass,
       
  1232           templ->name_template) == NULL);
       
  1233 
       
  1234   klass->padtemplates = g_list_append (klass->padtemplates,
       
  1235       gst_object_ref (templ));
       
  1236   klass->numpadtemplates++;
       
  1237 }
       
  1238 
       
  1239 /**
       
  1240  * gst_element_class_set_details:
       
  1241  * @klass: class to set details for
       
  1242  * @details: details to set
       
  1243  *
       
  1244  * Sets the detailed information for a #GstElementClass.
       
  1245  * <note>This function is for use in _base_init functions only.</note>
       
  1246  *
       
  1247  * The @details are copied.
       
  1248  */
       
  1249 #ifdef __SYMBIAN32__
       
  1250 EXPORT_C
       
  1251 #endif
       
  1252 
       
  1253 void
       
  1254 gst_element_class_set_details (GstElementClass * klass,
       
  1255     const GstElementDetails * details)
       
  1256 {
       
  1257   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
       
  1258   g_return_if_fail (GST_IS_ELEMENT_DETAILS (details));
       
  1259 
       
  1260   __gst_element_details_copy (&klass->details, details);
       
  1261 }
       
  1262 
       
  1263 /**
       
  1264  * gst_element_class_set_details_simple:
       
  1265  * @klass: class to set details for
       
  1266  * @longname: The long English name of the element. E.g. "File Sink"
       
  1267  * @classification: String describing the type of element, as an unordered list
       
  1268  * separated with slashes ('/'). See draft-klass.txt of the design docs
       
  1269  * for more details and common types. E.g: "Sink/File"
       
  1270  * @description: Sentence describing the purpose of the element. 
       
  1271  * E.g: "Write stream to a file"
       
  1272  * @author: Name and contact details of the author(s). Use \n to separate 
       
  1273  * multiple author details. E.g: "Joe Bloggs &lt;joe.blogs at foo.com&gt;"
       
  1274  *
       
  1275  * Sets the detailed information for a #GstElementClass. Simpler version of 
       
  1276  * gst_element_class_set_details() that generates less linker overhead.
       
  1277  * <note>This function is for use in _base_init functions only.</note>
       
  1278  *
       
  1279  * The detail parameter strings are copied into the #GstElementDetails for
       
  1280  * the element class.
       
  1281  *
       
  1282  * Since: 0.10.14
       
  1283  */
       
  1284 #ifdef __SYMBIAN32__
       
  1285 EXPORT_C
       
  1286 #endif
       
  1287 
       
  1288 void
       
  1289 gst_element_class_set_details_simple (GstElementClass * klass,
       
  1290     const gchar * longname, const gchar * classification,
       
  1291     const gchar * description, const gchar * author)
       
  1292 {
       
  1293 #ifdef __SYMBIAN32__ // VASU
       
  1294   const GstElementDetails details;
       
  1295   ((GstElementDetails*)&details)->longname = (gchar *) longname;
       
  1296   ((GstElementDetails*)&details)->klass = (gchar *) classification;
       
  1297   ((GstElementDetails*)&details)->description = (gchar *) description;
       
  1298   ((GstElementDetails*)&details)->author = (gchar *) author;
       
  1299   ((GstElementDetails*)&details)->_gst_reserved[0] = NULL;
       
  1300 #else
       
  1301   const GstElementDetails details =
       
  1302       GST_ELEMENT_DETAILS ((gchar *) longname, (gchar *) classification,
       
  1303       (gchar *) description, (gchar *) author);
       
  1304 #endif // __SYMBIAN32__
       
  1305 
       
  1306   g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
       
  1307 
       
  1308   __gst_element_details_copy (&klass->details, &details);
       
  1309 }
       
  1310 
       
  1311 /**
       
  1312  * gst_element_class_get_pad_template_list:
       
  1313  * @element_class: a #GstElementClass to get pad templates of.
       
  1314  *
       
  1315  * Retrieves a list of the pad templates associated with @element_class. The
       
  1316  * list must not be modified by the calling code.
       
  1317  * <note>If you use this function in the #GInstanceInitFunc of an object class
       
  1318  * that has subclasses, make sure to pass the g_class parameter of the
       
  1319  * #GInstanceInitFunc here.</note>
       
  1320  *
       
  1321  * Returns: the #GList of padtemplates.
       
  1322  */
       
  1323 #ifdef __SYMBIAN32__
       
  1324 EXPORT_C
       
  1325 #endif
       
  1326 
       
  1327 GList *
       
  1328 gst_element_class_get_pad_template_list (GstElementClass * element_class)
       
  1329 {
       
  1330   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
       
  1331 
       
  1332   return element_class->padtemplates;
       
  1333 }
       
  1334 
       
  1335 /**
       
  1336  * gst_element_class_get_pad_template:
       
  1337  * @element_class: a #GstElementClass to get the pad template of.
       
  1338  * @name: the name of the #GstPadTemplate to get.
       
  1339  *
       
  1340  * Retrieves a padtemplate from @element_class with the given name.
       
  1341  * <note>If you use this function in the #GInstanceInitFunc of an object class
       
  1342  * that has subclasses, make sure to pass the g_class parameter of the
       
  1343  * #GInstanceInitFunc here.</note>
       
  1344  *
       
  1345  * Returns: the #GstPadTemplate with the given name, or %NULL if none was found.
       
  1346  * No unreferencing is necessary.
       
  1347  */
       
  1348 #ifdef __SYMBIAN32__
       
  1349 EXPORT_C
       
  1350 #endif
       
  1351 
       
  1352 GstPadTemplate *
       
  1353 gst_element_class_get_pad_template (GstElementClass * element_class,
       
  1354     const gchar * name)
       
  1355 {
       
  1356   GList *padlist;
       
  1357 
       
  1358   g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
       
  1359   g_return_val_if_fail (name != NULL, NULL);
       
  1360 
       
  1361   padlist = gst_element_class_get_pad_template_list (element_class);
       
  1362 
       
  1363   while (padlist) {
       
  1364     GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
       
  1365 
       
  1366     if (strcmp (padtempl->name_template, name) == 0)
       
  1367       return padtempl;
       
  1368 
       
  1369     padlist = g_list_next (padlist);
       
  1370   }
       
  1371 
       
  1372   return NULL;
       
  1373 }
       
  1374 
       
  1375 static GstPadTemplate *
       
  1376 gst_element_class_get_request_pad_template (GstElementClass * element_class,
       
  1377     const gchar * name)
       
  1378 {
       
  1379   GstPadTemplate *tmpl;
       
  1380 
       
  1381   tmpl = gst_element_class_get_pad_template (element_class, name);
       
  1382   if (tmpl != NULL && tmpl->presence == GST_PAD_REQUEST)
       
  1383     return tmpl;
       
  1384 
       
  1385   return NULL;
       
  1386 }
       
  1387 
       
  1388 /* get a random pad on element of the given direction.
       
  1389  * The pad is random in a sense that it is the first pad that is (optionaly) linked.
       
  1390  */
       
  1391 static GstPad *
       
  1392 gst_element_get_random_pad (GstElement * element, gboolean need_linked,
       
  1393     GstPadDirection dir)
       
  1394 {
       
  1395   GstPad *result = NULL;
       
  1396   GList *pads;
       
  1397 
       
  1398   GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
       
  1399 
       
  1400   switch (dir) {
       
  1401     case GST_PAD_SRC:
       
  1402       GST_OBJECT_LOCK (element);
       
  1403       pads = element->srcpads;
       
  1404       break;
       
  1405     case GST_PAD_SINK:
       
  1406       GST_OBJECT_LOCK (element);
       
  1407       pads = element->sinkpads;
       
  1408       break;
       
  1409     default:
       
  1410       goto wrong_direction;
       
  1411   }
       
  1412   for (; pads; pads = g_list_next (pads)) {
       
  1413     GstPad *pad = GST_PAD_CAST (pads->data);
       
  1414 
       
  1415     GST_OBJECT_LOCK (pad);
       
  1416     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
       
  1417         GST_DEBUG_PAD_NAME (pad));
       
  1418 
       
  1419     if (need_linked && !GST_PAD_IS_LINKED (pad)) {
       
  1420       /* if we require a linked pad, and it is not linked, continue the
       
  1421        * search */
       
  1422       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
       
  1423           GST_DEBUG_PAD_NAME (pad));
       
  1424       GST_OBJECT_UNLOCK (pad);
       
  1425       continue;
       
  1426     } else {
       
  1427       /* found a pad, stop search */
       
  1428       GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
       
  1429           GST_DEBUG_PAD_NAME (pad));
       
  1430       GST_OBJECT_UNLOCK (pad);
       
  1431       result = pad;
       
  1432       break;
       
  1433     }
       
  1434   }
       
  1435   if (result)
       
  1436     gst_object_ref (result);
       
  1437 
       
  1438   GST_OBJECT_UNLOCK (element);
       
  1439 
       
  1440   return result;
       
  1441 
       
  1442   /* ERROR handling */
       
  1443 wrong_direction:
       
  1444   {
       
  1445     g_warning ("unknown pad direction %d", dir);
       
  1446     return NULL;
       
  1447   }
       
  1448 }
       
  1449 
       
  1450 static gboolean
       
  1451 gst_element_default_send_event (GstElement * element, GstEvent * event)
       
  1452 {
       
  1453   gboolean result = FALSE;
       
  1454   GstPad *pad;
       
  1455 
       
  1456   pad = GST_EVENT_IS_DOWNSTREAM (event) ?
       
  1457       gst_element_get_random_pad (element, TRUE, GST_PAD_SRC) :
       
  1458       gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
       
  1459 
       
  1460   if (pad) {
       
  1461     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
       
  1462         "pushing %s event to random %s pad %s:%s",
       
  1463         GST_EVENT_TYPE_NAME (event),
       
  1464         (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
       
  1465         GST_DEBUG_PAD_NAME (pad));
       
  1466 
       
  1467     result = gst_pad_push_event (pad, event);
       
  1468     gst_object_unref (pad);
       
  1469   } else {
       
  1470     GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
       
  1471         GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
       
  1472   }
       
  1473   return result;
       
  1474 }
       
  1475 
       
  1476 /**
       
  1477  * gst_element_send_event:
       
  1478  * @element: a #GstElement to send the event to.
       
  1479  * @event: the #GstEvent to send to the element.
       
  1480  *
       
  1481  * Sends an event to an element. If the element doesn't implement an
       
  1482  * event handler, the event will be pushed on a random linked sink pad for
       
  1483  * upstream events or a random linked source pad for downstream events.
       
  1484  *
       
  1485  * This function takes owership of the provided event so you should
       
  1486  * gst_event_ref() it if you want to reuse the event after this call.
       
  1487  *
       
  1488  * Returns: %TRUE if the event was handled.
       
  1489  *
       
  1490  * MT safe.
       
  1491  */
       
  1492 #ifdef __SYMBIAN32__
       
  1493 EXPORT_C
       
  1494 #endif
       
  1495 
       
  1496 gboolean
       
  1497 gst_element_send_event (GstElement * element, GstEvent * event)
       
  1498 {
       
  1499   GstElementClass *oclass;
       
  1500   gboolean result = FALSE;
       
  1501 
       
  1502   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1503   g_return_val_if_fail (event != NULL, FALSE);
       
  1504 
       
  1505   oclass = GST_ELEMENT_GET_CLASS (element);
       
  1506 
       
  1507   GST_STATE_LOCK (element);
       
  1508   if (oclass->send_event) {
       
  1509     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
       
  1510         GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
       
  1511     result = oclass->send_event (element, event);
       
  1512   } else {
       
  1513     result = gst_element_default_send_event (element, event);
       
  1514   }
       
  1515   GST_STATE_UNLOCK (element);
       
  1516 
       
  1517   return result;
       
  1518 }
       
  1519 
       
  1520 /**
       
  1521  * gst_element_seek:
       
  1522  * @element: a #GstElement to send the event to.
       
  1523  * @rate: The new playback rate
       
  1524  * @format: The format of the seek values
       
  1525  * @flags: The optional seek flags.
       
  1526  * @cur_type: The type and flags for the new current position
       
  1527  * @cur: The value of the new current position
       
  1528  * @stop_type: The type and flags for the new stop position
       
  1529  * @stop: The value of the new stop position
       
  1530  *
       
  1531  * Sends a seek event to an element. See gst_event_new_seek() for the details of
       
  1532  * the parameters. The seek event is sent to the element using
       
  1533  * gst_element_send_event().
       
  1534  *
       
  1535  * Returns: %TRUE if the event was handled.
       
  1536  *
       
  1537  * MT safe.
       
  1538  */
       
  1539 #ifdef __SYMBIAN32__
       
  1540 EXPORT_C
       
  1541 #endif
       
  1542 
       
  1543 gboolean
       
  1544 gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
       
  1545     GstSeekFlags flags, GstSeekType cur_type, gint64 cur,
       
  1546     GstSeekType stop_type, gint64 stop)
       
  1547 {
       
  1548   GstEvent *event;
       
  1549   gboolean result;
       
  1550 
       
  1551   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1552 
       
  1553   event =
       
  1554       gst_event_new_seek (rate, format, flags, cur_type, cur, stop_type, stop);
       
  1555   result = gst_element_send_event (element, event);
       
  1556 
       
  1557   return result;
       
  1558 }
       
  1559 
       
  1560 /**
       
  1561  * gst_element_get_query_types:
       
  1562  * @element: a #GstElement to query
       
  1563  *
       
  1564  * Get an array of query types from the element.
       
  1565  * If the element doesn't implement a query types function,
       
  1566  * the query will be forwarded to the peer of a random linked sink pad.
       
  1567  *
       
  1568  * Returns: An array of #GstQueryType elements that should not
       
  1569  * be freed or modified.
       
  1570  *
       
  1571  * MT safe.
       
  1572  */
       
  1573 #ifdef __SYMBIAN32__
       
  1574 EXPORT_C
       
  1575 #endif
       
  1576 
       
  1577 const GstQueryType *
       
  1578 gst_element_get_query_types (GstElement * element)
       
  1579 {
       
  1580   GstElementClass *oclass;
       
  1581   const GstQueryType *result = NULL;
       
  1582 
       
  1583   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  1584 
       
  1585   oclass = GST_ELEMENT_GET_CLASS (element);
       
  1586 
       
  1587   if (oclass->get_query_types) {
       
  1588     result = oclass->get_query_types (element);
       
  1589   } else {
       
  1590     GstPad *pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
       
  1591 
       
  1592     if (pad) {
       
  1593       GstPad *peer = gst_pad_get_peer (pad);
       
  1594 
       
  1595       if (peer) {
       
  1596         result = gst_pad_get_query_types (peer);
       
  1597 
       
  1598         gst_object_unref (peer);
       
  1599       }
       
  1600       gst_object_unref (pad);
       
  1601     }
       
  1602   }
       
  1603   return result;
       
  1604 }
       
  1605 
       
  1606 static gboolean
       
  1607 gst_element_default_query (GstElement * element, GstQuery * query)
       
  1608 {
       
  1609   gboolean result = FALSE;
       
  1610   GstPad *pad;
       
  1611 
       
  1612   pad = gst_element_get_random_pad (element, FALSE, GST_PAD_SRC);
       
  1613   if (pad) {
       
  1614     result = gst_pad_query (pad, query);
       
  1615 
       
  1616     gst_object_unref (pad);
       
  1617   } else {
       
  1618     pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
       
  1619     if (pad) {
       
  1620       GstPad *peer = gst_pad_get_peer (pad);
       
  1621 
       
  1622       if (peer) {
       
  1623         result = gst_pad_query (peer, query);
       
  1624 
       
  1625         gst_object_unref (peer);
       
  1626       }
       
  1627       gst_object_unref (pad);
       
  1628     }
       
  1629   }
       
  1630   return result;
       
  1631 }
       
  1632 
       
  1633 /**
       
  1634  * gst_element_query:
       
  1635  * @element: a #GstElement to perform the query on.
       
  1636  * @query: the #GstQuery.
       
  1637  *
       
  1638  * Performs a query on the given element.
       
  1639  *
       
  1640  * For elements that don't implement a query handler, this function
       
  1641  * forwards the query to a random srcpad or to the peer of a
       
  1642  * random linked sinkpad of this element.
       
  1643  *
       
  1644  * Returns: TRUE if the query could be performed.
       
  1645  *
       
  1646  * MT safe.
       
  1647  */
       
  1648 #ifdef __SYMBIAN32__
       
  1649 EXPORT_C
       
  1650 #endif
       
  1651 
       
  1652 gboolean
       
  1653 gst_element_query (GstElement * element, GstQuery * query)
       
  1654 {
       
  1655   GstElementClass *oclass;
       
  1656   gboolean result = FALSE;
       
  1657 
       
  1658   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1659   g_return_val_if_fail (query != NULL, FALSE);
       
  1660 
       
  1661   oclass = GST_ELEMENT_GET_CLASS (element);
       
  1662 
       
  1663   if (oclass->query) {
       
  1664     GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
       
  1665         GST_ELEMENT_NAME (element));
       
  1666     result = oclass->query (element, query);
       
  1667   } else {
       
  1668     result = gst_element_default_query (element, query);
       
  1669   }
       
  1670   return result;
       
  1671 }
       
  1672 
       
  1673 /**
       
  1674  * gst_element_post_message:
       
  1675  * @element: a #GstElement posting the message
       
  1676  * @message: a #GstMessage to post
       
  1677  *
       
  1678  * Post a message on the element's #GstBus. This function takes ownership of the
       
  1679  * message; if you want to access the message after this call, you should add an
       
  1680  * additional reference before calling.
       
  1681  *
       
  1682  * Returns: %TRUE if the message was successfully posted. The function returns
       
  1683  * %FALSE if the element did not have a bus.
       
  1684  *
       
  1685  * MT safe.
       
  1686  */
       
  1687 #ifdef __SYMBIAN32__
       
  1688 EXPORT_C
       
  1689 #endif
       
  1690 
       
  1691 gboolean
       
  1692 gst_element_post_message (GstElement * element, GstMessage * message)
       
  1693 {
       
  1694   GstBus *bus;
       
  1695   gboolean result = FALSE;
       
  1696 
       
  1697   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1698   g_return_val_if_fail (message != NULL, FALSE);
       
  1699 
       
  1700   GST_OBJECT_LOCK (element);
       
  1701   bus = element->bus;
       
  1702 
       
  1703   if (G_UNLIKELY (bus == NULL))
       
  1704     goto no_bus;
       
  1705 
       
  1706   gst_object_ref (bus);
       
  1707   GST_OBJECT_UNLOCK (element);
       
  1708 
       
  1709   /* we release the element lock when posting the message so that any
       
  1710    * (synchronous) message handlers can operate on the element */
       
  1711   result = gst_bus_post (bus, message);
       
  1712   gst_object_unref (bus);
       
  1713 
       
  1714   return result;
       
  1715 
       
  1716   /* ERRORS */
       
  1717 no_bus:
       
  1718   {
       
  1719     GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element,
       
  1720         "not posting message %p: no bus", message);
       
  1721     GST_OBJECT_UNLOCK (element);
       
  1722     gst_message_unref (message);
       
  1723     return FALSE;
       
  1724   }
       
  1725 }
       
  1726 
       
  1727 /**
       
  1728  * _gst_element_error_printf:
       
  1729  * @format: the printf-like format to use, or %NULL
       
  1730  *
       
  1731  * This function is only used internally by the gst_element_error() macro.
       
  1732  *
       
  1733  * Returns: a newly allocated string, or %NULL if the format was %NULL or ""
       
  1734  *
       
  1735  * MT safe.
       
  1736  */
       
  1737 #ifdef __SYMBIAN32__
       
  1738 EXPORT_C
       
  1739 #endif
       
  1740 
       
  1741 gchar *
       
  1742 _gst_element_error_printf (const gchar * format, ...)
       
  1743 {
       
  1744   va_list args;
       
  1745   gchar *buffer;
       
  1746 
       
  1747   if (format == NULL)
       
  1748     return NULL;
       
  1749   if (format[0] == 0)
       
  1750     return NULL;
       
  1751 
       
  1752   va_start (args, format);
       
  1753   buffer = g_strdup_vprintf (format, args);
       
  1754   va_end (args);
       
  1755   return buffer;
       
  1756 }
       
  1757 
       
  1758 /**
       
  1759  * gst_element_message_full:
       
  1760  * @element:  a #GstElement to send message from
       
  1761  * @type:     the #GstMessageType
       
  1762  * @domain:   the GStreamer GError domain this message belongs to
       
  1763  * @code:     the GError code belonging to the domain
       
  1764  * @text:     an allocated text string to be used as a replacement for the
       
  1765  *            default message connected to code, or %NULL
       
  1766  * @debug:    an allocated debug message to be used as a replacement for the
       
  1767  *            default debugging information, or %NULL
       
  1768  * @file:     the source code file where the error was generated
       
  1769  * @function: the source code function where the error was generated
       
  1770  * @line:     the source code line where the error was generated
       
  1771  *
       
  1772  * Post an error, warning or info message on the bus from inside an element.
       
  1773  *
       
  1774  * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
       
  1775  * #GST_MESSAGE_INFO.
       
  1776  *
       
  1777  * MT safe.
       
  1778  */
       
  1779 #ifdef __SYMBIAN32__
       
  1780 EXPORT_C
       
  1781 #endif
       
  1782 
       
  1783 void gst_element_message_full
       
  1784     (GstElement * element, GstMessageType type,
       
  1785     GQuark domain, gint code, gchar * text,
       
  1786     gchar * debug, const gchar * file, const gchar * function, gint line)
       
  1787 {
       
  1788   GError *gerror = NULL;
       
  1789   gchar *name;
       
  1790   gchar *sent_text;
       
  1791   gchar *sent_debug;
       
  1792   gboolean has_debug = TRUE;
       
  1793   GstMessage *message = NULL;
       
  1794 
       
  1795   /* checks */
       
  1796   GST_DEBUG_OBJECT (element, "start");
       
  1797   g_return_if_fail (GST_IS_ELEMENT (element));
       
  1798   g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
       
  1799       (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO));
       
  1800 
       
  1801   /* check if we send the given text or the default error text */
       
  1802   if ((text == NULL) || (text[0] == 0)) {
       
  1803     /* text could have come from g_strdup_printf (""); */
       
  1804     g_free (text);
       
  1805     sent_text = gst_error_get_message (domain, code);
       
  1806   } else
       
  1807     sent_text = text;
       
  1808 
       
  1809   /* construct a sent_debug with extra information from source */
       
  1810   if ((debug == NULL) || (debug[0] == 0)) {
       
  1811     /* debug could have come from g_strdup_printf (""); */
       
  1812     has_debug = FALSE;
       
  1813   }
       
  1814 
       
  1815   name = gst_object_get_path_string (GST_OBJECT_CAST (element));
       
  1816   if (has_debug)
       
  1817     sent_debug = g_strdup_printf ("%s(%d): %s (): %s:\n%s",
       
  1818         file, line, function, name, debug);
       
  1819   else
       
  1820     sent_debug = g_strdup_printf ("%s(%d): %s (): %s",
       
  1821         file, line, function, name);
       
  1822   g_free (name);
       
  1823   g_free (debug);
       
  1824 
       
  1825   /* create gerror and post message */
       
  1826   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
       
  1827       sent_text);
       
  1828   gerror = g_error_new_literal (domain, code, sent_text);
       
  1829 
       
  1830   switch (type) {
       
  1831     case GST_MESSAGE_ERROR:
       
  1832       message =
       
  1833           gst_message_new_error (GST_OBJECT_CAST (element), gerror, sent_debug);
       
  1834       break;
       
  1835     case GST_MESSAGE_WARNING:
       
  1836       message = gst_message_new_warning (GST_OBJECT_CAST (element), gerror,
       
  1837           sent_debug);
       
  1838       break;
       
  1839     case GST_MESSAGE_INFO:
       
  1840       message = gst_message_new_info (GST_OBJECT_CAST (element), gerror,
       
  1841           sent_debug);
       
  1842       break;
       
  1843     default:
       
  1844       g_assert_not_reached ();
       
  1845       break;
       
  1846   }
       
  1847   gst_element_post_message (element, message);
       
  1848 
       
  1849   GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s",
       
  1850       (type == GST_MESSAGE_ERROR ? "error" : "warning"), sent_text);
       
  1851 
       
  1852   /* cleanup */
       
  1853   g_error_free (gerror);
       
  1854   g_free (sent_debug);
       
  1855   g_free (sent_text);
       
  1856 }
       
  1857 
       
  1858 /**
       
  1859  * gst_element_is_locked_state:
       
  1860  * @element: a #GstElement.
       
  1861  *
       
  1862  * Checks if the state of an element is locked.
       
  1863  * If the state of an element is locked, state changes of the parent don't
       
  1864  * affect the element.
       
  1865  * This way you can leave currently unused elements inside bins. Just lock their
       
  1866  * state before changing the state from #GST_STATE_NULL.
       
  1867  *
       
  1868  * MT safe.
       
  1869  *
       
  1870  * Returns: TRUE, if the element's state is locked.
       
  1871  */
       
  1872 #ifdef __SYMBIAN32__
       
  1873 EXPORT_C
       
  1874 #endif
       
  1875 
       
  1876 gboolean
       
  1877 gst_element_is_locked_state (GstElement * element)
       
  1878 {
       
  1879   gboolean result;
       
  1880 
       
  1881   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1882 
       
  1883   GST_OBJECT_LOCK (element);
       
  1884   result = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
       
  1885   GST_OBJECT_UNLOCK (element);
       
  1886 
       
  1887   return result;
       
  1888 }
       
  1889 
       
  1890 /**
       
  1891  * gst_element_set_locked_state:
       
  1892  * @element: a #GstElement
       
  1893  * @locked_state: TRUE to lock the element's state
       
  1894  *
       
  1895  * Locks the state of an element, so state changes of the parent don't affect
       
  1896  * this element anymore.
       
  1897  *
       
  1898  * MT safe.
       
  1899  *
       
  1900  * Returns: TRUE if the state was changed, FALSE if bad parameters were given
       
  1901  * or the elements state-locking needed no change.
       
  1902  */
       
  1903 #ifdef __SYMBIAN32__
       
  1904 EXPORT_C
       
  1905 #endif
       
  1906 
       
  1907 gboolean
       
  1908 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
       
  1909 {
       
  1910   gboolean old;
       
  1911 
       
  1912   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1913 
       
  1914   GST_OBJECT_LOCK (element);
       
  1915   old = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
       
  1916 
       
  1917   if (G_UNLIKELY (old == locked_state))
       
  1918     goto was_ok;
       
  1919 
       
  1920   if (locked_state) {
       
  1921     GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
       
  1922         GST_ELEMENT_NAME (element));
       
  1923     GST_OBJECT_FLAG_SET (element, GST_ELEMENT_LOCKED_STATE);
       
  1924   } else {
       
  1925     GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
       
  1926         GST_ELEMENT_NAME (element));
       
  1927     GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_LOCKED_STATE);
       
  1928   }
       
  1929   GST_OBJECT_UNLOCK (element);
       
  1930 
       
  1931   return TRUE;
       
  1932 
       
  1933 was_ok:
       
  1934   {
       
  1935     GST_CAT_DEBUG (GST_CAT_STATES, "elements %s was in locked state %d",
       
  1936         GST_ELEMENT_NAME (element), old);
       
  1937     GST_OBJECT_UNLOCK (element);
       
  1938 
       
  1939     return FALSE;
       
  1940   }
       
  1941 }
       
  1942 
       
  1943 /**
       
  1944  * gst_element_sync_state_with_parent:
       
  1945  * @element: a #GstElement.
       
  1946  *
       
  1947  * Tries to change the state of the element to the same as its parent.
       
  1948  * If this function returns FALSE, the state of element is undefined.
       
  1949  *
       
  1950  * Returns: TRUE, if the element's state could be synced to the parent's state.
       
  1951  *
       
  1952  * MT safe.
       
  1953  */
       
  1954 #ifdef __SYMBIAN32__
       
  1955 EXPORT_C
       
  1956 #endif
       
  1957 
       
  1958 gboolean
       
  1959 gst_element_sync_state_with_parent (GstElement * element)
       
  1960 {
       
  1961   GstElement *parent;
       
  1962   GstState target;
       
  1963   GstStateChangeReturn ret;
       
  1964 
       
  1965   g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
       
  1966 
       
  1967   if ((parent = GST_ELEMENT_CAST (gst_element_get_parent (element)))) {
       
  1968     GstState parent_current, parent_pending;
       
  1969 
       
  1970     GST_OBJECT_LOCK (parent);
       
  1971     parent_current = GST_STATE (parent);
       
  1972     parent_pending = GST_STATE_PENDING (parent);
       
  1973     GST_OBJECT_UNLOCK (parent);
       
  1974 
       
  1975     /* set to pending if there is one, else we set it to the current state of
       
  1976      * the parent */
       
  1977     if (parent_pending != GST_STATE_VOID_PENDING)
       
  1978       target = parent_pending;
       
  1979     else
       
  1980       target = parent_current;
       
  1981 
       
  1982     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  1983         "syncing state (%s) to parent %s %s (%s, %s)",
       
  1984         gst_element_state_get_name (GST_STATE (element)),
       
  1985         GST_ELEMENT_NAME (parent), gst_element_state_get_name (target),
       
  1986         gst_element_state_get_name (parent_current),
       
  1987         gst_element_state_get_name (parent_pending));
       
  1988 
       
  1989     ret = gst_element_set_state (element, target);
       
  1990     if (ret == GST_STATE_CHANGE_FAILURE)
       
  1991       goto failed;
       
  1992 
       
  1993     gst_object_unref (parent);
       
  1994 
       
  1995     return TRUE;
       
  1996   } else {
       
  1997     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "element has no parent");
       
  1998   }
       
  1999   return FALSE;
       
  2000 
       
  2001   /* ERROR */
       
  2002 failed:
       
  2003   {
       
  2004     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2005         "syncing state failed (%s)",
       
  2006         gst_element_state_change_return_get_name (ret));
       
  2007     return FALSE;
       
  2008   }
       
  2009 }
       
  2010 
       
  2011 /* MT safe */
       
  2012 static GstStateChangeReturn
       
  2013 gst_element_get_state_func (GstElement * element,
       
  2014     GstState * state, GstState * pending, GstClockTime timeout)
       
  2015 {
       
  2016   GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
       
  2017   GstState old_pending;
       
  2018 
       
  2019   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "getting state, timeout %"
       
  2020       GST_TIME_FORMAT, GST_TIME_ARGS (timeout));
       
  2021 
       
  2022   GST_OBJECT_LOCK (element);
       
  2023   ret = GST_STATE_RETURN (element);
       
  2024   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "RETURN is %s",
       
  2025       gst_element_state_change_return_get_name (ret));
       
  2026 
       
  2027   /* we got an error, report immediatly */
       
  2028   if (ret == GST_STATE_CHANGE_FAILURE)
       
  2029     goto done;
       
  2030 
       
  2031   /* we got no_preroll, report immediatly */
       
  2032   if (ret == GST_STATE_CHANGE_NO_PREROLL)
       
  2033     goto done;
       
  2034 
       
  2035   /* no need to wait async if we are not async */
       
  2036   if (ret != GST_STATE_CHANGE_ASYNC)
       
  2037     goto done;
       
  2038 
       
  2039   old_pending = GST_STATE_PENDING (element);
       
  2040   if (old_pending != GST_STATE_VOID_PENDING) {
       
  2041     GTimeVal *timeval, abstimeout;
       
  2042     guint32 cookie;
       
  2043 
       
  2044     if (timeout != GST_CLOCK_TIME_NONE) {
       
  2045       glong add = timeout / 1000;
       
  2046 
       
  2047       if (add == 0)
       
  2048         goto done;
       
  2049 
       
  2050       /* make timeout absolute */
       
  2051       g_get_current_time (&abstimeout);
       
  2052       g_time_val_add (&abstimeout, add);
       
  2053       timeval = &abstimeout;
       
  2054     } else {
       
  2055       timeval = NULL;
       
  2056     }
       
  2057     /* get cookie to dected state change during waiting */
       
  2058     cookie = element->state_cookie;
       
  2059 
       
  2060     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2061         "waiting for element to commit state");
       
  2062 
       
  2063     /* we have a pending state change, wait for it to complete */
       
  2064     if (!GST_STATE_TIMED_WAIT (element, timeval)) {
       
  2065       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
       
  2066       /* timeout triggered */
       
  2067       ret = GST_STATE_CHANGE_ASYNC;
       
  2068     } else {
       
  2069       if (cookie != element->state_cookie)
       
  2070         goto interrupted;
       
  2071 
       
  2072       /* could be success or failure */
       
  2073       if (old_pending == GST_STATE (element)) {
       
  2074         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got success");
       
  2075         ret = GST_STATE_CHANGE_SUCCESS;
       
  2076       } else {
       
  2077         GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got failure");
       
  2078         ret = GST_STATE_CHANGE_FAILURE;
       
  2079       }
       
  2080     }
       
  2081     /* if nothing is pending anymore we can return SUCCESS */
       
  2082     if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
       
  2083       GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "nothing pending");
       
  2084       ret = GST_STATE_CHANGE_SUCCESS;
       
  2085     }
       
  2086   }
       
  2087 
       
  2088 done:
       
  2089   if (state)
       
  2090     *state = GST_STATE (element);
       
  2091   if (pending)
       
  2092     *pending = GST_STATE_PENDING (element);
       
  2093 
       
  2094   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2095       "state current: %s, pending: %s, result: %s",
       
  2096       gst_element_state_get_name (GST_STATE (element)),
       
  2097       gst_element_state_get_name (GST_STATE_PENDING (element)),
       
  2098       gst_element_state_change_return_get_name (ret));
       
  2099   GST_OBJECT_UNLOCK (element);
       
  2100 
       
  2101   return ret;
       
  2102 
       
  2103 interrupted:
       
  2104   {
       
  2105     if (state)
       
  2106       *state = GST_STATE_VOID_PENDING;
       
  2107     if (pending)
       
  2108       *pending = GST_STATE_VOID_PENDING;
       
  2109 
       
  2110     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "interruped");
       
  2111 
       
  2112     GST_OBJECT_UNLOCK (element);
       
  2113 
       
  2114     return GST_STATE_CHANGE_FAILURE;
       
  2115   }
       
  2116 }
       
  2117 
       
  2118 /**
       
  2119  * gst_element_get_state:
       
  2120  * @element: a #GstElement to get the state of.
       
  2121  * @state: a pointer to #GstState to hold the state. Can be %NULL.
       
  2122  * @pending: a pointer to #GstState to hold the pending state.
       
  2123  *           Can be %NULL.
       
  2124  * @timeout: a #GstClockTime to specify the timeout for an async
       
  2125  *           state change or %GST_CLOCK_TIME_NONE for infinite timeout.
       
  2126  *
       
  2127  * Gets the state of the element.
       
  2128  *
       
  2129  * For elements that performed an ASYNC state change, as reported by
       
  2130  * gst_element_set_state(), this function will block up to the
       
  2131  * specified timeout value for the state change to complete.
       
  2132  * If the element completes the state change or goes into
       
  2133  * an error, this function returns immediately with a return value of
       
  2134  * %GST_STATE_CHANGE_SUCCESS or %GST_STATE_CHANGE_FAILURE respectively.
       
  2135  *
       
  2136  * For elements that did not return %GST_STATE_CHANGE_ASYNC, this function
       
  2137  * returns the current and pending state immediately.
       
  2138  *
       
  2139  * This function returns %GST_STATE_CHANGE_NO_PREROLL if the element
       
  2140  * successfully changed its state but is not able to provide data yet.
       
  2141  * This mostly happens for live sources that only produce data in the PLAYING
       
  2142  * state. While the state change return is equivalent to
       
  2143  * %GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that
       
  2144  * some sink elements might not be able to complete their state change because
       
  2145  * an element is not producing data to complete the preroll. When setting the
       
  2146  * element to playing, the preroll will complete and playback will start.
       
  2147  *
       
  2148  * Returns: %GST_STATE_CHANGE_SUCCESS if the element has no more pending state
       
  2149  *          and the last state change succeeded, %GST_STATE_CHANGE_ASYNC if the
       
  2150  *          element is still performing a state change or
       
  2151  *          %GST_STATE_CHANGE_FAILURE if the last state change failed.
       
  2152  *
       
  2153  * MT safe.
       
  2154  */
       
  2155 #ifdef __SYMBIAN32__
       
  2156 EXPORT_C
       
  2157 #endif
       
  2158 
       
  2159 GstStateChangeReturn
       
  2160 gst_element_get_state (GstElement * element,
       
  2161     GstState * state, GstState * pending, GstClockTime timeout)
       
  2162 {
       
  2163   GstElementClass *oclass;
       
  2164   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
       
  2165 
       
  2166   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
       
  2167 
       
  2168   oclass = GST_ELEMENT_GET_CLASS (element);
       
  2169 
       
  2170   if (oclass->get_state)
       
  2171     result = (oclass->get_state) (element, state, pending, timeout);
       
  2172 
       
  2173   return result;
       
  2174 }
       
  2175 
       
  2176 /**
       
  2177  * gst_element_abort_state:
       
  2178  * @element: a #GstElement to abort the state of.
       
  2179  *
       
  2180  * Abort the state change of the element. This function is used
       
  2181  * by elements that do asynchronous state changes and find out
       
  2182  * something is wrong.
       
  2183  *
       
  2184  * This function should be called with the STATE_LOCK held.
       
  2185  *
       
  2186  * MT safe.
       
  2187  */
       
  2188 #ifdef __SYMBIAN32__
       
  2189 EXPORT_C
       
  2190 #endif
       
  2191 
       
  2192 void
       
  2193 gst_element_abort_state (GstElement * element)
       
  2194 {
       
  2195   GstState pending;
       
  2196 
       
  2197 #ifndef GST_DISABLE_GST_DEBUG
       
  2198   GstState old_state;
       
  2199 #endif
       
  2200 
       
  2201   g_return_if_fail (GST_IS_ELEMENT (element));
       
  2202 
       
  2203   GST_OBJECT_LOCK (element);
       
  2204   pending = GST_STATE_PENDING (element);
       
  2205 
       
  2206   if (pending == GST_STATE_VOID_PENDING ||
       
  2207       GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
       
  2208     goto nothing_aborted;
       
  2209 
       
  2210 #ifndef GST_DISABLE_GST_DEBUG
       
  2211   old_state = GST_STATE (element);
       
  2212 
       
  2213   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2214       "aborting state from %s to %s", gst_element_state_get_name (old_state),
       
  2215       gst_element_state_get_name (pending));
       
  2216 #endif
       
  2217 
       
  2218   /* flag error */
       
  2219   GST_STATE_RETURN (element) = GST_STATE_CHANGE_FAILURE;
       
  2220 
       
  2221   GST_STATE_BROADCAST (element);
       
  2222   GST_OBJECT_UNLOCK (element);
       
  2223 
       
  2224   return;
       
  2225 
       
  2226 nothing_aborted:
       
  2227   {
       
  2228     GST_OBJECT_UNLOCK (element);
       
  2229     return;
       
  2230   }
       
  2231 }
       
  2232 
       
  2233 /**
       
  2234  * gst_element_continue_state:
       
  2235  * @element: a #GstElement to continue the state change of.
       
  2236  * @ret: The previous state return value
       
  2237  *
       
  2238  * Commit the state change of the element and proceed to the next
       
  2239  * pending state if any. This function is used
       
  2240  * by elements that do asynchronous state changes.
       
  2241  * The core will normally call this method automatically when an
       
  2242  * element returned %GST_STATE_CHANGE_SUCCESS from the state change function.
       
  2243  *
       
  2244  * If after calling this method the element still has not reached
       
  2245  * the pending state, the next state change is performed.
       
  2246  *
       
  2247  * This method is used internally and should normally not be called by plugins
       
  2248  * or applications.
       
  2249  *
       
  2250  * Returns: The result of the commit state change.
       
  2251  *
       
  2252  * MT safe.
       
  2253  */
       
  2254 #ifdef __SYMBIAN32__
       
  2255 EXPORT_C
       
  2256 #endif
       
  2257 
       
  2258 GstStateChangeReturn
       
  2259 gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
       
  2260 {
       
  2261   GstStateChangeReturn old_ret;
       
  2262   GstState old_state, old_next;
       
  2263   GstState current, next, pending;
       
  2264   GstMessage *message;
       
  2265   GstStateChange transition;
       
  2266 
       
  2267   GST_OBJECT_LOCK (element);
       
  2268   old_ret = GST_STATE_RETURN (element);
       
  2269   GST_STATE_RETURN (element) = ret;
       
  2270   pending = GST_STATE_PENDING (element);
       
  2271 
       
  2272   /* check if there is something to commit */
       
  2273   if (pending == GST_STATE_VOID_PENDING)
       
  2274     goto nothing_pending;
       
  2275 
       
  2276   old_state = GST_STATE (element);
       
  2277   /* this is the state we should go to next */
       
  2278   old_next = GST_STATE_NEXT (element);
       
  2279   /* update current state */
       
  2280   current = GST_STATE (element) = old_next;
       
  2281 
       
  2282   /* see if we reached the final state */
       
  2283   if (pending == current)
       
  2284     goto complete;
       
  2285 
       
  2286   next = GST_STATE_GET_NEXT (current, pending);
       
  2287   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
       
  2288 
       
  2289   GST_STATE_NEXT (element) = next;
       
  2290   /* mark busy */
       
  2291   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
       
  2292   GST_OBJECT_UNLOCK (element);
       
  2293 
       
  2294   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2295       "committing state from %s to %s, pending %s",
       
  2296       gst_element_state_get_name (old_state),
       
  2297       gst_element_state_get_name (old_next),
       
  2298       gst_element_state_get_name (pending));
       
  2299 
       
  2300   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
       
  2301       old_state, old_next, pending);
       
  2302   gst_element_post_message (element, message);
       
  2303 
       
  2304   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2305       "continue state change %s to %s, final %s",
       
  2306       gst_element_state_get_name (current),
       
  2307       gst_element_state_get_name (next), gst_element_state_get_name (pending));
       
  2308 
       
  2309   ret = gst_element_change_state (element, transition);
       
  2310 
       
  2311   return ret;
       
  2312 
       
  2313 nothing_pending:
       
  2314   {
       
  2315     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
       
  2316     GST_OBJECT_UNLOCK (element);
       
  2317     return ret;
       
  2318   }
       
  2319 complete:
       
  2320   {
       
  2321     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
       
  2322     GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
       
  2323 
       
  2324     GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2325         "completed state change to %s", gst_element_state_get_name (pending));
       
  2326     GST_OBJECT_UNLOCK (element);
       
  2327 
       
  2328     /* don't post silly messages with the same state. This can happen
       
  2329      * when an element state is changed to what it already was. For bins
       
  2330      * this can be the result of a lost state, which we check with the
       
  2331      * previous return value.
       
  2332      * We do signal the cond though as a _get_state() might be blocking
       
  2333      * on it. */
       
  2334     if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
       
  2335       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2336           "posting state-changed %s to %s",
       
  2337           gst_element_state_get_name (old_state),
       
  2338           gst_element_state_get_name (old_next));
       
  2339       message =
       
  2340           gst_message_new_state_changed (GST_OBJECT_CAST (element), old_state,
       
  2341           old_next, GST_STATE_VOID_PENDING);
       
  2342       gst_element_post_message (element, message);
       
  2343     }
       
  2344 
       
  2345     GST_STATE_BROADCAST (element);
       
  2346 
       
  2347     return ret;
       
  2348   }
       
  2349 }
       
  2350 
       
  2351 /**
       
  2352  * gst_element_lost_state:
       
  2353  * @element: a #GstElement the state is lost of
       
  2354  *
       
  2355  * Brings the element to the lost state. The current state of the
       
  2356  * element is copied to the pending state so that any call to
       
  2357  * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
       
  2358  *
       
  2359  * An ASYNC_START message is posted with an indication to distribute a new
       
  2360  * base_time to the element.
       
  2361  * If the element was PLAYING, it will go to PAUSED. The element
       
  2362  * will be restored to its PLAYING state by the parent pipeline when it
       
  2363  * prerolls again.
       
  2364  *
       
  2365  * This is mostly used for elements that lost their preroll buffer
       
  2366  * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush,
       
  2367  * they will go to their pending state again when a new preroll buffer is
       
  2368  * queued. This function can only be called when the element is currently
       
  2369  * not in error or an async state change.
       
  2370  *
       
  2371  * This function is used internally and should normally not be called from
       
  2372  * plugins or applications.
       
  2373  *
       
  2374  * MT safe.
       
  2375  */
       
  2376 #ifdef __SYMBIAN32__
       
  2377 EXPORT_C
       
  2378 #endif
       
  2379 
       
  2380 void
       
  2381 gst_element_lost_state (GstElement * element)
       
  2382 {
       
  2383   GstState old_state, new_state;
       
  2384   GstMessage *message;
       
  2385 
       
  2386   g_return_if_fail (GST_IS_ELEMENT (element));
       
  2387 
       
  2388   GST_OBJECT_LOCK (element);
       
  2389   if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING ||
       
  2390       GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
       
  2391     goto nothing_lost;
       
  2392 
       
  2393   old_state = GST_STATE (element);
       
  2394 
       
  2395   /* when we were PLAYING, the new state is PAUSED. We will also not
       
  2396    * automatically go to PLAYING but let the parent bin(s) set us to PLAYING
       
  2397    * when we preroll. */
       
  2398   if (old_state > GST_STATE_PAUSED)
       
  2399     new_state = GST_STATE_PAUSED;
       
  2400   else
       
  2401     new_state = old_state;
       
  2402 
       
  2403   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2404       "lost state of %s to %s", gst_element_state_get_name (old_state),
       
  2405       gst_element_state_get_name (new_state));
       
  2406 
       
  2407   GST_STATE (element) = new_state;
       
  2408   GST_STATE_NEXT (element) = new_state;
       
  2409   GST_STATE_PENDING (element) = new_state;
       
  2410   GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
       
  2411   GST_OBJECT_UNLOCK (element);
       
  2412 
       
  2413   message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
       
  2414       new_state, new_state, new_state);
       
  2415   gst_element_post_message (element, message);
       
  2416 
       
  2417   message = gst_message_new_async_start (GST_OBJECT_CAST (element), TRUE);
       
  2418   gst_element_post_message (element, message);
       
  2419 
       
  2420   return;
       
  2421 
       
  2422 nothing_lost:
       
  2423   {
       
  2424     GST_OBJECT_UNLOCK (element);
       
  2425     return;
       
  2426   }
       
  2427 }
       
  2428 
       
  2429 /**
       
  2430  * gst_element_set_state:
       
  2431  * @element: a #GstElement to change state of.
       
  2432  * @state: the element's new #GstState.
       
  2433  *
       
  2434  * Sets the state of the element. This function will try to set the
       
  2435  * requested state by going through all the intermediary states and calling
       
  2436  * the class's state change function for each.
       
  2437  *
       
  2438  * This function can return #GST_STATE_CHANGE_ASYNC, in which case the
       
  2439  * element will perform the remainder of the state change asynchronously in
       
  2440  * another thread.
       
  2441  * An application can use gst_element_get_state() to wait for the completion
       
  2442  * of the state change or it can wait for a state change message on the bus.
       
  2443  *
       
  2444  * Returns: Result of the state change using #GstStateChangeReturn.
       
  2445  *
       
  2446  * MT safe.
       
  2447  */
       
  2448 #ifdef __SYMBIAN32__
       
  2449 EXPORT_C
       
  2450 #endif
       
  2451 
       
  2452 GstStateChangeReturn
       
  2453 gst_element_set_state (GstElement * element, GstState state)
       
  2454 {
       
  2455   GstElementClass *oclass;
       
  2456   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
       
  2457 
       
  2458   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
       
  2459 
       
  2460   oclass = GST_ELEMENT_GET_CLASS (element);
       
  2461 
       
  2462   if (oclass->set_state)
       
  2463     result = (oclass->set_state) (element, state);
       
  2464 
       
  2465   return result;
       
  2466 }
       
  2467 
       
  2468 /*
       
  2469  * default set state function, calculates the next state based
       
  2470  * on current state and calls the change_state function
       
  2471  */
       
  2472 static GstStateChangeReturn
       
  2473 gst_element_set_state_func (GstElement * element, GstState state)
       
  2474 {
       
  2475   GstState current, next, old_pending;
       
  2476   GstStateChangeReturn ret;
       
  2477   GstStateChange transition;
       
  2478   GstStateChangeReturn old_ret;
       
  2479 
       
  2480   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
       
  2481 
       
  2482   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "set_state to %s",
       
  2483       gst_element_state_get_name (state));
       
  2484 
       
  2485   /* state lock is taken to protect the set_state() and get_state()
       
  2486    * procedures, it does not lock any variables. */
       
  2487   GST_STATE_LOCK (element);
       
  2488 
       
  2489   /* now calculate how to get to the new state */
       
  2490   GST_OBJECT_LOCK (element);
       
  2491   old_ret = GST_STATE_RETURN (element);
       
  2492   /* previous state change returned an error, remove all pending
       
  2493    * and next states */
       
  2494   if (old_ret == GST_STATE_CHANGE_FAILURE) {
       
  2495     GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
       
  2496     GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
       
  2497     GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
       
  2498   }
       
  2499 
       
  2500   current = GST_STATE (element);
       
  2501   next = GST_STATE_NEXT (element);
       
  2502   old_pending = GST_STATE_PENDING (element);
       
  2503 
       
  2504   /* this is the (new) state we should go to. TARGET is the last state we set on
       
  2505    * the element. */
       
  2506   if (state != GST_STATE_TARGET (element)) {
       
  2507     GST_STATE_TARGET (element) = state;
       
  2508     /* increment state cookie so that we can track each state change. We only do
       
  2509      * this if this is actually a new state change. */
       
  2510     element->state_cookie++;
       
  2511   }
       
  2512   GST_STATE_PENDING (element) = state;
       
  2513 
       
  2514   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2515       "current %s, old_pending %s, next %s, old return %s",
       
  2516       gst_element_state_get_name (current),
       
  2517       gst_element_state_get_name (old_pending),
       
  2518       gst_element_state_get_name (next),
       
  2519       gst_element_state_change_return_get_name (old_ret));
       
  2520 
       
  2521   /* if the element was busy doing a state change, we just update the
       
  2522    * target state, it'll get to it async then. */
       
  2523   if (old_pending != GST_STATE_VOID_PENDING) {
       
  2524     /* upwards state change will happen ASYNC */
       
  2525     if (old_pending <= state)
       
  2526       goto was_busy;
       
  2527     /* element is going to this state already */
       
  2528     else if (next == state)
       
  2529       goto was_busy;
       
  2530     /* element was performing an ASYNC upward state change and
       
  2531      * we request to go downward again. Start from the next pending
       
  2532      * state then. */
       
  2533     else if (next > state
       
  2534         && GST_STATE_RETURN (element) == GST_STATE_CHANGE_ASYNC) {
       
  2535       current = next;
       
  2536     }
       
  2537   }
       
  2538   next = GST_STATE_GET_NEXT (current, state);
       
  2539   /* now we store the next state */
       
  2540   GST_STATE_NEXT (element) = next;
       
  2541   /* mark busy, we need to check that there is actually a state change
       
  2542    * to be done else we could accidentally override SUCCESS/NO_PREROLL and
       
  2543    * the default element change_state function has no way to know what the
       
  2544    * old value was... could consider this a FIXME...*/
       
  2545   if (current != next)
       
  2546     GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
       
  2547 
       
  2548   transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
       
  2549 
       
  2550   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2551       "%s: setting state from %s to %s",
       
  2552       (next != state ? "intermediate" : "final"),
       
  2553       gst_element_state_get_name (current), gst_element_state_get_name (next));
       
  2554 
       
  2555   /* now signal any waiters, they will error since the cookie was incremented */
       
  2556   GST_STATE_BROADCAST (element);
       
  2557 
       
  2558   GST_OBJECT_UNLOCK (element);
       
  2559 
       
  2560   ret = gst_element_change_state (element, transition);
       
  2561 
       
  2562   GST_STATE_UNLOCK (element);
       
  2563 
       
  2564   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "returned %s",
       
  2565       gst_element_state_change_return_get_name (ret));
       
  2566 
       
  2567   return ret;
       
  2568 
       
  2569 was_busy:
       
  2570   {
       
  2571     GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
       
  2572     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2573         "element was busy with async state change");
       
  2574     GST_OBJECT_UNLOCK (element);
       
  2575 
       
  2576     GST_STATE_UNLOCK (element);
       
  2577 
       
  2578     return GST_STATE_CHANGE_ASYNC;
       
  2579   }
       
  2580 }
       
  2581 
       
  2582 /**
       
  2583  * gst_element_change_state:
       
  2584  * @element: a #GstElement
       
  2585  * @transition: the requested transition
       
  2586  *
       
  2587  * Perform @transition on @element.
       
  2588  *
       
  2589  * This function must be called with STATE_LOCK held and is mainly used
       
  2590  * internally.
       
  2591  *
       
  2592  * Returns: the #GstStateChangeReturn of the state transition.
       
  2593  */
       
  2594 #ifdef __SYMBIAN32__
       
  2595 EXPORT_C
       
  2596 #endif
       
  2597 
       
  2598 GstStateChangeReturn
       
  2599 gst_element_change_state (GstElement * element, GstStateChange transition)
       
  2600 {
       
  2601   GstElementClass *oclass;
       
  2602   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
       
  2603   GstState current;
       
  2604   GstState next;
       
  2605 
       
  2606   oclass = GST_ELEMENT_GET_CLASS (element);
       
  2607 
       
  2608   /* start with the current state. */
       
  2609   current = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
       
  2610   next = GST_STATE_TRANSITION_NEXT (transition);
       
  2611 
       
  2612   /* call the state change function so it can set the state */
       
  2613   if (oclass->change_state)
       
  2614     ret = (oclass->change_state) (element, transition);
       
  2615   else
       
  2616     ret = GST_STATE_CHANGE_FAILURE;
       
  2617 
       
  2618   switch (ret) {
       
  2619     case GST_STATE_CHANGE_FAILURE:
       
  2620       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2621           "have FAILURE change_state return");
       
  2622       /* state change failure */
       
  2623       gst_element_abort_state (element);
       
  2624       break;
       
  2625     case GST_STATE_CHANGE_ASYNC:
       
  2626     {
       
  2627       GstState target;
       
  2628 
       
  2629       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2630           "element will change state ASYNC");
       
  2631 
       
  2632       target = GST_STATE_TARGET (element);
       
  2633 
       
  2634       if (target > GST_STATE_READY)
       
  2635         goto async;
       
  2636 
       
  2637       /* else we just continue the state change downwards */
       
  2638       GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
       
  2639           "forcing commit state %s <= %s",
       
  2640           gst_element_state_get_name (target),
       
  2641           gst_element_state_get_name (GST_STATE_READY));
       
  2642 
       
  2643       ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
       
  2644       break;
       
  2645     }
       
  2646     case GST_STATE_CHANGE_SUCCESS:
       
  2647       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2648           "element changed state SUCCESS");
       
  2649       /* we can commit the state now which will proceeed to
       
  2650        * the next state */
       
  2651       ret = gst_element_continue_state (element, ret);
       
  2652       break;
       
  2653     case GST_STATE_CHANGE_NO_PREROLL:
       
  2654       GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2655           "element changed state NO_PREROLL");
       
  2656       /* we can commit the state now which will proceeed to
       
  2657        * the next state */
       
  2658       ret = gst_element_continue_state (element, ret);
       
  2659       break;
       
  2660     default:
       
  2661       goto invalid_return;
       
  2662   }
       
  2663 
       
  2664   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit state change %d", ret);
       
  2665 
       
  2666   return ret;
       
  2667 
       
  2668 async:
       
  2669   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit async state change %d",
       
  2670       ret);
       
  2671 
       
  2672   return ret;
       
  2673 
       
  2674   /* ERROR */
       
  2675 invalid_return:
       
  2676   {
       
  2677     GST_OBJECT_LOCK (element);
       
  2678     /* somebody added a GST_STATE_ and forgot to do stuff here ! */
       
  2679     g_critical ("%s: unknown return value %d from a state change function",
       
  2680         GST_ELEMENT_NAME (element), ret);
       
  2681 
       
  2682     /* we are in error now */
       
  2683     ret = GST_STATE_CHANGE_FAILURE;
       
  2684     GST_STATE_RETURN (element) = ret;
       
  2685     GST_OBJECT_UNLOCK (element);
       
  2686 
       
  2687     return ret;
       
  2688   }
       
  2689 }
       
  2690 
       
  2691 /* gst_iterator_fold functions for pads_activate
       
  2692  * Note how we don't stop the iterator when we fail an activation. This is
       
  2693  * probably a FIXME since when one pad activation fails, we don't want to
       
  2694  * continue our state change. */
       
  2695 static gboolean
       
  2696 activate_pads (GstPad * pad, GValue * ret, gboolean * active)
       
  2697 {
       
  2698   if (!gst_pad_set_active (pad, *active))
       
  2699     g_value_set_boolean (ret, FALSE);
       
  2700 
       
  2701   /* unref the object that was reffed for us by _fold */
       
  2702   gst_object_unref (pad);
       
  2703   return TRUE;
       
  2704 }
       
  2705 
       
  2706 /* set the caps on the pad to NULL */
       
  2707 static gboolean
       
  2708 clear_caps (GstPad * pad, GValue * ret, gboolean * active)
       
  2709 {
       
  2710   gst_pad_set_caps (pad, NULL);
       
  2711   gst_object_unref (pad);
       
  2712   return TRUE;
       
  2713 }
       
  2714 
       
  2715 /* returns false on error or early cutout (will never happen because the fold
       
  2716  * function always returns TRUE, see FIXME above) of the fold, true if all
       
  2717  * pads in @iter were (de)activated successfully. */
       
  2718 static gboolean
       
  2719 iterator_activate_fold_with_resync (GstIterator * iter,
       
  2720     GstIteratorFoldFunction func, gpointer user_data)
       
  2721 {
       
  2722   GstIteratorResult ires;
       
  2723   GValue ret = { 0 };
       
  2724 
       
  2725   /* no need to unset this later, it's just a boolean */
       
  2726   g_value_init (&ret, G_TYPE_BOOLEAN);
       
  2727   g_value_set_boolean (&ret, TRUE);
       
  2728 
       
  2729   while (1) {
       
  2730     ires = gst_iterator_fold (iter, func, &ret, user_data);
       
  2731     switch (ires) {
       
  2732       case GST_ITERATOR_RESYNC:
       
  2733         /* need to reset the result again */
       
  2734         g_value_set_boolean (&ret, TRUE);
       
  2735         gst_iterator_resync (iter);
       
  2736         break;
       
  2737       case GST_ITERATOR_DONE:
       
  2738         /* all pads iterated, return collected value */
       
  2739         goto done;
       
  2740       default:
       
  2741         /* iterator returned _ERROR or premature end with _OK,
       
  2742          * mark an error and exit */
       
  2743         g_value_set_boolean (&ret, FALSE);
       
  2744         goto done;
       
  2745     }
       
  2746   }
       
  2747 done:
       
  2748   /* return collected value */
       
  2749   return g_value_get_boolean (&ret);
       
  2750 }
       
  2751 
       
  2752 /* is called with STATE_LOCK
       
  2753  *
       
  2754  * Pads are activated from source pads to sinkpads.
       
  2755  */
       
  2756 static gboolean
       
  2757 gst_element_pads_activate (GstElement * element, gboolean active)
       
  2758 {
       
  2759   GstIterator *iter;
       
  2760   gboolean res;
       
  2761 
       
  2762   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
       
  2763       "pads_activate with active %d", active);
       
  2764 
       
  2765   iter = gst_element_iterate_src_pads (element);
       
  2766   res =
       
  2767       iterator_activate_fold_with_resync (iter,
       
  2768       (GstIteratorFoldFunction) activate_pads, &active);
       
  2769   gst_iterator_free (iter);
       
  2770   if (G_UNLIKELY (!res))
       
  2771     goto src_failed;
       
  2772 
       
  2773   iter = gst_element_iterate_sink_pads (element);
       
  2774   res =
       
  2775       iterator_activate_fold_with_resync (iter,
       
  2776       (GstIteratorFoldFunction) activate_pads, &active);
       
  2777   gst_iterator_free (iter);
       
  2778   if (G_UNLIKELY (!res))
       
  2779     goto sink_failed;
       
  2780 
       
  2781   if (!active) {
       
  2782     /* clear the caps on all pads, this should never fail */
       
  2783     iter = gst_element_iterate_pads (element);
       
  2784     res =
       
  2785         iterator_activate_fold_with_resync (iter,
       
  2786         (GstIteratorFoldFunction) clear_caps, &active);
       
  2787     gst_iterator_free (iter);
       
  2788     if (G_UNLIKELY (!res))
       
  2789       goto caps_failed;
       
  2790   }
       
  2791 
       
  2792   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
       
  2793       "pads_activate successful");
       
  2794 
       
  2795   return TRUE;
       
  2796 
       
  2797   /* ERRORS */
       
  2798 src_failed:
       
  2799   {
       
  2800     GST_DEBUG_OBJECT (element, "source pads_activate failed");
       
  2801     return FALSE;
       
  2802   }
       
  2803 sink_failed:
       
  2804   {
       
  2805     GST_DEBUG_OBJECT (element, "sink pads_activate failed");
       
  2806     return FALSE;
       
  2807   }
       
  2808 caps_failed:
       
  2809   {
       
  2810     GST_DEBUG_OBJECT (element, "failed to clear caps on pads");
       
  2811     return FALSE;
       
  2812   }
       
  2813 }
       
  2814 
       
  2815 /* is called with STATE_LOCK */
       
  2816 static GstStateChangeReturn
       
  2817 gst_element_change_state_func (GstElement * element, GstStateChange transition)
       
  2818 {
       
  2819   GstState state, next;
       
  2820   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
       
  2821 
       
  2822   g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
       
  2823 
       
  2824   state = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
       
  2825   next = GST_STATE_TRANSITION_NEXT (transition);
       
  2826 
       
  2827   /* if the element already is in the given state, we just return success */
       
  2828   if (next == GST_STATE_VOID_PENDING || state == next)
       
  2829     goto was_ok;
       
  2830 
       
  2831   GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
       
  2832       "default handler tries setting state from %s to %s (%04x)",
       
  2833       gst_element_state_get_name (state),
       
  2834       gst_element_state_get_name (next), transition);
       
  2835 
       
  2836   switch (transition) {
       
  2837     case GST_STATE_CHANGE_NULL_TO_READY:
       
  2838       break;
       
  2839     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  2840       if (!gst_element_pads_activate (element, TRUE)) {
       
  2841         result = GST_STATE_CHANGE_FAILURE;
       
  2842       }
       
  2843       break;
       
  2844     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
       
  2845       break;
       
  2846     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
       
  2847       break;
       
  2848     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  2849     case GST_STATE_CHANGE_READY_TO_NULL:
       
  2850       /* deactivate pads in both cases, since they are activated on
       
  2851          ready->paused but the element might not have made it to paused */
       
  2852       if (!gst_element_pads_activate (element, FALSE)) {
       
  2853         result = GST_STATE_CHANGE_FAILURE;
       
  2854       } else {
       
  2855         gst_element_set_base_time (element, 0);
       
  2856       }
       
  2857       break;
       
  2858     default:
       
  2859       /* this will catch real but unhandled state changes;
       
  2860        * can only be caused by:
       
  2861        * - a new state was added
       
  2862        * - somehow the element was asked to jump across an intermediate state
       
  2863        */
       
  2864       g_warning ("Unhandled state change from %s to %s",
       
  2865           gst_element_state_get_name (state),
       
  2866           gst_element_state_get_name (next));
       
  2867       break;
       
  2868   }
       
  2869   return result;
       
  2870 
       
  2871 was_ok:
       
  2872   {
       
  2873     GST_OBJECT_LOCK (element);
       
  2874     result = GST_STATE_RETURN (element);
       
  2875     GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
       
  2876         "element is already in the %s state",
       
  2877         gst_element_state_get_name (state));
       
  2878     GST_OBJECT_UNLOCK (element);
       
  2879 
       
  2880     return result;
       
  2881   }
       
  2882 }
       
  2883 
       
  2884 /**
       
  2885  * gst_element_get_factory:
       
  2886  * @element: a #GstElement to request the element factory of.
       
  2887  *
       
  2888  * Retrieves the factory that was used to create this element.
       
  2889  *
       
  2890  * Returns: the #GstElementFactory used for creating this element.
       
  2891  * no refcounting is needed.
       
  2892  */
       
  2893 #ifdef __SYMBIAN32__
       
  2894 EXPORT_C
       
  2895 #endif
       
  2896 
       
  2897 GstElementFactory *
       
  2898 gst_element_get_factory (GstElement * element)
       
  2899 {
       
  2900   g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
       
  2901 
       
  2902   return GST_ELEMENT_GET_CLASS (element)->elementfactory;
       
  2903 }
       
  2904 
       
  2905 static void
       
  2906 gst_element_dispose (GObject * object)
       
  2907 {
       
  2908   GstElement *element = GST_ELEMENT (object);
       
  2909   GstClock **clock_p;
       
  2910   GstBus **bus_p;
       
  2911 
       
  2912   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose");
       
  2913 
       
  2914   if (GST_STATE (element) != GST_STATE_NULL)
       
  2915     goto not_null;
       
  2916 
       
  2917   GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
       
  2918       "removing %d pads", g_list_length (element->pads));
       
  2919   /* first we break all our links with the outside */
       
  2920   while (element->pads && element->pads->data) {
       
  2921     /* don't call _remove_pad with NULL */
       
  2922     gst_element_remove_pad (element, GST_PAD_CAST (element->pads->data));
       
  2923   }
       
  2924   if (G_UNLIKELY (element->pads != 0)) {
       
  2925     g_critical ("could not remove pads from element %s",
       
  2926         GST_STR_NULL (GST_OBJECT_NAME (object)));
       
  2927   }
       
  2928 
       
  2929   GST_OBJECT_LOCK (element);
       
  2930   clock_p = &element->clock;
       
  2931   bus_p = &element->bus;
       
  2932   gst_object_replace ((GstObject **) clock_p, NULL);
       
  2933   gst_object_replace ((GstObject **) bus_p, NULL);
       
  2934   GST_OBJECT_UNLOCK (element);
       
  2935 
       
  2936   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "parent class dispose");
       
  2937 
       
  2938   G_OBJECT_CLASS (parent_class)->dispose (object);
       
  2939 
       
  2940   return;
       
  2941 
       
  2942   /* ERRORS */
       
  2943 not_null:
       
  2944   {
       
  2945     g_critical
       
  2946         ("\nTrying to dispose element %s, but it is not in the NULL state.\n"
       
  2947         "You need to explicitly set elements to the NULL state before\n"
       
  2948         "dropping the final reference, to allow them to clean up.\n",
       
  2949         GST_OBJECT_NAME (element));
       
  2950     return;
       
  2951   }
       
  2952 }
       
  2953 
       
  2954 static void
       
  2955 gst_element_finalize (GObject * object)
       
  2956 {
       
  2957   GstElement *element = GST_ELEMENT (object);
       
  2958 
       
  2959   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
       
  2960 
       
  2961   GST_STATE_LOCK (element);
       
  2962   if (element->state_cond)
       
  2963     g_cond_free (element->state_cond);
       
  2964   element->state_cond = NULL;
       
  2965   GST_STATE_UNLOCK (element);
       
  2966   g_static_rec_mutex_free (element->state_lock);
       
  2967   g_free (element->state_lock);
       
  2968   element->state_lock = NULL;
       
  2969 
       
  2970   GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
       
  2971 
       
  2972   G_OBJECT_CLASS (parent_class)->finalize (object);
       
  2973 }
       
  2974 
       
  2975 #ifndef GST_DISABLE_LOADSAVE
       
  2976 /**
       
  2977  * gst_element_save_thyself:
       
  2978  * @element: a #GstElement to save.
       
  2979  * @parent: the xml parent node.
       
  2980  *
       
  2981  * Saves the element as part of the given XML structure.
       
  2982  *
       
  2983  * Returns: the new #xmlNodePtr.
       
  2984  */
       
  2985 static xmlNodePtr
       
  2986 gst_element_save_thyself (GstObject * object, xmlNodePtr parent)
       
  2987 {
       
  2988   GList *pads;
       
  2989   GstElementClass *oclass;
       
  2990   GParamSpec **specs, *spec;
       
  2991   guint nspecs;
       
  2992   guint i;
       
  2993   GValue value = { 0, };
       
  2994   GstElement *element;
       
  2995 
       
  2996   g_return_val_if_fail (GST_IS_ELEMENT (object), parent);
       
  2997 
       
  2998   element = GST_ELEMENT (object);
       
  2999 
       
  3000   oclass = GST_ELEMENT_GET_CLASS (element);
       
  3001 
       
  3002   xmlNewChild (parent, NULL, (xmlChar *) "name",
       
  3003       (xmlChar *) GST_ELEMENT_NAME (element));
       
  3004 
       
  3005   if (oclass->elementfactory != NULL) {
       
  3006     GstElementFactory *factory = (GstElementFactory *) oclass->elementfactory;
       
  3007 
       
  3008     xmlNewChild (parent, NULL, (xmlChar *) "type",
       
  3009         (xmlChar *) GST_PLUGIN_FEATURE (factory)->name);
       
  3010   }
       
  3011 
       
  3012   /* params */
       
  3013   specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &nspecs);
       
  3014 
       
  3015   for (i = 0; i < nspecs; i++) {
       
  3016     spec = specs[i];
       
  3017     if (spec->flags & G_PARAM_READABLE) {
       
  3018       xmlNodePtr param;
       
  3019       char *contents;
       
  3020 
       
  3021       g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (spec));
       
  3022 
       
  3023       g_object_get_property (G_OBJECT (element), spec->name, &value);
       
  3024       param = xmlNewChild (parent, NULL, (xmlChar *) "param", NULL);
       
  3025       xmlNewChild (param, NULL, (xmlChar *) "name", (xmlChar *) spec->name);
       
  3026 
       
  3027       if (G_IS_PARAM_SPEC_STRING (spec))
       
  3028         contents = g_value_dup_string (&value);
       
  3029       else if (G_IS_PARAM_SPEC_ENUM (spec))
       
  3030         contents = g_strdup_printf ("%d", g_value_get_enum (&value));
       
  3031       else if (G_IS_PARAM_SPEC_INT64 (spec))
       
  3032         contents = g_strdup_printf ("%" G_GINT64_FORMAT,
       
  3033             g_value_get_int64 (&value));
       
  3034       else
       
  3035         contents = g_strdup_value_contents (&value);
       
  3036 
       
  3037       xmlNewChild (param, NULL, (xmlChar *) "value", (xmlChar *) contents);
       
  3038       g_free (contents);
       
  3039 
       
  3040       g_value_unset (&value);
       
  3041     }
       
  3042   }
       
  3043 
       
  3044   g_free (specs);
       
  3045 
       
  3046   pads = GST_ELEMENT_PADS (element);
       
  3047 
       
  3048   while (pads) {
       
  3049     GstPad *pad = GST_PAD_CAST (pads->data);
       
  3050 
       
  3051     /* figure out if it's a direct pad or a ghostpad */
       
  3052     if (GST_ELEMENT (GST_OBJECT_PARENT (pad)) == element) {
       
  3053       xmlNodePtr padtag = xmlNewChild (parent, NULL, (xmlChar *) "pad", NULL);
       
  3054 
       
  3055       gst_object_save_thyself (GST_OBJECT_CAST (pad), padtag);
       
  3056     }
       
  3057     pads = g_list_next (pads);
       
  3058   }
       
  3059 
       
  3060   return parent;
       
  3061 }
       
  3062 
       
  3063 static void
       
  3064 gst_element_restore_thyself (GstObject * object, xmlNodePtr self)
       
  3065 {
       
  3066   xmlNodePtr children;
       
  3067   GstElement *element;
       
  3068   gchar *name = NULL;
       
  3069   gchar *value = NULL;
       
  3070 
       
  3071   element = GST_ELEMENT (object);
       
  3072   g_return_if_fail (element != NULL);
       
  3073 
       
  3074   /* parameters */
       
  3075   children = self->xmlChildrenNode;
       
  3076   while (children) {
       
  3077     if (!strcmp ((char *) children->name, "param")) {
       
  3078       xmlNodePtr child = children->xmlChildrenNode;
       
  3079 
       
  3080       while (child) {
       
  3081         if (!strcmp ((char *) child->name, "name")) {
       
  3082           name = (gchar *) xmlNodeGetContent (child);
       
  3083         } else if (!strcmp ((char *) child->name, "value")) {
       
  3084           value = (gchar *) xmlNodeGetContent (child);
       
  3085         }
       
  3086         child = child->next;
       
  3087       }
       
  3088       /* FIXME: can this just be g_object_set ? */
       
  3089       gst_util_set_object_arg (G_OBJECT (element), name, value);
       
  3090       /* g_object_set (G_OBJECT (element), name, value, NULL); */
       
  3091       g_free (name);
       
  3092       g_free (value);
       
  3093     }
       
  3094     children = children->next;
       
  3095   }
       
  3096 
       
  3097   /* pads */
       
  3098   children = self->xmlChildrenNode;
       
  3099   while (children) {
       
  3100     if (!strcmp ((char *) children->name, "pad")) {
       
  3101       gst_pad_load_and_link (children, GST_OBJECT_CAST (element));
       
  3102     }
       
  3103     children = children->next;
       
  3104   }
       
  3105 
       
  3106   if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
       
  3107     (GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
       
  3108 }
       
  3109 #endif /* GST_DISABLE_LOADSAVE */
       
  3110 
       
  3111 static void
       
  3112 gst_element_set_bus_func (GstElement * element, GstBus * bus)
       
  3113 {
       
  3114   GstBus **bus_p;
       
  3115 
       
  3116   g_return_if_fail (GST_IS_ELEMENT (element));
       
  3117 
       
  3118   GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
       
  3119 
       
  3120   GST_OBJECT_LOCK (element);
       
  3121   bus_p = &GST_ELEMENT_BUS (element);
       
  3122   gst_object_replace ((GstObject **) bus_p, GST_OBJECT_CAST (bus));
       
  3123   GST_OBJECT_UNLOCK (element);
       
  3124 }
       
  3125 
       
  3126 /**
       
  3127  * gst_element_set_bus:
       
  3128  * @element: a #GstElement to set the bus of.
       
  3129  * @bus: the #GstBus to set.
       
  3130  *
       
  3131  * Sets the bus of the element. Increases the refcount on the bus.
       
  3132  * For internal use only, unless you're testing elements.
       
  3133  *
       
  3134  * MT safe.
       
  3135  */
       
  3136 #ifdef __SYMBIAN32__
       
  3137 EXPORT_C
       
  3138 #endif
       
  3139 
       
  3140 void
       
  3141 gst_element_set_bus (GstElement * element, GstBus * bus)
       
  3142 {
       
  3143   GstElementClass *oclass;
       
  3144 
       
  3145   g_return_if_fail (GST_IS_ELEMENT (element));
       
  3146 
       
  3147   oclass = GST_ELEMENT_GET_CLASS (element);
       
  3148 
       
  3149   if (oclass->set_bus)
       
  3150     oclass->set_bus (element, bus);
       
  3151 }
       
  3152 
       
  3153 /**
       
  3154  * gst_element_get_bus:
       
  3155  * @element: a #GstElement to get the bus of.
       
  3156  *
       
  3157  * Returns the bus of the element. Note that only a #GstPipeline will provide a
       
  3158  * bus for the application.
       
  3159  *
       
  3160  * Returns: the element's #GstBus. unref after usage.
       
  3161  *
       
  3162  * MT safe.
       
  3163  */
       
  3164 #ifdef __SYMBIAN32__
       
  3165 EXPORT_C
       
  3166 #endif
       
  3167 
       
  3168 GstBus *
       
  3169 gst_element_get_bus (GstElement * element)
       
  3170 {
       
  3171   GstBus *result = NULL;
       
  3172 
       
  3173   g_return_val_if_fail (GST_IS_ELEMENT (element), result);
       
  3174 
       
  3175   GST_OBJECT_LOCK (element);
       
  3176   if ((result = GST_ELEMENT_BUS (element)))
       
  3177     gst_object_ref (result);
       
  3178   GST_OBJECT_UNLOCK (element);
       
  3179 
       
  3180   GST_CAT_DEBUG_OBJECT (GST_CAT_BUS, element, "got bus %" GST_PTR_FORMAT,
       
  3181       result);
       
  3182 
       
  3183   return result;
       
  3184 }