last batch of changes and fixes based on the libFLAC++ unit tests
[platform/upstream/flac.git] / include / FLAC++ / metadata.h
1 /* libFLAC++ - Free Lossless Audio Codec library
2  * Copyright (C) 2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #ifndef FLACPP__METADATA_H
21 #define FLACPP__METADATA_H
22
23 #include "FLAC/metadata.h"
24
25 // ===============================================================
26 //
27 //  Full documentation for the metadata interface can be found
28 //  in the C layer in include/FLAC/metadata.h
29 //
30 // ===============================================================
31
32
33 namespace FLAC {
34         namespace Metadata {
35
36                 // ============================================================
37                 //
38                 //  Metadata objects
39                 //
40                 // ============================================================
41
42                 class Prototype;
43
44                 Prototype *clone(const Prototype *);
45
46                 // NOTE: When the get_*() methods return you a const pointer,
47                 // DO NOT disobey and write into it.  Always use the set_*()
48                 // methods.
49
50                 // base class for all metadata blocks
51                 class Prototype {
52                 protected:
53                         Prototype(const Prototype &object); // this form always copies object.object_
54                         Prototype(const ::FLAC__StreamMetadata &object); // this form always copies
55                         Prototype(const ::FLAC__StreamMetadata *object); // this form always copies
56                         Prototype(::FLAC__StreamMetadata *object, bool copy); // this form allows you to pass ownership to the Prototype using copy=false
57
58                         void operator=(const Prototype &);
59                         void operator=(const ::FLAC__StreamMetadata &); // this form always copies
60                         void operator=(const ::FLAC__StreamMetadata *); // this form always copies
61
62                         virtual void clear();
63
64                         ::FLAC__StreamMetadata *object_;
65                 public:
66                         virtual ~Prototype();
67
68                         inline bool operator==(const Prototype &) const;
69                         inline bool operator==(const ::FLAC__StreamMetadata &) const;
70                         inline bool operator==(const ::FLAC__StreamMetadata *) const;
71                         inline bool operator!=(const Prototype &) const;
72                         inline bool operator!=(const ::FLAC__StreamMetadata &) const;
73                         inline bool operator!=(const ::FLAC__StreamMetadata *) const;
74
75                         friend class SimpleIterator;
76                         friend class Iterator;
77
78                         inline bool is_valid() const;
79
80                         bool get_is_last() const;
81                         FLAC__MetadataType get_type() const;
82                         unsigned get_length() const; // NOTE: does not include the header, per spec
83
84                         void set_is_last(bool);
85                 private:
86                         Prototype(); // Private and undefined so you can't use it
87
88                         // These are used only by Iterator
89                         bool is_reference_;
90                         inline void set_reference(bool x) { is_reference_ = x; }
91                 };
92
93                 inline bool Prototype::operator==(const Prototype &object) const 
94                 { return ::FLAC__metadata_object_is_equal(object_, object.object_); }
95
96                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata &object) const 
97                 { return ::FLAC__metadata_object_is_equal(object_, &object); }
98
99                 inline bool Prototype::operator==(const ::FLAC__StreamMetadata *object) const 
100                 { return ::FLAC__metadata_object_is_equal(object_, object); }
101
102                 inline bool Prototype::operator!=(const Prototype &object) const 
103                 { return !operator==(object); }
104
105                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata &object) const 
106                 { return !operator==(object); }
107
108                 inline bool Prototype::operator!=(const ::FLAC__StreamMetadata *object) const 
109                 { return !operator==(object); }
110
111                 inline bool Prototype::is_valid() const
112                 { return 0 != object_; }
113
114
115                 class StreamInfo : public Prototype {
116                 public:
117                         StreamInfo();
118                         inline StreamInfo(const StreamInfo &object): Prototype(object) { }
119                         inline StreamInfo(const ::FLAC__StreamMetadata &object): Prototype(object) { }
120                         inline StreamInfo(const ::FLAC__StreamMetadata *object): Prototype(object) { }
121                         inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
122                         ~StreamInfo();
123
124                         inline void operator=(const StreamInfo &object) { Prototype::operator=(object); }
125                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
126                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
127
128                         inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
129                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
130                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
131                         inline bool operator!=(const StreamInfo &object) const { return Prototype::operator!=(object); }
132                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
133                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
134
135                         unsigned get_min_blocksize() const;
136                         unsigned get_max_blocksize() const;
137                         unsigned get_min_framesize() const;
138                         unsigned get_max_framesize() const;
139                         unsigned get_sample_rate() const;
140                         unsigned get_channels() const;
141                         unsigned get_bits_per_sample() const;
142                         FLAC__uint64 get_total_samples() const;
143                         const FLAC__byte *get_md5sum() const;
144
145                         void set_min_blocksize(unsigned value);
146                         void set_max_blocksize(unsigned value);
147                         void set_min_framesize(unsigned value);
148                         void set_max_framesize(unsigned value);
149                         void set_sample_rate(unsigned value);
150                         void set_channels(unsigned value);
151                         void set_bits_per_sample(unsigned value);
152                         void set_total_samples(FLAC__uint64 value);
153                         void set_md5sum(const FLAC__byte value[16]);
154                 };
155
156                 class Padding : public Prototype {
157                 public:
158                         Padding();
159                         inline Padding(const Padding &object): Prototype(object) { }
160                         inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
161                         inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
162                         inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
163                         ~Padding();
164
165                         inline void operator=(const Padding &object) { Prototype::operator=(object); }
166                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
167                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
168
169                         inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
170                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
171                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
172                         inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
173                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
174                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
175
176                         void set_length(unsigned length);
177                 };
178
179                 class Application : public Prototype {
180                 public:
181                         Application();
182                         inline Application(const Application &object): Prototype(object) { }
183                         inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
184                         inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
185                         inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
186                         ~Application();
187
188                         inline void operator=(const Application &object) { Prototype::operator=(object); }
189                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
190                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
191
192                         inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
193                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
194                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
195                         inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
196                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
197                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
198
199                         const FLAC__byte *get_id() const;
200                         const FLAC__byte *get_data() const;
201
202                         void set_id(const FLAC__byte value[4]);
203                         bool set_data(const FLAC__byte *data, unsigned length); // this form always copies
204                         bool set_data(FLAC__byte *data, unsigned length, bool copy);
205                 };
206
207                 class SeekTable : public Prototype {
208                 public:
209                         SeekTable();
210                         inline SeekTable(const SeekTable &object): Prototype(object) { }
211                         inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
212                         inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
213                         inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
214                         ~SeekTable();
215
216                         inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
217                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
218                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
219
220                         inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
221                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
222                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
223                         inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
224                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
225                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
226
227                         unsigned get_num_points() const;
228                         ::FLAC__StreamMetadata_SeekPoint get_point(unsigned index) const;
229
230                         void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
231                         bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
232                         bool delete_point(unsigned index);
233
234                         bool is_legal() const;
235                 };
236
237                 class VorbisComment : public Prototype {
238                 public:
239                         class Entry {
240                         public:
241                                 Entry();
242                                 Entry(const char *field, unsigned field_length);
243                                 Entry(const char *field_name, const char *field_value, unsigned field_value_length);
244                                 Entry(const Entry &entry);
245                                 void operator=(const Entry &entry);
246
247                                 virtual ~Entry();
248
249                                 virtual bool is_valid() const;
250
251                                 unsigned get_field_length() const;
252                                 unsigned get_field_name_length() const;
253                                 unsigned get_field_value_length() const;
254
255                                 ::FLAC__StreamMetadata_VorbisComment_Entry get_entry() const;
256                                 const char *get_field() const;
257                                 const char *get_field_name() const;
258                                 const char *get_field_value() const;
259
260                                 bool set_field(const char *field, unsigned field_length);
261                                 bool set_field_name(const char *field_name);
262                                 bool set_field_value(const char *field_value, unsigned field_value_length);
263                         protected:
264                                 bool is_valid_;
265                                 ::FLAC__StreamMetadata_VorbisComment_Entry entry_;
266                                 char *field_name_;
267                                 unsigned field_name_length_;
268                                 char *field_value_;
269                                 unsigned field_value_length_;
270                         private:
271                                 void zero();
272                                 void clear();
273                                 void clear_entry();
274                                 void clear_field_name();
275                                 void clear_field_value();
276                                 void construct(const char *field, unsigned field_length);
277                                 void construct(const char *field_name, const char *field_value, unsigned field_value_length);
278                                 void compose_field();
279                                 void parse_field();
280                         };
281
282                         VorbisComment();
283                         inline VorbisComment(const VorbisComment &object): Prototype(object) { }
284                         inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
285                         inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
286                         inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
287                         ~VorbisComment();
288
289                         inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
290                         inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
291                         inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
292
293                         inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
294                         inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
295                         inline bool operator==(const ::FLAC__StreamMetadata *object) const { return Prototype::operator==(object); }
296                         inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
297                         inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
298                         inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
299
300                         unsigned get_num_comments() const;
301                         Entry get_vendor_string() const; // only the Entry's field name should be used
302                         Entry get_comment(unsigned index) const;
303
304                         bool set_vendor_string(const Entry &entry); // only the Entry's field name will be used
305                         bool set_comment(unsigned index, const Entry &entry);
306                         bool insert_comment(unsigned index, const Entry &entry);
307                         bool delete_comment(unsigned index);
308                 };
309
310
311                 // ============================================================
312                 //
313                 //  Level 0
314                 //
315                 // ============================================================
316
317                 bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
318
319
320                 // ============================================================
321                 //
322                 //  Level 1
323                 //
324                 //  ----------------------------------------------------------
325                 //
326                 //  The flow through the iterator in the C++ layer is similar
327                 //  to the C layer:
328                 //
329                 //    * Create a SimpleIterator instance
330                 //    * Check SimpleIterator::is_valid()
331                 //    * Call SimpleIterator::init() and check the return
332                 //    * Traverse and/or edit.  Edits are written to file
333                 //      immediately.
334                 //    * Destroy the SimpleIterator instance
335                 //
336                 //  ----------------------------------------------------------
337                 //
338                 //  The ownership of pointers in the C++ layer follows that in
339                 //  the C layer, i.e.
340                 //    * The objects returned by get_block() are yours to
341                 //      modify, but changes are not reflected in the FLAC file
342                 //      until you call set_block().  The objects are also
343                 //      yours to delete; they are not automatically deleted
344                 //      when passed to set_block() or insert_block_after().
345                 //
346                 // ============================================================
347
348                 class SimpleIterator {
349                 public:
350                         class Status {
351                         public:
352                                 inline Status(::FLAC__Metadata_SimpleIteratorStatus status): status_(status) { }
353                                 inline operator ::FLAC__Metadata_SimpleIteratorStatus() const { return status_; }
354                                 inline const char *as_cstring() const { return ::FLAC__Metadata_SimpleIteratorStatusString[status_]; }
355                         protected:
356                                 ::FLAC__Metadata_SimpleIteratorStatus status_;
357                         };
358
359                         SimpleIterator();
360                         virtual ~SimpleIterator();
361
362                         bool init(const char *filename, bool preserve_file_stats = false);
363
364                         bool is_valid() const;
365                         Status status();
366                         bool is_writable() const;
367
368                         bool next();
369                         bool prev();
370
371                         ::FLAC__MetadataType get_block_type() const;
372                         Prototype *get_block();
373                         bool set_block(Prototype *block, bool use_padding = true);
374                         bool insert_block_after(Prototype *block, bool use_padding = true);
375                         bool delete_block(bool use_padding = true);
376
377                 protected:
378                         ::FLAC__Metadata_SimpleIterator *iterator_;
379                         void clear();
380                 };
381
382
383                 // ============================================================
384                 //
385                 //  Level 2
386                 //
387                 //  ----------------------------------------------------------
388                 //
389                 //  The flow through the iterator in the C++ layer is similar
390                 //  to the C layer:
391                 //
392                 //    * Create a Chain instance
393                 //    * Check Chain::is_valid()
394                 //    * Call Chain::read() and check the return
395                 //    * Traverse and/or edit with an Iterator or with
396                 //      Chain::merge_padding() or Chain::sort_padding()
397                 //    * Write changes back to FLAC file with Chain::write()
398                 //    * Destroy the Chain instance
399                 //
400                 //  ----------------------------------------------------------
401                 //
402                 //  The ownership of pointers in the C++ layer follows that in
403                 //  the C layer, i.e.
404                 //    * The objects returned by Iterator::get_block() are
405                 //      owned by the iterator and should not be deleted.
406                 //      When you modify the block, you are directly editing
407                 //      what's in the chain and do not need to call
408                 //      Iterator::set_block().  However the changes will not
409                 //      be reflected in the FLAC file until the chain is
410                 //      written with Chain::write().
411                 //
412                 //    * When you pass an object to Iterator::set_block(),
413                 //      Iterator::insert_block_before(), or
414                 //      Iterator::insert_block_after(), the iterator takes
415                 //      ownership of the block and it will be deleted with the
416                 //      chain.
417                 //
418                 // ============================================================
419
420                 class Chain {
421                 public:
422                         class Status {
423                         public:
424                                 inline Status(::FLAC__Metadata_ChainStatus status): status_(status) { }
425                                 inline operator ::FLAC__Metadata_ChainStatus() const { return status_; }
426                                 inline const char *as_cstring() const { return ::FLAC__Metadata_ChainStatusString[status_]; }
427                         protected:
428                                 ::FLAC__Metadata_ChainStatus status_;
429                         };
430
431                         Chain();
432                         virtual ~Chain();
433
434                         friend class Iterator;
435
436                         bool is_valid() const;
437                         Status status();
438
439                         bool read(const char *filename);
440                         bool write(bool use_padding = true, bool preserve_file_stats = false);
441
442                         void merge_padding();
443                         void sort_padding();
444
445                 protected:
446                         ::FLAC__Metadata_Chain *chain_;
447                         virtual void clear();
448                 };
449
450                 class Iterator {
451                 public:
452                         Iterator();
453                         virtual ~Iterator();
454
455                         bool is_valid() const;
456
457                         void init(Chain &chain);
458
459                         bool next();
460                         bool prev();
461
462                         ::FLAC__MetadataType get_block_type() const;
463                         Prototype *get_block();
464                         bool set_block(Prototype *block);
465                         bool delete_block(bool replace_with_padding);
466                         bool insert_block_before(Prototype *block);
467                         bool insert_block_after(Prototype *block);
468
469                 protected:
470                         ::FLAC__Metadata_Iterator *iterator_;
471                         virtual void clear();
472                 };
473
474         };
475 };
476
477 #endif