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


#include <glibmm/ustring.h>
#include <sigc++/sigc++.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/gsttaglist.h>
#include <gstreamermm/structure.h>


namespace Gst
{

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

/**
 * @ingroup gstreamermmEnums
 */
enum TagMergeMode
{
  TAG_MERGE_UNDEFINED,
  TAG_MERGE_REPLACE_ALL,
  TAG_MERGE_REPLACE,
  TAG_MERGE_APPEND,
  TAG_MERGE_PREPEND,
  TAG_MERGE_KEEP,
  TAG_MERGE_KEEP_ALL,
  TAG_MERGE_COUNT
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

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

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


namespace Gst
{

/**
 * @ingroup gstreamermmEnums
 */
enum TagFlag
{
  TAG_FLAG_UNDEFINED,
  TAG_FLAG_META,
  TAG_FLAG_ENCODED,
  TAG_FLAG_DECODED,
  TAG_FLAG_COUNT
};

} // namespace Gst


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

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

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


namespace Gst
{


// When adding tags, make sure that they are added to this enum and then in the
// ccg file in the correct order.  Also make sure that the size of the array of
// strings is updated in the declaration below and in the ccg file.
// These correspond to the GST_TAG_* #defines in the C API.
//TODO: Maybe do something like Glib::StockID instead?
/** Identifiers for commonly-used tags.
 */
enum Tag
{
/** The commonly used title (string).
 * The title as it should be displayed, e.g. 'The Doll House'.
 */
TAG_TITLE,

/** The commonly used title, as used for sorting (string).
 * The title as it should be sorted, e.g. 'Doll House, The'.
 *
 * Since 0.10.15.
 */
TAG_TITLE_SORTNAME,

/** The person(s) responsible for the recording (string).
 * The artist name as it should be displayed, e.g. 'Jimi Hendrix' or 'The
 * Guitar Heroes'.
 */
TAG_ARTIST,

/** The person(s) responsible for the recording, as used for sorting (string).
 * The artist name as it should be sorted, e.g. 'Hendrix, Jimi' or 'Guitar
 * Heroes, The'.
 *
 * Since 0.10.15.
 */
TAG_ARTIST_SORTNAME,

/** The album containing this data (string).
 * The album name as it should be displayed, e.g. 'The Jazz Guitar'.
 */
TAG_ALBUM,

/** The album containing this data, as used for sorting (string).
 * The album name as it should be sorted, e.g. 'Jazz Guitar, The'.
 *
 * Since 0.10.15.
 */
TAG_ALBUM_SORTNAME,

/** The date the data was created (GDate structure).
 */
TAG_DATE,

/** The genre this data belongs to (string).
 */
TAG_GENRE,

/** The free text commenting the data (string).
 */
TAG_COMMENT,

/** The Key/value text commenting the data (string).
 * Must be in the form of 'key=comment' or 'key[lc]=comment' where 'lc' is an
 * ISO-639 language code.
 *
 * This tag is used for unknown Vorbis comment tags, unknown APE tags and
 * certain ID3v2 comment fields.
 *
 * Since 0.10.10.
 */
TAG_EXTENDED_COMMENT,

/** The track number inside a collection (unsigned integer).
 */
TAG_TRACK_NUMBER,

/** The count of tracks inside collection this track belongs to (unsigned
 * integer).
 */
TAG_TRACK_COUNT,

/** The disc number inside a collection (unsigned integer).
 */
TAG_ALBUM_VOLUME_NUMBER,

/** The count of discs inside collection this disc belongs to (unsigned
 * integer).
 */
TAG_ALBUM_VOLUME_COUNT,

/** The original location of file as a URI (string).
 */
TAG_LOCATION,

/** The short text describing the content of the data (string).
 */
TAG_DESCRIPTION,

/** The version of this data (string).
 */
TAG_VERSION,

/** The International Standard Recording Code - see http://www.ifpi.org/isrc/
 * (string).
 */
TAG_ISRC,

/** The organization (string).
 */
TAG_ORGANIZATION,

/** The copyright notice of the data (string).
 */
TAG_COPYRIGHT,

/** The URI to location where copyright details can be found (string).
 * Since 0.10.14.
 */
TAG_COPYRIGHT_URI,

/** The person(s) who composed the recording (string).
 * Since 0.10.15.
 */
TAG_COMPOSER,

/** The contact information (string).
 */
TAG_CONTACT,

/** The license of the data (string).
 */
TAG_LICENSE,

/** The URI to the location where license details can be found (string).
 * Since 0.10.14.
 */
TAG_LICENSE_URI,

/** The person(s) performing (string).
 */
TAG_PERFORMER,

/** The length in GStreamer time units (nanoseconds) (unsigned 64-bit
 * integer).
 */
TAG_DURATION,

/** The codec the data is stored in (string).
 */
TAG_CODEC,

/** The codec the video data is stored in (string).
 */
TAG_VIDEO_CODEC,

/** The codec the audio data is stored in (string).
 */
TAG_AUDIO_CODEC,

/** The exact or average bitrate in bits/s (unsigned integer).
 */
TAG_BITRATE,

/** The nominal bitrate in bits/s (unsigned integer).
 */
TAG_NOMINAL_BITRATE,

/** The minimum bitrate in bits/s (unsigned integer).
 */
TAG_MINIMUM_BITRATE,

/** The maximum bitrate in bits/s (unsigned integer).
 */
TAG_MAXIMUM_BITRATE,

/** The serial number of track (unsigned integer).
 */
TAG_SERIAL,

/** The encoder used to encode this stream (string).
 */
TAG_ENCODER,

/** The version of the encoder used to encode this stream (unsigned integer).
 */
TAG_ENCODER_VERSION,

/** The track gain in db (double).
 */
TAG_TRACK_GAIN,

/** The peak of the track (double).
 */
TAG_TRACK_PEAK,

/** The album gain in db (double).
 */
TAG_ALBUM_GAIN,

/** The peak of the album (double).
 */
TAG_ALBUM_PEAK,

/** The reference level of track and album gain values (double).
 * Since 0.10.12.
 */
TAG_REFERENCE_LEVEL,

/** The language code (ISO-639-1) (string) of the content.
 */
TAG_LANGUAGE_CODE,

/** The image (buffer) (buffer caps should specify the content type and
 * preferably also set "image-type" field as GstTagImageType).
 * Since 0.10.6 
 */
TAG_IMAGE,

/** The image that is meant for preview purposes, e.g.\ small icon-sized
 * version (buffer) (buffer caps should specify the content type).
 * Since 0.10.7.
 */
TAG_PREVIEW_IMAGE,

/** The generic file attachment (buffer) (buffer caps should specify the
 * content type and if possible set "filename" to the file name of the
 * attachment).
 *
 * Since 0.10.21.
 */
TAG_ATTACHMENT,

/** The number of beats per minute in audio (double).
 * Since 0.10.12.
 */
TAG_BEATS_PER_MINUTE,

/** The comma separated keywords describing the content (string).
 *
 * Since 0.10.21
 */
TAG_KEYWORDS,

/** The human readable descriptive location of where the media has been
 * recorded or produced. (string).
 *
 * Since 0.10.21.
 */
TAG_GEO_LOCATION_NAME,

/** The geo latitude location of where the media has been recorded or produced
 * in degrees according to WGS84 (zero at the equator, negative values for
 * southern latitudes) (double).
 *
 * Since 0.10.21.
 */
TAG_GEO_LOCATION_LATITUDE,

/** The geo longitude location of where the media has been recorded or
 * produced in degrees according to WGS84 (zero at the prime meridian in
 * Greenwich/UK, negative values for western longitudes). (double).
 *
 * Since 0.10.21.
 */
TAG_GEO_LOCATION_LONGITUDE,

/** The geo elevation of where the media has been recorded or produced in
 * meters according to WGS84 (zero is average sea level) (double).
 *
 * Since 0.10.21.
 */
TAG_GEO_LOCATION_ELEVATION
};

/** An Output stream operator for the Gst::Tag enum (this will output a
 * string).
 */
std::ostream& operator<<(std::ostream& stream, Tag tag);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
const char* gstreamermm_get_stock_tag(Tag tag);
#endif

/** A class tha represents a list of tags and values used to describe media
 * metadata.
 * Taglists form part of media streams and describe the content of a stream in
 * a non-technical way. Examples include the author of a song, the title of
 * that very same song or the album it is a part of. Tag reading is done
 * through a Gst::Bus. You can listen for Gst::MESSAGE_TAG messages and handle
 * them as you wish.
 *
 * Note, however, that the Gst::MESSAGE_TAG  message may be fired multiple
 * times in the pipeline. It is the application's responsibility to put all
 * those tags together and display them to the user in a nice, coherent way.
 * Usually, using merge() is a good enough way of doing this; make sure to
 * empty the cache when loading a new song, or after every few minutes when
 * listening to internet radio. Also, make sure you use Gst::TAG_MERGE_PREPEND
 * as merging mode, so that a new title (which came in later) has a preference
 * over the old one for display.
 */
class TagList
{
  
