blob: fa7418847ad5a74124f197058fbcb46df0d5b943 [file] [log] [blame]
Josh Coalsonfda98fb2002-05-17 06:33:39 +00001/* 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
Josh Coalsonfb74f102002-05-22 05:33:29 +000025// ===============================================================
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
Josh Coalsonfda98fb2002-05-17 06:33:39 +000033namespace FLAC {
34 namespace Metadata {
35
Josh Coalsonfb74f102002-05-22 05:33:29 +000036 // ============================================================
37 //
38 // Metadata objects
39 //
40 // ============================================================
41
Josh Coalsonfda98fb2002-05-17 06:33:39 +000042 // NOTE: When the get_*() methods return you a const pointer,
Josh Coalsonfb74f102002-05-22 05:33:29 +000043 // DO NOT disobey and write into it. Always use the set_*()
Josh Coalsonfda98fb2002-05-17 06:33:39 +000044 // methods.
45
46 // base class for all metadata blocks
47 class Prototype {
48 protected:
49 Prototype(::FLAC__StreamMetaData *object, bool copy);
Josh Coalsonfda98fb2002-05-17 06:33:39 +000050
Josh Coalsonfb74f102002-05-22 05:33:29 +000051 void operator=(const Prototype &);
52 void operator=(const ::FLAC__StreamMetaData &);
53 void operator=(const ::FLAC__StreamMetaData *);
54
Josh Coalson57ba6f42002-06-07 05:27:37 +000055 inline bool operator==(const Prototype &) const;
56 inline bool operator==(const ::FLAC__StreamMetaData &) const;
57 inline bool operator==(const ::FLAC__StreamMetaData *) const;
58 inline bool operator!=(const Prototype &) const;
59 inline bool operator!=(const ::FLAC__StreamMetaData &) const;
60 inline bool operator!=(const ::FLAC__StreamMetaData *) const;
61
Josh Coalsonfb74f102002-05-22 05:33:29 +000062 virtual void clear();
63
Josh Coalsonfda98fb2002-05-17 06:33:39 +000064 ::FLAC__StreamMetaData *object_;
65 public:
Josh Coalson57ba6f42002-06-07 05:27:37 +000066 virtual ~Prototype();
67
Josh Coalsonfb74f102002-05-22 05:33:29 +000068 friend class SimpleIterator;
69 friend class Iterator;
70
Josh Coalson57ba6f42002-06-07 05:27:37 +000071 inline bool is_valid() const;
Josh Coalsonfda98fb2002-05-17 06:33:39 +000072
73 bool get_is_last() const;
74 FLAC__MetaDataType get_type() const;
75 unsigned get_length() const; // NOTE: does not include the header, per spec
Josh Coalsonfb74f102002-05-22 05:33:29 +000076 private:
Josh Coalson5ac8bd12002-05-29 05:53:57 +000077 Prototype(); // Private and undefined so you can't use it
Josh Coalsonfb74f102002-05-22 05:33:29 +000078
79 // These are used only by Iterator
80 bool is_reference_;
81 inline void set_reference(bool x) { is_reference_ = x; }
Josh Coalsonfda98fb2002-05-17 06:33:39 +000082 };
83
Josh Coalson57ba6f42002-06-07 05:27:37 +000084 inline bool Prototype::operator==(const Prototype &object) const
85 { return ::FLAC__metadata_object_is_equal(object_, object.object_); }
86
87 inline bool Prototype::operator==(const ::FLAC__StreamMetaData &object) const
88 { return ::FLAC__metadata_object_is_equal(object_, &object); }
89
90 inline bool Prototype::operator==(const ::FLAC__StreamMetaData *object) const
91 { return ::FLAC__metadata_object_is_equal(object_, object); }
92
93 inline bool Prototype::operator!=(const Prototype &object) const
94 { return !operator==(object); }
95
96 inline bool Prototype::operator!=(const ::FLAC__StreamMetaData &object) const
97 { return !operator==(object); }
98
99 inline bool Prototype::operator!=(const ::FLAC__StreamMetaData *object) const
100 { return !operator==(object); }
101
102 inline bool Prototype::is_valid() const
103 { return 0 != object_; }
104
105
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000106 class StreamInfo : public Prototype {
107 public:
108 StreamInfo();
109 StreamInfo(::FLAC__StreamMetaData *object, bool copy = false);
110 ~StreamInfo();
111
Josh Coalsonfb74f102002-05-22 05:33:29 +0000112 inline void operator=(const StreamInfo &object) { Prototype::operator=(object); }
113 inline void operator=(const ::FLAC__StreamMetaData &object) { Prototype::operator=(object); }
114 inline void operator=(const ::FLAC__StreamMetaData *object) { Prototype::operator=(object); }
115
Josh Coalson57ba6f42002-06-07 05:27:37 +0000116 inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
117 inline bool operator==(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
118 inline bool operator==(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
119 inline bool operator!=(const StreamInfo &object) const { return Prototype::operator!=(object); }
120 inline bool operator!=(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
121 inline bool operator!=(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
122
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000123 unsigned get_min_blocksize() const;
124 unsigned get_max_blocksize() const;
125 unsigned get_min_framesize() const;
126 unsigned get_max_framesize() const;
127 unsigned get_sample_rate() const;
128 unsigned get_channels() const;
129 unsigned get_bits_per_sample() const;
130 FLAC__uint64 get_total_samples() const;
131 const FLAC__byte *get_md5sum() const;
132
133 void set_min_blocksize(unsigned value);
134 void set_max_blocksize(unsigned value);
135 void set_min_framesize(unsigned value);
136 void set_max_framesize(unsigned value);
137 void set_sample_rate(unsigned value);
138 void set_channels(unsigned value);
139 void set_bits_per_sample(unsigned value);
140 void set_total_samples(FLAC__uint64 value);
141 void set_md5sum(const FLAC__byte value[16]);
142 };
143
144 class Padding : public Prototype {
145 public:
146 Padding();
147 Padding(::FLAC__StreamMetaData *object, bool copy = false);
148 ~Padding();
Josh Coalsonfb74f102002-05-22 05:33:29 +0000149
150 inline void operator=(const Padding &object) { Prototype::operator=(object); }
151 inline void operator=(const ::FLAC__StreamMetaData &object) { Prototype::operator=(object); }
152 inline void operator=(const ::FLAC__StreamMetaData *object) { Prototype::operator=(object); }
Josh Coalsonb2b53582002-05-31 06:20:50 +0000153
Josh Coalson57ba6f42002-06-07 05:27:37 +0000154 inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
155 inline bool operator==(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
156 inline bool operator==(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
157 inline bool operator!=(const Padding &object) const { return Prototype::operator!=(object); }
158 inline bool operator!=(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
159 inline bool operator!=(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
160
Josh Coalsonb2b53582002-05-31 06:20:50 +0000161 void set_length(unsigned length);
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000162 };
163
164 class Application : public Prototype {
165 public:
166 Application();
167 Application(::FLAC__StreamMetaData *object, bool copy = false);
168 ~Application();
169
Josh Coalsonfb74f102002-05-22 05:33:29 +0000170 inline void operator=(const Application &object) { Prototype::operator=(object); }
171 inline void operator=(const ::FLAC__StreamMetaData &object) { Prototype::operator=(object); }
172 inline void operator=(const ::FLAC__StreamMetaData *object) { Prototype::operator=(object); }
173
Josh Coalson57ba6f42002-06-07 05:27:37 +0000174 inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
175 inline bool operator==(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
176 inline bool operator==(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
177 inline bool operator!=(const Application &object) const { return Prototype::operator!=(object); }
178 inline bool operator!=(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
179 inline bool operator!=(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
180
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000181 const FLAC__byte *get_id() const;
182 const FLAC__byte *get_data() const;
183
184 void set_id(FLAC__byte value[4]);
185 bool set_data(FLAC__byte *data, unsigned length, bool copy = false);
186 };
187
188 class SeekTable : public Prototype {
189 public:
190 SeekTable();
191 SeekTable(::FLAC__StreamMetaData *object, bool copy = false);
192 ~SeekTable();
Josh Coalsonfb74f102002-05-22 05:33:29 +0000193
194 inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
195 inline void operator=(const ::FLAC__StreamMetaData &object) { Prototype::operator=(object); }
196 inline void operator=(const ::FLAC__StreamMetaData *object) { Prototype::operator=(object); }
Josh Coalsonb2b53582002-05-31 06:20:50 +0000197
Josh Coalson57ba6f42002-06-07 05:27:37 +0000198 inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
199 inline bool operator==(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
200 inline bool operator==(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
201 inline bool operator!=(const SeekTable &object) const { return Prototype::operator!=(object); }
202 inline bool operator!=(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
203 inline bool operator!=(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
204
Josh Coalsonb2b53582002-05-31 06:20:50 +0000205 unsigned get_num_points() const;
206 ::FLAC__StreamMetaData_SeekPoint get_point(unsigned index) const;
207
208 void set_point(unsigned index, const ::FLAC__StreamMetaData_SeekPoint &point);
209 bool insert_point(unsigned index, const ::FLAC__StreamMetaData_SeekPoint &point);
210 bool delete_point(unsigned index);
Josh Coalson28e08d82002-06-05 05:56:41 +0000211
212 bool is_legal() const;
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000213 };
214
215 class VorbisComment : public Prototype {
216 public:
Josh Coalsonb2b53582002-05-31 06:20:50 +0000217 class Entry {
218 public:
219 Entry();
220 Entry(const char *field, unsigned field_length);
221 Entry(const char *field_name, const char *field_value, unsigned field_value_length);
222 Entry(const Entry &entry);
223 void operator=(const Entry &entry);
224
225 virtual ~Entry();
226
227 virtual bool is_valid() const;
Josh Coalsonb2b53582002-05-31 06:20:50 +0000228
229 unsigned get_field_length() const;
230 unsigned get_field_name_length() const;
231 unsigned get_field_value_length() const;
232
233 ::FLAC__StreamMetaData_VorbisComment_Entry get_entry() const;
234 const char *get_field() const;
235 const char *get_field_name() const;
236 const char *get_field_value() const;
237
238 bool set_field(const char *field, unsigned field_length);
239 bool set_field_name(const char *field_name);
240 bool set_field_value(const char *field_value, unsigned field_value_length);
241 protected:
242 bool is_valid_;
243 ::FLAC__StreamMetaData_VorbisComment_Entry entry_;
244 char *field_name_;
245 unsigned field_name_length_;
246 char *field_value_;
247 unsigned field_value_length_;
248 private:
249 void zero();
250 void clear();
251 void clear_entry();
252 void clear_field_name();
253 void clear_field_value();
254 void construct(const char *field, unsigned field_length);
255 void construct(const char *field_name, const char *field_value, unsigned field_value_length);
256 void compose_field();
257 void parse_field();
258 };
259
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000260 VorbisComment();
261 VorbisComment(::FLAC__StreamMetaData *object, bool copy = false);
262 ~VorbisComment();
Josh Coalsonfb74f102002-05-22 05:33:29 +0000263
264 inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
265 inline void operator=(const ::FLAC__StreamMetaData &object) { Prototype::operator=(object); }
266 inline void operator=(const ::FLAC__StreamMetaData *object) { Prototype::operator=(object); }
Josh Coalsonb2b53582002-05-31 06:20:50 +0000267
Josh Coalson57ba6f42002-06-07 05:27:37 +0000268 inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
269 inline bool operator==(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
270 inline bool operator==(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
271 inline bool operator!=(const VorbisComment &object) const { return Prototype::operator!=(object); }
272 inline bool operator!=(const ::FLAC__StreamMetaData &object) const { return Prototype::operator==(object); }
273 inline bool operator!=(const ::FLAC__StreamMetaData *object) const { return Prototype::operator==(object); }
274
Josh Coalsonb2b53582002-05-31 06:20:50 +0000275 unsigned get_num_comments() const;
276 Entry get_vendor_string() const;
277 Entry get_comment(unsigned index) const;
278
279 bool set_vendor_string(const Entry &entry);
280 bool set_comment(unsigned index, const Entry &entry);
281 bool insert_comment(unsigned index, const Entry &entry);
282 bool delete_comment(unsigned index);
Josh Coalsonfb74f102002-05-22 05:33:29 +0000283 };
284
Josh Coalsonb2b53582002-05-31 06:20:50 +0000285
Josh Coalsonfb74f102002-05-22 05:33:29 +0000286 // ============================================================
287 //
288 // Level 0
289 //
290 // ============================================================
291
292 bool get_streaminfo(const char *filename, StreamInfo &streaminfo);
293
Josh Coalsonb2b53582002-05-31 06:20:50 +0000294
Josh Coalsonfb74f102002-05-22 05:33:29 +0000295 // ============================================================
296 //
297 // Level 1
298 //
299 // ----------------------------------------------------------
300 //
301 // The flow through the iterator in the C++ layer is similar
302 // to the C layer:
303 //
304 // * Create a SimpleIterator instance
305 // * Check SimpleIterator::is_valid()
306 // * Call SimpleIterator::init() and check the return
307 // * Traverse and/or edit. Edits are written to file
308 // immediately.
309 // * Destroy the SimpleIterator instance
310 //
311 // ----------------------------------------------------------
312 //
313 // The ownership of pointers in the C++ layer follows that in
314 // the C layer, i.e.
315 // * The objects returned by get_block() are yours to
316 // modify, but changes are not reflected in the FLAC file
317 // until you call set_block(). The objects are also
318 // yours to delete; they are not automatically deleted
319 // when passed to set_block() or insert_block_after().
320 //
321 // ============================================================
322
323 class SimpleIterator {
324 public:
325 class Status {
326 public:
327 inline Status(::FLAC__MetaData_SimpleIteratorStatus status): status_(status) { }
328 inline operator ::FLAC__MetaData_SimpleIteratorStatus() const { return status_; }
329 inline const char *as_cstring() const { return ::FLAC__MetaData_SimpleIteratorStatusString[status_]; }
330 protected:
331 ::FLAC__MetaData_SimpleIteratorStatus status_;
332 };
333
334 SimpleIterator();
335 virtual ~SimpleIterator();
336
337 bool init(const char *filename, bool preserve_file_stats = false);
338
339 bool is_valid() const;
Josh Coalsonfb74f102002-05-22 05:33:29 +0000340 Status status();
341 bool is_writable() const;
342
343 bool next();
344 bool prev();
345
346 ::FLAC__MetaDataType get_block_type() const;
347 Prototype *get_block();
348 bool set_block(Prototype *block, bool use_padding = true);
349 bool insert_block_after(Prototype *block, bool use_padding = true);
350 bool delete_block(bool use_padding = true);
351
352 protected:
353 ::FLAC__MetaData_SimpleIterator *iterator_;
354 void clear();
355 };
356
Josh Coalsonb2b53582002-05-31 06:20:50 +0000357
Josh Coalsonfb74f102002-05-22 05:33:29 +0000358 // ============================================================
359 //
360 // Level 2
361 //
362 // ----------------------------------------------------------
363 //
364 // The flow through the iterator in the C++ layer is similar
365 // to the C layer:
366 //
367 // * Create a Chain instance
368 // * Check Chain::is_valid()
369 // * Call Chain::read() and check the return
370 // * Traverse and/or edit with an Iterator or with
371 // Chain::merge_padding() or Chain::sort_padding()
372 // * Write changes back to FLAC file with Chain::write()
373 // * Destroy the Chain instance
374 //
375 // ----------------------------------------------------------
376 //
377 // The ownership of pointers in the C++ layer follows that in
378 // the C layer, i.e.
379 // * The objects returned by Iterator::get_block() are
380 // owned by the iterator and should not be deleted.
381 // When you modify the block, you are directly editing
382 // what's in the chain and do not need to call
383 // Iterator::set_block(). However the changes will not
384 // be reflected in the FLAC file until the chain is
385 // written with Chain::write().
386 //
387 // * When you pass an object to Iterator::set_block(),
388 // Iterator::insert_block_before(), or
389 // Iterator::insert_block_after(), the iterator takes
390 // ownership of the block and it will be deleted with the
391 // chain.
392 //
393 // ============================================================
394
395 class Chain {
396 public:
397 class Status {
398 public:
399 inline Status(::FLAC__MetaData_ChainStatus status): status_(status) { }
400 inline operator ::FLAC__MetaData_ChainStatus() const { return status_; }
401 inline const char *as_cstring() const { return ::FLAC__MetaData_ChainStatusString[status_]; }
402 protected:
403 ::FLAC__MetaData_ChainStatus status_;
404 };
405
406 Chain();
407 virtual ~Chain();
408
409 friend class Iterator;
410
411 bool is_valid() const;
Josh Coalsonfb74f102002-05-22 05:33:29 +0000412 Status status();
413
414 bool read(const char *filename);
415 bool write(bool use_padding = true, bool preserve_file_stats = false);
416
417 void merge_padding();
418 void sort_padding();
419
420 protected:
421 ::FLAC__MetaData_Chain *chain_;
422 virtual void clear();
423 };
424
425 class Iterator {
426 public:
427 Iterator();
428 virtual ~Iterator();
429
430 bool is_valid() const;
Josh Coalsonfb74f102002-05-22 05:33:29 +0000431
432 void init(Chain *chain);
433
434 bool next();
435 bool prev();
436
437 ::FLAC__MetaDataType get_block_type() const;
438 Prototype *get_block();
439 bool set_block(Prototype *block);
440 bool delete_block(bool replace_with_padding);
441 bool insert_block_before(Prototype *block);
442 bool insert_block_after(Prototype *block);
443
444 protected:
445 ::FLAC__MetaData_Iterator *iterator_;
446 virtual void clear();
Josh Coalsonfda98fb2002-05-17 06:33:39 +0000447 };
448
449 };
450};
451
452#endif