// -*- c++ -*-
// Generated by gtkmmproc -- DO NOT MODIFY!
#ifndef _GSTREAMERMM_ELEMENT_H
#define _GSTREAMERMM_ELEMENT_H


#include <glibmm.h>

/* gstreamermm - a C++ wrapper for gstreamer
 *
 * Copyright 2008 The gstreamermm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gst/gstelement.h>
#include <gstreamermm/object.h>
#include <gstreamermm/clock.h>
#include <gstreamermm/enums.h>
#include <gstreamermm/error.h>
#include <gstreamermm/event.h>
#include <gstreamermm/message.h>
#include <gstreamermm/query.h>


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _GstElement GstElement;
typedef struct _GstElementClass GstElementClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{ class Element_Class; } // namespace Gst
namespace Gst
{

/** @defgroup GstBaseClasses gstreamermm Base Classes
 *  Wrapped GStreamer base classes (plug-ins derrive from these).
 */

/** @defgroup GstPlugins gstreamermm Plugins
 *  Wrapped GStreamer plugins.
 */

 /** @defgroup GstInterfaces gstreamermm Interfaces
 *  Wrapped GStreamer interfaces and classes related to them.
 */

class Bus;
class Caps;
class Clock;
class ElementFactory;
class Event;
class Index;
class Interface;
class Message;
class Pad;
class PadTemplate;
class Query;
class TagList;

//Gst::Iterator<> forward declaration.
template <class CppType>
class Iterator;

/** @addtogroup gstreamermmEnums gstreamermm Enums and Flags */

/**
 * @ingroup gstreamermmEnums
 * @par Bitwise operators:
 * <tt>%ElementFlags operator|(ElementFlags, ElementFlags)</tt><br>
 * <tt>%ElementFlags operator&(ElementFlags, ElementFlags)</tt><br>
 * <tt>%ElementFlags operator^(ElementFlags, ElementFlags)</tt><br>
 * <tt>%ElementFlags operator~(ElementFlags)</tt><br>
 * <tt>%ElementFlags& operator|=(ElementFlags&, ElementFlags)</tt><br>
 * <tt>%ElementFlags& operator&=(ElementFlags&, ElementFlags)</tt><br>
 * <tt>%ElementFlags& operator^=(ElementFlags&, ElementFlags)</tt><br>
 */
enum ElementFlags
{
  ELEMENT_LOCKED_STATE = (GST_OBJECT_FLAG_LAST << 0),
  ELEMENT_IS_SINK = (GST_OBJECT_FLAG_LAST << 1),
  ELEMENT_UNPARENTING = (GST_OBJECT_FLAG_LAST << 2),
  ELEMENT_FLAG_LAST = (GST_OBJECT_FLAG_LAST << 16)
};

