add libFLAC++ equivalent callback-based chain reading/writing and tests
[platform/upstream/flac.git] / include / FLAC++ / metadata.h
1 /* libFLAC++ - Free Lossless Audio Codec library
2  * Copyright (C) 2002,2003,2004  Josh Coalson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of the Xiph.org Foundation nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #ifndef FLACPP__METADATA_H
33 #define FLACPP__METADATA_H
34
35 #include "export.h"
36
37 #include "FLAC/metadata.h"
38
39 // ===============================================================
40 //
41 //  Full documentation for the metadata interface can be found
42 //  in the C layer in include/FLAC/metadata.h
43 //
44 // ===============================================================
45
46 /** \file include/FLAC++/metadata.h
47  *
48  *  \brief
49  *  This module provides classes for creating and manipulating FLAC
50  *  metadata blocks in memory, and three progressively more powerful
51  *  interfaces for traversing and editing metadata in FLAC files.
52  *
53  *  See the detailed documentation for each interface in the
54  *  \link flacpp_metadata metadata \endlink module.
55  */
56
57 /** \defgroup flacpp_metadata FLAC++/metadata.h: metadata interfaces
58  *  \ingroup flacpp
59  *
60  *  \brief
61  *  This module provides classes for creating and manipulating FLAC
62  *  metadata blocks in memory, and three progressively more powerful
63  *  interfaces for traversing and editing metadata in FLAC files.
64  *
65  *  The behavior closely mimics the C layer interface; be sure to read
66  *  the detailed description of the
67  *  \link flac_metadata C metadata module \endlink.
68  */
69
70
71 namespace FLAC {
72         namespace Metadata {
73
74                 // ============================================================
75                 //
76                 //  Metadata objects
77                 //
78                 // ============================================================
79
80                 /** \defgroup flacpp_metadata_object FLAC++/metadata.h: metadata object classes
81                  *  \ingroup flacpp_metadata
82                  *
83                  * This module contains classes representing FLAC metadata
84                  * blocks in memory.
85                  *
86                  * The behavior closely mimics the C layer interface; be
87                  * sure to read the detailed description of the
88                  * \link flac_metadata_object C metadata object module \endlink.
89                  *
90                  * Any time a metadata object is constructed or assigned, you
91                  * should check is_valid() to make sure the underlying
92                  * ::FLAC__StreamMetadata object was able to be created.
93                  *
94                  * \warning
95                  * When the get_*() methods of any metadata object method
96                  * return you a const pointer, DO NOT disobey and write into it.
97                  * Always use the set_*() methods.
98                  *
99                  * \{
100                  */
101
102                 /** Base class for all metadata block types.
103                  */
104                 class FLACPP_API Prototype {
105                 protected:
106                         //@{
107                         /** Constructs a copy of the given object.  This form
108                          *  always performs a deep copy.
109                          */
110                         Prototype(const Prototype &);
111                         Prototype(const ::FLAC__StreamMetadata &);
112                         Prototype(const ::FLAC__StreamMetadata *);
113                         //@}
114
115                         /** Constructs an object with copy control.  When \a copy
116                          *  is \c true, behaves identically to
117                          *  FLAC::Metadata::Prototype::Prototype(const ::FLAC__StreamMetadata *object).
118                          *  When \a copy is \c false, the instance takes ownership of
119                          *  the pointer and the ::FLAC__StreamMetadata object will
120                          *  be freed by the destructor.
121                          *
122                          *  \assert
123                          *    \code object != NULL \endcode
124                          */
125                         Prototype(::FLAC__StreamMetadata *object, bool copy);
126
127                         //@{
128                         /** Assign from another object.  Always performs a deep copy. */
129                         void operator=(const Prototype &);
130                         void operator=(const ::FLAC__StreamMetadata &);
131                         void operator=(const ::FLAC__StreamMetadata *);
132                         //@}
133
134                         /** Deletes the underlying ::FLAC__StreamMetadata object.
135                          */
136                         virtual void clear();
137
138                         ::FLAC__StreamMetadata *object_;
139                 public:
140                         /** Deletes the underlying ::FLAC__StreamMetadata object.
141                          */
142                         virtual ~Prototype();
143
144                         //@{
145                         /** Check for equality, performing a deep compare by following pointers. */
146                         inline bool operator==(const Prototype &) const;
147                         inline bool operator==(const ::FLAC__StreamMetadata &) const;
148                         inline bool operator==(const ::FLAC__StreamMetadata *) const;
149                         //@}
150
151                         //@{
152                         /** Check for inequality, performing a deep compare by following pointers. */
153                         inline bool operator!=(const Prototype &) const;
154                         inline bool operator!=(const ::FLAC__StreamMetadata &) const;
155                         inline bool operator!=(const ::FLAC__StreamMetadata *) const;
156                         //@}
157
158                         friend class SimpleIterator;
159                         friend class Iterator;
160
161                         /** Returns \c true if the object was correctly constructed
162                          *  (i.e. the underlying ::FLAC__StreamMetadata object was
163                          *  properly allocated), else \c false.
164                          */
165                         inline bool is_valid() const;
166
167                         /** Returns \c true if this block is the last block in a
168                          *  stream, else \c false.
169                          *
170                          * \assert
171                          *   \code is_valid() \endcode
172                          */
173                         bool get_is_last() const;
174
175                         /** Returns the type of the block.
176                          *
177                          * \assert
178                          *   \code is_valid() \endcode
179                          */
180                         ::FLAC__MetadataType get_type() const;
181
182                         /** Returns the stream length of the metadata block.
183                          *
184                          * \note
185                          *   The length does not include the metadata block header,
186                          *   per spec.
187                          *
188                          * \assert
189                          *   \code is_valid() \endcode
190                          */
191                         unsigned get_length() const;
192
193                         /** Sets the "is_last" flag for the block.  When using the iterators
194                          *  it is not necessary to set this flag; they will do it for you.
195                          *
196                          * \assert
197                          *   \code is_valid() \endcode
198                          */
199                         void set_is_last(bool);
200                 private:
201                         /** Private and undefined so you can't use it. */
202                         Prototype();
203
204                         // These are used only by Iterator
205                         bool is_reference_;
206                         inline void set_reference(bool x) { is_reference_ = x; }
207                 };
208
209                 inline bool Prototype::operator==(const Prototype &object) const
210                 { return (bool)::FLAC__metadata_object_is_equal(object_, object.object_); }
211
212                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata &object) const
213                 { return (bool)::FLAC__metadata_object_is_equal(object_, &object); }
214
215                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata *object) const
216                 { return (bool)::FLAC__metadata_object_is_equal(object_, object); }
217
218                 inline bool Prototype::operator!=(const Prototype &object) const
219                 { return !operator==(object); }
220
221                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata &object) const
222                 { return !operator==(object); }
223
224                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata *object) const
225                 { return !operator==(object); }
226
227                 inline bool Prototype::is_valid() const
228                 { return 0 != object_; }
229
230                 /** Create a deep copy of an object and return it. */
231                 FLACPP_API Prototype *clone(const Prototype *);
232
233
234                 /** STREAMINFO metadata block.
235                  *  See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>.
236                  */
237                 class FLACPP_API StreamInfo : public Prototype {
238                 public:
239                         StreamInfo();
240
241                         //@{
242                         /** Constructs a copy of the given object.  This form
243                          *  always performs a deep copy.
244                          */
245                         inline StreamInfo(const StreamInfo &object): Prototype(object) { }
246                         inline StreamInfo(const ::FLAC__StreamMetadata &object): Prototype(object) { }
247                         inline StreamInfo(const ::FLAC__StreamMetadata *object): Prototype(object) { }
248                         //@}
249
250                         /** Constructs an object with copy control.  See
251                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
252                          */
253                         inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
254
255                         ~StreamInfo();
256
257                         //@{
258                         /** Assign from another object.  Always performs a deep copy. */
259                         inline void operator=(const StreamInfo &object) { Prototype::operator=(object); }
260                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
261                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
262                         //@}
263
264                         //@{
265                         /** Check for equality, performing a deep compare by following pointers. */
266                         inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
267                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
268                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
269                         //@}
270
271                         //@{
272                         /** Check for inequality, performing a deep compare by following pointers. */
273                         inline bool operator!=(const StreamInfo &object) const { return Prototype::operator!=(object); }
274                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
275                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
276                         //@}
277
278                         //@{
279                         /** See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>. */
280                         unsigned get_min_blocksize() const;
281                         unsigned get_max_blocksize() const;
282                         unsigned get_min_framesize() const;
283                         unsigned get_max_framesize() const;
284                         unsigned get_sample_rate() const;
285                         unsigned get_channels() const;
286                         unsigned get_bits_per_sample() const;
287                         FLAC__uint64 get_total_samples() const;
288                         const FLAC__byte *get_md5sum() const;
289
290                         void set_min_blocksize(unsigned value);
291                         void set_max_blocksize(unsigned value);
292                         void set_min_framesize(unsigned value);
293                         void set_max_framesize(unsigned value);
294                         void set_sample_rate(unsigned value);
295                         void set_channels(unsigned value);
296                         void set_bits_per_sample(unsigned value);
297                         void set_total_samples(FLAC__uint64 value);
298                         void set_md5sum(const FLAC__byte value[16]);
299                         //@}
300                 };
301
302                 /** PADDING metadata block.
303                  *  See <A HREF="../format.html#metadata_block_padding">format specification</A>.
304                  */
305                 class FLACPP_API Padding : public Prototype {
306                 public:
307                         Padding();
308
309                         //@{
310                         /** Constructs a copy of the given object.  This form
311                          *  always performs a deep copy.
312                          */
313                         inline Padding(const Padding &object): Prototype(object) { }
314                         inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
315                         inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
316                         //@}
317
318                         /** Constructs an object with copy control.  See
319                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
320                          */
321                         inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
322
323                         ~Padding();
324
325                         //@{
326                         /** Assign from another object.  Always performs a deep copy. */
327                         inline void operator=(const Padding &object) { Prototype::operator=(object); }
328                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
329                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
330                         //@}
331
332                         //@{
333                         /** Check for equality, performing a deep compare by following pointers. */
334                         inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
335                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
336                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
337                         //@}
338
339                         //@{
340                         /** Check for inequality, performing a deep compare by following pointers. */
341                         inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
342                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
343                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
344                         //@}
345
346                         void set_length(unsigned length);
347                 };
348
349                 /** APPLICATION metadata block.
350                  *  See <A HREF="../format.html#metadata_block_application">format specification</A>.
351                  */
352                 class FLACPP_API Application : public Prototype {
353                 public:
354                         Application();
355                         //
356                         //@{
357                         /** Constructs a copy of the given object.  This form
358                          *  always performs a deep copy.
359                          */
360                         inline Application(const Application &object): Prototype(object) { }
361                         inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
362                         inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
363                         //@}
364
365                         /** Constructs an object with copy control.  See
366                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
367                          */
368                         inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
369
370                         ~Application();
371
372                         //@{
373                         /** Assign from another object.  Always performs a deep copy. */
374                         inline void operator=(const Application &object) { Prototype::operator=(object); }
375                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
376                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
377                         //@}
378
379                         //@{
380                         /** Check for equality, performing a deep compare by following pointers. */
381                         inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
382                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
383                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
384                         //@}
385
386                         //@{
387                         /** Check for inequality, performing a deep compare by following pointers. */
388                         inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
389                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
390                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
391                         //@}
392
393                         const FLAC__byte *get_id() const;
394                         const FLAC__byte *get_data() const;
395
396                         void set_id(const FLAC__byte value[4]);
397                         //! This form always copies \a data
398                         bool set_data(const FLAC__byte *data, unsigned length);
399                         bool set_data(FLAC__byte *data, unsigned length, bool copy);
400                 };
401
402                 /** SEEKTABLE metadata block.
403                  *  See <A HREF="../format.html#metadata_block_seektable">format specification</A>.
404                  */
405                 class FLACPP_API SeekTable : public Prototype {
406                 public:
407                         SeekTable();
408
409                         //@{
410                         /** Constructs a copy of the given object.  This form
411                          *  always performs a deep copy.
412                          */
413                         inline SeekTable(const SeekTable &object): Prototype(object) { }
414                         inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
415                         inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
416                         //@}
417
418                         /** Constructs an object with copy control.  See
419                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
420                          */
421                         inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
422
423                         ~SeekTable();
424
425                         //@{
426                         /** Assign from another object.  Always performs a deep copy. */
427                         inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
428                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
429                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
430                         //@}
431
432                         //@{
433                         /** Check for equality, performing a deep compare by following pointers. */
434                         inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
435                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
436                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
437                         //@}
438
439                         //@{
440                         /** Check for inequality, performing a deep compare by following pointers. */
441                         inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
442                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
443                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
444                         //@}
445
446                         unsigned get_num_points() const;
447                         ::FLAC__StreamMetadata_SeekPoint get_point(unsigned index) const;
448
449                         //! See FLAC__metadata_object_seektable_set_point()
450                         void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
451
452                         //! See FLAC__metadata_object_seektable_insert_point()
453                         bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
454
455                         //! See FLAC__metadata_object_seektable_delete_point()
456                         bool delete_point(unsigned index);
457
458                         //! See FLAC__metadata_object_seektable_is_legal()
459                         bool is_legal() const;
460                 };
461
462                 /** VORBIS_COMMENT metadata block.
463                  *  See <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>.
464                  */
465                 class FLACPP_API VorbisComment : public Prototype {
466                 public:
467                         /** Convenience class for encapsulating Vorbis comment
468                          *  entries.  An entry is a vendor string or a comment
469                          *  field.  In the case of a vendor string, the field
470                          *  name is undefined; only the field value is relevant.
471                          *
472                          *  A \a field as used in the methods refers to an
473                          *  entire 'NAME=VALUE' string; the string is not null-
474                          *  terminated and a length field is required since the
475                          *  string may contain embedded nulls.
476                          *
477                          *  A \a field_name is what is on the left side of the
478                          *  first '=' in the \a field.  By definition it is ASCII
479                          *  and so is null-terminated and does not require a
480                          *  length to describe it.  \a field_name is undefined
481                          *  for a vendor string entry.
482                          *
483                          *  A \a field_value is what is on the right side of the
484                          *  first '=' in the \a field.  By definition, this may
485                          *  contain embedded nulls and so a \a field_value_length
486                          *  is requires to describe it.
487                          *
488                          *  Always check is_valid() after the constructor or operator=
489                          *  to make sure memory was properly allocated.
490                          */
491                         class FLACPP_API Entry {
492                         public:
493                                 Entry();
494                                 Entry(const char *field, unsigned field_length);
495                                 Entry(const char *field_name, const char *field_value, unsigned field_value_length);
496                                 Entry(const Entry &entry);
497                                 void operator=(const Entry &entry);
498
499                                 virtual ~Entry();
500
501                                 virtual bool is_valid() const;
502
503                                 unsigned get_field_length() const;
504                                 unsigned get_field_name_length() const;
505                                 unsigned get_field_value_length() const;
506
507                                 ::FLAC__StreamMetadata_VorbisComment_Entry get_entry() const;
508                                 const char *get_field() const;
509                                 const char *get_field_name() const;
510                                 const char *get_field_value() const;
511
512                                 bool set_field(const char *field, unsigned field_length);
513                                 bool set_field_name(const char *field_name);
514                                 bool set_field_value(const char *field_value, unsigned field_value_length);
515                         protected:
516                                 bool is_valid_;
517                                 ::FLAC__StreamMetadata_VorbisComment_Entry entry_;
518                                 char *field_name_;
519                                 unsigned field_name_length_;
520                                 char *field_value_;
521                                 unsigned field_value_length_;
522                         private:
523                                 void zero();
524                                 void clear();
525                                 void clear_entry();
526                                 void clear_field_name();
527                                 void clear_field_value();
528                                 void construct(const char *field, unsigned field_length);
529                                 void construct(const char *field_name, const char *field_value, unsigned field_value_length);
530                                 void compose_field();
531                                 void parse_field();
532                         };
533
534                         VorbisComment();
535
536                         //@{
537                         /** Constructs a copy of the given object.  This form
538                          *  always performs a deep copy.
539                          */
540                         inline VorbisComment(const VorbisComment &object): Prototype(object) { }
541                         inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
542                         inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
543                         //@}
544
545                         /** Constructs an object with copy control.  See
546                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
547                          */
548                         inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
549
550                         ~VorbisComment();
551
552                         //@{
553                         /** Assign from another object.  Always performs a deep copy. */
554                         inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
555                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
556                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
557                         //@}
558
559                         //@{
560                         /** Check for equality, performing a deep compare by following pointers. */
561                         inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
562                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
563                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
564                         //@}
565
566                         //@{
567                         /** Check for inequality, performing a deep compare by following pointers. */
568                         inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
569                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
570                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
571                         //@}
572
573                         unsigned get_num_comments() const;
574                         Entry get_vendor_string() const; // only the Entry's field name should be used
575                         Entry get_comment(unsigned index) const;
576
577                         //! See FLAC__metadata_object_vorbiscomment_set_vendor_string()
578                         //! \note Only the Entry's field name will be used.
579                         bool set_vendor_string(const Entry &entry);
580
581                         //! See FLAC__metadata_object_vorbiscomment_set_comment()
582                         bool set_comment(unsigned index, const Entry &entry);
583
584                         //! See FLAC__metadata_object_vorbiscomment_insert_comment()
585                         bool insert_comment(unsigned index, const Entry &entry);
586
587                         //! See FLAC__metadata_object_vorbiscomment_delete_comment()
588                         bool delete_comment(unsigned index);
589                 };
590
591                 /** CUESHEET metadata block.
592                  *  See <A HREF="../format.html#metadata_block_cuesheet">format specification</A>.
593                  */
594                 class FLACPP_API CueSheet : public Prototype {
595                 public:
596                         /** Convenience class for encapsulating a cue sheet
597                          *  track.
598                          *
599                          *  Always check is_valid() after the constructor or operator=
600                          *  to make sure memory was properly allocated.
601                          */
602                         class FLACPP_API Track {
603                         protected:
604                                 ::FLAC__StreamMetadata_CueSheet_Track *object_;
605                         public:
606                                 Track();
607                                 Track(const ::FLAC__StreamMetadata_CueSheet_Track *track);
608                                 Track(const Track &track);
609                                 void operator=(const Track &track);
610
611                                 virtual ~Track();
612
613                                 virtual bool is_valid() const;
614
615                                 inline FLAC__uint64 get_offset() const { return object_->offset; }
616                                 inline FLAC__byte get_number() const { return object_->number; }
617                                 inline const char *get_isrc() const { return object_->isrc; }
618                                 inline unsigned get_type() const { return object_->type; }
619                                 inline bool get_pre_emphasis() const { return object_->pre_emphasis; }
620
621                                 inline FLAC__byte get_num_indices() const { return object_->num_indices; }
622                                 ::FLAC__StreamMetadata_CueSheet_Index get_index(unsigned i) const;
623
624                                 inline const ::FLAC__StreamMetadata_CueSheet_Track *get_track() const { return object_; }
625
626                                 inline void set_offset(FLAC__uint64 value) { object_->offset = value; }
627                                 inline void set_number(FLAC__byte value) { object_->number = value; }
628                                 void set_isrc(const char value[12]);
629                                 void set_type(unsigned value);
630                                 inline void set_pre_emphasis(bool value) { object_->pre_emphasis = value? 1 : 0; }
631
632                                 void set_index(unsigned i, const ::FLAC__StreamMetadata_CueSheet_Index &index);
633                                 //@@@ It's awkward but to insert/delete index points
634                                 //@@@ you must use the routines in the CueSheet class.
635                         };
636
637                         CueSheet();
638
639                         //@{
640                         /** Constructs a copy of the given object.  This form
641                          *  always performs a deep copy.
642                          */
643                         inline CueSheet(const CueSheet &object): Prototype(object) { }
644                         inline CueSheet(const ::FLAC__StreamMetadata &object): Prototype(object) { }
645                         inline CueSheet(const ::FLAC__StreamMetadata *object): Prototype(object) { }
646                         //@}
647
648                         /** Constructs an object with copy control.  See
649                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
650                          */
651                         inline CueSheet(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
652
653                         ~CueSheet();
654
655                         //@{
656                         /** Assign from another object.  Always performs a deep copy. */
657                         inline void operator=(const CueSheet &object) { Prototype::operator=(object); }
658                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
659                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
660                         //@}
661
662                         //@{
663                         /** Check for equality, performing a deep compare by following pointers. */
664                         inline bool operator==(const CueSheet &object) const { return Prototype::operator==(object); }
665                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
666                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
667                         //@}
668
669                         //@{
670                         /** Check for inequality, performing a deep compare by following pointers. */
671                         inline bool operator!=(const CueSheet &object) const { return Prototype::operator!=(object); }
672                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
673                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
674                         //@}
675
676                         const char *get_media_catalog_number() const;
677                         FLAC__uint64 get_lead_in() const;
678                         bool get_is_cd() const;
679
680                         unsigned get_num_tracks() const;
681                         Track get_track(unsigned i) const;
682
683                         void set_media_catalog_number(const char value[128]);
684                         void set_lead_in(FLAC__uint64 value);
685                         void set_is_cd(bool value);
686
687                         void set_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index);
688
689                         //! See FLAC__metadata_object_cuesheet_track_insert_index()
690                         bool insert_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index);
691
692                         //! See FLAC__metadata_object_cuesheet_track_delete_index()
693                         bool delete_index(unsigned track_num, unsigned index_num);
694
695                         //! See FLAC__metadata_object_cuesheet_set_track()
696                         bool set_track(unsigned i, const Track &track);
697
698                         //! See FLAC__metadata_object_cuesheet_insert_track()
699                         bool insert_track(unsigned i, const Track &track);
700
701                         //! See FLAC__metadata_object_cuesheet_delete_track()
702                         bool delete_track(unsigned i);
703
704                         //! See FLAC__metadata_object_cuesheet_is_legal()
705                         bool is_legal(bool check_cd_da_subset = false, const char **violation = 0) const;
706                 };
707
708                 /** Opaque metadata block for storing unknown types.
709                  *  This should not be used unless you know what you are doing;
710                  *  it is currently used only internally to support forward
711                  *  compatibility of metadata blocks.
712                  */
713                 class FLACPP_API Unknown : public Prototype {
714                 public:
715                         Unknown();
716                         //
717                         //@{
718                         /** Constructs a copy of the given object.  This form
719                          *  always performs a deep copy.
720                          */
721                         inline Unknown(const Unknown &object): Prototype(object) { }
722                         inline Unknown(const ::FLAC__StreamMetadata &object): Prototype(object) { }
723                         inline Unknown(const ::FLAC__StreamMetadata *object): Prototype(object) { }
724                         //@}
725
726                         /** Constructs an object with copy control.  See
727                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
728                          */
729                         inline Unknown(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
730
731                         ~Unknown();
732
733                         //@{
734                         /** Assign from another object.  Always performs a deep copy. */
735                         inline void operator=(const Unknown &object) { Prototype::operator=(object); }
736                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
737                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
738                         //@}
739
740                         //@{
741                         /** Check for equality, performing a deep compare by following pointers. */
742                         inline bool operator==(const Unknown &object) const { return Prototype::operator==(object); }
743                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
744                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
745                         //@}
746
747                         //@{
748                         /** Check for inequality, performing a deep compare by following pointers. */
749                         inline bool operator!=(const Unknown &object) const { return Prototype::operator!=(object); }
750                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
751                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
752                         //@}
753
754                         const FLAC__byte *get_data() const;
755
756                         //! This form always copies \a data
757                         bool set_data(const FLAC__byte *data, unsigned length);
758                         bool set_data(FLAC__byte *data, unsigned length, bool copy);
759                 };
760
761                 /* \} */
762
763
764                 /** \defgroup flacpp_metadata_level0 FLAC++/metadata.h: metadata level 0 interface
765                  *  \ingroup flacpp_metadata
766                  *
767                  *  \brief
768                  *  Level 0 metadata iterator.
769                  *
770                  *  See the \link flac_metadata_level0 C layer equivalent \endlink
771                  *  for more.
772                  *
773                  * \{
774                  */
775
776                 //! See FLAC__metadata_get_streaminfo().
777                 FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
778
779                 /* \} */
780
781
782                 /** \defgroup flacpp_metadata_level1 FLAC++/metadata.h: metadata level 1 interface
783                  *  \ingroup flacpp_metadata
784                  *
785                  *  \brief
786                  *  Level 1 metadata iterator.
787                  *
788                  *  The flow through the iterator in the C++ layer is similar
789                  *  to the C layer:
790                  *    - Create a SimpleIterator instance
791                  *    - Check SimpleIterator::is_valid()
792                  *    - Call SimpleIterator::init() and check the return
793                  *    - Traverse and/or edit.  Edits are written to file
794                  *      immediately.
795                  *    - Destroy the SimpleIterator instance
796                  *
797                  *  The ownership of pointers in the C++ layer follows that in
798                  *  the C layer, i.e.
799                  *    - The objects returned by get_block() are yours to
800                  *      modify, but changes are not reflected in the FLAC file
801                  *      until you call set_block().  The objects are also
802                  *      yours to delete; they are not automatically deleted
803                  *      when passed to set_block() or insert_block_after().
804                  *
805                  *  See the \link flac_metadata_level1 C layer equivalent \endlink
806                  *  for more.
807                  *
808                  * \{
809                  */
810
811                 /** This class is a wrapper around the FLAC__metadata_simple_iterator
812                  *  structures and methods; see ::FLAC__Metadata_SimpleIterator.
813                  */
814                 class FLACPP_API SimpleIterator {
815                 public:
816                         class FLACPP_API Status {
817                         public:
818                                 inline Status(::FLAC__Metadata_SimpleIteratorStatus status): status_(status) { }
819                                 inline operator ::FLAC__Metadata_SimpleIteratorStatus() const { return status_; }
820                                 inline const char *as_cstring() const { return ::FLAC__Metadata_SimpleIteratorStatusString[status_]; }
821                         protected:
822                                 ::FLAC__Metadata_SimpleIteratorStatus status_;
823                         };
824
825                         SimpleIterator();
826                         virtual ~SimpleIterator();
827
828                         bool init(const char *filename, bool read_only, bool preserve_file_stats);
829
830                         bool is_valid() const;
831                         Status status();
832                         bool is_writable() const;
833
834                         bool next();
835                         bool prev();
836
837                         ::FLAC__MetadataType get_block_type() const;
838                         Prototype *get_block();
839                         bool set_block(Prototype *block, bool use_padding = true);
840                         bool insert_block_after(Prototype *block, bool use_padding = true);
841                         bool delete_block(bool use_padding = true);
842
843                 protected:
844                         ::FLAC__Metadata_SimpleIterator *iterator_;
845                         void clear();
846                 };
847
848                 /* \} */
849
850
851                 /** \defgroup flacpp_metadata_level2 FLAC++/metadata.h: metadata level 2 interface
852                  *  \ingroup flacpp_metadata
853                  *
854                  *  \brief
855                  *  Level 2 metadata iterator.
856                  *
857                  *  The flow through the iterator in the C++ layer is similar
858                  *  to the C layer:
859                  *    - Create a Chain instance
860                  *    - Check Chain::is_valid()
861                  *    - Call Chain::read() and check the return
862                  *    - Traverse and/or edit with an Iterator or with
863                  *      Chain::merge_padding() or Chain::sort_padding()
864                  *    - Write changes back to FLAC file with Chain::write()
865                  *    - Destroy the Chain instance
866                  *
867                  *  The ownership of pointers in the C++ layer is slightly
868                  *  different than in the C layer, i.e.
869                  *    - The objects returned by Iterator::get_block() are NOT
870                  *      owned by the iterator and should be deleted by the
871                  *      caller when finished, BUT, when you modify the block,
872                  *      it will directly edit what's in the chain and you do
873                  *      not need to call Iterator::set_block().  However the
874                  *      changes will not be reflected in the FLAC file until
875                  *      the chain is written with Chain::write().
876                  *    - When you pass an object to Iterator::set_block(),
877                  *      Iterator::insert_block_before(), or
878                  *      Iterator::insert_block_after(), the iterator takes
879                  *      ownership of the block and it will be deleted by the
880                  *      chain.
881                  *
882                  *  See the \link flac_metadata_level2 C layer equivalent \endlink
883                  *  for more.
884                  *
885                  * \{
886                  */
887
888                 /** This class is a wrapper around the FLAC__metadata_chain
889                  *  structures and methods; see ::FLAC__Metadata_Chain.
890                  */
891                 class FLACPP_API Chain {
892                 public:
893                         class FLACPP_API Status {
894                         public:
895                                 inline Status(::FLAC__Metadata_ChainStatus status): status_(status) { }
896                                 inline operator ::FLAC__Metadata_ChainStatus() const { return status_; }
897                                 inline const char *as_cstring() const { return ::FLAC__Metadata_ChainStatusString[status_]; }
898                         protected:
899                                 ::FLAC__Metadata_ChainStatus status_;
900                         };
901
902                         Chain();
903                         virtual ~Chain();
904
905                         friend class Iterator;
906
907                         bool is_valid() const;
908                         Status status();
909
910                         bool read(const char *filename);
911                         bool read(FLAC__IOHandle handle, FLAC__IOCallbacks callbacks);
912
913                         bool check_if_tempfile_needed(bool use_padding);
914
915                         bool write(bool use_padding = true, bool preserve_file_stats = false);
916                         bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks);
917                         bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks);
918
919                         void merge_padding();
920                         void sort_padding();
921
922                 protected:
923                         ::FLAC__Metadata_Chain *chain_;
924                         virtual void clear();
925                 };
926
927                 /** This class is a wrapper around the FLAC__metadata_iterator
928                  *  structures and methods; see ::FLAC__Metadata_Iterator.
929                  */
930                 class FLACPP_API Iterator {
931                 public:
932                         Iterator();
933                         virtual ~Iterator();
934
935                         bool is_valid() const;
936
937                         void init(Chain &chain);
938
939                         bool next();
940                         bool prev();
941
942                         ::FLAC__MetadataType get_block_type() const;
943                         Prototype *get_block();
944                         bool set_block(Prototype *block);
945                         bool delete_block(bool replace_with_padding);
946                         bool insert_block_before(Prototype *block);
947                         bool insert_block_after(Prototype *block);
948
949                 protected:
950                         ::FLAC__Metadata_Iterator *iterator_;
951                         virtual void clear();
952                 };
953
954                 /* \} */
955
956         };
957 };
958
959 #endif