libFLAC++: all metadata object operator=() funcs now return *this; add Metadata:...
[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                         Prototype &operator=(const Prototype &);
130                         Prototype &operator=(const ::FLAC__StreamMetadata &);
131                         Prototype &operator=(const ::FLAC__StreamMetadata *);
132                         //@}
133
134                         /** Assigns an object with copy control.  See
135                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
136                          */
137                         Prototype &assign_object(::FLAC__StreamMetadata *object, bool copy);
138
139                         /** Deletes the underlying ::FLAC__StreamMetadata object.
140                          */
141                         virtual void clear();
142
143                         ::FLAC__StreamMetadata *object_;
144                 public:
145                         /** Deletes the underlying ::FLAC__StreamMetadata object.
146                          */
147                         virtual ~Prototype();
148
149                         //@{
150                         /** Check for equality, performing a deep compare by following pointers. */
151                         inline bool operator==(const Prototype &) const;
152                         inline bool operator==(const ::FLAC__StreamMetadata &) const;
153                         inline bool operator==(const ::FLAC__StreamMetadata *) const;
154                         //@}
155
156                         //@{
157                         /** Check for inequality, performing a deep compare by following pointers. */
158                         inline bool operator!=(const Prototype &) const;
159                         inline bool operator!=(const ::FLAC__StreamMetadata &) const;
160                         inline bool operator!=(const ::FLAC__StreamMetadata *) const;
161                         //@}
162
163                         friend class SimpleIterator;
164                         friend class Iterator;
165
166                         /** Returns \c true if the object was correctly constructed
167                          *  (i.e. the underlying ::FLAC__StreamMetadata object was
168                          *  properly allocated), else \c false.
169                          */
170                         inline bool is_valid() const;
171
172                         /** Returns \c true if this block is the last block in a
173                          *  stream, else \c false.
174                          *
175                          * \assert
176                          *   \code is_valid() \endcode
177                          */
178                         bool get_is_last() const;
179
180                         /** Returns the type of the block.
181                          *
182                          * \assert
183                          *   \code is_valid() \endcode
184                          */
185                         ::FLAC__MetadataType get_type() const;
186
187                         /** Returns the stream length of the metadata block.
188                          *
189                          * \note
190                          *   The length does not include the metadata block header,
191                          *   per spec.
192                          *
193                          * \assert
194                          *   \code is_valid() \endcode
195                          */
196                         unsigned get_length() const;
197
198                         /** Sets the "is_last" flag for the block.  When using the iterators
199                          *  it is not necessary to set this flag; they will do it for you.
200                          *
201                          * \assert
202                          *   \code is_valid() \endcode
203                          */
204                         void set_is_last(bool);
205
206                         /** Returns a pointer to the underlying ::FLAC__StreamMetadata
207                          *  object.  This can be useful for plugging any holes between
208                          *  the C++ and C interfaces.
209                          *
210                          * \assert
211                          *   \code is_valid() \endcode
212                          */
213                         inline operator const ::FLAC__StreamMetadata *() const;
214                 private:
215                         /** Private and undefined so you can't use it. */
216                         Prototype();
217
218                         // These are used only by Iterator
219                         bool is_reference_;
220                         inline void set_reference(bool x) { is_reference_ = x; }
221                 };
222
223 #ifdef _MSC_VER
224 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
225 #pragma warning ( disable : 4800 )
226 #endif
227
228                 inline bool Prototype::operator==(const Prototype &object) const
229                 { return (bool)::FLAC__metadata_object_is_equal(object_, object.object_); }
230
231                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata &object) const
232                 { return (bool)::FLAC__metadata_object_is_equal(object_, &object); }
233
234                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata *object) const
235                 { return (bool)::FLAC__metadata_object_is_equal(object_, object); }
236
237 #ifdef _MSC_VER
238 // @@@ how to re-enable?  the following doesn't work
239 // #pragma warning ( enable : 4800 )
240 #endif
241
242                 inline bool Prototype::operator!=(const Prototype &object) const
243                 { return !operator==(object); }
244
245                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata &object) const
246                 { return !operator==(object); }
247
248                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata *object) const
249                 { return !operator==(object); }
250
251                 inline bool Prototype::is_valid() const
252                 { return 0 != object_; }
253
254                 inline Prototype::operator const ::FLAC__StreamMetadata *() const
255                 { return object_; }
256
257                 /** Create a deep copy of an object and return it. */
258                 FLACPP_API Prototype *clone(const Prototype *);
259
260
261                 /** STREAMINFO metadata block.
262                  *  See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>.
263                  */
264                 class FLACPP_API StreamInfo : public Prototype {
265                 public:
266                         StreamInfo();
267
268                         //@{
269                         /** Constructs a copy of the given object.  This form
270                          *  always performs a deep copy.
271                          */
272                         inline StreamInfo(const StreamInfo &object): Prototype(object) { }
273                         inline StreamInfo(const ::FLAC__StreamMetadata &object): Prototype(object) { }
274                         inline StreamInfo(const ::FLAC__StreamMetadata *object): Prototype(object) { }
275                         //@}
276
277                         /** Constructs an object with copy control.  See
278                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
279                          */
280                         inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
281
282                         ~StreamInfo();
283
284                         //@{
285                         /** Assign from another object.  Always performs a deep copy. */
286                         inline StreamInfo &operator=(const StreamInfo &object) { Prototype::operator=(object); return *this; }
287                         inline StreamInfo &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
288                         inline StreamInfo &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
289                         //@}
290
291                         /** Assigns an object with copy control.  See
292                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
293                          */
294                         inline StreamInfo &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
295
296                         //@{
297                         /** Check for equality, performing a deep compare by following pointers. */
298                         inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
299                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
300                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
301                         //@}
302
303                         //@{
304                         /** Check for inequality, performing a deep compare by following pointers. */
305                         inline bool operator!=(const StreamInfo &object) const { return Prototype::operator!=(object); }
306                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
307                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
308                         //@}
309
310                         //@{
311                         /** See <A HREF="../format.html#metadata_block_streaminfo">format specification</A>. */
312                         unsigned get_min_blocksize() const;
313                         unsigned get_max_blocksize() const;
314                         unsigned get_min_framesize() const;
315                         unsigned get_max_framesize() const;
316                         unsigned get_sample_rate() const;
317                         unsigned get_channels() const;
318                         unsigned get_bits_per_sample() const;
319                         FLAC__uint64 get_total_samples() const;
320                         const FLAC__byte *get_md5sum() const;
321
322                         void set_min_blocksize(unsigned value);
323                         void set_max_blocksize(unsigned value);
324                         void set_min_framesize(unsigned value);
325                         void set_max_framesize(unsigned value);
326                         void set_sample_rate(unsigned value);
327                         void set_channels(unsigned value);
328                         void set_bits_per_sample(unsigned value);
329                         void set_total_samples(FLAC__uint64 value);
330                         void set_md5sum(const FLAC__byte value[16]);
331                         //@}
332                 };
333
334                 /** PADDING metadata block.
335                  *  See <A HREF="../format.html#metadata_block_padding">format specification</A>.
336                  */
337                 class FLACPP_API Padding : public Prototype {
338                 public:
339                         Padding();
340
341                         //@{
342                         /** Constructs a copy of the given object.  This form
343                          *  always performs a deep copy.
344                          */
345                         inline Padding(const Padding &object): Prototype(object) { }
346                         inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
347                         inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
348                         //@}
349
350                         /** Constructs an object with copy control.  See
351                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
352                          */
353                         inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
354
355                         ~Padding();
356
357                         //@{
358                         /** Assign from another object.  Always performs a deep copy. */
359                         inline Padding &operator=(const Padding &object) { Prototype::operator=(object); return *this; }
360                         inline Padding &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
361                         inline Padding &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
362                         //@}
363
364                         /** Assigns an object with copy control.  See
365                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
366                          */
367                         inline Padding &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
368
369                         //@{
370                         /** Check for equality, performing a deep compare by following pointers. */
371                         inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
372                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
373                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
374                         //@}
375
376                         //@{
377                         /** Check for inequality, performing a deep compare by following pointers. */
378                         inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
379                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
380                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
381                         //@}
382
383                         void set_length(unsigned length);
384                 };
385
386                 /** APPLICATION metadata block.
387                  *  See <A HREF="../format.html#metadata_block_application">format specification</A>.
388                  */
389                 class FLACPP_API Application : public Prototype {
390                 public:
391                         Application();
392                         //
393                         //@{
394                         /** Constructs a copy of the given object.  This form
395                          *  always performs a deep copy.
396                          */
397                         inline Application(const Application &object): Prototype(object) { }
398                         inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
399                         inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
400                         //@}
401
402                         /** Constructs an object with copy control.  See
403                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
404                          */
405                         inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
406
407                         ~Application();
408
409                         //@{
410                         /** Assign from another object.  Always performs a deep copy. */
411                         inline Application &operator=(const Application &object) { Prototype::operator=(object); return *this; }
412                         inline Application &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
413                         inline Application &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
414                         //@}
415
416                         /** Assigns an object with copy control.  See
417                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
418                          */
419                         inline Application &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
420
421                         //@{
422                         /** Check for equality, performing a deep compare by following pointers. */
423                         inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
424                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
425                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
426                         //@}
427
428                         //@{
429                         /** Check for inequality, performing a deep compare by following pointers. */
430                         inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
431                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
432                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
433                         //@}
434
435                         const FLAC__byte *get_id() const;
436                         const FLAC__byte *get_data() const;
437
438                         void set_id(const FLAC__byte value[4]);
439                         //! This form always copies \a data
440                         bool set_data(const FLAC__byte *data, unsigned length);
441                         bool set_data(FLAC__byte *data, unsigned length, bool copy);
442                 };
443
444                 /** SEEKTABLE metadata block.
445                  *  See <A HREF="../format.html#metadata_block_seektable">format specification</A>.
446                  */
447                 class FLACPP_API SeekTable : public Prototype {
448                 public:
449                         SeekTable();
450
451                         //@{
452                         /** Constructs a copy of the given object.  This form
453                          *  always performs a deep copy.
454                          */
455                         inline SeekTable(const SeekTable &object): Prototype(object) { }
456                         inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
457                         inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
458                         //@}
459
460                         /** Constructs an object with copy control.  See
461                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
462                          */
463                         inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
464
465                         ~SeekTable();
466
467                         //@{
468                         /** Assign from another object.  Always performs a deep copy. */
469                         inline SeekTable &operator=(const SeekTable &object) { Prototype::operator=(object); return *this; }
470                         inline SeekTable &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
471                         inline SeekTable &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
472                         //@}
473
474                         /** Assigns an object with copy control.  See
475                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
476                          */
477                         inline SeekTable &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
478
479                         //@{
480                         /** Check for equality, performing a deep compare by following pointers. */
481                         inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
482                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
483                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
484                         //@}
485
486                         //@{
487                         /** Check for inequality, performing a deep compare by following pointers. */
488                         inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
489                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
490                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
491                         //@}
492
493                         unsigned get_num_points() const;
494                         ::FLAC__StreamMetadata_SeekPoint get_point(unsigned index) const;
495
496                         //! See FLAC__metadata_object_seektable_set_point()
497                         void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
498
499                         //! See FLAC__metadata_object_seektable_insert_point()
500                         bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
501
502                         //! See FLAC__metadata_object_seektable_delete_point()
503                         bool delete_point(unsigned index);
504
505                         //! See FLAC__metadata_object_seektable_is_legal()
506                         bool is_legal() const;
507                 };
508
509                 /** VORBIS_COMMENT metadata block.
510                  *  See <A HREF="../format.html#metadata_block_vorbis_comment">format specification</A>.
511                  */
512                 class FLACPP_API VorbisComment : public Prototype {
513                 public:
514                         /** Convenience class for encapsulating Vorbis comment
515                          *  entries.  An entry is a vendor string or a comment
516                          *  field.  In the case of a vendor string, the field
517                          *  name is undefined; only the field value is relevant.
518                          *
519                          *  A \a field as used in the methods refers to an
520                          *  entire 'NAME=VALUE' string; for convenience the
521                          *  string is NUL-terminated.  A length field is
522                          *  required in the unlikely event that the value
523                          *  contains contain embedded NULs.
524                          *
525                          *  A \a field_name is what is on the left side of the
526                          *  first '=' in the \a field.  By definition it is ASCII
527                          *  and so is NUL-terminated and does not require a
528                          *  length to describe it.  \a field_name is undefined
529                          *  for a vendor string entry.
530                          *
531                          *  A \a field_value is what is on the right side of the
532                          *  first '=' in the \a field.  By definition, this may
533                          *  contain embedded NULs and so a \a field_value_length
534                          *  is required to describe it.  However in practice,
535                          *  embedded NULs are not known to be used, so it is
536                          *  generally safe to treat field values as NUL-
537                          *  terminated UTF-8 strings.
538                          *
539                          *  Always check is_valid() after the constructor or operator=
540                          *  to make sure memory was properly allocated and that the
541                          *  Entry conforms to the Vorbis comment specification.
542                          */
543                         class FLACPP_API Entry {
544                         public:
545                                 Entry();
546
547                                 Entry(const char *field, unsigned field_length);
548                                 Entry(const char *field); // assumes \a field is NUL-terminated
549
550                                 Entry(const char *field_name, const char *field_value, unsigned field_value_length);
551                                 Entry(const char *field_name, const char *field_value); // assumes \a field_value is NUL-terminated
552
553                                 Entry(const Entry &entry);
554
555                                 Entry &operator=(const Entry &entry);
556
557                                 virtual ~Entry();
558
559                                 virtual bool is_valid() const;
560
561                                 unsigned get_field_length() const;
562                                 unsigned get_field_name_length() const;
563                                 unsigned get_field_value_length() const;
564
565                                 ::FLAC__StreamMetadata_VorbisComment_Entry get_entry() const;
566                                 const char *get_field() const;
567                                 const char *get_field_name() const;
568                                 const char *get_field_value() const;
569
570                                 bool set_field(const char *field, unsigned field_length);
571                                 bool set_field(const char *field); // assumes \a field is NUL-terminated
572                                 bool set_field_name(const char *field_name);
573                                 bool set_field_value(const char *field_value, unsigned field_value_length);
574                                 bool set_field_value(const char *field_value); // assumes \a field_value is NUL-terminated
575                         protected:
576                                 bool is_valid_;
577                                 ::FLAC__StreamMetadata_VorbisComment_Entry entry_;
578                                 char *field_name_;
579                                 unsigned field_name_length_;
580                                 char *field_value_;
581                                 unsigned field_value_length_;
582                         private:
583                                 void zero();
584                                 void clear();
585                                 void clear_entry();
586                                 void clear_field_name();
587                                 void clear_field_value();
588                                 void construct(const char *field, unsigned field_length);
589                                 void construct(const char *field); // assumes \a field is NUL-terminated
590                                 void construct(const char *field_name, const char *field_value, unsigned field_value_length);
591                                 void construct(const char *field_name, const char *field_value); // assumes \a field_value is NUL-terminated
592                                 void compose_field();
593                                 void parse_field();
594                         };
595
596                         VorbisComment();
597
598                         //@{
599                         /** Constructs a copy of the given object.  This form
600                          *  always performs a deep copy.
601                          */
602                         inline VorbisComment(const VorbisComment &object): Prototype(object) { }
603                         inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
604                         inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
605                         //@}
606
607                         /** Constructs an object with copy control.  See
608                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
609                          */
610                         inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
611
612                         ~VorbisComment();
613
614                         //@{
615                         /** Assign from another object.  Always performs a deep copy. */
616                         inline VorbisComment &operator=(const VorbisComment &object) { Prototype::operator=(object); return *this; }
617                         inline VorbisComment &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
618                         inline VorbisComment &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
619                         //@}
620
621                         /** Assigns an object with copy control.  See
622                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
623                          */
624                         inline VorbisComment &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
625
626                         //@{
627                         /** Check for equality, performing a deep compare by following pointers. */
628                         inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
629                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
630                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
631                         //@}
632
633                         //@{
634                         /** Check for inequality, performing a deep compare by following pointers. */
635                         inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
636                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
637                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
638                         //@}
639
640                         unsigned get_num_comments() const;
641                         const FLAC__byte *get_vendor_string() const; // NUL-terminated UTF-8 string
642                         Entry get_comment(unsigned index) const;
643
644                         //! See FLAC__metadata_object_vorbiscomment_set_vendor_string()
645                         bool set_vendor_string(const FLAC__byte *string); // NUL-terminated UTF-8 string
646
647                         //! See FLAC__metadata_object_vorbiscomment_set_comment()
648                         bool set_comment(unsigned index, const Entry &entry);
649
650                         //! See FLAC__metadata_object_vorbiscomment_insert_comment()
651                         bool insert_comment(unsigned index, const Entry &entry);
652
653                         //! See FLAC__metadata_object_vorbiscomment_append_comment()
654                         bool append_comment(const Entry &entry);
655
656                         //! See FLAC__metadata_object_vorbiscomment_delete_comment()
657                         bool delete_comment(unsigned index);
658                 };
659
660                 /** CUESHEET metadata block.
661                  *  See <A HREF="../format.html#metadata_block_cuesheet">format specification</A>.
662                  */
663                 class FLACPP_API CueSheet : public Prototype {
664                 public:
665                         /** Convenience class for encapsulating a cue sheet
666                          *  track.
667                          *
668                          *  Always check is_valid() after the constructor or operator=
669                          *  to make sure memory was properly allocated.
670                          */
671                         class FLACPP_API Track {
672                         protected:
673                                 ::FLAC__StreamMetadata_CueSheet_Track *object_;
674                         public:
675                                 Track();
676                                 Track(const ::FLAC__StreamMetadata_CueSheet_Track *track);
677                                 Track(const Track &track);
678                                 Track &operator=(const Track &track);
679
680                                 virtual ~Track();
681
682                                 virtual bool is_valid() const;
683
684                                 inline FLAC__uint64 get_offset() const { return object_->offset; }
685                                 inline FLAC__byte get_number() const { return object_->number; }
686                                 inline const char *get_isrc() const { return object_->isrc; }
687                                 inline unsigned get_type() const { return object_->type; }
688                                 inline bool get_pre_emphasis() const { return object_->pre_emphasis; }
689
690                                 inline FLAC__byte get_num_indices() const { return object_->num_indices; }
691                                 ::FLAC__StreamMetadata_CueSheet_Index get_index(unsigned i) const;
692
693                                 inline const ::FLAC__StreamMetadata_CueSheet_Track *get_track() const { return object_; }
694
695                                 inline void set_offset(FLAC__uint64 value) { object_->offset = value; }
696                                 inline void set_number(FLAC__byte value) { object_->number = value; }
697                                 void set_isrc(const char value[12]);
698                                 void set_type(unsigned value);
699                                 inline void set_pre_emphasis(bool value) { object_->pre_emphasis = value? 1 : 0; }
700
701                                 void set_index(unsigned i, const ::FLAC__StreamMetadata_CueSheet_Index &index);
702                                 //@@@ It's awkward but to insert/delete index points
703                                 //@@@ you must use the routines in the CueSheet class.
704                         };
705
706                         CueSheet();
707
708                         //@{
709                         /** Constructs a copy of the given object.  This form
710                          *  always performs a deep copy.
711                          */
712                         inline CueSheet(const CueSheet &object): Prototype(object) { }
713                         inline CueSheet(const ::FLAC__StreamMetadata &object): Prototype(object) { }
714                         inline CueSheet(const ::FLAC__StreamMetadata *object): Prototype(object) { }
715                         //@}
716
717                         /** Constructs an object with copy control.  See
718                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
719                          */
720                         inline CueSheet(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
721
722                         ~CueSheet();
723
724                         //@{
725                         /** Assign from another object.  Always performs a deep copy. */
726                         inline CueSheet &operator=(const CueSheet &object) { Prototype::operator=(object); return *this; }
727                         inline CueSheet &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
728                         inline CueSheet &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
729                         //@}
730
731                         /** Assigns an object with copy control.  See
732                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
733                          */
734                         inline CueSheet &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
735
736                         //@{
737                         /** Check for equality, performing a deep compare by following pointers. */
738                         inline bool operator==(const CueSheet &object) const { return Prototype::operator==(object); }
739                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
740                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
741                         //@}
742
743                         //@{
744                         /** Check for inequality, performing a deep compare by following pointers. */
745                         inline bool operator!=(const CueSheet &object) const { return Prototype::operator!=(object); }
746                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
747                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
748                         //@}
749
750                         const char *get_media_catalog_number() const;
751                         FLAC__uint64 get_lead_in() const;
752                         bool get_is_cd() const;
753
754                         unsigned get_num_tracks() const;
755                         Track get_track(unsigned i) const;
756
757                         void set_media_catalog_number(const char value[128]);
758                         void set_lead_in(FLAC__uint64 value);
759                         void set_is_cd(bool value);
760
761                         void set_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index);
762
763                         //! See FLAC__metadata_object_cuesheet_track_insert_index()
764                         bool insert_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index);
765
766                         //! See FLAC__metadata_object_cuesheet_track_delete_index()
767                         bool delete_index(unsigned track_num, unsigned index_num);
768
769                         //! See FLAC__metadata_object_cuesheet_set_track()
770                         bool set_track(unsigned i, const Track &track);
771
772                         //! See FLAC__metadata_object_cuesheet_insert_track()
773                         bool insert_track(unsigned i, const Track &track);
774
775                         //! See FLAC__metadata_object_cuesheet_delete_track()
776                         bool delete_track(unsigned i);
777
778                         //! See FLAC__metadata_object_cuesheet_is_legal()
779                         bool is_legal(bool check_cd_da_subset = false, const char **violation = 0) const;
780                 };
781
782                 /** Opaque metadata block for storing unknown types.
783                  *  This should not be used unless you know what you are doing;
784                  *  it is currently used only internally to support forward
785                  *  compatibility of metadata blocks.
786                  */
787                 class FLACPP_API Unknown : public Prototype {
788                 public:
789                         Unknown();
790                         //
791                         //@{
792                         /** Constructs a copy of the given object.  This form
793                          *  always performs a deep copy.
794                          */
795                         inline Unknown(const Unknown &object): Prototype(object) { }
796                         inline Unknown(const ::FLAC__StreamMetadata &object): Prototype(object) { }
797                         inline Unknown(const ::FLAC__StreamMetadata *object): Prototype(object) { }
798                         //@}
799
800                         /** Constructs an object with copy control.  See
801                          *  Prototype(::FLAC__StreamMetadata *object, bool copy).
802                          */
803                         inline Unknown(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
804
805                         ~Unknown();
806
807                         //@{
808                         /** Assign from another object.  Always performs a deep copy. */
809                         inline Unknown &operator=(const Unknown &object) { Prototype::operator=(object); return *this; }
810                         inline Unknown &operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); return *this; }
811                         inline Unknown &operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); return *this; }
812                         //@}
813
814                         /** Assigns an object with copy control.  See
815                          *  Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy).
816                          */
817                         inline Unknown &assign(::FLAC__StreamMetadata *object, bool copy) { Prototype::assign_object(object, copy); return *this; }
818
819                         //@{
820                         /** Check for equality, performing a deep compare by following pointers. */
821                         inline bool operator==(const Unknown &object) const { return Prototype::operator==(object); }
822                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
823                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
824                         //@}
825
826                         //@{
827                         /** Check for inequality, performing a deep compare by following pointers. */
828                         inline bool operator!=(const Unknown &object) const { return Prototype::operator!=(object); }
829                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
830                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
831                         //@}
832
833                         const FLAC__byte *get_data() const;
834
835                         //! This form always copies \a data
836                         bool set_data(const FLAC__byte *data, unsigned length);
837                         bool set_data(FLAC__byte *data, unsigned length, bool copy);
838                 };
839
840                 /* \} */
841
842
843                 /** \defgroup flacpp_metadata_level0 FLAC++/metadata.h: metadata level 0 interface
844                  *  \ingroup flacpp_metadata
845                  *
846                  *  \brief
847                  *  Level 0 metadata iterators.
848                  *
849                  *  See the \link flac_metadata_level0 C layer equivalent \endlink
850                  *  for more.
851                  *
852                  * \{
853                  */
854
855                 //! See FLAC__metadata_get_streaminfo().
856                 FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
857
858                 //! See FLAC__metadata_get_tags().
859                 FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags);
860                 FLACPP_API bool get_tags(const char *filename, VorbisComment &tags);
861
862                 /* \} */
863
864
865                 /** \defgroup flacpp_metadata_level1 FLAC++/metadata.h: metadata level 1 interface
866                  *  \ingroup flacpp_metadata
867                  *
868                  *  \brief
869                  *  Level 1 metadata iterator.
870                  *
871                  *  The flow through the iterator in the C++ layer is similar
872                  *  to the C layer:
873                  *    - Create a SimpleIterator instance
874                  *    - Check SimpleIterator::is_valid()
875                  *    - Call SimpleIterator::init() and check the return
876                  *    - Traverse and/or edit.  Edits are written to file
877                  *      immediately.
878                  *    - Destroy the SimpleIterator instance
879                  *
880                  *  The ownership of pointers in the C++ layer follows that in
881                  *  the C layer, i.e.
882                  *    - The objects returned by get_block() are yours to
883                  *      modify, but changes are not reflected in the FLAC file
884                  *      until you call set_block().  The objects are also
885                  *      yours to delete; they are not automatically deleted
886                  *      when passed to set_block() or insert_block_after().
887                  *
888                  *  See the \link flac_metadata_level1 C layer equivalent \endlink
889                  *  for more.
890                  *
891                  * \{
892                  */
893
894                 /** This class is a wrapper around the FLAC__metadata_simple_iterator
895                  *  structures and methods; see ::FLAC__Metadata_SimpleIterator.
896                  */
897                 class FLACPP_API SimpleIterator {
898                 public:
899                         class FLACPP_API Status {
900                         public:
901                                 inline Status(::FLAC__Metadata_SimpleIteratorStatus status): status_(status) { }
902                                 inline operator ::FLAC__Metadata_SimpleIteratorStatus() const { return status_; }
903                                 inline const char *as_cstring() const { return ::FLAC__Metadata_SimpleIteratorStatusString[status_]; }
904                         protected:
905                                 ::FLAC__Metadata_SimpleIteratorStatus status_;
906                         };
907
908                         SimpleIterator();
909                         virtual ~SimpleIterator();
910
911                         bool init(const char *filename, bool read_only, bool preserve_file_stats);
912
913                         bool is_valid() const;
914                         Status status();
915                         bool is_writable() const;
916
917                         bool next();
918                         bool prev();
919
920                         ::FLAC__MetadataType get_block_type() const;
921                         Prototype *get_block();
922                         bool set_block(Prototype *block, bool use_padding = true);
923                         bool insert_block_after(Prototype *block, bool use_padding = true);
924                         bool delete_block(bool use_padding = true);
925
926                 protected:
927                         ::FLAC__Metadata_SimpleIterator *iterator_;
928                         void clear();
929                 };
930
931                 /* \} */
932
933
934                 /** \defgroup flacpp_metadata_level2 FLAC++/metadata.h: metadata level 2 interface
935                  *  \ingroup flacpp_metadata
936                  *
937                  *  \brief
938                  *  Level 2 metadata iterator.
939                  *
940                  *  The flow through the iterator in the C++ layer is similar
941                  *  to the C layer:
942                  *    - Create a Chain instance
943                  *    - Check Chain::is_valid()
944                  *    - Call Chain::read() and check the return
945                  *    - Traverse and/or edit with an Iterator or with
946                  *      Chain::merge_padding() or Chain::sort_padding()
947                  *    - Write changes back to FLAC file with Chain::write()
948                  *    - Destroy the Chain instance
949                  *
950                  *  The ownership of pointers in the C++ layer is slightly
951                  *  different than in the C layer, i.e.
952                  *    - The objects returned by Iterator::get_block() are NOT
953                  *      owned by the iterator and should be deleted by the
954                  *      caller when finished, BUT, when you modify the block,
955                  *      it will directly edit what's in the chain and you do
956                  *      not need to call Iterator::set_block().  However the
957                  *      changes will not be reflected in the FLAC file until
958                  *      the chain is written with Chain::write().
959                  *    - When you pass an object to Iterator::set_block(),
960                  *      Iterator::insert_block_before(), or
961                  *      Iterator::insert_block_after(), the iterator takes
962                  *      ownership of the block and it will be deleted by the
963                  *      chain.
964                  *
965                  *  See the \link flac_metadata_level2 C layer equivalent \endlink
966                  *  for more.
967                  *
968                  * \{
969                  */
970
971                 /** This class is a wrapper around the FLAC__metadata_chain
972                  *  structures and methods; see ::FLAC__Metadata_Chain.
973                  */
974                 class FLACPP_API Chain {
975                 public:
976                         class FLACPP_API Status {
977                         public:
978                                 inline Status(::FLAC__Metadata_ChainStatus status): status_(status) { }
979                                 inline operator ::FLAC__Metadata_ChainStatus() const { return status_; }
980                                 inline const char *as_cstring() const { return ::FLAC__Metadata_ChainStatusString[status_]; }
981                         protected:
982                                 ::FLAC__Metadata_ChainStatus status_;
983                         };
984
985                         Chain();
986                         virtual ~Chain();
987
988                         friend class Iterator;
989
990                         bool is_valid() const;
991                         Status status();
992
993                         bool read(const char *filename);
994                         bool read(FLAC__IOHandle handle, FLAC__IOCallbacks callbacks);
995
996                         bool check_if_tempfile_needed(bool use_padding);
997
998                         bool write(bool use_padding = true, bool preserve_file_stats = false);
999                         bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks);
1000                         bool write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks);
1001
1002                         void merge_padding();
1003                         void sort_padding();
1004
1005                 protected:
1006                         ::FLAC__Metadata_Chain *chain_;
1007                         virtual void clear();
1008                 };
1009
1010                 /** This class is a wrapper around the FLAC__metadata_iterator
1011                  *  structures and methods; see ::FLAC__Metadata_Iterator.
1012                  */
1013                 class FLACPP_API Iterator {
1014                 public:
1015                         Iterator();
1016                         virtual ~Iterator();
1017
1018                         bool is_valid() const;
1019
1020                         void init(Chain &chain);
1021
1022                         bool next();
1023                         bool prev();
1024
1025                         ::FLAC__MetadataType get_block_type() const;
1026                         Prototype *get_block();
1027                         bool set_block(Prototype *block);
1028                         bool delete_block(bool replace_with_padding);
1029                         bool insert_block_before(Prototype *block);
1030                         bool insert_block_after(Prototype *block);
1031
1032                 protected:
1033                         ::FLAC__Metadata_Iterator *iterator_;
1034                         virtual void clear();
1035                 };
1036
1037                 /* \} */
1038
1039         };
1040 };
1041
1042 #endif