/** @ingroup gstreamermmEnums */
inline ElementFlags operator|(ElementFlags lhs, ElementFlags rhs)
  { return static_cast<ElementFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline ElementFlags operator&(ElementFlags lhs, ElementFlags rhs)
  { return static_cast<ElementFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline ElementFlags operator^(ElementFlags lhs, ElementFlags rhs)
  { return static_cast<ElementFlags>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); }

/** @ingroup gstreamermmEnums */
inline ElementFlags operator~(ElementFlags flags)
  { return static_cast<ElementFlags>(~static_cast<unsigned>(flags)); }

/** @ingroup gstreamermmEnums */
inline ElementFlags& operator|=(ElementFlags& lhs, ElementFlags rhs)
  { return (lhs = static_cast<ElementFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); }

/** @ingroup gstreamermmEnums */
inline ElementFlags& operator&=(ElementFlags& lhs, ElementFlags rhs)
  { return (lhs = static_cast<ElementFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); }

/** @ingroup gstreamermmEnums */
inline ElementFlags& operator^=(ElementFlags& lhs, ElementFlags rhs)
  { return (lhs = static_cast<ElementFlags>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); }

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::ElementFlags> : public Glib::Value_Flags<Gst::ElementFlags>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{


//TODO: Fix gmmproc so that definition in gst_enums.defs does not cause errors
//and this can be wrapped with _WRAP_ENUM.
enum StateChange
{
  STATE_CHANGE_NULL_TO_READY = GST_STATE_CHANGE_NULL_TO_READY,
  STATE_CHANGE_READY_TO_PAUSED = GST_STATE_CHANGE_READY_TO_PAUSED,
  STATE_CHANGE_PAUSED_TO_PLAYING = GST_STATE_CHANGE_PAUSED_TO_PLAYING,
  STATE_CHANGE_PLAYING_TO_PAUSED = GST_STATE_CHANGE_PLAYING_TO_PAUSED,
  STATE_CHANGE_PAUSED_TO_READY = GST_STATE_CHANGE_PAUSED_TO_READY,
  STATE_CHANGE_READY_TO_NULL = GST_STATE_CHANGE_READY_TO_NULL 
};

/**
 * @ingroup gstreamermmEnums
 */
enum StateChangeReturn
{
  STATE_CHANGE_FAILURE,
  STATE_CHANGE_SUCCESS,
  STATE_CHANGE_ASYNC,
  STATE_CHANGE_NO_PREROLL
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gst::StateChangeReturn> : public Glib::Value_Enum<Gst::StateChangeReturn>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gst
{


namespace Enums
{

/**  Gets a string representing the given state.
 *
 * @param state A Gst::State to get the name of.
 * @return A Glib::ustring with the name of the state.
 */
Glib::ustring get_name(State state);

/** Gets a string representing the given state change result.
 *
 * @param state_ret A Gst::StateChangeReturn to get the name of.
 * @return A Glib::ustring with the name of the state change result.
 */
Glib::ustring get_name(StateChangeReturn state_ret);

} //namespace Enums

/** The abstract base class for all pipeline elements.
 * Gst::Element is the abstract base class needed to construct an element that
 * can be used in a GStreamer pipeline. Please refer to the plugin writers
 * guide for more information on creating Gst::Element subclasses.
 *
 * The name of a Gst::Element can be get with get_name() and set with
 * set_name().
 *
 * All elements have pads (of the type Gst::Pad). These pads link to pads on
 * other elements. Gst::Buffer flow between these linked pads. An Element has a
 * GList of Gst::Pad structures for all their input (or sink) and output (or
 * source) pads.  Core and plug-in writers can add and remove pads with
 * add_pad() and remove_pad().
 *
 * A pad of an element can be retrieved by name with get_request_pad() or
 * get_static_pad(). An iterator of all pads can be retrieved with
 * iterate_pads().
 *
 * Gst::Elements can be linked through their pads. Use the link() function to
 * link elements. Use link_filtered() to link two elements constrained by a
 * specified set of Gst::Caps. For finer control, use link_pads() and
 * link_pads_filtered() to specify the pads to link on each element by name.
 *
 * Each element has a state (see State). You can get and set the state of an
 * element with get_state() and set_state(). To get a string representation of
 * a State, use Gst::Enums::get_name().
 *
 * You can get and set a Clock on an element using get_clock() and set_clock().
 * Some elements can provide a clock for the pipeline if provides_clock()
 * returns true. With the provide_clock() method one can retrieve the clock
 * provided by such an element. Not all elements require a clock to operate
 * correctly. If requires_clock() returns true, a clock should be set on the
 * element with set_clock().
 *
 * Note that clock slection and distribution is normally handled by the
 * toplevel Gst::Pipeline so the clock functions are only to be used in very
 * specific situations.
 *
 * Last reviewed on 2006-03-12 (0.10.5).
 * @ingroup GstBaseClasses
 */

class Element : public Gst::Object
{
  
#ifndef DOXYGEN_SHOULD_SKIP_THIS

public:
  typedef Element CppObjectType;
  typedef Element_Class CppClassType;
  typedef GstElement BaseObjectType;
  typedef GstElementClass BaseClassType;

private:  friend class Element_Class;
  static CppClassType element_class_;

private:
  // noncopyable
  Element(const Element&);
  Element& operator=(const Element&);

protected:
  explicit Element(const Glib::ConstructParams& construct_params);
  explicit Element(GstElement* castitem);

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~Element();

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  static GType get_type()      G_GNUC_CONST;


  static GType get_base_type() G_GNUC_CONST;
#endif

  ///Provides access to the underlying C GObject.
  GstElement*       gobj()       { return reinterpret_cast<GstElement*>(gobject_); }

  ///Provides access to the underlying C GObject.
  const GstElement* gobj() const { return reinterpret_cast<GstElement*>(gobject_); }

  ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
  GstElement* gobj_copy();

private:


protected:
  //Needed for ElementInterfaced derived class
  Element();

public:
  /** Links this source element to the @dest element.
   * The link must be from source to destination - the other direction will not
   * be tried.  The function looks for existing pads that aren't linked yet. It
   * will request new pads if necessary. Such pads need to be released manually
   * when unlinking.  If multiple links are possible, only one is established.
   *
   * Make sure you have added your elements to a bin or pipeline with
   * Gst::Bin::add() before trying to link them.
   *
   * @param dest the Gst::Element containing the destination pad.
   * @return the destination element for further linking if desired.
   * @throws std::runtime_error If the elements could not be linked.
   */
  Glib::RefPtr<Gst::Element> link(const Glib::RefPtr<Gst::Element>& dest);
  

  /** Adds a pad (link point) to @a element. @a pad's parent will be set to @a element;
   * see Gst::Object::set_parent() for refcounting information.
   * 
   * Pads are not automatically activated so elements should perform the needed
   * steps to activate the pad in case this pad is added in the PAUSED or PLAYING
   * state. See Gst::Pad::set_active() for more information about activating pads.
   * 
   * The pad and the element should be unlocked when calling this function.
   * 
   * This function will emit the Gst::Element::pad-added signal on the element.
   * @param pad The Gst::Pad to add to the element.
   * @return <tt>true</tt> if the pad could be added. This function can fail when
   * a pad with the same name already existed or the pad already had another
   * parent.
   * 
   * MT safe.
   */
  bool add_pad(const Glib::RefPtr<Gst::Pad>& pad);
  
  /** Creates a pad for each pad template that is always available.
   * This function is only useful during object intialization of
   * subclasses of Gst::Element.
   */
  void create_all_pads();

  
  /** Looks for an unlinked pad to which the given pad can link. It is not
   * guaranteed that linking the pads will work, though it should work in most
   * cases.
   * @param pad The Gst::Pad to find a compatible one for.
   * @param caps The Gst::Caps to use as a filter.
   * @return The Gst::Pad to which a link can be made, or <tt>0</tt> if one cannot be
   * found. Gst::Object::unref() after usage.
   */
  Glib::RefPtr<Gst::Pad> create_compatible_pad(const Glib::RefPtr<const Gst::Pad>& pad, const Glib::RefPtr<const Gst::Caps>& caps);
  
  /** Retrieves a pad template from @a element that is compatible with @a compattempl.
   * Pads from compatible templates can be linked together.
   * @param compattempl The Gst::PadTemplate to find a compatible template for.
   * @return A compatible Gst::PadTemplate, or <tt>0</tt> if none was found. No
   * unreferencing is necessary.
   */
  Glib::RefPtr<Gst::PadTemplate> get_compatible_pad_template(const Glib::RefPtr<const Gst::PadTemplate>& compattempl);
  
  /** Retrieves a pad template from @a element that is compatible with @a compattempl.
   * Pads from compatible templates can be linked together.
   * @param compattempl The Gst::PadTemplate to find a compatible template for.
   * @return A compatible Gst::PadTemplate, or <tt>0</tt> if none was found. No
   * unreferencing is necessary.
   */
  Glib::RefPtr<const Gst::PadTemplate> get_compatible_pad_template(const Glib::RefPtr<const Gst::PadTemplate>& compattempl) const;

  //TODO: The documentation says "The pad should be released with gst_element_release_request_pad().", which is odd. murrayc
  
  /** Retrieves a pad from the element by name. This version only retrieves
   * request pads. The pad should be released with
   * release_request_pad().
   * @param name The name of the request Gst::Pad to retrieve.
   * @return Requested Gst::Pad if found, otherwise <tt>0</tt>. Release after usage.
   */
  Glib::RefPtr<Gst::Pad> get_request_pad(const Glib::ustring& name);

  
  /** Retrieves a pad from @a element by name. This version only retrieves
   * already-existing (i.e. 'static') pads.
   * @param name The name of the static Gst::Pad to retrieve.
   * @return The requested Gst::Pad if found, otherwise <tt>0</tt>. unref after
   * usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Pad> get_static_pad(const Glib::ustring& name);
  
  /** Retrieves a pad from @a element by name. This version only retrieves
   * already-existing (i.e. 'static') pads.
   * @param name The name of the static Gst::Pad to retrieve.
   * @return The requested Gst::Pad if found, otherwise <tt>0</tt>. unref after
   * usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Pad> get_static_pad(const Glib::ustring& name) const;
  

  /** Use this function to signal that the element does not expect any more pads
   * to show up in the current pipeline. This function should be called whenever
   * pads have been added by the element itself. Elements with Gst::PAD_SOMETIMES
   * pad templates use this in combination with autopluggers to figure out that
   * the element is done initializing its pads.
   * 
   * This function emits the Gst::Element::no-more-pads signal.
   * 
   * MT safe.
   */
  void no_more_pads();

  
  /** Makes the element free the previously requested pad as obtained with
   * get_request_pad().
   * MT safe.
   * @param pad The Gst::Pad to release.
   */
  void release_request_pad(const Glib::RefPtr<Gst::Pad>& pad);

  
  /** Removes @a pad from @a element. @a pad will be destroyed if it has not been
   * referenced elsewhere using Gst::Object::unparent().
   * 
   * This function is used by plugin developers and should not be used
   * by applications. Pads that were dynamically requested from elements
   * with get_request_pad() should be released with the
   * release_request_pad() function instead.
   * 
   * Pads are not automatically deactivated so elements should perform the needed
   * steps to deactivate the pad in case this pad is removed in the PAUSED or
   * PLAYING state. See Gst::Pad::set_active() for more information about
   * deactivating pads.
   * 
   * The pad and the element should be unlocked when calling this function.
   * 
   * This function will emit the Gst::Element::pad-removed signal on the element.
   * @param pad The Gst::Pad to remove from the element.
   * @return <tt>true</tt> if the pad could be removed. Can return <tt>false</tt> if the
   * pad does not belong to the provided element.
   * 
   * MT safe.
   */
  bool remove_pad(const Glib::RefPtr<Gst::Pad>& pad);
  
  /** Retrieves an iterattor of @a element's pads. The iterator should
   * be freed after usage.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<Gst::Pad> iterate_pads();
  
  /** Retrieves an iterattor of @a element's pads. The iterator should
   * be freed after usage.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<const Gst::Pad> iterate_pads() const;
  
  /** Retrieves an iterator of @a element's sink pads.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<Gst::Pad> iterate_sink_pads();
  
  /** Retrieves an iterator of @a element's sink pads.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<const Gst::Pad> iterate_sink_pads() const;
  
  /** Retrieves an iterator of @a element's source pads.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<Gst::Pad> iterate_src_pads();
  
  /** Retrieves an iterator of @a element's source pads.
   * @return The Gst::Iterator of Gst::Pad. Unref each pad after use.
   * 
   * MT safe.
   */
  Gst::Iterator<const Gst::Pad> iterate_src_pads() const;
  
  /** Unlinks all source pads of the source element with all sink pads
   * of the sink element to which they are linked.
   * 
   * If the link has been made using link(), it could have created an
   * requestpad, which has to be released using release_request_pad().
   * @param dest The sink Gst::Element to unlink.
   */
  void unlink(const Glib::RefPtr<Gst::Element>& dest);
  

  //This is not like link() because link() was written to return the
  //destination element as a convenience for further linking to compensate for
  //C API's convenience function gst_element_link_many().
  
  /** Links the two named pads of the source and destination elements.
   * Side effect is that if one of the pads has no parent, it becomes a
   * child of the parent of the other element.  If they have different
   * parents, the link fails.
   * @param srcpadname The name of the Gst::Pad in source element or <tt>0</tt> for any pad.
   * @param dest The Gst::Element containing the destination pad.
   * @param destpadname The name of the Gst::Pad in destination element,
   * or <tt>0</tt> for any pad.
   * @return <tt>true</tt> if the pads could be linked, <tt>false</tt> otherwise.
   */
  bool link_pads(const Glib::ustring& srcpadname, const Glib::RefPtr<Gst::Element>& dest, const Glib::ustring& destpadname);

  
  /** Unlinks the two named pads of the source and destination elements.
   * @param srcpadname The name of the Gst::Pad in source element.
   * @param dest A Gst::Element containing the destination pad.
   * @param destpadname The name of the Gst::Pad in destination element.
   */
  void unlink_pads(const Glib::ustring& srcpadname, const Glib::RefPtr<Gst::Element>& dest, const Glib::ustring& destpadname);

  //This is not like link() because link() was written to return the
  //destination element as a convenience for further linking to compensate for
  //C API's convenience function gst_element_link_many().
  
  /** Links the two named pads of the source and destination elements. Side effect
   * is that if one of the pads has no parent, it becomes a child of the parent of
   * the other element. If they have different parents, the link fails. If @a caps
   * is not #<tt>0</tt>, makes sure that the caps of the link is a subset of @a caps.
   * @param srcpadname The name of the Gst::Pad in source element or <tt>0</tt> for any pad.
   * @param dest The Gst::Element containing the destination pad.
   * @param destpadname The name of the Gst::Pad in destination element or <tt>0</tt> for any pad.
   * @param filter The Gst::Caps to filter the link, or #<tt>0</tt> for no filter.
   * @return <tt>true</tt> if the pads could be linked, <tt>false</tt> otherwise.
   */
  bool link_pads(const Glib::ustring& srcpadname, const Glib::RefPtr<Gst::Element>& dest, const Glib::ustring& destpadname, const Glib::RefPtr<Gst::Caps>& filter);

  /** Links @a src to @a dest using the given caps as filtercaps. The link must
   * be from source to destination; the other direction will not be tried. The
   * function looks for existing pads that aren't linked yet. It will request
   * new pads if necessary. If multiple links are possible, only one is
   * established.
   *
   * Make sure you have added your elements to a bin or pipeline with
   * Gst::Bin::add() before trying to link them.
   *
   * @param dest The Gst::Element containing the destination pad.
   * @param filter The Gst::Caps to filter the link.
   * @return the destination element for further linking if desired.
   * @throws std::runtime_error If the elements could not be linked.
   */
  Glib::RefPtr<Gst::Element> link(const Glib::RefPtr<Gst::Element>& dest, const Glib::RefPtr<Gst::Caps>& filter);
  

  /** Set the base time of an element. See get_base_time().
   * 
   * MT safe.
   * @param time The base time to set.
   */
  void set_base_time(ClockTime time);
  
  /** Returns the base time of the element. The base time is the
   * absolute time of the clock when this element was last put to
   * PLAYING. Subtracting the base time from the clock time gives
   * the running time of the element.
   * @return The base time of the element.
   * 
   * MT safe.
   */
  ClockTime get_base_time() const;
  
  /** Set the start time of an element. The start time of the element is the
   * running time of the element when it last went to the PAUSED state. In READY
   * or after a flushing seek, it is set to 0.
   * 
   * Toplevel elements like Gst::Pipeline will manage the start_time and
   * base_time on its children. Setting the start_time to Gst::CLOCK_TIME_NONE
   * on such a toplevel element will disable the distribution of the base_time to
   * the children and can be useful if the application manages the base_time
   * itself, for example if you want to synchronize capture from multiple
   * pipelines, and you can also ensure that the pipelines have the same clock.
   * 
   * MT safe.
   * 
   * @newin{0,10}.24
   * @param time The base time to set.
   */
  void set_start_time(Gst::ClockTime time);
  
  /** Returns the start time of the element. The start time is the
   * running time of the clock when this element was last put to PAUSED.
   * 
   * Usually the start_time is managed by a toplevel element such as
   * Gst::Pipeline.
   * 
   * MT safe.
   * 
   * @newin{0,10}.24
   * @return The start time of the element.
   */
  Gst::ClockTime get_start_time() const;
  
  /** Sets the bus of the element. Increases the refcount on the bus.
   * For internal use only, unless you're testing elements.
   * 
   * MT safe.
   * @param bus The Gst::Bus to set.
   */
  void set_bus(const Glib::RefPtr<Gst::Bus>& bus);
  
  /** Returns the bus of the element. Note that only a Gst::Pipeline will provide a
   * bus for the application.
   * @return The element's Gst::Bus. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Bus> get_bus();
  
  /** Returns the bus of the element. Note that only a Gst::Pipeline will provide a
   * bus for the application.
   * @return The element's Gst::Bus. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Bus> get_bus() const;
  
  /** Set @a index on the element. The refcount of the index
   * will be increased, any previously set index is unreffed.
   * 
   * MT safe.
   * @param index A Gst::Index.
   */
  void set_index(const Glib::RefPtr<Gst::Index>& index);

  //Note: gst_element_get_index provides a reference.
  
  /** Gets the index from the element.
   * @return A Gst::Index or <tt>0</tt> when no index was set on the
   * element. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Index> get_index();
  
  /** Gets the index from the element.
   * @return A Gst::Index or <tt>0</tt> when no index was set on the
   * element. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Index > get_index() const;

  
  /** Retrieves the factory that was used to create this element.
   * @return The Gst::ElementFactory used for creating this element.
   * no refcounting is needed.
   */
  Glib::RefPtr<Gst::ElementFactory> get_factory();
  
  /** Retrieves the factory that was used to create this element.
   * @return The Gst::ElementFactory used for creating this element.
   * no refcounting is needed.
   */
  Glib::RefPtr<const Gst::ElementFactory> get_factory() const;

  
  /** Queries if the element can be indexed.
   * @return <tt>true</tt> if the element can be indexed.
   * 
   * MT safe.
   */
  bool is_indexable() const;

  // We don't wrap the gst_element_get_name(), gst_element_set_name(), 
  // gst_element_get_parent(), and gst_element_set_parent() macros because they 
  // just calls the base (GstObject) class's functions anyway.

  
  /** Query if the element requires a clock.
   * @return <tt>true</tt> if the element requires a clock
   * 
   * MT safe.
   */
  bool requires_clock() const;
  
  /** Sets the clock for the element. This function increases the
   * refcount on the clock. Any previously set clock on the object
   * is unreffed.
   * @param clock The Gst::Clock to set for the element.
   * @return <tt>true</tt> if the element accepted the clock. An element can refuse a
   * clock when it, for example, is not able to slave its internal clock to the
   *  @a clock or when it requires a specific clock to operate.
   * 
   * MT safe.
   */
  bool set_clock(const Glib::RefPtr<Gst::Clock>& clock);
  
  /** Gets the currently configured clock of the element. This is the clock as was
   * last set with set_clock().
   * @return The Gst::Clock of the element. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Clock> get_clock();
  
  /** Gets the currently configured clock of the element. This is the clock as was
   * last set with set_clock().
   * @return The Gst::Clock of the element. unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Clock> get_clock() const;
  
  /** Query if the element provides a clock. A Gst::Clock provided by an
   * element can be used as the global Gst::Clock for the pipeline.
   * An element that can provide a clock is only required to do so in the PAUSED
   * state, this means when it is fully negotiated and has allocated the resources
   * to operate the clock.
   * @return <tt>true</tt> if the element provides a clock
   * 
   * MT safe.
   */
  bool provides_clock() const;
  
  /** Get the clock provided by the given element.
   * <note>An element is only required to provide a clock in the PAUSED
   * state. Some elements can provide a clock in other states.</note>
   * @return The GstClock provided by the element or <tt>0</tt>
   * if no clock could be provided.  Unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<Gst::Clock> provide_clock();
  
  /** Get the clock provided by the given element.
   * <note>An element is only required to provide a clock in the PAUSED
   * state. Some elements can provide a clock in other states.</note>
   * @return The GstClock provided by the element or <tt>0</tt>
   * if no clock could be provided.  Unref after usage.
   * 
   * MT safe.
   */
  Glib::RefPtr<const Gst::Clock> provide_clock() const;
  
  /** Sets the state of the element. This function will try to set the
   * requested state by going through all the intermediary states and calling
   * the class's state change function for each.
   * 
   * This function can return Gst::STATE_CHANGE_ASYNC, in which case the
   * element will perform the remainder of the state change asynchronously in
   * another thread.
   * An application can use get_state() to wait for the completion
   * of the state change or it can wait for a state change message on the bus.
   * 
   * State changes to Gst::STATE_READY or Gst::STATE_<tt>0</tt> never return
   * Gst::STATE_CHANGE_ASYNC.
   * @param state The element's new Gst::State.
   * @return Result of the state change using Gst::StateChangeReturn.
   * 
   * MT safe.
   */
  StateChangeReturn set_state(State state);
  
  /** Gets the state of the element.
   * 
   * For elements that performed an ASYNC state change, as reported by
   * set_state(), this function will block up to the
   * specified timeout value for the state change to complete.
   * If the element completes the state change or goes into
   * an error, this function returns immediately with a return value of
   * Gst::STATE_CHANGE_SUCCESS or Gst::STATE_CHANGE_FAILURE respectively.
   * 
   * For elements that did not return Gst::STATE_CHANGE_ASYNC, this function
   * returns the current and pending state immediately.
   * 
   * This function returns Gst::STATE_CHANGE_NO_PREROLL if the element
   * successfully changed its state but is not able to provide data yet.
   * This mostly happens for live sources that only produce data in 
   * Gst::STATE_PLAYING. While the state change return is equivalent to
   * Gst::STATE_CHANGE_SUCCESS, it is returned to the application to signal that
   * some sink elements might not be able to complete their state change because
   * an element is not producing data to complete the preroll. When setting the
   * element to playing, the preroll will complete and playback will start.
   * @param state A pointer to Gst::State to hold the state. Can be <tt>0</tt>.
   * @param pending A pointer to Gst::State to hold the pending state.
   * Can be <tt>0</tt>.
   * @param timeout A Gst::ClockTime to specify the timeout for an async
   * state change or Gst::CLOCK_TIME_NONE for infinite timeout.
   * @return Gst::STATE_CHANGE_SUCCESS if the element has no more pending state
   * and the last state change succeeded, Gst::STATE_CHANGE_ASYNC if the
   * element is still performing a state change or
   * Gst::STATE_CHANGE_FAILURE if the last state change failed.
   * 
   * MT safe.
   */
  StateChangeReturn get_state(State& state, State& pending, ClockTime timeout) const;
  
  /** Locks the state of an element, so state changes of the parent don't affect
   * this element anymore.
   * 
   * MT safe.
   * @param locked_state <tt>true</tt> to lock the element's state.
   * @return <tt>true</tt> if the state was changed, <tt>false</tt> if bad parameters were given
   * or the elements state-locking needed no change.
   */
  bool set_locked_state(gboolean locked_state);
  
  /** Checks if the state of an element is locked.
   * If the state of an element is locked, state changes of the parent don't
   * affect the element.
   * This way you can leave currently unused elements inside bins. Just lock their
   * state before changing the state from Gst::STATE_<tt>0</tt>.
   * 
   * MT safe.
   * @return <tt>true</tt>, if the element's state is locked.
   */
  bool is_locked_state() const;
  
  /** Abort the state change of the element. This function is used
   * by elements that do asynchronous state changes and find out
   * something is wrong.
   * 
   * This function should be called with the STATE_LOCK held.
   * 
   * MT safe.
   */
  void abort_state();
  
  /** Commit the state change of the element and proceed to the next
   * pending state if any. This function is used
   * by elements that do asynchronous state changes.
   * The core will normally call this method automatically when an
   * element returned Gst::STATE_CHANGE_SUCCESS from the state change function.
   * 
   * If after calling this method the element still has not reached
   * the pending state, the next state change is performed.
   * 
   * This method is used internally and should normally not be called by plugins
   * or applications.
   * @param ret The previous state return value.
   * @return The result of the commit state change.
   * 
   * MT safe.
   */
  StateChangeReturn continue_state(StateChangeReturn ret);
  
  /** Brings the element to the lost state. This function calls
   * lost_state_full() with the new_base_time set to <tt>true</tt>.
   * 
   * This function is used internally and should normally not be called from
   * plugins or applications.
   * 
   * MT safe.
   */
  void lost_state();
  
  /** Brings the element to the lost state. The current state of the
   * element is copied to the pending state so that any call to
   * get_state() will return Gst::STATE_CHANGE_ASYNC.
   * 
   * An ASYNC_START message is posted with indication to distribute a new
   * base_time to the element when @a new_base_time is <tt>true</tt>.
   * If the element was PLAYING, it will go to PAUSED. The element
   * will be restored to its PLAYING state by the parent pipeline when it
   * prerolls again.
   * 
   * This is mostly used for elements that lost their preroll buffer
   * in the Gst::STATE_PAUSED or Gst::STATE_PLAYING state after a flush,
   * they will go to their pending state again when a new preroll buffer is
   * queued. This function can only be called when the element is currently
   * not in error or an async state change.
   * 
   * This function is used internally and should normally not be called from
   * plugins or applications.
   * 
   * MT safe.
   * 
   * @newin{0,10}.24
   * @param new_base_time If a new base time should be distributed.
   */
  void lost_state(bool new_base_time);
  
  /** Tries to change the state of the element to the same as its parent.
   * If this function returns <tt>false</tt>, the state of element is undefined.
   * @return <tt>true</tt>, if the element's state could be synced to the parent's state.
   * 
   * MT safe.
   */
  bool sync_state_with_parent();
  
  /** Perform @a transition on @a element.
   * 
   * This function must be called with STATE_LOCK held and is mainly used
   * internally.
   * @param transition The requested transition.
   * @return The Gst::StateChangeReturn of the state transition.
   */
  StateChangeReturn change_state(StateChange transition);
  
  /** Posts a message to the bus that new tags were found, and pushes an event
   * to all sourcepads. Takes ownership of the @a list.
   * 
   * This is a utility method for elements. Applications should use the
   * Gst::TagSetter interface.
   * @param list List of tags.
   */
  void found_tags(Gst::TagList& list);
  
  /** Posts a message to the bus that new tags were found and pushes the
   * tags as event. Takes ownership of the @a list.
   * 
   * This is a utility method for elements. Applications should use the
   * Gst::TagSetter interface.
   * @param pad Pad on which to push tag-event.
   * @param list The taglist to post on the bus and create event from.
   */
  void found_tags_for_pad(const Glib::RefPtr<Gst::Pad>& pad, Gst::TagList& list);

  /** Post an error, warning or info message on the bus from inside an element.
   *
   * type must be of Gst::MESSAGE_ERROR, Gst::MESSAGE_WARNING or
   * Gst::MESSAGE_INFO.
   *
   * MT safe.
   *
   * @param code The GError code belonging to the domain.
   * @param line The source code line where the error was generated.
   * @param type The GstMessageType.
   * @param domain The GStreamer GError domain this message belongs to.
   * @param text A text string to be used as a replacement for the default
   * message connected to code.
   * @param debug A debug message to be used as a replacement for the default
   * debugging information.
   * @param file The source code file where the error was generated.
   * @param function The source code function where the error was generated.
   */
  void post_message(int code, int line, MessageType type = Gst::MESSAGE_INFO,
    const Glib::QueryQuark& domain = get_core_error_quark(),
    const Glib::ustring& text = Glib::ustring(),
    const Glib::ustring& debug = Glib::ustring(),
    const Glib::ustring& file = Glib::ustring(),
    const Glib::ustring& function = Glib::ustring());
  

  /** Post a message on the element's Gst::Bus. This function takes ownership of the
   * message; if you want to access the message after this call, you should add an
   * additional reference before calling.
   * @param message A Gst::Message to post.
   * @return <tt>true</tt> if the message was successfully posted. The function returns
   * <tt>false</tt> if the element did not have a bus.
   * 
   * MT safe.
   */
  bool post_message(const Glib::RefPtr<Gst::Message>& message);

 
  /** Get an array of query types from the element.
   * If the element doesn't implement a query types function,
   * the query will be forwarded to the peer of a random linked sink pad.
   * @return An array of Gst::QueryType elements that should not
   * be freed or modified.
   * 
   * MT safe.
   */
  Glib::ArrayHandle<QueryType> get_query_types() const;

  
  /** Performs a query on the given element.
   * 
   * For elements that don't implement a query handler, this function
   * forwards the query to a random srcpad or to the peer of a
   * random linked sinkpad of this element.
   * @param query The Gst::Query.
   * @return <tt>true</tt> if the query could be performed.
   * 
   * MT safe.
   */
  bool query(const Glib::RefPtr<Gst::Query>& query) const;
  
  /** Queries an element to convert @a src_val in @a src_format to @a dest_format.
   * @param src_format A Gst::Format to convert from.
   * @param src_val A value to convert.
   * @param dest_format A pointer to the Gst::Format to convert to.
   * @param dest_val A pointer to the result.
   * @return <tt>true</tt> if the query could be performed.
   */
  bool query_convert(Format src_format, gint64 src_val, Format& dest_format, gint64& dest_val) const;
  
  /** Queries an element for the stream position.
   * @param format A pointer to the Gst::Format asked for.
   * On return contains the Gst::Format used.
   * @param cur A location in which to store the current position, or <tt>0</tt>.
   * @return <tt>true</tt> if the query could be performed.
   */
  bool query_position(Format& format, gint64& cur) const;

  /** Queries an element for the stream position.
   *
   * @param format A pointer to the Gst::Format asked for. On return will
   * contain the Gst::Format used.
   * @return true if the query could be performed.
   */
  bool query_position(Format& format) const;

  
  /** Queries an element for the total stream duration.
   * @param format A pointer to the Gst::Format asked for.
   * On return contains the Gst::Format used.
   * @param duration A location in which to store the total duration, or <tt>0</tt>.
   * @return <tt>true</tt> if the query could be performed.
   */
  bool query_duration(Format& format, gint64& duration) const;

  /** Queries an element for the total stream duration.
   *
   * @param format A pointer to the Gst::Format asked for. On return contains
   * the Gst::Format used.
   * @return true if the query could be performed.
   */
  bool query_duration(Format& format) const;

  
  /** Simple API to perform a seek on the given element, meaning it just seeks
   * to the given position relative to the start of the stream. For more complex
   * operations like segment seeks (e.g. for looping) or changing the playback
   * rate or seeking relative to the last configured playback segment you should
   * use seek().
   * 
   * In a completely prerolled PAUSED or PLAYING pipeline, seeking is always
   * guaranteed to return <tt>true</tt> on a seekable media type or <tt>false</tt> when the media
   * type is certainly not seekable (such as a live stream).
   * 
   * Some elements allow for seeking in the READY state, in this
   * case they will store the seek event and execute it when they are put to
   * PAUSED. If the element supports seek in READY, it will always return <tt>true</tt> when
   * it receives the event in the READY state.
   * 
   * @newin{0,10}.7
   * @param format A Gst::Format to execute the seek in, such as Gst::FORMAT_TIME.
   * @param seek_flags Seek options; playback applications will usually want to use
   * GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT here.
   * @param seek_pos Position to seek to (relative to the start); if you are doing
   * a seek in Gst::FORMAT_TIME this value is in nanoseconds -
   * multiply with Gst::SECOND to convert seconds to nanoseconds or
   * with Gst::MSECOND to convert milliseconds to nanoseconds.
   * @return <tt>true</tt> if the seek operation succeeded (the seek might not always be
   * executed instantly though).
   */
  bool seek(Format format, SeekFlags seek_flags, gint64 seek_pos);
  
  /** Sends a seek event to an element. See Gst::Event::new_seek() for the details of
   * the parameters. The seek event is sent to the element using
   * send_event().
   * @param rate The new playback rate.
   * @param format The format of the seek values.
   * @param flags The optional seek flags.
   * @param cur_type The type and flags for the new current position.
   * @param cur The value of the new current position.
   * @param stop_type The type and flags for the new stop position.
   * @param stop The value of the new stop position.
   * @return <tt>true</tt> if the event was handled.
   * 
   * MT safe.
   */
  bool seek(double rate, Format format, SeekFlags flags, SeekType cur_type, gint64 cur, SeekType stop_type, gint64 stop);

  /** Sends an event to an element. If the element doesn't implement an event
   * handler, the event will be pushed on a random linked sink pad for upstream
   * events or a random linked source pad for downstream events.
   *
   * This function takes owership of the provided event.
   *
   * @param event The Gst::Event to send to the element.
   * @return true if the event was handled. MT safe. 
   */
  bool send_event(const Glib::RefPtr<Gst::Event>& event);
  

  /** Test whether the given element implements a certain interface of type
   * iface_type, and test whether it is supported for this specific instance.
   * @param iface_type (final) type of the interface which we want to be implemented.
   * @return Whether or not the element implements the interface.
   */
  bool implements_interface(GType iface_type) const;

  /** This signals that the element will not generate more dynamic pads.
   *
   * @par Prototype:
   * <tt>void on_my_%no_more_pads()</tt>
   */

  Glib::SignalProxy0< void > signal_no_more_pads();


  /** Signals that a new Gst::Pad has been added to the element.
   *
   * @par Prototype:
   * <tt>void on_my_%pad_added(const Glib::RefPtr<Gst::Pad>& new_pad)</tt>
   */

  Glib::SignalProxy1< void,const Glib::RefPtr<Gst::Pad>& > signal_pad_added();


  /** Signals that a Gst::Pad has been removed from the element.
   *
   * @par Prototype:
   * <tt>void on_my_%pad_removed(const Glib::RefPtr<Gst::Pad>& old_pad)</tt>
   */

  Glib::SignalProxy1< void,const Glib::RefPtr<Gst::Pad>& > signal_pad_removed();


  /** Called when a new pad is requested.
   */
    virtual Glib::RefPtr<Gst::Pad> request_new_pad_vfunc(const Glib::RefPtr<const Gst::PadTemplate>& templ, const Glib::ustring& name);


  /** Called when a request pad is to be released.
   */
    virtual void release_pad_vfunc(const Glib::RefPtr<Gst::Pad>& pad);


  /** Get the state of the element.
   */
    virtual StateChangeReturn get_state_vfunc(State& state, State& pending, ClockTime timeout) const;


  /** Set a new state on the element.
   */
    virtual StateChangeReturn set_state_vfunc(State state);


  /** Called by set_state to perform an incremental state change.
   */
    virtual StateChangeReturn change_state_vfunc(StateChange transition);


  /** Set a Gst::Bus on the element.
   */
    virtual void set_bus_vfunc(const Glib::RefPtr<Gst::Bus>& bus);


  /** Gets the Gst::Clock provided by the element.
   */
    virtual Glib::RefPtr<Gst::Clock> provide_clock_vfunc();


  // This vfunc is hand-coded because it is necessary for the callback to
  // return true instead of false (as would happen with the default gmmproc
  // callback) because GstElement does not set its set_clock() vfunc
  // by default and yet gst_element_set_clock() returns true when GstElement's
  // set_clock() vfunc is not set (it's a strange thing, but look at
  // gst_element_class_init() and gst_element_set_clock() for insight).
  /** Set the Gst::Clock on the element.
   */
  virtual bool set_clock_vfunc(const Glib::RefPtr<Gst::Clock>& clock);

  // This vfunc is handwritten because the default gmmproc code produces a
  // compile error related to tyring to use Glib::ArrayHandle<>'s default
  // constructor when returning a default value at the end of both the callback
  // and the vfunc.
  /** Get the supported Gst::QueryType of this element.
   */
   virtual Glib::ArrayHandle<QueryType> get_query_types_vfunc() const;

  /** Get a Gst::Index on the element.
   */
    virtual Glib::RefPtr<Gst::Index> get_index_vfunc() const;


  /** Set the Gst::Index of an element.
   */
    virtual void set_index_vfunc(const Glib::RefPtr<Gst::Index>& index);


  /** Send a Gst::Event to the element.
   */
    virtual bool send_event_vfunc(const Glib::RefPtr<Gst::Event>& event);


  /** Perform a Gst::Query on the element.
   */
    virtual bool query_vfunc(const Glib::RefPtr<Gst::Query>& query) const;


protected:

  
public:

public:
  //C++ methods used to invoke GTK+ virtual functions:

protected:
  //GTK+ Virtual Functions (override these to change behaviour):

  //Default Signal Handlers::
  virtual void on_no_more_pads();
  virtual void on_pad_added(const Glib::RefPtr<Gst::Pad>& new_pad);
  virtual void on_pad_removed(const Glib::RefPtr<Gst::Pad>& old_pad);


};

/** A templated class used for casting Gst::Element to interfaces that its
 * underlying gobject implements.
 * Gst::ElementInterfaced is a templated class which, in conjunction with
 * Gst::Interface::cast(), is used to cast a Gst::Element obtained by
 * Gst::ElementFactory::create_element() into underlying GStreamer interfaces
 * that the element may implement.  A 'filesrc' element, for example,
 * implements the Gst::URIHandler interface (which is not reflected in a
 * Gst::Element obtained from a Gst::ElementFactory).  To use the
 * Gst::URIHandler methods with a 'filesrc' element obtained from a
 * Gst::ElementFactory, one would do the following:
 * @code
 * ...
 * Glib::RefPtr<Gst::Element> element =
 * Gst::ElementFactory::create_element("filesrc", "source");
 *
 * Glib::RefPtr< Gst::ElementInterfaced<Gst::URIHandler> > handler =
 *   Gst::Interface::cast<Gst::URIHandler>(element);
 *
 * if(handler)
 * {
 *   std::cout << "element '" << element->get_name() <<
 *     "' implements URIHandler interface." << std::endl;
 *
 *   // Use uri handler interface methods:
 *
 *   handler->set_uri("file:///tmp/media.file");
 *
 *   std::cout << handler->get_name() << " uri = '" << handler->get_uri() <<
 *     "'." << std::endl;
 * }
 * @endcode
 * @ingroup GstInterfaces
 */
template <class T_Interface>
class ElementInterfaced
: public Element,
  public T_Interface
{

#ifndef DOXYGEN_SHOULD_SKIP_THIS
private:
  friend class Gst::Interface;

private:
  // noncopyable
  ElementInterfaced(const ElementInterfaced&);
  ElementInterfaced& operator=(const ElementInterfaced&);

protected:
  explicit ElementInterfaced(GstElement* castitem);
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~ElementInterfaced();

  // The gobj() methods make calls involving access to the underlying gobject
  // unambiguous (specifically, gobj() is ambiguous when called from an
  // ElementInterfaced<..> class).

  /// Gets the underlying gobject.
  GstElement* gobj() { return Element::gobj(); };

  /// Gets the underlying gobject.
  const GstElement* gobj() const { return Element::gobj(); };

  /// Gets a copy of the underlying gobject.  The copy should be freed.
  GstElement* gobj_copy() { return Element::gobj_copy(); };
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

extern "C"
void ElementInterfaced_WeakNotify_gstreamermm_callback(void* data, GObject* where_the_object_was);

template <class T_Interface>
ElementInterfaced<T_Interface>::ElementInterfaced(GstElement* castitem)
{
  gobject_ = (GObject*)castitem;
  if(gobject_) {
    gst_object_ref(gobj());
    g_object_weak_ref(gobject_,
      &ElementInterfaced_WeakNotify_gstreamermm_callback, this);
  }
}

template <class T_Interface>
ElementInterfaced<T_Interface>::~ElementInterfaced()
{
  // Set the gobject_ to null so that when this is deleted, the gobject doesn't
  // go with it and other elements "wrapping" the gobject are not affected
  gobject_ = 0;
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Gst


namespace Glib
{
  /** A Glib::wrap() method for this object.
   * 
   * @param object The C instance.
   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
   * @result A C++ instance that wraps this C instance.
   *
   * @relates Gst::Element
   */
  Glib::RefPtr<Gst::Element> wrap(GstElement* object, bool take_copy = false);
}


#endif /* _GSTREAMERMM_ELEMENT_H */

