/* 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/gst.h>
#include <gstreamermm/object.h>
#include <glibmm/arrayhandle.h>

_DEFS(gstreamermm,gst)

namespace Gst
{

_WRAP_ENUM(PluginDependencyFlags, GstPluginDependencyFlags)

/** The plugin loading errors.
 *
 * - MODULE - The plugin could not be loaded
 * - DEPENDENCIES - The plugin has unresolved dependencies
 * - NAME_MISMATCH - The plugin has already be loaded from a different file
 */
_WRAP_GERROR(PluginError, GstPluginError, GST_PLUGIN_ERROR)

class Structure;

/** A container for features loaded from a shared object module.
 * GStreamer is extensible, so Gst::Element instances can be loaded at runtime.
 * A plugin system can provide one or more of the basic GStreamer
 * Gst::PluginFeature subclasses.
 *
 * TODO: Edit following paragraph to use gstreamermm classes/methods:
 *
 * A plugin should export a symbol gst_plugin_desc that is a struct of type
 * PluginDesc. the plugin loader will check the version of the core library
 * the plugin was linked against and will create a new Gst::Plugin. It will
 * then call the PluginInitFunc function that was provided in the
 * gst_plugin_desc.
 *
 * Once you have a handle to a Gst::Plugin (e.g. from the RegistryPool), you
 * can add any object that subclasses Gst::PluginFeature.
 *
 * Usually plugins are always automaticlly loaded so you don't need to call
 * gst_plugin_load() explicitly to bring it into memory. There are options to
 * statically link plugins to an app or even use GStreamer without a plugin
 * repository in which case load() can be needed to bring the plugin
 * into memory.
 */
class Plugin : public Object
{
  _CLASS_GOBJECT(Plugin, GstPlugin, GST_PLUGIN, Object, GstObject)

public:
  /** For example,
   * bool on_plugin_init(const Glib::RefPtr<Gst::Plugin>& plugin);.
   * The init function should return true if plugin was initialized
   * successfully, false otherwise.
   */
  typedef sigc::slot< bool, const Glib::RefPtr<Gst::Plugin>& > SlotInit;

  /** For example,
   * bool on_plugin_filter(const Glib::RefPtr<Gst::Plugin>& plugin);.
   * The filter function should return true if plugin is a match, false
   * otherwise.
   */
  typedef sigc::slot< bool, const Glib::RefPtr<Gst::Plugin>& > SlotFilter;

  _WRAP_METHOD(static Glib::QueryQuark error_quark(), gst_plugin_error_quark)
  _WRAP_METHOD(Glib::ustring get_name() const, gst_plugin_get_name)
  _WRAP_METHOD(Glib::ustring get_description() const, gst_plugin_get_description)
  _WRAP_METHOD(Glib::ustring get_filename() const, gst_plugin_get_filename)
  _WRAP_METHOD(Glib::ustring get_license() const, gst_plugin_get_license)
  _WRAP_METHOD(Glib::ustring get_package() const, gst_plugin_get_package)
  _WRAP_METHOD(Glib::ustring get_origin() const, gst_plugin_get_origin)
  _WRAP_METHOD(Glib::ustring get_source() const, gst_plugin_get_source)
  _WRAP_METHOD(Glib::ustring get_version() const, gst_plugin_get_version)
  _WRAP_METHOD(Glib::ustring get_release_date_string() const, gst_plugin_get_release_date_string)

  _WRAP_METHOD(bool is_loaded() const, gst_plugin_is_loaded)

// A copy is taken so that the original is not freed by the wrapper.
#m4 _CONVERSION(`const GstStructure*',`Gst::Structure',`Glib::wrap(const_cast<GstStructure*>($3), true)')
  _WRAP_METHOD(Gst::Structure get_cache_data() const, gst_plugin_get_cache_data)

  _WRAP_METHOD(void set_cache_data(Gst::Structure& cache_data), gst_plugin_set_cache_data)

  //gst_plugin_name_filter is a C API convenience function which tells if a
  //plugin has a given name so ignore it.
  _IGNORE(gst_plugin_name_filter)

  /** @throw Gst::PluginError.
   */
  _WRAP_METHOD(static Glib::RefPtr<Gst::Plugin> load_file(const Glib::ustring& filename), gst_plugin_load_file, errthrow)

  _WRAP_METHOD(Glib::RefPtr<Gst::Plugin> load(), gst_plugin_load)
  _WRAP_METHOD(static Glib::RefPtr<Gst::Plugin> load_by_name(const Glib::ustring& name), gst_plugin_load_by_name)

  // Don't wrap gst_plugin_list_free because Glib::ListHandle<> already takes
  // care of freeing.
  _IGNORE(gst_plugin_list_free)

  static bool register_static(int major_version, int minor_version,
    const Glib::ustring& name, const Glib::ustring& description,
    const SlotInit& init_slot, const Glib::ustring& version,
    const Glib::ustring& license, const Glib::ustring& source,
    const Glib::ustring& package, const Glib::ustring& origin);

  _WRAP_METHOD(void add_dependency(const Glib::StringArrayHandle& env_vars,
    const Glib::StringArrayHandle& paths,
    const Glib::StringArrayHandle& names,
    Gst::PluginDependencyFlags flags), gst_plugin_add_dependency)

  _WRAP_METHOD(void add_dependency(const Glib::ustring& env_vars,
    const Glib::ustring& paths,
    const Glib::ustring& names,
    Gst::PluginDependencyFlags flags), gst_plugin_add_dependency_simple)
};

} // namespace Gst
