metadata.h 18.4 KB
Newer Older
Josh Coalson's avatar
Josh Coalson committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* libFLAC++ - Free Lossless Audio Codec library
 * Copyright (C) 2002  Josh Coalson
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */

#ifndef FLACPP__METADATA_H
#define FLACPP__METADATA_H

#include "FLAC/metadata.h"

Josh Coalson's avatar
Josh Coalson committed
25
26
27
28
29
30
31
32
// ===============================================================
//
//  Full documentation for the metadata interface can be found
//  in the C layer in include/FLAC/metadata.h
//
// ===============================================================


Josh Coalson's avatar
Josh Coalson committed
33
34
35
namespace FLAC {
	namespace Metadata {

Josh Coalson's avatar
Josh Coalson committed
36
37
38
39
40
41
		// ============================================================
		//
		//  Metadata objects
		//
		// ============================================================

42
43
44
45
		class Prototype;

		Prototype *clone(const Prototype *);

Josh Coalson's avatar
Josh Coalson committed
46
		// NOTE: When the get_*() methods return you a const pointer,
Josh Coalson's avatar
Josh Coalson committed
47
		// DO NOT disobey and write into it.  Always use the set_*()
Josh Coalson's avatar
Josh Coalson committed
48
49
50
51
52
		// methods.

		// base class for all metadata blocks
		class Prototype {
		protected:
53
54
55
56
			Prototype(const Prototype &object); // this form always copies object.object_
			Prototype(const ::FLAC__StreamMetadata &object); // this form always copies
			Prototype(const ::FLAC__StreamMetadata *object); // this form always copies
			Prototype(::FLAC__StreamMetadata *object, bool copy); // this form allows you to pass ownership to the Prototype using copy=false
Josh Coalson's avatar
Josh Coalson committed
57

Josh Coalson's avatar
Josh Coalson committed
58
			void operator=(const Prototype &);
59
60
			void operator=(const ::FLAC__StreamMetadata &); // this form always copies
			void operator=(const ::FLAC__StreamMetadata *); // this form always copies
61

Josh Coalson's avatar
Josh Coalson committed
62
63
			virtual void clear();

64
			::FLAC__StreamMetadata *object_;
Josh Coalson's avatar
Josh Coalson committed
65
		public:
66
67
			virtual ~Prototype();

68
69
70
71
72
73
74
			inline bool operator==(const Prototype &) const;
			inline bool operator==(const ::FLAC__StreamMetadata &) const;
			inline bool operator==(const ::FLAC__StreamMetadata *) const;
			inline bool operator!=(const Prototype &) const;
			inline bool operator!=(const ::FLAC__StreamMetadata &) const;
			inline bool operator!=(const ::FLAC__StreamMetadata *) const;

Josh Coalson's avatar
Josh Coalson committed
75
76
77
			friend class SimpleIterator;
			friend class Iterator;

78
			inline bool is_valid() const;
Josh Coalson's avatar
Josh Coalson committed
79
80

			bool get_is_last() const;
81
			FLAC__MetadataType get_type() const;
Josh Coalson's avatar
Josh Coalson committed
82
			unsigned get_length() const; // NOTE: does not include the header, per spec
83
84

			void set_is_last(bool);
Josh Coalson's avatar
Josh Coalson committed
85
		private:
Josh Coalson's avatar
Josh Coalson committed
86
			Prototype(); // Private and undefined so you can't use it
Josh Coalson's avatar
Josh Coalson committed
87
88
89
90

			// These are used only by Iterator
			bool is_reference_;
			inline void set_reference(bool x) { is_reference_ = x; }
Josh Coalson's avatar
Josh Coalson committed
91
92
		};

93
94
95
		inline bool Prototype::operator==(const Prototype &object) const 
		{ return ::FLAC__metadata_object_is_equal(object_, object.object_); }

96
		inline bool Prototype::operator==(const ::FLAC__StreamMetadata &object) const 
97
98
		{ return ::FLAC__metadata_object_is_equal(object_, &object); }

99
		inline bool Prototype::operator==(const ::FLAC__StreamMetadata *object) const 
100
101
102
103
104
		{ return ::FLAC__metadata_object_is_equal(object_, object); }

		inline bool Prototype::operator!=(const Prototype &object) const 
		{ return !operator==(object); }

105
		inline bool Prototype::operator!=(const ::FLAC__StreamMetadata &object) const 
106
107
		{ return !operator==(object); }

108
		inline bool Prototype::operator!=(const ::FLAC__StreamMetadata *object) const 
109
110
111
112
113
114
		{ return !operator==(object); }

