more doxygen docs
diff --git a/include/FLAC++/metadata.h b/include/FLAC++/metadata.h
index f9d7325..6ba0ce7 100644
--- a/include/FLAC++/metadata.h
+++ b/include/FLAC++/metadata.h
@@ -218,6 +218,7 @@
 
 
 		/** STREAMINFO metadata block.
+		 *  See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>.
 		 */
 		class StreamInfo : public Prototype {
 		public:
@@ -234,9 +235,6 @@
 
 			/** Constructs an object with copy control.  See
 			 *  Prototype(::FLAC__StreamMetadata *object, bool copy).
-			 *
-			 *  \assert
-			 *    \code object != NULL \endcode
 			 */
 			inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
 
@@ -263,6 +261,8 @@
 			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
 			//@}
 
+			//@{
+			/** See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>. */
 			unsigned get_min_blocksize() const;
 			unsigned get_max_blocksize() const;
 			unsigned get_min_framesize() const;
@@ -282,100 +282,197 @@
 			void set_bits_per_sample(unsigned value);
 			void set_total_samples(FLAC__uint64 value);
 			void set_md5sum(const FLAC__byte value[16]);
+			//@}
 		};
 
-		/** PADDING block.
+		/** PADDING metadata block.
+		 *  See <A HREF="../format.html#metadata_block_padding">format specification</A>.
 		 */
 		class Padding : public Prototype {
 		public:
 			Padding();
+
+			//@{
+			/** Constructs a copy of the given object.  This form
+			 *  always performs a deep copy.
+			 */
 			inline Padding(const Padding &object): Prototype(object) { }
 			inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
 			inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
+			//@}
+
+			/** Constructs an object with copy control.  See
+			 *  Prototype(::FLAC__StreamMetadata *object, bool copy).
+			 */
 			inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
+
 			~Padding();
 
+			//@{
+			/** Assign from another object.  Always performs a deep copy. */
 			inline void operator=(const Padding &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
+			//@}
 
+			//@{
+			/** Check for equality, performing a deep compare by following pointers. */
 			inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
+			//@}
+
+			//@{
+			/** Check for inequality, performing a deep compare by following pointers. */
 			inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
+			//@}
 
 			void set_length(unsigned length);
 		};
 
-		/** APPLICATION block.
+		/** APPLICATION metadata block.
+		 *  See <A HREF="../format.html#metadata_block_application">format specification</A>.
 		 */
 		class Application : public Prototype {
 		public:
 			Application();
+			//
+			//@{
+			/** Constructs a copy of the given object.  This form
+			 *  always performs a deep copy.
+			 */
 			inline Application(const Application &object): Prototype(object) { }
 			inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
 			inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
+			//@}
+
+			/** Constructs an object with copy control.  See
+			 *  Prototype(::FLAC__StreamMetadata *object, bool copy).
+			 */
 			inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
+
 			~Application();
 
+			//@{
+			/** Assign from another object.  Always performs a deep copy. */
 			inline void operator=(const Application &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
+			//@}
 
+			//@{
+			/** Check for equality, performing a deep compare by following pointers. */
 			inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
+			//@}
+
+			//@{
+			/** Check for inequality, performing a deep compare by following pointers. */
 			inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
+			//@}
 
 			const FLAC__byte *get_id() const;
 			const FLAC__byte *get_data() const;
 
 			void set_id(const FLAC__byte value[4]);
-			bool set_data(const FLAC__byte *data, unsigned length); // this form always copies
+			//! This form always copies \a data
+			bool set_data(const FLAC__byte *data, unsigned length);
 			bool set_data(FLAC__byte *data, unsigned length, bool copy);
 		};
 
-		/** SEEKTABLE block.
+		/** SEEKTABLE metadata block.
+		 *  See <A HREF="../format.html#metadata_block_seektable">format specification</A>.
 		 */
 		class SeekTable : public Prototype {
 		public:
 			SeekTable();
+
+			//@{
+			/** Constructs a copy of the given object.  This form
+			 *  always performs a deep copy.
+			 */
 			inline SeekTable(const SeekTable &object): Prototype(object) { }
 			inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
 			inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
+			//@}
+
+			/** Constructs an object with copy control.  See
+			 *  Prototype(::FLAC__StreamMetadata *object, bool copy).
+			 */
 			inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
+
 			~SeekTable();
 
+			//@{
+			/** Assign from another object.  Always performs a deep copy. */
 			inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
+			//@}
 
+			//@{
+			/** Check for equality, performing a deep compare by following pointers. */
 			inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
+			//@}
+
+			//@{
+			/** Check for inequality, performing a deep compare by following pointers. */
 			inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
+			//@}
 
 			unsigned get_num_points() const;
 			::FLAC__StreamMetadata_SeekPoint get_point(unsigned index) const;
 
+			//! See FLAC__metadata_object_seektable_set_point()
 			void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
+
+			//! See FLAC__metadata_object_seektable_insert_point()
 			bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
+
+			//! See FLAC__metadata_object_seektable_delete_point()
 			bool delete_point(unsigned index);
 
+			//! See FLAC__metadata_object_seektable_is_legal()
 			bool is_legal() const;
 		};
 
-		/** VORBIS_COMMENT block.
+		/** VORBIS_COMMENT metadata block.
+		 *  See <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>.
 		 */
 		class VorbisComment : public Prototype {
 		public:
-			/** XXX class VorbisComment::Entry
+			/** Convenience class for encapsulating Vorbis comment
+			 *  entries.  An entry is a vendor string or a comment
+			 *  field.  In the case of a vendor string, the field
+			 *  name is undefined; only the field value is relevant.
+			 *
+			 *  A \a field as used in the methods refers to an
+			 *  entire 'NAME=VALUE' string; the string is not null-
+			 *  terminated and a length field is required since the
+			 *  string may contain embedded nulls.
+			 *
+			 *  A \a field_name is what is on the left side of the
+			 *  first '=' in the \a field.  By definition it is ASCII
+			 *  and so is null-terminated and does not require a
+			 *  length to describe it.  \a field_name is undefined
+			 *  for a vendor string entry.
+			 *
+			 *  A \a field_value is what is on the right side of the
+			 *  first '=' in the \a field.  By definition, this may
+			 *  contain embedded nulls and so a \a field_value_length
+			 *  is requires to describe it.
+			 *
+			 *  Always check is_valid() after the constructor or operator=
+			 *  to make sure memory was properly allocated.
 			 */
 			class Entry {
 			public:
@@ -421,93 +518,108 @@
 			};
 
 			VorbisComment();
+
+			//@{
+			/** Constructs a copy of the given object.  This form
+			 *  always performs a deep copy.
+			 */
 			inline VorbisComment(const VorbisComment &object): Prototype(object) { }
 			inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
 			inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
+			//@}
+
+			/** Constructs an object with copy control.  See
+			 *  Prototype(::FLAC__StreamMetadata *object, bool copy).
+			 */
 			inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
+
 			~VorbisComment();
 
+			//@{
+			/** Assign from another object.  Always performs a deep copy. */
 			inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
 			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
+			//@}
 
+			//@{
+			/** Check for equality, performing a deep compare by following pointers. */
 			inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
 			inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
+			//@}
+
+			//@{
+			/** Check for inequality, performing a deep compare by following pointers. */
 			inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
 			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
+			//@}
 
 			unsigned get_num_comments() const;
 			Entry get_vendor_string() const; // only the Entry's field name should be used
 			Entry get_comment(unsigned index) const;
 
+			//! See FLAC__metadata_object_vorbis_comment_set_vendor_string()
+			//! \note Only the Entry's field name will be used.
 			bool set_vendor_string(const Entry &entry); // only the Entry's field name will be used
+
+			//! See FLAC__metadata_object_vorbis_comment_set_comment()
 			bool set_comment(unsigned index, const Entry &entry);
+
+			//! See FLAC__metadata_object_vorbis_comment_insert_comment()
 			bool insert_comment(unsigned index, const Entry &entry);
+
+			//! See FLAC__metadata_object_vorbis_comment_delete_comment()
 			bool delete_comment(unsigned index);
 		};
 
 		/* \} */
 
 
-		// ============================================================
-		//
-		//  Level 0
-		//
-		// ============================================================
-
 		/** \defgroup flacpp_metadata_level0 FLAC++/metadata.h: metadata level 0 interface
 		 *  \ingroup flacpp_metadata
 		 *
 		 *  \brief
-		 *  XXX
+		 *  Level 0 metadata iterator.
 		 *
-		 * Detailed XXX.
+		 *  See the \link flac_metadata_level0 C layer equivalent \endlink
+		 *  for more.
 		 *
 		 * \{
 		 */
 
+	 	//! See FLAC__metadata_get_streaminfo().
 		bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
 
 		/* \} */
 
 
-		// ============================================================
-		//
-		//  Level 1
-		//
-		//  ----------------------------------------------------------
-		//
-		//  The flow through the iterator in the C++ layer is similar
-		//  to the C layer:
-		//
-		//    * Create a SimpleIterator instance
-		//    * Check SimpleIterator::is_valid()
-		//    * Call SimpleIterator::init() and check the return
-		//    * Traverse and/or edit.  Edits are written to file
-		//      immediately.
-		//    * Destroy the SimpleIterator instance
-		//
-		//  ----------------------------------------------------------
-		//
-		//  The ownership of pointers in the C++ layer follows that in
-		//  the C layer, i.e.
-		//    * The objects returned by get_block() are yours to
-		//      modify, but changes are not reflected in the FLAC file
-		//      until you call set_block().  The objects are also
-		//      yours to delete; they are not automatically deleted
-		//      when passed to set_block() or insert_block_after().
-		//
-		// ============================================================
-
 		/** \defgroup flacpp_metadata_level1 FLAC++/metadata.h: metadata level 1 interface
 		 *  \ingroup flacpp_metadata
 		 *
-		 * \brief
-		 * XXX
+		 *  \brief
+		 *  Level 1 metadata iterator.
 		 *
-		 * Detailed XXX.
+		 *  The flow through the iterator in the C++ layer is similar
+		 *  to the C layer:
+		 *    - Create a SimpleIterator instance
+		 *    - Check SimpleIterator::is_valid()
+		 *    - Call SimpleIterator::init() and check the return
+		 *    - Traverse and/or edit.  Edits are written to file
+		 *      immediately.
+		 *    - Destroy the SimpleIterator instance
+		 *
+		 *  The ownership of pointers in the C++ layer follows that in
+		 *  the C layer, i.e.
+		 *    - The objects returned by get_block() are yours to
+		 *      modify, but changes are not reflected in the FLAC file
+		 *      until you call set_block().  The objects are also
+		 *      yours to delete; they are not automatically deleted
+		 *      when passed to set_block() or insert_block_after().
+		 *
+		 *  See the \link flac_metadata_level1 C layer equivalent \endlink
+		 *  for more.
 		 *
 		 * \{
 		 */
@@ -553,50 +665,39 @@
 		/* \} */
 
 
-		// ============================================================
-		//
-		//  Level 2
-		//
-		//  ----------------------------------------------------------
-		//
-		//  The flow through the iterator in the C++ layer is similar
-		//  to the C layer:
-		//
-		//    * Create a Chain instance
-		//    * Check Chain::is_valid()
-		//    * Call Chain::read() and check the return
-		//    * Traverse and/or edit with an Iterator or with
-		//      Chain::merge_padding() or Chain::sort_padding()
-		//    * Write changes back to FLAC file with Chain::write()
-		//    * Destroy the Chain instance
-		//
-		//  ----------------------------------------------------------
-		//
-		//  The ownership of pointers in the C++ layer follows that in
-		//  the C layer, i.e.
-		//    * The objects returned by Iterator::get_block() are
-		//      owned by the iterator and should not be deleted.
-		//      When you modify the block, you are directly editing
-		//      what's in the chain and do not need to call
-		//      Iterator::set_block().  However the changes will not
-		//      be reflected in the FLAC file until the chain is
-		//      written with Chain::write().
-		//
-		//    * When you pass an object to Iterator::set_block(),
-		//      Iterator::insert_block_before(), or
-		//      Iterator::insert_block_after(), the iterator takes
-		//      ownership of the block and it will be deleted with the
-		//      chain.
-		//
-		// ============================================================
-
 		/** \defgroup flacpp_metadata_level2 FLAC++/metadata.h: metadata level 2 interface
 		 *  \ingroup flacpp_metadata
 		 *
-		 * \brief
-		 * XXX
+		 *  \brief
+		 *  Level 2 metadata iterator.
 		 *
-		 * Detailed XXX.
+		 *  The flow through the iterator in the C++ layer is similar
+		 *  to the C layer:
+		 *    - Create a Chain instance
+		 *    - Check Chain::is_valid()
+		 *    - Call Chain::read() and check the return
+		 *    - Traverse and/or edit with an Iterator or with
+		 *      Chain::merge_padding() or Chain::sort_padding()
+		 *    - Write changes back to FLAC file with Chain::write()
+		 *    - Destroy the Chain instance
+		 *
+		 *  The ownership of pointers in the C++ layer follows that in
+		 *  the C layer, i.e.
+		 *    - The objects returned by Iterator::get_block() are
+		 *      owned by the iterator and should not be deleted.
+		 *      When you modify the block, you are directly editing
+		 *      what's in the chain and do not need to call
+		 *      Iterator::set_block().  However the changes will not
+		 *      be reflected in the FLAC file until the chain is
+		 *      written with Chain::write().
+		 *    - When you pass an object to Iterator::set_block(),
+		 *      Iterator::insert_block_before(), or
+		 *      Iterator::insert_block_after(), the iterator takes
+		 *      ownership of the block and it will be deleted with the
+		 *      chain.
+		 *
+		 *  See the \link flac_metadata_level2 C layer equivalent \endlink
+		 *  for more.
 		 *
 		 * \{
 		 */
@@ -667,866 +768,3 @@
 };
 
 #endif
-#if 0
-		Prototype *clone(const Prototype *object)
-		{
-			FLAC__ASSERT(0 != object);
-
-			const StreamInfo *streaminfo = dynamic_cast<const StreamInfo *>(object);
-			const Padding *padding = dynamic_cast<const Padding *>(object);
-			const Application *application = dynamic_cast<const Application *>(object);
-			const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
-			const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
-
-			if(0 != streaminfo)
-				return new StreamInfo(*streaminfo);
-			else if(0 != padding)
-				return new Padding(*padding);
-			else if(0 != application)
-				return new Application(*application);
-			else if(0 != seektable)
-				return new SeekTable(*seektable);
-			else if(0 != vorbiscomment)
-				return new VorbisComment(*vorbiscomment);
-			else {
-				FLAC__ASSERT(0);
-				return 0;
-			}
-		}
-
-		//
-		// StreamInfo
-		//
-
-		StreamInfo::StreamInfo():
-		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false)
-		{ }
-
-		StreamInfo::~StreamInfo()
-		{ }
-
-		unsigned StreamInfo::get_min_blocksize() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.min_blocksize;
-		}
-
-		unsigned StreamInfo::get_max_blocksize() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.max_blocksize;
-		}
-
-		unsigned StreamInfo::get_min_framesize() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.min_framesize;
-		}
-
-		unsigned StreamInfo::get_max_framesize() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.max_framesize;
-		}
-
-		unsigned StreamInfo::get_sample_rate() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.sample_rate;
-		}
-
-		unsigned StreamInfo::get_channels() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.channels;
-		}
-
-		unsigned StreamInfo::get_bits_per_sample() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.bits_per_sample;
-		}
-
-		FLAC__uint64 StreamInfo::get_total_samples() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.total_samples;
-		}
-
-		const FLAC__byte *StreamInfo::get_md5sum() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.stream_info.md5sum;
-		}
-
-		void StreamInfo::set_min_blocksize(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
-			FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
-			object_->data.stream_info.min_blocksize = value;
-		}
-
-		void StreamInfo::set_max_blocksize(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
-			FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
-			object_->data.stream_info.max_blocksize = value;
-		}
-
-		void StreamInfo::set_min_framesize(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
-			object_->data.stream_info.min_framesize = value;
-		}
-
-		void StreamInfo::set_max_framesize(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
-			object_->data.stream_info.max_framesize = value;
-		}
-
-		void StreamInfo::set_sample_rate(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(FLAC__format_sample_rate_is_valid(value));
-			object_->data.stream_info.sample_rate = value;
-		}
-
-		void StreamInfo::set_channels(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value > 0);
-			FLAC__ASSERT(value <= FLAC__MAX_CHANNELS);
-			object_->data.stream_info.channels = value;
-		}
-
-		void StreamInfo::set_bits_per_sample(unsigned value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE);
-			FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE);
-			object_->data.stream_info.bits_per_sample = value;
-		}
-
-		void StreamInfo::set_total_samples(FLAC__uint64 value)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
-			object_->data.stream_info.total_samples = value;
-		}
-
-		void StreamInfo::set_md5sum(const FLAC__byte value[16])
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(0 != value);
-			memcpy(object_->data.stream_info.md5sum, value, 16);
-		}
-
-
-		//
-		// Padding
-		//
-
-		Padding::Padding():
-		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
-		{ }
-
-		Padding::~Padding()
-		{ }
-
-		void Padding::set_length(unsigned length)
-		{
-			FLAC__ASSERT(is_valid());
-			object_->length = length;
-		}
-
-
-		//
-		// Application
-		//
-
-		Application::Application():
-		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
-		{ }
-
-		Application::~Application()
-		{ }
-
-		const FLAC__byte *Application::get_id() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.application.id;
-		}
-
-		const FLAC__byte *Application::get_data() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.application.data;
-		}
-
-		void Application::set_id(const FLAC__byte value[4])
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(0 != value);
-			memcpy(object_->data.application.id, value, 4);
-		}
-
-		bool Application::set_data(const FLAC__byte *data, unsigned length)
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
-		}
-
-		bool Application::set_data(FLAC__byte *data, unsigned length, bool copy)
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
-		}
-
-
-		//
-		// SeekTable
-		//
-
-		SeekTable::SeekTable():
-		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false)
-		{ }
-
-		SeekTable::~SeekTable()
-		{ }
-
-		unsigned SeekTable::get_num_points() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.seek_table.num_points;
-		}
-
-		::FLAC__StreamMetadata_SeekPoint SeekTable::get_point(unsigned index) const
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.seek_table.num_points);
-			return object_->data.seek_table.points[index];
-		}
-
-		void SeekTable::set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.seek_table.num_points);
-			::FLAC__metadata_object_seektable_set_point(object_, index, point);
-		}
-
-		bool SeekTable::insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index <= object_->data.seek_table.num_points);
-			return (bool)::FLAC__metadata_object_seektable_insert_point(object_, index, point);
-		}
-
-		bool SeekTable::delete_point(unsigned index)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.seek_table.num_points);
-			return (bool)::FLAC__metadata_object_seektable_delete_point(object_, index);
-		}
-
-		bool SeekTable::is_legal() const
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_object_seektable_is_legal(object_);
-		}
-
-
-		//
-		// VorbisComment::Entry
-		//
-
-		VorbisComment::Entry::Entry()
-		{
-			zero();
-		}
-
-		VorbisComment::Entry::Entry(const char *field, unsigned field_length)
-		{
-			zero();
-			construct(field, field_length);
-		}
-
-		VorbisComment::Entry::Entry(const char *field_name, const char *field_value, unsigned field_value_length)
-		{
-			zero();
-			construct(field_name, field_value, field_value_length);
-		}
-
-		VorbisComment::Entry::Entry(const Entry &entry)
-		{
-			FLAC__ASSERT(entry.is_valid());
-			zero();
-			construct((const char *)entry.entry_.entry, entry.entry_.length);
-		}
-
-		void VorbisComment::Entry::operator=(const Entry &entry)
-		{
-			FLAC__ASSERT(entry.is_valid());
-			clear();
-			construct((const char *)entry.entry_.entry, entry.entry_.length);
-		}
-
-		VorbisComment::Entry::~Entry()
-		{
-			clear();
-		}
-
-		bool VorbisComment::Entry::is_valid() const
-		{
-			return is_valid_;
-		}
-
-		unsigned VorbisComment::Entry::get_field_length() const
-		{
-			FLAC__ASSERT(is_valid());
-			return entry_.length;
-		}
-
-		unsigned VorbisComment::Entry::get_field_name_length() const
-		{
-			FLAC__ASSERT(is_valid());
-			return field_name_length_;
-		}
-
-		unsigned VorbisComment::Entry::get_field_value_length() const
-		{
-			FLAC__ASSERT(is_valid());
-			return field_value_length_;
-		}
-
-		::FLAC__StreamMetadata_VorbisComment_Entry VorbisComment::Entry::get_entry() const
-		{
-			FLAC__ASSERT(is_valid());
-			return entry_;
-		}
-
-		const char *VorbisComment::Entry::get_field() const
-		{
-			FLAC__ASSERT(is_valid());
-			return (const char *)entry_.entry;
-		}
-
-		const char *VorbisComment::Entry::get_field_name() const
-		{
-			FLAC__ASSERT(is_valid());
-			return field_name_;
-		}
-
-		const char *VorbisComment::Entry::get_field_value() const
-		{
-			FLAC__ASSERT(is_valid());
-			return field_value_;
-		}
-
-		bool VorbisComment::Entry::set_field(const char *field, unsigned field_length)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(0 != field);
-
-			clear_entry();
-
-			if(0 == (entry_.entry = (FLAC__byte*)malloc(field_length))) {
-				is_valid_ = false;
-			}
-			else {
-				entry_.length = field_length;
-				memcpy(entry_.entry, field, field_length);
-				(void) parse_field();
-			}
-
-			return is_valid_;
-		}
-
-		bool VorbisComment::Entry::set_field_name(const char *field_name)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(0 != field_name);
-
-			clear_field_name();
-
-			if(0 == (field_name_ = strdup(field_name))) {
-				is_valid_ = false;
-			}
-			else {
-				field_name_length_ = strlen(field_name_);
-				compose_field();
-			}
-
-			return is_valid_;
-		}
-
-		bool VorbisComment::Entry::set_field_value(const char *field_value, unsigned field_value_length)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(0 != field_value);
-
-			clear_field_value();
-
-			if(0 == (field_value_ = (char *)malloc(field_value_length))) {
-				is_valid_ = false;
-			}
-			else {
-				field_value_length_ = field_value_length;
-				memcpy(field_value_, field_value, field_value_length);
-				compose_field();
-			}
-
-			return is_valid_;
-		}
-
-		void VorbisComment::Entry::zero()
-		{
-			is_valid_ = true;
-			entry_.length = 0;
-			entry_.entry = 0;
-			field_name_ = 0;
-			field_name_length_ = 0;
-			field_value_ = 0;
-			field_value_length_ = 0;
-		}
-
-		void VorbisComment::Entry::clear()
-		{
-			clear_entry();
-			clear_field_name();
-			clear_field_value();
-			is_valid_ = true;
-		}
-
-		void VorbisComment::Entry::clear_entry()
-		{
-			if(0 != entry_.entry) {
-				free(entry_.entry);
-				entry_.entry = 0;
-				entry_.length = 0;
-			}
-		}
-
-		void VorbisComment::Entry::clear_field_name()
-		{
-			if(0 != field_name_) {
-				free(field_name_);
-				field_name_ = 0;
-				field_name_length_ = 0;
-			}
-		}
-
-		void VorbisComment::Entry::clear_field_value()
-		{
-			if(0 != field_value_) {
-				free(field_value_);
-				field_value_ = 0;
-				field_value_length_ = 0;
-			}
-		}
-
-		void VorbisComment::Entry::construct(const char *field, unsigned field_length)
-		{
-			if(set_field(field, field_length))
-				parse_field();
-		}
-
-		void VorbisComment::Entry::construct(const char *field_name, const char *field_value, unsigned field_value_length)
-		{
-			if(set_field_name(field_name) && set_field_value(field_value, field_value_length))
-				compose_field();
-		}
-
-		void VorbisComment::Entry::compose_field()
-		{
-			clear_entry();
-
-			if(0 == (entry_.entry = (FLAC__byte*)malloc(field_name_length_ + 1 + field_value_length_))) {
-				is_valid_ = false;
-			}
-			else {
-				memcpy(entry_.entry, field_name_, field_name_length_);
-				entry_.length += field_name_length_;
-				memcpy(entry_.entry + entry_.length, "=", 1);
-				entry_.length += 1;
-				memcpy(entry_.entry + entry_.length, field_value_, field_value_length_);
-				entry_.length += field_value_length_;
-				is_valid_ = true;
-			}
-		}
-
-		void VorbisComment::Entry::parse_field()
-		{
-			clear_field_name();
-			clear_field_value();
-
-			const char *p = (const char *)memchr(entry_.entry, '=', entry_.length);
-
-			if(0 == p)
-				p = (const char *)entry_.entry + entry_.length;
-
-			field_name_length_ = p - (const char *)entry_.entry;
-			if(0 == (field_name_ = (char *)malloc(field_name_length_ + 1))) { // +1 for the trailing \0
-				is_valid_ = false;
-				return;
-			}
-			memcpy(field_name_, entry_.entry, field_name_length_);
-			field_name_[field_name_length_] = '\0';
-
-			if(entry_.length - field_name_length_ == 0) {
-				field_value_length_ = 0;
-				if(0 == (field_value_ = (char *)malloc(0))) {
-					is_valid_ = false;
-					return;
-				}
-			}
-			else {
-				field_value_length_ = entry_.length - field_name_length_ - 1;
-				if(0 == (field_value_ = (char *)malloc(field_value_length_))) {
-					is_valid_ = false;
-					return;
-				}
-				memcpy(field_value_, ++p, field_value_length_);
-			}
-
-			is_valid_ = true;
-		}
-
-
-		//
-		// VorbisComment
-		//
-
-		VorbisComment::VorbisComment():
-		Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false)
-		{ }
-
-		VorbisComment::~VorbisComment()
-		{ }
-
-		unsigned VorbisComment::get_num_comments() const
-		{
-			FLAC__ASSERT(is_valid());
-			return object_->data.vorbis_comment.num_comments;
-		}
-
-		VorbisComment::Entry VorbisComment::get_vendor_string() const
-		{
-			FLAC__ASSERT(is_valid());
-			return Entry((const char *)object_->data.vorbis_comment.vendor_string.entry, object_->data.vorbis_comment.vendor_string.length);
-		}
-
-		VorbisComment::Entry VorbisComment::get_comment(unsigned index) const
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
-			return Entry((const char *)object_->data.vorbis_comment.comments[index].entry, object_->data.vorbis_comment.comments[index].length);
-		}
-
-		bool VorbisComment::set_vendor_string(const VorbisComment::Entry &entry)
-		{
-			FLAC__ASSERT(is_valid());
-			// vendor_string is a special kind of entry
-			::FLAC__StreamMetadata_VorbisComment_Entry vendor_string;
-			vendor_string.length = entry.get_field_name_length();
-			vendor_string.entry = (FLAC__byte*)entry.get_field_name(); // we can cheat on const-ness because we make a copy below:
-			return (bool)::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true);
-		}
-
-		bool VorbisComment::set_comment(unsigned index, const VorbisComment::Entry &entry)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
-			return (bool)::FLAC__metadata_object_vorbiscomment_set_comment(object_, index, entry.get_entry(), /*copy=*/true);
-		}
-
-		bool VorbisComment::insert_comment(unsigned index, const VorbisComment::Entry &entry)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index <= object_->data.vorbis_comment.num_comments);
-			return (bool)::FLAC__metadata_object_vorbiscomment_insert_comment(object_, index, entry.get_entry(), /*copy=*/true);
-		}
-
-		bool VorbisComment::delete_comment(unsigned index)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
-			return (bool)::FLAC__metadata_object_vorbiscomment_delete_comment(object_, index);
-		}
-
-
-		// ============================================================
-		//
-		//  Level 0
-		//
-		// ============================================================
-
-		bool get_streaminfo(const char *filename, StreamInfo &streaminfo)
-		{
-			FLAC__ASSERT(0 != filename);
-
-			::FLAC__StreamMetadata s;
-
-			if(::FLAC__metadata_get_streaminfo(filename, &s)) {
-				streaminfo = s;
-				return true;
-			}
-			else
-				return false;
-		}
-
-
-		// ============================================================
-		//
-		//  Level 1
-		//
-		// ============================================================
-
-		SimpleIterator::SimpleIterator():
-		iterator_(::FLAC__metadata_simple_iterator_new())
-		{ }
-
-		SimpleIterator::~SimpleIterator()
-		{
-			clear();
-		}
-
-		void SimpleIterator::clear()
-		{
-			if(0 != iterator_)
-				FLAC__metadata_simple_iterator_delete(iterator_);
-			iterator_ = 0;
-		}
-
-		bool SimpleIterator::init(const char *filename, bool preserve_file_stats)
-		{
-			FLAC__ASSERT(0 != filename);
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_init(iterator_, filename, preserve_file_stats);
-		}
-
-		bool SimpleIterator::is_valid() const
-		{
-			return 0 != iterator_;
-		}
-
-		SimpleIterator::Status SimpleIterator::status()
-		{
-			FLAC__ASSERT(is_valid());
-			return Status(::FLAC__metadata_simple_iterator_status(iterator_));
-		}
-
-		bool SimpleIterator::is_writable() const
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_is_writable(iterator_);
-		}
-
-		bool SimpleIterator::next()
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_next(iterator_);
-		}
-
-		bool SimpleIterator::prev()
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_prev(iterator_);
-		}
-
-		::FLAC__MetadataType SimpleIterator::get_block_type() const
-		{
-			FLAC__ASSERT(is_valid());
-			return ::FLAC__metadata_simple_iterator_get_block_type(iterator_);
-		}
-
-		Prototype *SimpleIterator::get_block()
-		{
-			FLAC__ASSERT(is_valid());
-			return local::construct_block(::FLAC__metadata_simple_iterator_get_block(iterator_));
-		}
-
-		bool SimpleIterator::set_block(Prototype *block, bool use_padding)
-		{
-			FLAC__ASSERT(0 != block);
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_set_block(iterator_, block->object_, use_padding);
-		}
-
-		bool SimpleIterator::insert_block_after(Prototype *block, bool use_padding)
-		{
-			FLAC__ASSERT(0 != block);
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_insert_block_after(iterator_, block->object_, use_padding);
-		}
-
-		bool SimpleIterator::delete_block(bool use_padding)
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_simple_iterator_delete_block(iterator_, use_padding);
-		}
-
-
-		// ============================================================
-		//
-		//  Level 2
-		//
-		// ============================================================
-
-		Chain::Chain():
-		chain_(::FLAC__metadata_chain_new())
-		{ }
-
-		Chain::~Chain()
-		{
-			clear();
-		}
-
-		void Chain::clear()
-		{
-			if(0 != chain_)
-				FLAC__metadata_chain_delete(chain_);
-			chain_ = 0;
-		}
-
-		bool Chain::is_valid() const
-		{
-			return 0 != chain_;
-		}
-
-		Chain::Status Chain::status()
-		{
-			FLAC__ASSERT(is_valid());
-			return Status(::FLAC__metadata_chain_status(chain_));
-		}
-
-		bool Chain::read(const char *filename)
-		{
-			FLAC__ASSERT(0 != filename);
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_chain_read(chain_, filename);
-		}
-
-		bool Chain::write(bool use_padding, bool preserve_file_stats)
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats);
-		}
-
-		void Chain::merge_padding()
-		{
-			FLAC__ASSERT(is_valid());
-			::FLAC__metadata_chain_merge_padding(chain_);
-		}
-
-		void Chain::sort_padding()
-		{
-			FLAC__ASSERT(is_valid());
-			::FLAC__metadata_chain_sort_padding(chain_);
-		}
-
-
-		Iterator::Iterator():
-		iterator_(::FLAC__metadata_iterator_new())
-		{ }
-
-		Iterator::~Iterator()
-		{
-			clear();
-		}
-
-		void Iterator::clear()
-		{
-			if(0 != iterator_)
-				FLAC__metadata_iterator_delete(iterator_);
-			iterator_ = 0;
-		}
-
-		bool Iterator::is_valid() const
-		{
-			return 0 != iterator_;
-		}
-
-		void Iterator::init(Chain &chain)
-		{
-			FLAC__ASSERT(is_valid());
-			FLAC__ASSERT(chain.is_valid());
-			::FLAC__metadata_iterator_init(iterator_, chain.chain_);
-		}
-
-		bool Iterator::next()
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_iterator_next(iterator_);
-		}
-
-		bool Iterator::prev()
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_iterator_prev(iterator_);
-		}
-
-		::FLAC__MetadataType Iterator::get_block_type() const 
-		{
-			FLAC__ASSERT(is_valid());
-			return ::FLAC__metadata_iterator_get_block_type(iterator_);
-		}
-
-		Prototype *Iterator::get_block()
-		{
-			FLAC__ASSERT(is_valid());
-			Prototype *block = local::construct_block(::FLAC__metadata_iterator_get_block(iterator_));
-			if(0 != block)
-				block->set_reference(true);
-			return block;
-		}
-
-		bool Iterator::set_block(Prototype *block)
-		{
-			FLAC__ASSERT(0 != block);
-			FLAC__ASSERT(is_valid());
-			bool ret = (bool)::FLAC__metadata_iterator_set_block(iterator_, block->object_);
-			if(ret) {
-				block->set_reference(true);
-				delete block;
-			}
-			return ret;
-		}
-
-		bool Iterator::delete_block(bool replace_with_padding)
-		{
-			FLAC__ASSERT(is_valid());
-			return (bool)::FLAC__metadata_iterator_delete_block(iterator_, replace_with_padding);
-		}
-
-		bool Iterator::insert_block_before(Prototype *block)
-		{
-			FLAC__ASSERT(0 != block);
-			FLAC__ASSERT(is_valid());
-			bool ret = (bool)::FLAC__metadata_iterator_insert_block_before(iterator_, block->object_);
-			if(ret) {
-				block->set_reference(true);
-				delete block;
-			}
-			return ret;
-		}
-
-		bool Iterator::insert_block_after(Prototype *block)
-		{
-			FLAC__ASSERT(0 != block);
-			FLAC__ASSERT(is_valid());
-			bool ret = (bool)::FLAC__metadata_iterator_insert_block_after(iterator_, block->object_);
-			if(ret) {
-				block->set_reference(true);
-				delete block;
-			}
-			return ret;
-		}
-
-	};
-};
-#endif