more doxygen docs
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 20 Aug 2002 03:56:52 +0000 (03:56 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 20 Aug 2002 03:56:52 +0000 (03:56 +0000)
include/FLAC++/all.h
include/FLAC++/decoder.h
include/FLAC++/encoder.h
include/FLAC++/metadata.h

index ab91978..72820ad 100644 (file)
  * that encapsulate the encoders, decoders, and metadata interfaces
  * in libFLAC.
  *
+ * Note that Doxygen currently has some quirks (bugs?) in the way
+ * it deals with some member groups and C++ constructs.  You will find
+ * some document entries in the wrong place under [NOHEADER] sections.
+ * Hopefully this is not too annoying.
  */
 
 #endif
index 89cb359..37d114f 100644 (file)
@@ -57,10 +57,10 @@ namespace FLAC {
                // ============================================================
                //
                //  The only real difference here is that instead of passing
-               //  in C function pointers for callbacks, you inherit from
-               //  stream and provide implementations for the callbacks in
-               //  the derived class; because of this there is no need for a
-               //  'client_data' property.
+               //  in C function pointers for callbacks, you inherit from the
+               //  decoder class and provide implementations for the callbacks
+               //  in the derived class; because of this there is no need for
+               //  'client_data' property.
                //
                // ============================================================
 
index 6fa5f61..9af6569 100644 (file)
@@ -62,10 +62,10 @@ namespace FLAC {
                //  ----------------------------------------------------------
                //
                //  The only real difference here is that instead of passing
-               //  in C function pointers for callbacks, you inherit from
-               //  stream and provide implementations for the callbacks in
-               //  the derived class; because of this there is no need for a
-               //  'client_data' property.
+               //  in C function pointers for callbacks, you inherit from the
+               //  encoder class and provide implementations for the callbacks
+               //  in the derived class; because of this there is no need for
+               //  'client_data' property.
                //
                // ============================================================
 
index f9d7325..6ba0ce7 100644 (file)
@@ -218,6 +218,7 @@ namespace FLAC {
 
 
                /** STREAMINFO metadata block.
+                *  See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>.
                 */
                class StreamInfo : public Prototype {
                public:
@@ -234,9 +235,6 @@ namespace FLAC {
 
                        /** 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 @@ namespace FLAC {
                        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 @@ namespace FLAC {
                        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 @@ namespace FLAC {
                        };
 
                        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.
+                *
+                *  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().
                 *
-                * Detailed XXX.
+                *  See the \link flac_metadata_level1 C layer equivalent \endlink
+                *  for more.
                 *
                 * \{
                 */
@@ -553,50 +665,39 @@ namespace FLAC {
                /* \} */
 
 
-               // ============================================================
-               //
-               //  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.
+                *
+                *  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.
                 *
-                * Detailed XXX.
+                *  See the \link flac_metadata_level2 C layer equivalent \endlink
+                *  for more.
                 *
                 * \{
                 */
@@ -667,866 +768,3 @@ namespace FLAC {
 };
 
 #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