		inline bool Prototype::is_valid() const
		{ return 0 != object_; }


Josh Coalson's avatar
Josh Coalson committed
115
116
117
		class StreamInfo : public Prototype {
		public:
			StreamInfo();
118
119
120
121
			inline StreamInfo(const StreamInfo &object): Prototype(object) { }
			inline StreamInfo(const ::FLAC__StreamMetadata &object): Prototype(object) { }
			inline StreamInfo(const ::FLAC__StreamMetadata *object): Prototype(object) { }
			inline StreamInfo(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
Josh Coalson's avatar
Josh Coalson committed
122
123
			~StreamInfo();

Josh Coalson's avatar
Josh Coalson committed
124
			inline void operator=(const StreamInfo &object) { Prototype::operator=(object); }
125
126
			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
Josh Coalson's avatar
Josh Coalson committed
127

128
			inline bool operator==(const StreamInfo &object) const { return Prototype::operator==(object); }
129
130
			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
			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
133
			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
134

Josh Coalson's avatar
Josh Coalson committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
			unsigned get_min_blocksize() const;
			unsigned get_max_blocksize() const;
			unsigned get_min_framesize() const;
			unsigned get_max_framesize() const;
			unsigned get_sample_rate() const;
			unsigned get_channels() const;
			unsigned get_bits_per_sample() const;
			FLAC__uint64 get_total_samples() const;
			const FLAC__byte *get_md5sum() const;

			void set_min_blocksize(unsigned value);
			void set_max_blocksize(unsigned value);
			void set_min_framesize(unsigned value);
			void set_max_framesize(unsigned value);
			void set_sample_rate(unsigned value);
			void set_channels(unsigned value);
			void set_bits_per_sample(unsigned value);
			void set_total_samples(FLAC__uint64 value);
			void set_md5sum(const FLAC__byte value[16]);
		};

		class Padding : public Prototype {
		public:
			Padding();
159
160
161
162
			inline Padding(const Padding &object): Prototype(object) { }
			inline Padding(const ::FLAC__StreamMetadata &object): Prototype(object) { }
			inline Padding(const ::FLAC__StreamMetadata *object): Prototype(object) { }
			inline Padding(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
Josh Coalson's avatar
Josh Coalson committed
163
			~Padding();
Josh Coalson's avatar
Josh Coalson committed
164
165

			inline void operator=(const Padding &object) { Prototype::operator=(object); }
166
167
			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
168

169
			inline bool operator==(const Padding &object) const { return Prototype::operator==(object); }
170
171
			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
			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
174
			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
175

176
			void set_length(unsigned length);
Josh Coalson's avatar
Josh Coalson committed
177
178
179
180
181
		};

		class Application : public Prototype {
		public:
			Application();
182
183
184
185
			inline Application(const Application &object): Prototype(object) { }
			inline Application(const ::FLAC__StreamMetadata &object): Prototype(object) { }
			inline Application(const ::FLAC__StreamMetadata *object): Prototype(object) { }
			inline Application(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
Josh Coalson's avatar
Josh Coalson committed
186
187
			~Application();

Josh Coalson's avatar
Josh Coalson committed
188
			inline void operator=(const Application &object) { Prototype::operator=(object); }
189
190
			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
Josh Coalson's avatar
Josh Coalson committed
191

192
			inline bool operator==(const Application &object) const { return Prototype::operator==(object); }
193
194
			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
			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
197
			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
			inline bool operator!=(const ::FLAC__StreamMetadata *object) const { return Prototype::operator!=(object); }
198

Josh Coalson's avatar
Josh Coalson committed
199
200
201
			const FLAC__byte *get_id() const;
			const FLAC__byte *get_data() const;

202
203
204
			void set_id(const FLAC__byte value[4]);
			bool set_data(const FLAC__byte *data, unsigned length); // this form always copies
			bool set_data(FLAC__byte *data, unsigned length, bool copy);
Josh Coalson's avatar
Josh Coalson committed
205
206
207
208
209
		};

		class SeekTable : public Prototype {
		public:
			SeekTable();
210
211
212
213
			inline SeekTable(const SeekTable &object): Prototype(object) { }
			inline SeekTable(const ::FLAC__StreamMetadata &object): Prototype(object) { }
			inline SeekTable(const ::FLAC__StreamMetadata *object): Prototype(object) { }
			inline SeekTable(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
Josh Coalson's avatar
Josh Coalson committed
214
			~SeekTable();
Josh Coalson's avatar
Josh Coalson committed
215
216

			inline void operator=(const SeekTable &object) { Prototype::operator=(object); }
217
218
			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
219

220
			inline bool operator==(const SeekTable &object) const { return Prototype::operator==(object); }
221
222
			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
			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
225
			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
			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
231
			void set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
			bool insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point);
232
			bool delete_point(unsigned index);
233
234

