1 /* libFLAC++ - Free Lossless Audio Codec library
2 * Copyright (C) 2002 Josh Coalson
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #ifndef FLACPP__METADATA_H
21 #define FLACPP__METADATA_H
23 #include "FLAC/metadata.h"
25 // ===============================================================
27 // Full documentation for the metadata interface can be found
28 // in the C layer in include/FLAC/metadata.h
30 // ===============================================================
32 /** \file include/FLAC++/metadata.h
35 * This module provides classes for creating and manipulating FLAC
36 * metadata blocks in memory, and three progressively more powerful
37 * interfaces for traversing and editing metadata in FLAC files.
39 * See the detailed documentation for each interface in the
40 * \link flacpp_metadata metadata \endlink module.
43 /** \defgroup flacpp_metadata FLAC++/metadata.h: metadata interfaces
47 * This module provides classes for creating and manipulating FLAC
48 * metadata blocks in memory, and three progressively more powerful
49 * interfaces for traversing and editing metadata in FLAC files.
51 * The behavior closely mimics the C layer interface; be sure to read
52 * the detailed description of the
53 * \link flac_metadata C metadata module \endlink.
60 // ============================================================
64 // ============================================================
66 /** \defgroup flacpp_metadata_object FLAC++/metadata.h: metadata object classes
67 * \ingroup flacpp_metadata
69 * This module contains classes representing FLAC metadata
72 * The behavior closely mimics the C layer interface; be
73 * sure to read the detailed description of the
74 * \link flac_metadata_object C metadata object module \endlink.
76 * Any time a metadata object is constructed or assigned, you
77 * should check is_valid() to make sure the underlying
78 * ::FLAC__StreamMetadata object was able to be created.
81 * When the get_*() methods of any metadata object method
82 * return you a const pointer, DO NOT disobey and write into it.
83 * Always use the set_*() methods.
88 /** Base class for all metadata block types.
93 /** Constructs a copy of the given object. This form
94 * always performs a deep copy.
96 Prototype(const Prototype &);
97 Prototype(const ::FLAC__StreamMetadata &);
98 Prototype(const ::FLAC__StreamMetadata *);
101 /** Constructs an object with copy control. When \a copy
102 * is \c true, behaves identically to
103 * FLAC::Metadata::Prototype::Prototype(const ::FLAC__StreamMetadata *object).
104 * When \a copy is \c false, the instance takes ownership of
105 * the pointer and the ::FLAC__StreamMetadata object will
106 * be freed by the destructor.
109 * \code object != NULL \endcode
111 Prototype(::FLAC__StreamMetadata *object, bool copy);
114 /** Assign from another object. Always performs a deep copy. */
115 void operator=(const Prototype &);
116 void operator=(const ::FLAC__StreamMetadata &);
117 void operator=(const ::FLAC__StreamMetadata *);
120 /** Deletes the underlying ::FLAC__StreamMetadata object.
122 virtual void clear();
124 ::FLAC__StreamMetadata *object_;
126 /** Deletes the underlying ::FLAC__StreamMetadata object.
128 virtual ~Prototype();
131 /** Check for equality, performing a deep compare by following pointers. */
132 inline bool operator==(const Prototype &) const;
133 inline bool operator==(const ::FLAC__StreamMetadata &) const;
134 inline bool operator==(const ::FLAC__StreamMetadata *) const;
138 /** Check for inequality, performing a deep compare by following pointers. */
139 inline bool operator!=(const Prototype &) const;
140 inline bool operator!=(const ::FLAC__StreamMetadata &) const;
141 inline bool operator!=(const ::FLAC__StreamMetadata *) const;
144 friend class SimpleIterator;
145 friend class Iterator;
147 /** Returns \c true if the object was correctly constructed
148 * (i.e. the underlying ::FLAC__StreamMetadata object was
149 * properly allocated), else \c false.
151 inline bool is_valid() const;
153 /** Returns \c true if this block is the last block in a
154 * stream, else \c false.
157 * \code is_valid() \endcode
159 bool get_is_last() const;
161 /** Returns the type of the block.
164 * \code is_valid() \endcode
166 ::FLAC__MetadataType get_type() const;
168 /** Returns the stream length of the metadata block.
171 * The length does not include the metadata block header,
175 * \code is_valid() \endcode
177 unsigned get_length() const;
179 /** Sets the "is_last" flag for the block. When using the iterators
180 * it is not necessary to set this flag; they will do it for you.
183 * \code is_valid() \endcode
185 void set_is_last(bool);
187 /** Private and undefined so you can't use it. */
190 // These are used only by Iterator
192 inline void set_reference(bool x) { is_reference_ = x; }
195 inline bool Prototype::operator==(const Prototype &object) const
196 { return (bool)::FLAC__metadata_object_is_equal(object_, object.object_); }
198 inline bool Prototype::operator==(const ::FLAC__StreamMetadata &object) const
199 { return (bool)::FLAC__metadata_object_is_equal(object_, &object); }
201 inline bool Prototype::operator==(const ::FLAC__StreamMetadata *object) const
202 { return (bool)::FLAC__metadata_object_is_equal(object_, object); }
204 inline bool Prototype::operator!=(const Prototype &object) const
205 { return !operator==(object); }
207 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata &object) const
208 { return !operator==(object); }
210 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata *object) const
211 { return !operator==(object); }
213 inline bool Prototype::is_valid() const
214 { return 0 != object_; }
216 /** Create a deep copy of an object and return it. */
217 Prototype *clone(const Prototype *);
220 /** STREAMINFO metadata block.
221 * See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>.
223 class StreamInfo : public Prototype {
228 /** Constructs a copy of the given object. This form
229 * always performs a deep copy.
231 inline StreamInfo(const StreamInfo &object): Prototype(object) { }
232 inline StreamInfo(const ::FLAC__StreamMetadata &object): Prototype(object) { }
233 inline StreamInfo(const ::FLAC__StreamMetadata *object): Prototype(object) { }
236 /** Constructs an object with copy control. See
237 * Prototype(::FLAC__StreamMetadata *object, bool copy).
239 inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
244 /** Assign from another object. Always performs a deep copy. */
245 inline void operator=(const StreamInfo &object) { Prototype::operator=(object); }
246 inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
247 inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
251 /** Check for equality, performing a deep compare by following pointers. */
252 inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
253 inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
254 inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
258 /** Check for inequality, performing a deep compare by following pointers. */
259 inline bool operator!=(const StreamInfo &object) const { return Prototype::operator!=(object); }
260 inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
261 inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
265 /** See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>. */
266 unsigned get_min_blocksize() const;
267 unsigned get_max_blocksize() const;
268 unsigned get_min_framesize() const;
269 unsigned get_max_framesize() const;
270 unsigned get_sample_rate() const;
271 unsigned get_channels() const;
272 unsigned get_bits_per_sample() const;
273 FLAC__uint64 get_total_samples() const;
274 const FLAC__byte *get_md5sum() const;
276 void set_min_blocksize(unsigned value);
277 void set_max_blocksize(unsigned value);
278 void set_min_framesize(unsigned value);
279 void set_max_framesize(unsigned value);
280 void set_sample_rate(unsigned value);
281 void set_channels(unsigned value);
282 void set_bits_per_sample(unsigned value);
283 void set_total_samples(FLAC__uint64 value);
284 void set_md5sum(const FLAC__byte value[16]);
288 /** PADDING metadata block.
289 * See <A HREF="../format.html#metadata_block_padding">format specification</A>.
291 class Padding : public Prototype {
296 /** Constructs a copy of the given object. This form
297 * always performs a deep copy.
299 inline Padding(const Padding &object): Prototype(object) { }
300 inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
301 inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
304 /** Constructs an object with copy control. See
305 * Prototype(::FLAC__StreamMetadata *object, bool copy).
307 inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
312 /** Assign from another object. Always performs a deep copy. */
313 inline void operator=(const Padding &object) { Prototype::operator=(object); }
314 inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
315 inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
319 /** Check for equality, performing a deep compare by following pointers. */
320 inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
321 inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
322 inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
326 /** Check for inequality, performing a deep compare by following pointers. */
327 inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
328 inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
329 inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
332 void set_length(unsigned length);
335 /** APPLICATION metadata block.
336 * See <A HREF="../format.html#metadata_block_application">format specification</A>.
338 class Application : public Prototype {
343 /** Constructs a copy of the given object. This form
344 * always performs a deep copy.
346 inline Application(const Application &object): Prototype(object) { }
347 inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
348 inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
351 /** Constructs an object with copy control. See
352 * Prototype(::FLAC__StreamMetadata *object, bool copy).
354 inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
359 /** Assign from another object. Always performs a deep copy. */
360 inline void operator=(const Application &object) { Prototype::operator=(object); }
361 inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
362 inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
366 /** Check for equality, performing a deep compare by following pointers. */
367 inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
368 inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
369 inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
373 /** Check for inequality, performing a deep compare by following pointers. */
374 inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
375 inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
376 inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
379 const FLAC__byte *get_id() const;
380 const FLAC__byte *get_data() const;
382 void set_id(const FLAC__byte value[4]);
383 //! This form always copies \a data
384 bool set_data(const FLAC__byte *data, unsigned length);
385 bool set_data(FLAC__byte *data, unsigned length, bool copy);
388 /** SEEKTABLE metadata block.
389 * See <A HREF="../format.html#metadata_block_seektable">format specification</A>.
391 class SeekTable : public Prototype {
396 /** Constructs a copy of the given object. This form
397 * always performs a deep copy.
399 inline SeekTable(const SeekTable &object): Prototype(object) { }
400 inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
401 inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
404 /** Constructs an object with copy control. See
405 * Prototype(::FLAC__StreamMetadata *object, bool copy).
407 inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
412 /** Assign from another object. Always performs a deep copy. */
413 inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
414 inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
415 inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
419 /** Check for equality, performing a deep compare by following pointers. */
420 inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
421 inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
422 inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
426 /** Check for inequality, performing a deep compare by following pointers. */
427 inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
428 inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
429 inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
432 unsigned get_num_points() const;
433 ::FLAC__StreamMetadata_SeekPoint get_point(unsigned index) const;
435 //! See FLAC__metadata_object_seektable_set_point()
436 void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
438 //! See FLAC__metadata_object_seektable_insert_point()
439 bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
441 //! See FLAC__metadata_object_seektable_delete_point()
442 bool delete_point(unsigned index);
444 //! See FLAC__metadata_object_seektable_is_legal()
445 bool is_legal() const;
448 /** VORBIS_COMMENT metadata block.
449 * See <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>.
451 class VorbisComment : public Prototype {
453 /** Convenience class for encapsulating Vorbis comment
454 * entries. An entry is a vendor string or a comment
455 * field. In the case of a vendor string, the field
456 * name is undefined; only the field value is relevant.
458 * A \a field as used in the methods refers to an
459 * entire 'NAME=VALUE' string; the string is not null-
460 * terminated and a length field is required since the
461 * string may contain embedded nulls.
463 * A \a field_name is what is on the left side of the
464 * first '=' in the \a field. By definition it is ASCII
465 * and so is null-terminated and does not require a
466 * length to describe it. \a field_name is undefined
467 * for a vendor string entry.
469 * A \a field_value is what is on the right side of the
470 * first '=' in the \a field. By definition, this may
471 * contain embedded nulls and so a \a field_value_length
472 * is requires to describe it.
474 * Always check is_valid() after the constructor or operator=
475 * to make sure memory was properly allocated.
480 Entry(const char *field, unsigned field_length);
481 Entry(const char *field_name, const char *field_value, unsigned field_value_length);
482 Entry(const Entry &entry);
483 void operator=(const Entry &entry);
487 virtual bool is_valid() const;
489 unsigned get_field_length() const;
490 unsigned get_field_name_length() const;
491 unsigned get_field_value_length() const;
493 ::FLAC__StreamMetadata_VorbisComment_Entry get_entry() const;
494 const char *get_field() const;
495 const char *get_field_name() const;
496 const char *get_field_value() const;
498 bool set_field(const char *field, unsigned field_length);
499 bool set_field_name(const char *field_name);
500 bool set_field_value(const char *field_value, unsigned field_value_length);
503 ::FLAC__StreamMetadata_VorbisComment_Entry entry_;
505 unsigned field_name_length_;
507 unsigned field_value_length_;
512 void clear_field_name();
513 void clear_field_value();
514 void construct(const char *field, unsigned field_length);
515 void construct(const char *field_name, const char *field_value, unsigned field_value_length);
516 void compose_field();
523 /** Constructs a copy of the given object. This form
524 * always performs a deep copy.
526 inline VorbisComment(const VorbisComment &object): Prototype(object) { }
527 inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
528 inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
531 /** Constructs an object with copy control. See
532 * Prototype(::FLAC__StreamMetadata *object, bool copy).
534 inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
539 /** Assign from another object. Always performs a deep copy. */
540 inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
541 inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
542 inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
546 /** Check for equality, performing a deep compare by following pointers. */
547 inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
548 inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
549 inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
553 /** Check for inequality, performing a deep compare by following pointers. */
554 inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
555 inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
556 inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
559 unsigned get_num_comments() const;
560 Entry get_vendor_string() const; // only the Entry's field name should be used
561 Entry get_comment(unsigned index) const;
563 //! See FLAC__metadata_object_vorbiscomment_set_vendor_string()
564 //! \note Only the Entry's field name will be used.
565 bool set_vendor_string(const Entry &entry); // only the Entry's field name will be used
567 //! See FLAC__metadata_object_vorbiscomment_set_comment()
568 bool set_comment(unsigned index, const Entry &entry);
570 //! See FLAC__metadata_object_vorbiscomment_insert_comment()
571 bool insert_comment(unsigned index, const Entry &entry);
573 //! See FLAC__metadata_object_vorbiscomment_delete_comment()
574 bool delete_comment(unsigned index);
580 /** \defgroup flacpp_metadata_level0 FLAC++/metadata.h: metadata level 0 interface
581 * \ingroup flacpp_metadata
584 * Level 0 metadata iterator.
586 * See the \link flac_metadata_level0 C layer equivalent \endlink
592 //! See FLAC__metadata_get_streaminfo().
593 bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
598 /** \defgroup flacpp_metadata_level1 FLAC++/metadata.h: metadata level 1 interface
599 * \ingroup flacpp_metadata
602 * Level 1 metadata iterator.
604 * The flow through the iterator in the C++ layer is similar
606 * - Create a SimpleIterator instance
607 * - Check SimpleIterator::is_valid()
608 * - Call SimpleIterator::init() and check the return
609 * - Traverse and/or edit. Edits are written to file
611 * - Destroy the SimpleIterator instance
613 * The ownership of pointers in the C++ layer follows that in
615 * - The objects returned by get_block() are yours to
616 * modify, but changes are not reflected in the FLAC file
617 * until you call set_block(). The objects are also
618 * yours to delete; they are not automatically deleted
619 * when passed to set_block() or insert_block_after().
621 * See the \link flac_metadata_level1 C layer equivalent \endlink
627 /** This class is a wrapper around the FLAC__metadata_simple_iterator
628 * structures and methods; see ::FLAC__Metadata_SimpleIterator.
630 class SimpleIterator {
634 inline Status(::FLAC__Metadata_SimpleIteratorStatus status): status_(status) { }
635 inline operator ::FLAC__Metadata_SimpleIteratorStatus() const { return status_; }
636 inline const char *as_cstring() const { return ::FLAC__Metadata_SimpleIteratorStatusString[status_]; }
638 ::FLAC__Metadata_SimpleIteratorStatus status_;
642 virtual ~SimpleIterator();
644 bool init(const char *filename, bool read_only, bool preserve_file_stats);
646 bool is_valid() const;
648 bool is_writable() const;
653 ::FLAC__MetadataType get_block_type() const;
654 Prototype *get_block();
655 bool set_block(Prototype *block, bool use_padding = true);
656 bool insert_block_after(Prototype *block, bool use_padding = true);
657 bool delete_block(bool use_padding = true);
660 ::FLAC__Metadata_SimpleIterator *iterator_;
667 /** \defgroup flacpp_metadata_level2 FLAC++/metadata.h: metadata level 2 interface
668 * \ingroup flacpp_metadata
671 * Level 2 metadata iterator.
673 * The flow through the iterator in the C++ layer is similar
675 * - Create a Chain instance
676 * - Check Chain::is_valid()
677 * - Call Chain::read() and check the return
678 * - Traverse and/or edit with an Iterator or with
679 * Chain::merge_padding() or Chain::sort_padding()
680 * - Write changes back to FLAC file with Chain::write()
681 * - Destroy the Chain instance
683 * The ownership of pointers in the C++ layer follows that in
685 * - The objects returned by Iterator::get_block() are
686 * owned by the iterator and should not be deleted.
687 * When you modify the block, you are directly editing
688 * what's in the chain and do not need to call
689 * Iterator::set_block(). However the changes will not
690 * be reflected in the FLAC file until the chain is
691 * written with Chain::write().
692 * - When you pass an object to Iterator::set_block(),
693 * Iterator::insert_block_before(), or
694 * Iterator::insert_block_after(), the iterator takes
695 * ownership of the block and it will be deleted with the
698 * See the \link flac_metadata_level2 C layer equivalent \endlink
704 /** This class is a wrapper around the FLAC__metadata_chain
705 * structures and methods; see ::FLAC__Metadata_Chain.
711 inline Status(::FLAC__Metadata_ChainStatus status): status_(status) { }
712 inline operator ::FLAC__Metadata_ChainStatus() const { return status_; }
713 inline const char *as_cstring() const { return ::FLAC__Metadata_ChainStatusString[status_]; }
715 ::FLAC__Metadata_ChainStatus status_;
721 friend class Iterator;
723 bool is_valid() const;
726 bool read(const char *filename);
727 bool write(bool use_padding = true, bool preserve_file_stats = false);
729 void merge_padding();
733 ::FLAC__Metadata_Chain *chain_;
734 virtual void clear();
737 /** This class is a wrapper around the FLAC__metadata_iterator
738 * structures and methods; see ::FLAC__Metadata_Iterator.
745 bool is_valid() const;
747 void init(Chain &chain);
752 ::FLAC__MetadataType get_block_type() const;
753 Prototype *get_block();
754 bool set_block(Prototype *block);
755 bool delete_block(bool replace_with_padding);
756 bool insert_block_before(Prototype *block);
757 bool insert_block_after(Prototype *block);
760 ::FLAC__Metadata_Iterator *iterator_;
761 virtual void clear();