  public:
#ifndef DOXYGEN_SHOULD_SKIP_THIS
  typedef TagList CppObjectType;
  typedef GstTagList BaseObjectType;

  static GType get_type() G_GNUC_CONST;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

  TagList();

  explicit TagList(GstTagList* gobject, bool make_a_copy = true);

  TagList(const TagList& other);
  TagList& operator=(const TagList& other);

  ~TagList();

  void swap(TagList& other);

  ///Provides access to the underlying C instance.
  GstTagList*       gobj()       { return gobject_; }

  ///Provides access to the underlying C instance.
  const GstTagList* gobj() const { return gobject_; }

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

protected:
  GstTagList* gobject_;

private:

  
public:
  /** Use this to discover if the TagList is a valid object.
   */
  operator bool() const;

  
  /** Checks if the given type is already registered.
   * @param tag Name of the tag.
   * @return <tt>true</tt> if the type is already registered.
   */
  static bool exists(const Glib::ustring& tag);
  
  /** Gets the Type used for this tag.
   * @param tag The tag.
   * @return The Type of this tag.
   */
  static GType get_type(const Glib::ustring& tag);
  
  /** Returns the human-readable name of this tag, You must not change or free
   * this string.
   * @param tag The tag.
   * @return The human-readable name of this tag.
   */
  static Glib::ustring get_nick(const Glib::ustring& tag);
  