			bool is_legal() const;
Josh Coalson's avatar
Josh Coalson committed
235
236
237
238
		};

		class VorbisComment : public Prototype {
		public:
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
			class Entry {
			public:
				Entry();
				Entry(const char *field, unsigned field_length);
				Entry(const char *field_name, const char *field_value, unsigned field_value_length);
				Entry(const Entry &entry);
				void operator=(const Entry &entry);

				virtual ~Entry();

				virtual bool is_valid() const;

				unsigned get_field_length() const;
				unsigned get_field_name_length() const;
				unsigned get_field_value_length() const;

255
				::FLAC__StreamMetadata_VorbisComment_Entry get_entry() const;
256
257
258
259
260
261
262
263
264
				const char *get_field() const;
				const char *get_field_name() const;
				const char *get_field_value() const;

				bool set_field(const char *field, unsigned field_length);
				bool set_field_name(const char *field_name);
				bool set_field_value(const char *field_value, unsigned field_value_length);
			protected:
				bool is_valid_;
265
				::FLAC__StreamMetadata_VorbisComment_Entry entry_;
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
				char *field_name_;
				unsigned field_name_length_;
				char *field_value_;
				unsigned field_value_length_;
			private:
				void zero();
				void clear();
				void clear_entry();
				void clear_field_name();
				void clear_field_value();
				void construct(const char *field, unsigned field_length);
				void construct(const char *field_name, const char *field_value, unsigned field_value_length);
				void compose_field();
				void parse_field();
			};

Josh Coalson's avatar
Josh Coalson committed
282
			VorbisComment();
283
284
285
286
			inline VorbisComment(const VorbisComment &object): Prototype(object) { }
			inline VorbisComment(const ::FLAC__StreamMetadata &object): Prototype(object) { }
			inline VorbisComment(const ::FLAC__StreamMetadata *object): Prototype(object) { }
			inline VorbisComment(::FLAC__StreamMetadata *object, bool copy): Prototype(object, copy) { }
Josh Coalson's avatar
Josh Coalson committed
287
			~VorbisComment();
Josh Coalson's avatar
Josh Coalson committed
288
289

			inline void operator=(const VorbisComment &object) { Prototype::operator=(object); }
290
291
			inline void operator=(const ::FLAC__StreamMetadata &object) { Prototype::operator=(object); }
			inline void operator=(const ::FLAC__StreamMetadata *object) { Prototype::operator=(object); }
292

293
			inline bool operator==(const VorbisComment &object) const { return Prototype::operator==(object); }
294
295
			inline bool operator==(const ::FLAC__StreamMetadata &object) const { return Prototype::operator==(object); }
			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
298
			inline bool operator!=(const ::FLAC__StreamMetadata &object) const { return Prototype::operator!=(object); }
			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
303
			Entry get_comment(unsigned index) const;

304
			bool set_vendor_string(const Entry &entry); // only the Entry's field name will be used
305
306
307
			bool set_comment(unsigned index, const Entry &entry);
			bool insert_comment(unsigned index, const Entry &entry);
			bool delete_comment(unsigned index);
Josh Coalson's avatar
Josh Coalson committed
308
309
		};

310

Josh Coalson's avatar
Josh Coalson committed
311
312
313
314
315
316
317
318
		// ============================================================
		//
		//  Level 0
		//
		// ============================================================

		bool get_streaminfo(const char *filename, StreamInfo &streaminfo);

319

Josh Coalson's avatar
Josh Coalson committed
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
		// ============================================================
		//
		//  Level 1
		//
		//  ----------------------------------------------------------
		//
		//  The flow through the iterator in the C++ layer is similar
		//  to the C layer:
		//
		//    * Create a SimpleIterator instance
		//    * Check SimpleIterator::is_valid()
		//    * Call SimpleIterator::init() and check the return
		//    * Traverse and/or edit.  Edits are written to file
		//      immediately.
		//    * Destroy the SimpleIterator instance
		//
		//  ----------------------------------------------------------
		//
		//  The ownership of pointers in the C++ layer follows that in
		//  the C layer, i.e.
		//    * The objects returned by get_block() are yours to
		//      modify, but changes are not reflected in the FLAC file
		//      until you call set_block().  The objects are also
		//      yours to delete; they are not automatically deleted
		//      when passed to set_block() or insert_block_after().
		//
		// ============================================================

