/* 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 <glibmm/interface.h>
#include <gstreamermm/element.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

/** Core interface implemented by Gst::Element instances that
 * allows runtime querying of interface availability.
 * This provides interface functionality on a per-instance basis and not a per-class
 * basis, which is the case for GObject.
 * @ingroup GstInterfaces
 */
class Interface : public Glib::Interface
{
  _CLASS_INTERFACE(Interface, GstImplementsInterface, GST_IMPLEMENTS_INTERFACE, GstImplementsInterface)

public:
  _WRAP_METHOD(static bool element_implements(const Glib::RefPtr<const Gst::Element>&element, GType iface_type), gst_element_implements_interface)

  template <class T_CastTo>
  static Glib::RefPtr< Gst::ElementInterfaced<T_CastTo> > cast(const Glib::RefPtr<Gst::Element>& element);

  //For some reason, gmmproc thinks that all of the GstElement functions (and
  //signals) are also members of GstImplementsInterface.
  _IGNORE(gst_element_remove_pad,
          gst_element_change_state,
          gst_element_set_locked_state,
          gst_element_iterate_pads,
          gst_element_get_compatible_pad,
          gst_element_seek_simple,
          gst_element_send_event,
          gst_element_set_bus,
          gst_element_link,
          gst_element_query_duration,
          gst_element_abort_state,
          gst_element_create_all_pads,
          gst_element_sync_state_with_parent,
          gst_element_link_pads_filtered,
          gst_element_get_bus,
          gst_element_provide_clock,
          gst_element_get_state,
          gst_element_set_state,
          gst_element_found_tags,
          gst_element_get_index,
          gst_element_set_index,
          gst_element_get_compatible_pad_template,
          gst_element_link_many,
          gst_element_set_clock,
          gst_element_set_base_time,
          gst_element_unlink_pads,
          gst_element_requires_clock,
          gst_element_query_convert,
          gst_element_unlink_many,
          gst_element_is_indexable,
          gst_element_query_position,
          gst_element_query,
          gst_element_get_request_pad,
          gst_element_get_base_time,
          gst_element_get_pad,
          gst_element_release_request_pad,
          gst_element_no_more_pads,
          gst_element_is_locked_state,
          gst_element_message_full,
          gst_element_get_factory,
          gst_element_unlink,
          gst_element_iterate_sink_pads,
          gst_element_seek,
          gst_element_lost_state,
          gst_element_iterate_src_pads,
          gst_element_get_clock,
          gst_element_continue_state,
          gst_element_add_pad,
          gst_element_post_message,
          gst_element_link_filtered,
          gst_element_provides_clock,
          gst_element_found_tags_for_pad,
          gst_element_get_query_types,
          gst_element_get_static_pad,
          gst_element_link_pads)
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

template <class T_CastTo>
Glib::RefPtr< Gst::ElementInterfaced<T_CastTo> > Interface::cast(const Glib::RefPtr<Gst::Element>& element)
{
  if (element && gst_element_implements_interface(element->gobj(), T_CastTo::get_type()))
  {
    void* result =
      gst_implements_interface_cast(element->gobj(), T_CastTo::get_type());

    Gst::ElementInterfaced<T_CastTo>* element_interfaced =
      new ElementInterfaced<T_CastTo>((GstElement*) result);

    return Glib::RefPtr< Gst::ElementInterfaced<T_CastTo> >(element_interfaced);
  }
  else
    return Glib::RefPtr< Gst::ElementInterfaced<T_CastTo> >(0);
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} //namespace Gst