  /** Returns the human-readable description of this tag, You must not change or
   * free this string.
   * @param tag The tag.
   * @return The human-readable description of this tag.
   */
  static Glib::ustring get_description(const Glib::ustring& tag);
  
  /** Gets the flag of @a tag.
   * @param tag The tag.
   * @return The flag of this tag.
   */
  static TagFlag get_flag(const Glib::ustring& tag);
  
  /** Checks if the given tag is fixed. A fixed tag can only contain one value.
   * Unfixed tags can contain lists of values.
   * @param tag Tag to check.
   * @return <tt>true</tt>, if the given tag is fixed.
   */
  static bool is_fixed(const Glib::ustring& tag);
  
  /** Checks if the given taglist is empty.
   * @return <tt>true</tt> if the taglist is empty, otherwise <tt>false</tt>.
   */
  bool is_empty() const;
  
  /** Inserts the tags of the @a from list into the first list using the given mode.
   * @param from List to merge from.
   * @param mode The mode to use.
   */
  void insert(const Gst::TagList& other, TagMergeMode mode =  TAG_MERGE_PREPEND);

 
  /** Merges the two given lists into a new list. If one of the lists is <tt>0</tt>, a
   * copy of the other is returned. If both lists are <tt>0</tt>, <tt>0</tt> is returned.
   * 
   * Free-function: gst_tag_list_free
   * @param list2 Second list to merge.
   * @param mode The mode to use.
   * @return The new list.
   */
  Gst::TagList merge(const Gst::TagList& other, TagMergeMode mode =  TAG_MERGE_PREPEND);

  
  /** Checks how many value are stored in this tag list for the given tag.
   * @param tag The tag to query.
   * @return The number of tags stored.
   */
  guint size(const Glib::ustring& tag) const;