		class SimpleIterator {
		public:
			class Status {
			public:
352
353
354
				inline Status(::FLAC__Metadata_SimpleIteratorStatus status): status_(status) { }
				inline operator ::FLAC__Metadata_SimpleIteratorStatus() const { return status_; }
				inline const char *as_cstring() const { return ::FLAC__Metadata_SimpleIteratorStatusString[status_]; }
Josh Coalson's avatar
Josh Coalson committed
355
			protected:
356
				::FLAC__Metadata_SimpleIteratorStatus status_;
Josh Coalson's avatar
Josh Coalson committed
357
358
359
360
361
362
363
364
365
366
367
368
369
370
			};

			SimpleIterator();
			virtual ~SimpleIterator();

			bool init(const char *filename, bool preserve_file_stats = false);

			bool is_valid() const;
			Status status();
			bool is_writable() const;

			bool next();
			bool prev();

371
			::FLAC__MetadataType get_block_type() const;
Josh Coalson's avatar
Josh Coalson committed
372
373
374
375
376
377
			Prototype *get_block();
			bool set_block(Prototype *block, bool use_padding = true);
			bool insert_block_after(Prototype *block, bool use_padding = true);
			bool delete_block(bool use_padding = true);

		protected:
378
			::FLAC__Metadata_SimpleIterator *iterator_;
Josh Coalson's avatar
Josh Coalson committed
379
380
381
			void clear();
		};

382

Josh Coalson's avatar
Josh Coalson committed
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
		// ============================================================
		//
		//  Level 2
		//
		//  ----------------------------------------------------------
		//
		//  The flow through the iterator in the C++ layer is similar
		//  to the C layer:
		//
		//    * Create a Chain instance
		//    * Check Chain::is_valid()
		//    * Call Chain::read() and check the return
		//    * Traverse and/or edit with an Iterator or with
		//      Chain::merge_padding() or Chain::sort_padding()
		//    * Write changes back to FLAC file with Chain::write()
		//    * Destroy the Chain instance
		//
		//  ----------------------------------------------------------
		//
		//  The ownership of pointers in the C++ layer follows that in
		//  the C layer, i.e.
		//    * The objects returned by Iterator::get_block() are
		//      owned by the iterator and should not be deleted.
		//      When you modify the block, you are directly editing
		//      what's in the chain and do not need to call
		//      Iterator::set_block().  However the changes will not
		//      be reflected in the FLAC file until the chain is
		//      written with Chain::write().
		//
		//    * When you pass an object to Iterator::set_block(),
		//      Iterator::insert_block_before(), or
		//      Iterator::insert_block_after(), the iterator takes
		//      ownership of the block and it will be deleted with the
		//      chain.
		//
		// ============================================================

		class Chain {
		public:
			class Status {
			public:
424
425
426
				inline Status(::FLAC__Metadata_ChainStatus status): status_(status) { }
				inline operator ::FLAC__Metadata_ChainStatus() const { return status_; }
				inline const char *as_cstring() const { return ::FLAC__Metadata_ChainStatusString[status_]; }
Josh Coalson's avatar
Josh Coalson committed
427
			protected:
428
				::FLAC__Metadata_ChainStatus status_;
Josh Coalson's avatar
Josh Coalson committed
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
			};

			Chain();
			virtual ~Chain();

			friend class Iterator;

			bool is_valid() const;
			Status status();

			bool read(const char *filename);
			bool write(bool use_padding = true, bool preserve_file_stats = false);

			void merge_padding();
			void sort_padding();

		protected:
446
			::FLAC__Metadata_Chain *chain_;
Josh Coalson's avatar
Josh Coalson committed
447
448
449
450
451
452
453
454
455
456
			virtual void clear();
		};

		class Iterator {
		public:
			Iterator();
			virtual ~Iterator();

			bool is_valid() const;

457
			void init(Chain &chain);
Josh Coalson's avatar
Josh Coalson committed
458
459
460
461

			bool next();
			bool prev();

462
			::FLAC__MetadataType get_block_type() const;
Josh Coalson's avatar
Josh Coalson committed
463
464
465
466
467
468
469
			Prototype *get_block();
			bool set_block(Prototype *block);
			bool delete_block(bool replace_with_padding);
			bool insert_block_before(Prototype *block);
			bool insert_block_after(Prototype *block);

		protected:
470
			::FLAC__Metadata_Iterator *iterator_;
Josh Coalson's avatar
Josh Coalson committed
471
			virtual void clear();
Josh Coalson's avatar
Josh Coalson committed
472
473
474
475
476
477
		};

	};
};

#endif