  /** Sets a GValue for the given @a tag using the specified mode.
   *
   * @param tag The tag name.
   * @param mode The mode to use.
   * @param value The Glib::Value<> to use.
   */
  void add_value(Tag tag, const Glib::ValueBase& value, TagMergeMode mode = TAG_MERGE_PREPEND);

  /** Sets a GValue for the given @a tag using the specified mode.
   *
   * @param tag The tag name.
   * @param mode The mode to use.
   * @param value The Glib::Value<> to use.
   */
  void add_value(const Glib::ustring& tag, const Glib::ValueBase& value, TagMergeMode mode = TAG_MERGE_PREPEND);

  
  //TODO: Doesn't this conflict with the template? murrayc.
  //
  //It doesn't seem so.  The taglist test (test-taglist) uses it when adding a
  //title and an artist tag (lines 35, 36).  The test wont compile without it
  //and declaring the template before this doesn't seem to make the compiler
  //select the template over this method. I could be wrong. Jose.
  /** Sets the value for the given tag to string @a data using the specified
   * mode.
   *
   * @param tag The tag name.
   * @param data A string to which the tag should be set to.
   * @param mode The merge mode to use.
   */
  void add(Tag tag, const char* data, TagMergeMode mode = TAG_MERGE_PREPEND);

  /** Sets the value for the given tag to string @a data using the specified
   * mode.
   *
   * @param tag The tag name.
   * @param data A string to which the tag should be set to.
   * @param mode The merge mode to use.
   */
  void add(const Glib::ustring& tag, const char* data, TagMergeMode mode = TAG_MERGE_PREPEND);

  /** Sets the value for the given tag using the specified mode.
   *
   * @param tag The tag name.
   * @param data A value which the tag should be set to (this can be any
   * supported C++ type).
   * @param mode The merge mode to use.
   */
  template <class DataType>
  void add(Tag tag, const DataType& data, TagMergeMode mode = TAG_MERGE_PREPEND);

  /** Sets the value for the given tag using the specified mode.
   *
   * @param tag The tag name.
   * @param data A value which the tag should be set to (this can be any
   * supported C++ type).
   * @param mode The merge mode to use.
   */
  template <class DataType>
  void add(const Glib::ustring& tag, const DataType& data, TagMergeMode mode = TAG_MERGE_PREPEND);

  
  /** Removes the given tag from the taglist.
   * @param tag Tag to remove.
   */
  void remove_tag(Tag tag);

  
  /** Removes the given tag from the taglist.
   * @param tag Tag to remove.
   */
  void remove_tag(const Glib::ustring& tag);

  /** For example,
   * void on_foreach(const Glib::ustring& tag);.
   */
  typedef sigc::slot<void, const Glib::ustring&> SlotForeach;

  /** Calls the given slot for each tag inside the tag list. Note that if there
   * is no tag, the slot won't be called at all.
   *
   * @param slot Slot to be called for each tag.
   */
  void foreach(const SlotForeach& slot);
  

  /** Copies the contents for the given tag into the value, merging multiple
   * values into one if multiple values are associated with the tag.
   *
   * @param dest An uninitialized Glib::ValueBase to copy into.
   * @param tag The tag to read out.
   * @return true, if a value was copied, false if the tag didn't exist in the
   * list.
   */
  bool get_value(Tag tag, Glib::ValueBase& dest) const;
  

  /** Copies the contents for the given tag into the value, merging multiple
   * values into one if multiple values are associated with the tag.
   *
   * @param dest An uninitialized Glib::ValueBase to copy into.
   * @param tag The tag to read out.
   * @return true, if a value was copied, false if the tag didn't exist in the
   * list.
   */
  bool get_value(const Glib::ustring& tag, Glib::ValueBase& dest) const;
  

  /** Gets the value that is at the given index for the given tag.
   * @param tag The tag to read out.
   * @param index Number of entry to read out.
   * @@param The Glib::ValueBase to store the value in.
   * @return true if tag was available and had right number of entries, false
   * otherwise.
   */
  bool get_value(Tag tag, guint index, Glib::ValueBase& dest) const;
  

  /** Gets the value that is at the given index for the given tag.
   * @param tag The tag to read out.
   * @param index Number of entry to read out.
   * @@param The Glib::ValueBase to store the value in.
   * @return true if tag was available and had right number of entries, false
   * otherwise.
   */
  bool get_value(const Glib::ustring& tag, guint index, Glib::ValueBase& dest) const;
  

  /** Copies the contents for the given tag into the value, merging multiple
   * values into one if multiple values are associated with the tag.
   * @param tag The tag to read out.
   * @param value Location for the result (this can be any supported C++ type).
   * @return true, if a value was copied, false if the tag didn't exist in the
   * given list.
   */
  template<class DataType>
  bool get(Tag tag, DataType& value) const;

  /** Copies the contents for the given tag into the value, merging multiple
   * values into one if multiple values are associated with the tag.
   * @param tag The tag to read out.
   * @param value Location for the result (this can be any supported C++ type).
   * @return true, if a value was copied, false if the tag didn't exist in the
   * given list.
   */
  template<class DataType>
  bool get(const Glib::ustring& tag, DataType& value) const;

  
  /** Gets the value that is at the given index for the given tag.
   * @param tag The tag to read out.
   * @param index Number of entry to read out.
   * @param value Location for the result (this can be any supported C++ type).
   * @return true, if a value was copied, false if the tag didn't exist in the
   * given list.
   */
  template<class DataType>
  bool get(Tag tag, guint index, DataType& value) const;

  /** Gets the value that is at the given index for the given tag.
   * @param tag The tag to read out.
   * @param index Number of entry to read out.
   * @param value Location for the result (this can be any supported C++ type).
   * @return true, if a value was copied, false if the tag didn't exist in the
   * given list.
   */
  template<class DataType>
  bool get(const Glib::ustring& tag, guint index, DataType& value) const;

  
  //Variable argument functions are ignored.
  

};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

/***************************** Gst::TagList *****************************/

template <class DataType>
void TagList::add(Tag tag, const DataType& data, TagMergeMode mode)
{
  typedef Glib::Value<DataType> ValueType;

  ValueType value;
  value.init(ValueType::value_type());
  value.set(data);
  this->add_value(tag, value, mode);
}

template <class DataType>
void TagList::add(const Glib::ustring& tag, const DataType& data, TagMergeMode mode)
{
  typedef Glib::Value<DataType> ValueType;

  ValueType value;
  value.init(ValueType::value_type());
  value.set(data);
  this->add_value(tag, value, mode);
}

template<class DataType>
bool TagList::get(Tag tag, DataType& data) const
{
  Glib::Value<DataType> value;
  const bool result = this->get_value(tag, value);

  if(result)
    data = value.get();

  return result;
}

template<class DataType>
bool TagList::get(const Glib::ustring& tag, DataType& data) const
{
  Glib::Value<DataType> value;
  const bool result = this->get_value(tag, value);

  if(result)
    data = value.get();

  return result;
}

template<class DataType>
bool TagList::get(Tag tag, guint index, DataType& data) const
{
  Glib::Value<DataType> value;
  bool result = this->get_value(tag, index, value);

  if(result)
    data = value.get();

  return result;
}

template<class DataType>
bool TagList::get(const Glib::ustring& tag, guint index, DataType& data) const
{
  Glib::Value<DataType> value;
  bool result = this->get_value(tag, index, value);

  if(result)
    data = value.get();

  return result;
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} //namespace Gst


namespace Gst
{

/** @relates Gst::TagList
 * @param lhs The left-hand side
 * @param rhs The right-hand side
 */
inline void swap(TagList& lhs, TagList& rhs)
  { lhs.swap(rhs); }

} // namespace Gst

namespace Glib
{

/** A Glib::wrap() method for this object. The method has a non-standard name because otherwise it would collide with the wrap method for Gst::Structure because both Gst::TagList and Gst::Structure wrap the same underlying C type.
 * 
 * @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::TagList
 */
Gst::TagList wrap_taglist(GstTagList* object, bool take_copy = false);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template <>
class Value<Gst::TagList> : public Glib::Value_Boxed<Gst::TagList>
{};
#endif /* DOXYGEN_SHOULD_SKIP_THIS */

} // namespace Glib


#endif /* _GSTREAMERMM_TAGLIST_H */

