Improve description of encoding preset equivalents.
[flac.git] / src / libFLAC++ / metadata.cpp
blob7dbfc3102b527e60e0ed8bfc77509f203afbdb9f
1 /* libFLAC++ - Free Lossless Audio Codec library
2 * Copyright (C) 2002-2009 Josh Coalson
3 * Copyright (C) 2011-2013 Xiph.Org Foundation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * - Neither the name of the Xiph.org Foundation nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #define __STDC_LIMIT_MACROS 1 /* otherwise SIZE_MAX is not defined for c++ */
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include "share/alloc.h"
39 #include "FLAC++/metadata.h"
40 #include "FLAC/assert.h"
41 #include <stdlib.h> // for malloc(), free()
42 #include <string.h> // for memcpy() etc.
44 #ifdef _MSC_VER
45 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
46 #pragma warning ( disable : 4800 )
47 #endif
49 namespace FLAC {
50 namespace Metadata {
52 // local utility routines
54 namespace local {
56 Prototype *construct_block(::FLAC__StreamMetadata *object)
58 Prototype *ret = 0;
59 switch(object->type) {
60 case FLAC__METADATA_TYPE_STREAMINFO:
61 ret = new StreamInfo(object, /*copy=*/false);
62 break;
63 case FLAC__METADATA_TYPE_PADDING:
64 ret = new Padding(object, /*copy=*/false);
65 break;
66 case FLAC__METADATA_TYPE_APPLICATION:
67 ret = new Application(object, /*copy=*/false);
68 break;
69 case FLAC__METADATA_TYPE_SEEKTABLE:
70 ret = new SeekTable(object, /*copy=*/false);
71 break;
72 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
73 ret = new VorbisComment(object, /*copy=*/false);
74 break;
75 case FLAC__METADATA_TYPE_CUESHEET:
76 ret = new CueSheet(object, /*copy=*/false);
77 break;
78 case FLAC__METADATA_TYPE_PICTURE:
79 ret = new Picture(object, /*copy=*/false);
80 break;
81 default:
82 ret = new Unknown(object, /*copy=*/false);
83 break;
85 return ret;
90 FLACPP_API Prototype *clone(const Prototype *object)
92 FLAC__ASSERT(0 != object);
94 const StreamInfo *streaminfo = dynamic_cast<const StreamInfo *>(object);
95 const Padding *padding = dynamic_cast<const Padding *>(object);
96 const Application *application = dynamic_cast<const Application *>(object);
97 const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
98 const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
99 const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object);
100 const Picture *picture = dynamic_cast<const Picture *>(object);
101 const Unknown *unknown = dynamic_cast<const Unknown *>(object);
103 if(0 != streaminfo)
104 return new StreamInfo(*streaminfo);
105 else if(0 != padding)
106 return new Padding(*padding);
107 else if(0 != application)
108 return new Application(*application);
109 else if(0 != seektable)
110 return new SeekTable(*seektable);
111 else if(0 != vorbiscomment)
112 return new VorbisComment(*vorbiscomment);
113 else if(0 != cuesheet)
114 return new CueSheet(*cuesheet);
115 else if(0 != picture)
116 return new Picture(*picture);
117 else if(0 != unknown)
118 return new Unknown(*unknown);
119 else {
120 FLAC__ASSERT(0);
121 return 0;
126 // Prototype
129 Prototype::Prototype(const Prototype &object):
130 object_(::FLAC__metadata_object_clone(object.object_)),
131 is_reference_(false)
133 FLAC__ASSERT(object.is_valid());
136 Prototype::Prototype(const ::FLAC__StreamMetadata &object):
137 object_(::FLAC__metadata_object_clone(&object)),
138 is_reference_(false)
142 Prototype::Prototype(const ::FLAC__StreamMetadata *object):
143 object_(::FLAC__metadata_object_clone(object)),
144 is_reference_(false)
146 FLAC__ASSERT(0 != object);
149 Prototype::Prototype(::FLAC__StreamMetadata *object, bool copy):
150 object_(copy? ::FLAC__metadata_object_clone(object) : object),
151 is_reference_(false)
153 FLAC__ASSERT(0 != object);
156 Prototype::~Prototype()
158 clear();
161 void Prototype::clear()
163 if(0 != object_ && !is_reference_)
164 FLAC__metadata_object_delete(object_);
165 object_ = 0;
168 Prototype &Prototype::operator=(const Prototype &object)
170 FLAC__ASSERT(object.is_valid());
171 clear();
172 is_reference_ = false;
173 object_ = ::FLAC__metadata_object_clone(object.object_);
174 return *this;
177 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata &object)
179 clear();
180 is_reference_ = false;
181 object_ = ::FLAC__metadata_object_clone(&object);
182 return *this;
185 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata *object)
187 FLAC__ASSERT(0 != object);
188 clear();
189 is_reference_ = false;
190 object_ = ::FLAC__metadata_object_clone(object);
191 return *this;
194 Prototype &Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy)
196 FLAC__ASSERT(0 != object);
197 clear();
198 object_ = (copy? ::FLAC__metadata_object_clone(object) : object);
199 is_reference_ = false;
200 return *this;
203 bool Prototype::get_is_last() const
205 FLAC__ASSERT(is_valid());
206 return (bool)object_->is_last;
209 FLAC__MetadataType Prototype::get_type() const
211 FLAC__ASSERT(is_valid());
212 return object_->type;
215 unsigned Prototype::get_length() const
217 FLAC__ASSERT(is_valid());
218 return object_->length;
221 void Prototype::set_is_last(bool value)
223 FLAC__ASSERT(is_valid());
224 object_->is_last = value;
229 // StreamInfo
232 StreamInfo::StreamInfo():
233 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false)
236 StreamInfo::~StreamInfo()
239 unsigned StreamInfo::get_min_blocksize() const
241 FLAC__ASSERT(is_valid());
242 return object_->data.stream_info.min_blocksize;
245 unsigned StreamInfo::get_max_blocksize() const
247 FLAC__ASSERT(is_valid());
248 return object_->data.stream_info.max_blocksize;
251 unsigned StreamInfo::get_min_framesize() const
253 FLAC__ASSERT(is_valid());
254 return object_->data.stream_info.min_framesize;
257 unsigned StreamInfo::get_max_framesize() const
259 FLAC__ASSERT(is_valid());
260 return object_->data.stream_info.max_framesize;
263 unsigned StreamInfo::get_sample_rate() const
265 FLAC__ASSERT(is_valid());
266 return object_->data.stream_info.sample_rate;
269 unsigned StreamInfo::get_channels() const
271 FLAC__ASSERT(is_valid());
272 return object_->data.stream_info.channels;
275 unsigned StreamInfo::get_bits_per_sample() const
277 FLAC__ASSERT(is_valid());
278 return object_->data.stream_info.bits_per_sample;
281 FLAC__uint64 StreamInfo::get_total_samples() const
283 FLAC__ASSERT(is_valid());
284 return object_->data.stream_info.total_samples;
287 const FLAC__byte *StreamInfo::get_md5sum() const
289 FLAC__ASSERT(is_valid());
290 return object_->data.stream_info.md5sum;
293 void StreamInfo::set_min_blocksize(unsigned value)
295 FLAC__ASSERT(is_valid());
296 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
297 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
298 object_->data.stream_info.min_blocksize = value;
301 void StreamInfo::set_max_blocksize(unsigned value)
303 FLAC__ASSERT(is_valid());
304 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
305 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
306 object_->data.stream_info.max_blocksize = value;
309 void StreamInfo::set_min_framesize(unsigned value)
311 FLAC__ASSERT(is_valid());
312 FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
313 object_->data.stream_info.min_framesize = value;
316 void StreamInfo::set_max_framesize(unsigned value)
318 FLAC__ASSERT(is_valid());
319 FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
320 object_->data.stream_info.max_framesize = value;
323 void StreamInfo::set_sample_rate(unsigned value)
325 FLAC__ASSERT(is_valid());
326 FLAC__ASSERT(FLAC__format_sample_rate_is_valid(value));
327 object_->data.stream_info.sample_rate = value;
330 void StreamInfo::set_channels(unsigned value)
332 FLAC__ASSERT(is_valid());
333 FLAC__ASSERT(value > 0);
334 FLAC__ASSERT(value <= FLAC__MAX_CHANNELS);
335 object_->data.stream_info.channels = value;
338 void StreamInfo::set_bits_per_sample(unsigned value)
340 FLAC__ASSERT(is_valid());
341 FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE);
342 FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE);
343 object_->data.stream_info.bits_per_sample = value;
346 void StreamInfo::set_total_samples(FLAC__uint64 value)
348 FLAC__ASSERT(is_valid());
349 FLAC__ASSERT(value < (((FLAC__uint64)1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
350 object_->data.stream_info.total_samples = value;
353 void StreamInfo::set_md5sum(const FLAC__byte value[16])
355 FLAC__ASSERT(is_valid());
356 FLAC__ASSERT(0 != value);
357 memcpy(object_->data.stream_info.md5sum, value, 16);
362 // Padding
365 Padding::Padding():
366 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
369 Padding::Padding(unsigned length):
370 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
372 set_length(length);
375 Padding::~Padding()
378 void Padding::set_length(unsigned length)
380 FLAC__ASSERT(is_valid());
381 object_->length = length;
386 // Application
389 Application::Application():
390 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
393 Application::~Application()
396 const FLAC__byte *Application::get_id() const
398 FLAC__ASSERT(is_valid());
399 return object_->data.application.id;
402 const FLAC__byte *Application::get_data() const
404 FLAC__ASSERT(is_valid());
405 return object_->data.application.data;
408 void Application::set_id(const FLAC__byte value[4])
410 FLAC__ASSERT(is_valid());
411 FLAC__ASSERT(0 != value);
412 memcpy(object_->data.application.id, value, 4);
415 bool Application::set_data(const FLAC__byte *data, unsigned length)
417 FLAC__ASSERT(is_valid());
418 return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
421 bool Application::set_data(FLAC__byte *data, unsigned length, bool copy)
423 FLAC__ASSERT(is_valid());
424 return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
429 // SeekTable
432 SeekTable::SeekTable():
433 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false)
436 SeekTable::~SeekTable()
439 unsigned SeekTable::get_num_points() const
441 FLAC__ASSERT(is_valid());
442 return object_->data.seek_table.num_points;
445 ::FLAC__StreamMetadata_SeekPoint SeekTable::get_point(unsigned indx) const
447 FLAC__ASSERT(is_valid());
448 FLAC__ASSERT(indx < object_->data.seek_table.num_points);
449 return object_->data.seek_table.points[indx];
452 bool SeekTable::resize_points(unsigned new_num_points)
454 FLAC__ASSERT(is_valid());
455 return (bool)::FLAC__metadata_object_seektable_resize_points(object_, new_num_points);
458 void SeekTable::set_point(unsigned indx, const ::FLAC__StreamMetadata_SeekPoint &point)
460 FLAC__ASSERT(is_valid());
461 FLAC__ASSERT(indx < object_->data.seek_table.num_points);
462 ::FLAC__metadata_object_seektable_set_point(object_, indx, point);
465 bool SeekTable::insert_point(unsigned indx, const ::FLAC__StreamMetadata_SeekPoint &point)
467 FLAC__ASSERT(is_valid());
468 FLAC__ASSERT(indx <= object_->data.seek_table.num_points);
469 return (bool)::FLAC__metadata_object_seektable_insert_point(object_, indx, point);
472 bool SeekTable::delete_point(unsigned indx)
474 FLAC__ASSERT(is_valid());
475 FLAC__ASSERT(indx < object_->data.seek_table.num_points);
476 return (bool)::FLAC__metadata_object_seektable_delete_point(object_, indx);
479 bool SeekTable::is_legal() const
481 FLAC__ASSERT(is_valid());
482 return (bool)::FLAC__metadata_object_seektable_is_legal(object_);
485 bool SeekTable::template_append_placeholders(unsigned num)
487 FLAC__ASSERT(is_valid());
488 return (bool)::FLAC__metadata_object_seektable_template_append_placeholders(object_, num);
491 bool SeekTable::template_append_point(FLAC__uint64 sample_number)
493 FLAC__ASSERT(is_valid());
494 return (bool)::FLAC__metadata_object_seektable_template_append_point(object_, sample_number);
497 bool SeekTable::template_append_points(FLAC__uint64 sample_numbers[], unsigned num)
499 FLAC__ASSERT(is_valid());
500 return (bool)::FLAC__metadata_object_seektable_template_append_points(object_, sample_numbers, num);
503 bool SeekTable::template_append_spaced_points(unsigned num, FLAC__uint64 total_samples)
505 FLAC__ASSERT(is_valid());
506 return (bool)::FLAC__metadata_object_seektable_template_append_spaced_points(object_, num, total_samples);
509 bool SeekTable::template_append_spaced_points_by_samples(unsigned samples, FLAC__uint64 total_samples)
511 FLAC__ASSERT(is_valid());
512 return (bool)::FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(object_, samples, total_samples);
515 bool SeekTable::template_sort(bool compact)
517 FLAC__ASSERT(is_valid());
518 return (bool)::FLAC__metadata_object_seektable_template_sort(object_, compact);
523 // VorbisComment::Entry
526 VorbisComment::Entry::Entry() :
527 is_valid_(true),
528 entry_(),
529 field_name_(0),
530 field_name_length_(0),
531 field_value_(0),
532 field_value_length_(0)
534 zero();
537 VorbisComment::Entry::Entry(const char *field, unsigned field_length) :
538 is_valid_(true),
539 entry_(),
540 field_name_(0),
541 field_name_length_(0),
542 field_value_(0),
543 field_value_length_(0)
545 zero();
546 construct(field, field_length);
549 VorbisComment::Entry::Entry(const char *field) :
550 is_valid_(true),
551 entry_(),
552 field_name_(0),
553 field_name_length_(0),
554 field_value_(0),
555 field_value_length_(0)
557 zero();
558 construct(field);
561 VorbisComment::Entry::Entry(const char *field_name, const char *field_value, unsigned field_value_length) :
562 is_valid_(true),
563 entry_(),
564 field_name_(0),
565 field_name_length_(0),
566 field_value_(0),
567 field_value_length_(0)
569 zero();
570 construct(field_name, field_value, field_value_length);
573 VorbisComment::Entry::Entry(const char *field_name, const char *field_value) :
574 is_valid_(true),
575 entry_(),
576 field_name_(0),
577 field_name_length_(0),
578 field_value_(0),
579 field_value_length_(0)
581 zero();
582 construct(field_name, field_value);
585 VorbisComment::Entry::Entry(const Entry &entry) :
586 is_valid_(true),
587 entry_(),
588 field_name_(0),
589 field_name_length_(0),
590 field_value_(0),
591 field_value_length_(0)
593 FLAC__ASSERT(entry.is_valid());
594 zero();
595 construct((const char *)entry.entry_.entry, entry.entry_.length);
598 VorbisComment::Entry &VorbisComment::Entry::operator=(const Entry &entry)
600 FLAC__ASSERT(entry.is_valid());
601 clear();
602 construct((const char *)entry.entry_.entry, entry.entry_.length);
603 return *this;
606 VorbisComment::Entry::~Entry()
608 clear();
611 bool VorbisComment::Entry::is_valid() const
613 return is_valid_;
616 unsigned VorbisComment::Entry::get_field_length() const
618 FLAC__ASSERT(is_valid());
619 return entry_.length;
622 unsigned VorbisComment::Entry::get_field_name_length() const
624 FLAC__ASSERT(is_valid());
625 return field_name_length_;
628 unsigned VorbisComment::Entry::get_field_value_length() const
630 FLAC__ASSERT(is_valid());
631 return field_value_length_;
634 ::FLAC__StreamMetadata_VorbisComment_Entry VorbisComment::Entry::get_entry() const
636 FLAC__ASSERT(is_valid());
637 return entry_;
640 const char *VorbisComment::Entry::get_field() const
642 FLAC__ASSERT(is_valid());
643 return (const char *)entry_.entry;
646 const char *VorbisComment::Entry::get_field_name() const
648 FLAC__ASSERT(is_valid());
649 return field_name_;
652 const char *VorbisComment::Entry::get_field_value() const
654 FLAC__ASSERT(is_valid());
655 return field_value_;
658 bool VorbisComment::Entry::set_field(const char *field, unsigned field_length)
660 FLAC__ASSERT(is_valid());
661 FLAC__ASSERT(0 != field);
663 if(!::FLAC__format_vorbiscomment_entry_is_legal((const ::FLAC__byte*)field, field_length))
664 return is_valid_ = false;
666 clear_entry();
668 if(0 == (entry_.entry = (FLAC__byte*)safe_malloc_add_2op_(field_length, /*+*/1))) {
669 is_valid_ = false;
671 else {
672 entry_.length = field_length;
673 memcpy(entry_.entry, field, field_length);
674 entry_.entry[field_length] = '\0';
675 (void) parse_field();
678 return is_valid_;
681 bool VorbisComment::Entry::set_field(const char *field)
683 return set_field(field, strlen(field));
686 bool VorbisComment::Entry::set_field_name(const char *field_name)
688 FLAC__ASSERT(is_valid());
689 FLAC__ASSERT(0 != field_name);
691 if(!::FLAC__format_vorbiscomment_entry_name_is_legal(field_name))
692 return is_valid_ = false;
694 clear_field_name();
696 if(0 == (field_name_ = strdup(field_name))) {
697 is_valid_ = false;
699 else {
700 field_name_length_ = strlen(field_name_);
701 compose_field();
704 return is_valid_;
707 bool VorbisComment::Entry::set_field_value(const char *field_value, unsigned field_value_length)
709 FLAC__ASSERT(is_valid());
710 FLAC__ASSERT(0 != field_value);
712 if(!::FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte*)field_value, field_value_length))
713 return is_valid_ = false;
715 clear_field_value();
717 if(0 == (field_value_ = (char *)safe_malloc_add_2op_(field_value_length, /*+*/1))) {
718 is_valid_ = false;
720 else {
721 field_value_length_ = field_value_length;
722 memcpy(field_value_, field_value, field_value_length);
723 field_value_[field_value_length] = '\0';
724 compose_field();
727 return is_valid_;
730 bool VorbisComment::Entry::set_field_value(const char *field_value)
732 return set_field_value(field_value, strlen(field_value));
735 void VorbisComment::Entry::zero()
737 is_valid_ = true;
738 entry_.length = 0;
739 entry_.entry = 0;
740 field_name_ = 0;
741 field_name_length_ = 0;
742 field_value_ = 0;
743 field_value_length_ = 0;
746 void VorbisComment::Entry::clear()
748 clear_entry();
749 clear_field_name();
750 clear_field_value();
751 is_valid_ = true;
754 void VorbisComment::Entry::clear_entry()
756 if(0 != entry_.entry) {
757 free(entry_.entry);
758 entry_.entry = 0;
759 entry_.length = 0;
763 void VorbisComment::Entry::clear_field_name()
765 if(0 != field_name_) {
766 free(field_name_);
767 field_name_ = 0;
768 field_name_length_ = 0;
772 void VorbisComment::Entry::clear_field_value()
774 if(0 != field_value_) {
775 free(field_value_);
776 field_value_ = 0;
777 field_value_length_ = 0;
781 void VorbisComment::Entry::construct(const char *field, unsigned field_length)
783 if(set_field(field, field_length))
784 parse_field();
787 void VorbisComment::Entry::construct(const char *field)
789 construct(field, strlen(field));
792 void VorbisComment::Entry::construct(const char *field_name, const char *field_value, unsigned field_value_length)
794 if(set_field_name(field_name) && set_field_value(field_value, field_value_length))
795 compose_field();
798 void VorbisComment::Entry::construct(const char *field_name, const char *field_value)
800 construct(field_name, field_value, strlen(field_value));
803 void VorbisComment::Entry::compose_field()
805 clear_entry();
807 if(0 == (entry_.entry = (FLAC__byte*)safe_malloc_add_4op_(field_name_length_, /*+*/1, /*+*/field_value_length_, /*+*/1))) {
808 is_valid_ = false;
810 else {
811 memcpy(entry_.entry, field_name_, field_name_length_);
812 entry_.length += field_name_length_;
813 memcpy(entry_.entry + entry_.length, "=", 1);
814 entry_.length += 1;
815 memcpy(entry_.entry + entry_.length, field_value_, field_value_length_);
816 entry_.length += field_value_length_;
817 entry_.entry[entry_.length] = '\0';
818 is_valid_ = true;
822 void VorbisComment::Entry::parse_field()
824 clear_field_name();
825 clear_field_value();
827 const char *p = (const char *)memchr(entry_.entry, '=', entry_.length);
829 if(0 == p)
830 p = (const char *)entry_.entry + entry_.length;
832 field_name_length_ = (unsigned)(p - (const char *)entry_.entry);
833 if(0 == (field_name_ = (char *)safe_malloc_add_2op_(field_name_length_, /*+*/1))) { // +1 for the trailing \0
834 is_valid_ = false;
835 return;
837 memcpy(field_name_, entry_.entry, field_name_length_);
838 field_name_[field_name_length_] = '\0';
840 if(entry_.length - field_name_length_ == 0) {
841 field_value_length_ = 0;
842 if(0 == (field_value_ = (char *)safe_malloc_(0))) {
843 is_valid_ = false;
844 return;
847 else {
848 field_value_length_ = entry_.length - field_name_length_ - 1;
849 if(0 == (field_value_ = (char *)safe_malloc_add_2op_(field_value_length_, /*+*/1))) { // +1 for the trailing \0
850 is_valid_ = false;
851 return;
853 memcpy(field_value_, ++p, field_value_length_);
854 field_value_[field_value_length_] = '\0';
857 is_valid_ = true;
862 // VorbisComment
865 VorbisComment::VorbisComment():
866 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false)
869 VorbisComment::~VorbisComment()
872 unsigned VorbisComment::get_num_comments() const
874 FLAC__ASSERT(is_valid());
875 return object_->data.vorbis_comment.num_comments;
878 const FLAC__byte *VorbisComment::get_vendor_string() const
880 FLAC__ASSERT(is_valid());
881 return object_->data.vorbis_comment.vendor_string.entry;
884 VorbisComment::Entry VorbisComment::get_comment(unsigned indx) const
886 FLAC__ASSERT(is_valid());
887 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments);
888 return Entry((const char *)object_->data.vorbis_comment.comments[indx].entry, object_->data.vorbis_comment.comments[indx].length);
891 bool VorbisComment::set_vendor_string(const FLAC__byte *string)
893 FLAC__ASSERT(is_valid());
894 // vendor_string is a special kind of entry
895 const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { static_cast<FLAC__uint32>(strlen((const char *)string)), (FLAC__byte*)string }; // we can cheat on const-ness because we make a copy below:
896 return (bool)::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true);
899 bool VorbisComment::resize_comments(unsigned new_num_comments)
901 FLAC__ASSERT(is_valid());
902 return (bool)::FLAC__metadata_object_vorbiscomment_resize_comments(object_, new_num_comments);
905 bool VorbisComment::set_comment(unsigned indx, const VorbisComment::Entry &entry)
907 FLAC__ASSERT(is_valid());
908 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments);
909 return (bool)::FLAC__metadata_object_vorbiscomment_set_comment(object_, indx, entry.get_entry(), /*copy=*/true);
912 bool VorbisComment::insert_comment(unsigned indx, const VorbisComment::Entry &entry)
914 FLAC__ASSERT(is_valid());
915 FLAC__ASSERT(indx <= object_->data.vorbis_comment.num_comments);
916 return (bool)::FLAC__metadata_object_vorbiscomment_insert_comment(object_, indx, entry.get_entry(), /*copy=*/true);
919 bool VorbisComment::append_comment(const VorbisComment::Entry &entry)
921 FLAC__ASSERT(is_valid());
922 return (bool)::FLAC__metadata_object_vorbiscomment_append_comment(object_, entry.get_entry(), /*copy=*/true);
925 bool VorbisComment::replace_comment(const VorbisComment::Entry &entry, bool all)
927 FLAC__ASSERT(is_valid());
928 return (bool)::FLAC__metadata_object_vorbiscomment_replace_comment(object_, entry.get_entry(), all, /*copy=*/true);
931 bool VorbisComment::delete_comment(unsigned indx)
933 FLAC__ASSERT(is_valid());
934 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments);
935 return (bool)::FLAC__metadata_object_vorbiscomment_delete_comment(object_, indx);
938 int VorbisComment::find_entry_from(unsigned offset, const char *field_name)
940 FLAC__ASSERT(is_valid());
941 return ::FLAC__metadata_object_vorbiscomment_find_entry_from(object_, offset, field_name);
944 int VorbisComment::remove_entry_matching(const char *field_name)
946 FLAC__ASSERT(is_valid());
947 return ::FLAC__metadata_object_vorbiscomment_remove_entry_matching(object_, field_name);
950 int VorbisComment::remove_entries_matching(const char *field_name)
952 FLAC__ASSERT(is_valid());
953 return ::FLAC__metadata_object_vorbiscomment_remove_entries_matching(object_, field_name);
958 // CueSheet::Track
961 CueSheet::Track::Track():
962 object_(::FLAC__metadata_object_cuesheet_track_new())
965 CueSheet::Track::Track(const ::FLAC__StreamMetadata_CueSheet_Track *track):
966 object_(::FLAC__metadata_object_cuesheet_track_clone(track))
969 CueSheet::Track::Track(const Track &track):
970 object_(::FLAC__metadata_object_cuesheet_track_clone(track.object_))
973 CueSheet::Track &CueSheet::Track::operator=(const Track &track)
975 if(0 != object_)
976 ::FLAC__metadata_object_cuesheet_track_delete(object_);
977 object_ = ::FLAC__metadata_object_cuesheet_track_clone(track.object_);
978 return *this;
981 CueSheet::Track::~Track()
983 if(0 != object_)
984 ::FLAC__metadata_object_cuesheet_track_delete(object_);
987 bool CueSheet::Track::is_valid() const
989 return(0 != object_);
992 ::FLAC__StreamMetadata_CueSheet_Index CueSheet::Track::get_index(unsigned i) const
994 FLAC__ASSERT(is_valid());
995 FLAC__ASSERT(i < object_->num_indices);
996 return object_->indices[i];
999 void CueSheet::Track::set_isrc(const char value[12])
1001 FLAC__ASSERT(is_valid());
1002 FLAC__ASSERT(0 != value);
1003 memcpy(object_->isrc, value, 12);
1004 object_->isrc[12] = '\0';
1007 void CueSheet::Track::set_type(unsigned value)
1009 FLAC__ASSERT(is_valid());
1010 FLAC__ASSERT(value <= 1);
1011 object_->type = value;
1014 void CueSheet::Track::set_index(unsigned i, const ::FLAC__StreamMetadata_CueSheet_Index &indx)
1016 FLAC__ASSERT(is_valid());
1017 FLAC__ASSERT(i < object_->num_indices);
1018 object_->indices[i] = indx;
1023 // CueSheet
1026 CueSheet::CueSheet():
1027 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET), /*copy=*/false)
1030 CueSheet::~CueSheet()
1033 const char *CueSheet::get_media_catalog_number() const
1035 FLAC__ASSERT(is_valid());
1036 return object_->data.cue_sheet.media_catalog_number;
1039 FLAC__uint64 CueSheet::get_lead_in() const
1041 FLAC__ASSERT(is_valid());
1042 return object_->data.cue_sheet.lead_in;
1045 bool CueSheet::get_is_cd() const
1047 FLAC__ASSERT(is_valid());
1048 return object_->data.cue_sheet.is_cd? true : false;
1051 unsigned CueSheet::get_num_tracks() const
1053 FLAC__ASSERT(is_valid());
1054 return object_->data.cue_sheet.num_tracks;
1057 CueSheet::Track CueSheet::get_track(unsigned i) const
1059 FLAC__ASSERT(is_valid());
1060 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
1061 return Track(object_->data.cue_sheet.tracks + i);
1064 void CueSheet::set_media_catalog_number(const char value[128])
1066 FLAC__ASSERT(is_valid());
1067 FLAC__ASSERT(0 != value);
1068 memcpy(object_->data.cue_sheet.media_catalog_number, value, 128);
1069 object_->data.cue_sheet.media_catalog_number[128] = '\0';
1072 void CueSheet::set_lead_in(FLAC__uint64 value)
1074 FLAC__ASSERT(is_valid());
1075 object_->data.cue_sheet.lead_in = value;
1078 void CueSheet::set_is_cd(bool value)
1080 FLAC__ASSERT(is_valid());
1081 object_->data.cue_sheet.is_cd = value;
1084 void CueSheet::set_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &indx)
1086 FLAC__ASSERT(is_valid());
1087 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
1088 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
1089 object_->data.cue_sheet.tracks[track_num].indices[index_num] = indx;
1092 bool CueSheet::resize_indices(unsigned track_num, unsigned new_num_indices)
1094 FLAC__ASSERT(is_valid());
1095 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
1096 return (bool)::FLAC__metadata_object_cuesheet_track_resize_indices(object_, track_num, new_num_indices);
1099 bool CueSheet::insert_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &indx)
1101 FLAC__ASSERT(is_valid());
1102 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
1103 FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices);
1104 return (bool)::FLAC__metadata_object_cuesheet_track_insert_index(object_, track_num, index_num, indx);
1107 bool CueSheet::insert_blank_index(unsigned track_num, unsigned index_num)
1109 FLAC__ASSERT(is_valid());
1110 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
1111 FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices);
1112 return (bool)::FLAC__metadata_object_cuesheet_track_insert_blank_index(object_, track_num, index_num);
1115 bool CueSheet::delete_index(unsigned track_num, unsigned index_num)
1117 FLAC__ASSERT(is_valid());
1118 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
1119 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
1120 return (bool)::FLAC__metadata_object_cuesheet_track_delete_index(object_, track_num, index_num);
1123 bool CueSheet::resize_tracks(unsigned new_num_tracks)
1125 FLAC__ASSERT(is_valid());
1126 return (bool)::FLAC__metadata_object_cuesheet_resize_tracks(object_, new_num_tracks);
1129 bool CueSheet::set_track(unsigned i, const CueSheet::Track &track)
1131 FLAC__ASSERT(is_valid());
1132 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
1133 // We can safely const_cast since copy=true
1134 return (bool)::FLAC__metadata_object_cuesheet_set_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
1137 bool CueSheet::insert_track(unsigned i, const CueSheet::Track &track)
1139 FLAC__ASSERT(is_valid());
1140 FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks);
1141 // We can safely const_cast since copy=true
1142 return (bool)::FLAC__metadata_object_cuesheet_insert_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
1145 bool CueSheet::insert_blank_track(unsigned i)
1147 FLAC__ASSERT(is_valid());
1148 FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks);
1149 return (bool)::FLAC__metadata_object_cuesheet_insert_blank_track(object_, i);
1152 bool CueSheet::delete_track(unsigned i)
1154 FLAC__ASSERT(is_valid());
1155 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
1156 return (bool)::FLAC__metadata_object_cuesheet_delete_track(object_, i);
1159 bool CueSheet::is_legal(bool check_cd_da_subset, const char **violation) const
1161 FLAC__ASSERT(is_valid());
1162 return (bool)::FLAC__metadata_object_cuesheet_is_legal(object_, check_cd_da_subset, violation);
1165 FLAC__uint32 CueSheet::calculate_cddb_id() const
1167 FLAC__ASSERT(is_valid());
1168 return ::FLAC__metadata_object_cuesheet_calculate_cddb_id(object_);
1173 // Picture
1176 Picture::Picture():
1177 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE), /*copy=*/false)
1180 Picture::~Picture()
1183 ::FLAC__StreamMetadata_Picture_Type Picture::get_type() const
1185 FLAC__ASSERT(is_valid());
1186 return object_->data.picture.type;
1189 const char *Picture::get_mime_type() const
1191 FLAC__ASSERT(is_valid());
1192 return object_->data.picture.mime_type;
1195 const FLAC__byte *Picture::get_description() const
1197 FLAC__ASSERT(is_valid());
1198 return object_->data.picture.description;
1201 FLAC__uint32 Picture::get_width() const
1203 FLAC__ASSERT(is_valid());
1204 return object_->data.picture.width;
1207 FLAC__uint32 Picture::get_height() const
1209 FLAC__ASSERT(is_valid());
1210 return object_->data.picture.height;
1213 FLAC__uint32 Picture::get_depth() const
1215 FLAC__ASSERT(is_valid());
1216 return object_->data.picture.depth;
1219 FLAC__uint32 Picture::get_colors() const
1221 FLAC__ASSERT(is_valid());
1222 return object_->data.picture.colors;
1225 FLAC__uint32 Picture::get_data_length() const
1227 FLAC__ASSERT(is_valid());
1228 return object_->data.picture.data_length;
1231 const FLAC__byte *Picture::get_data() const
1233 FLAC__ASSERT(is_valid());
1234 return object_->data.picture.data;
1237 void Picture::set_type(::FLAC__StreamMetadata_Picture_Type type)
1239 FLAC__ASSERT(is_valid());
1240 object_->data.picture.type = type;
1243 bool Picture::set_mime_type(const char *string)
1245 FLAC__ASSERT(is_valid());
1246 // We can safely const_cast since copy=true
1247 return (bool)::FLAC__metadata_object_picture_set_mime_type(object_, const_cast<char*>(string), /*copy=*/true);
1250 bool Picture::set_description(const FLAC__byte *string)
1252 FLAC__ASSERT(is_valid());
1253 // We can safely const_cast since copy=true
1254 return (bool)::FLAC__metadata_object_picture_set_description(object_, const_cast<FLAC__byte*>(string), /*copy=*/true);
1257 void Picture::set_width(FLAC__uint32 value) const
1259 FLAC__ASSERT(is_valid());
1260 object_->data.picture.width = value;
1263 void Picture::set_height(FLAC__uint32 value) const
1265 FLAC__ASSERT(is_valid());
1266 object_->data.picture.height = value;
1269 void Picture::set_depth(FLAC__uint32 value) const
1271 FLAC__ASSERT(is_valid());
1272 object_->data.picture.depth = value;
1275 void Picture::set_colors(FLAC__uint32 value) const
1277 FLAC__ASSERT(is_valid());
1278 object_->data.picture.colors = value;
1281 bool Picture::set_data(const FLAC__byte *data, FLAC__uint32 data_length)
1283 FLAC__ASSERT(is_valid());
1284 // We can safely const_cast since copy=true
1285 return (bool)::FLAC__metadata_object_picture_set_data(object_, const_cast<FLAC__byte*>(data), data_length, /*copy=*/true);
1288 bool Picture::is_legal(const char **violation)
1290 FLAC__ASSERT(is_valid());
1291 return (bool)::FLAC__metadata_object_picture_is_legal(object_, violation);
1296 // Unknown
1299 Unknown::Unknown():
1300 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
1303 Unknown::~Unknown()
1306 const FLAC__byte *Unknown::get_data() const
1308 FLAC__ASSERT(is_valid());
1309 return object_->data.application.data;
1312 bool Unknown::set_data(const FLAC__byte *data, unsigned length)
1314 FLAC__ASSERT(is_valid());
1315 return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
1318 bool Unknown::set_data(FLAC__byte *data, unsigned length, bool copy)
1320 FLAC__ASSERT(is_valid());
1321 return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
1325 // ============================================================
1327 // Level 0
1329 // ============================================================
1331 FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo)
1333 FLAC__ASSERT(0 != filename);
1335 ::FLAC__StreamMetadata object;
1337 if(::FLAC__metadata_get_streaminfo(filename, &object)) {
1338 streaminfo = object;
1339 return true;
1341 else
1342 return false;
1345 FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags)
1347 FLAC__ASSERT(0 != filename);
1349 ::FLAC__StreamMetadata *object;
1351 tags = 0;
1353 if(::FLAC__metadata_get_tags(filename, &object)) {
1354 tags = new VorbisComment(object, /*copy=*/false);
1355 return true;
1357 else
1358 return false;
1361 FLACPP_API bool get_tags(const char *filename, VorbisComment &tags)
1363 FLAC__ASSERT(0 != filename);
1365 ::FLAC__StreamMetadata *object;
1367 if(::FLAC__metadata_get_tags(filename, &object)) {
1368 tags.assign(object, /*copy=*/false);
1369 return true;
1371 else
1372 return false;
1375 FLACPP_API bool get_cuesheet(const char *filename, CueSheet *&cuesheet)
1377 FLAC__ASSERT(0 != filename);
1379 ::FLAC__StreamMetadata *object;
1381 cuesheet = 0;
1383 if(::FLAC__metadata_get_cuesheet(filename, &object)) {
1384 cuesheet = new CueSheet(object, /*copy=*/false);
1385 return true;
1387 else
1388 return false;
1391 FLACPP_API bool get_cuesheet(const char *filename, CueSheet &cuesheet)
1393 FLAC__ASSERT(0 != filename);
1395 ::FLAC__StreamMetadata *object;
1397 if(::FLAC__metadata_get_cuesheet(filename, &object)) {
1398 cuesheet.assign(object, /*copy=*/false);
1399 return true;
1401 else
1402 return false;
1405 FLACPP_API bool get_picture(const char *filename, Picture *&picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors)
1407 FLAC__ASSERT(0 != filename);
1409 ::FLAC__StreamMetadata *object;
1411 picture = 0;
1413 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) {
1414 picture = new Picture(object, /*copy=*/false);
1415 return true;
1417 else
1418 return false;
1421 FLACPP_API bool get_picture(const char *filename, Picture &picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors)
1423 FLAC__ASSERT(0 != filename);
1425 ::FLAC__StreamMetadata *object;
1427 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) {
1428 picture.assign(object, /*copy=*/false);
1429 return true;
1431 else
1432 return false;
1436 // ============================================================
1438 // Level 1
1440 // ============================================================
1442 SimpleIterator::SimpleIterator():
1443 iterator_(::FLAC__metadata_simple_iterator_new())
1446 SimpleIterator::~SimpleIterator()
1448 clear();
1451 void SimpleIterator::clear()
1453 if(0 != iterator_)
1454 FLAC__metadata_simple_iterator_delete(iterator_);
1455 iterator_ = 0;
1458 bool SimpleIterator::init(const char *filename, bool read_only, bool preserve_file_stats)
1460 FLAC__ASSERT(0 != filename);
1461 FLAC__ASSERT(is_valid());
1462 return (bool)::FLAC__metadata_simple_iterator_init(iterator_, filename, read_only, preserve_file_stats);
1465 bool SimpleIterator::is_valid() const
1467 return 0 != iterator_;
1470 SimpleIterator::Status SimpleIterator::status()
1472 FLAC__ASSERT(is_valid());
1473 return Status(::FLAC__metadata_simple_iterator_status(iterator_));
1476 bool SimpleIterator::is_writable() const
1478 FLAC__ASSERT(is_valid());
1479 return (bool)::FLAC__metadata_simple_iterator_is_writable(iterator_);
1482 bool SimpleIterator::next()
1484 FLAC__ASSERT(is_valid());
1485 return (bool)::FLAC__metadata_simple_iterator_next(iterator_);
1488 bool SimpleIterator::prev()
1490 FLAC__ASSERT(is_valid());
1491 return (bool)::FLAC__metadata_simple_iterator_prev(iterator_);
1494 //@@@@ add to tests
1495 bool SimpleIterator::is_last() const
1497 FLAC__ASSERT(is_valid());
1498 return (bool)::FLAC__metadata_simple_iterator_is_last(iterator_);
1501 //@@@@ add to tests
1502 off_t SimpleIterator::get_block_offset() const
1504 FLAC__ASSERT(is_valid());
1505 return ::FLAC__metadata_simple_iterator_get_block_offset(iterator_);
1508 ::FLAC__MetadataType SimpleIterator::get_block_type() const
1510 FLAC__ASSERT(is_valid());
1511 return ::FLAC__metadata_simple_iterator_get_block_type(iterator_);
1514 //@@@@ add to tests
1515 unsigned SimpleIterator::get_block_length() const
1517 FLAC__ASSERT(is_valid());
1518 return ::FLAC__metadata_simple_iterator_get_block_length(iterator_);
1521 //@@@@ add to tests
1522 bool SimpleIterator::get_application_id(FLAC__byte *id)
1524 FLAC__ASSERT(is_valid());
1525 return (bool)::FLAC__metadata_simple_iterator_get_application_id(iterator_, id);
1528 Prototype *SimpleIterator::get_block()
1530 FLAC__ASSERT(is_valid());
1531 return local::construct_block(::FLAC__metadata_simple_iterator_get_block(iterator_));
1534 bool SimpleIterator::set_block(Prototype *block, bool use_padding)
1536 FLAC__ASSERT(0 != block);
1537 FLAC__ASSERT(is_valid());
1538 return (bool)::FLAC__metadata_simple_iterator_set_block(iterator_, block->object_, use_padding);
1541 bool SimpleIterator::insert_block_after(Prototype *block, bool use_padding)
1543 FLAC__ASSERT(0 != block);
1544 FLAC__ASSERT(is_valid());
1545 return (bool)::FLAC__metadata_simple_iterator_insert_block_after(iterator_, block->object_, use_padding);
1548 bool SimpleIterator::delete_block(bool use_padding)
1550 FLAC__ASSERT(is_valid());
1551 return (bool)::FLAC__metadata_simple_iterator_delete_block(iterator_, use_padding);
1555 // ============================================================
1557 // Level 2
1559 // ============================================================
1561 Chain::Chain():
1562 chain_(::FLAC__metadata_chain_new())
1565 Chain::~Chain()
1567 clear();
1570 void Chain::clear()
1572 if(0 != chain_)
1573 FLAC__metadata_chain_delete(chain_);
1574 chain_ = 0;
1577 bool Chain::is_valid() const
1579 return 0 != chain_;
1582 Chain::Status Chain::status()
1584 FLAC__ASSERT(is_valid());
1585 return Status(::FLAC__metadata_chain_status(chain_));
1588 bool Chain::read(const char *filename, bool is_ogg)
1590 FLAC__ASSERT(0 != filename);
1591 FLAC__ASSERT(is_valid());
1592 return is_ogg?
1593 (bool)::FLAC__metadata_chain_read_ogg(chain_, filename) :
1594 (bool)::FLAC__metadata_chain_read(chain_, filename)
1598 bool Chain::read(FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, bool is_ogg)
1600 FLAC__ASSERT(is_valid());
1601 return is_ogg?
1602 (bool)::FLAC__metadata_chain_read_ogg_with_callbacks(chain_, handle, callbacks) :
1603 (bool)::FLAC__metadata_chain_read_with_callbacks(chain_, handle, callbacks)
1607 bool Chain::check_if_tempfile_needed(bool use_padding)
1609 FLAC__ASSERT(is_valid());
1610 return (bool)::FLAC__metadata_chain_check_if_tempfile_needed(chain_, use_padding);
1613 bool Chain::write(bool use_padding, bool preserve_file_stats)
1615 FLAC__ASSERT(is_valid());
1616 return (bool)::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats);
1619 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks)
1621 FLAC__ASSERT(is_valid());
1622 return (bool)::FLAC__metadata_chain_write_with_callbacks(chain_, use_padding, handle, callbacks);
1625 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks)
1627 FLAC__ASSERT(is_valid());
1628 return (bool)::FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain_, use_padding, handle, callbacks, temp_handle, temp_callbacks);
1631 void Chain::merge_padding()
1633 FLAC__ASSERT(is_valid());
1634 ::FLAC__metadata_chain_merge_padding(chain_);
1637 void Chain::sort_padding()
1639 FLAC__ASSERT(is_valid());
1640 ::FLAC__metadata_chain_sort_padding(chain_);
1644 Iterator::Iterator():
1645 iterator_(::FLAC__metadata_iterator_new())
1648 Iterator::~Iterator()
1650 clear();
1653 void Iterator::clear()
1655 if(0 != iterator_)
1656 FLAC__metadata_iterator_delete(iterator_);
1657 iterator_ = 0;
1660 bool Iterator::is_valid() const
1662 return 0 != iterator_;
1665 void Iterator::init(Chain &chain)
1667 FLAC__ASSERT(is_valid());
1668 FLAC__ASSERT(chain.is_valid());
1669 ::FLAC__metadata_iterator_init(iterator_, chain.chain_);
1672 bool Iterator::next()
1674 FLAC__ASSERT(is_valid());
1675 return (bool)::FLAC__metadata_iterator_next(iterator_);
1678 bool Iterator::prev()
1680 FLAC__ASSERT(is_valid());
1681 return (bool)::FLAC__metadata_iterator_prev(iterator_);
1684 ::FLAC__MetadataType Iterator::get_block_type() const
1686 FLAC__ASSERT(is_valid());
1687 return ::FLAC__metadata_iterator_get_block_type(iterator_);
1690 Prototype *Iterator::get_block()
1692 FLAC__ASSERT(is_valid());
1693 Prototype *block = local::construct_block(::FLAC__metadata_iterator_get_block(iterator_));
1694 if(0 != block)
1695 block->set_reference(true);
1696 return block;
1699 bool Iterator::set_block(Prototype *block)
1701 FLAC__ASSERT(0 != block);
1702 FLAC__ASSERT(is_valid());
1703 bool ret = (bool)::FLAC__metadata_iterator_set_block(iterator_, block->object_);
1704 if(ret) {
1705 block->set_reference(true);
1706 delete block;
1708 return ret;
1711 bool Iterator::delete_block(bool replace_with_padding)
1713 FLAC__ASSERT(is_valid());
1714 return (bool)::FLAC__metadata_iterator_delete_block(iterator_, replace_with_padding);
1717 bool Iterator::insert_block_before(Prototype *block)
1719 FLAC__ASSERT(0 != block);
1720 FLAC__ASSERT(is_valid());
1721 bool ret = (bool)::FLAC__metadata_iterator_insert_block_before(iterator_, block->object_);
1722 if(ret) {
1723 block->set_reference(true);
1724 delete block;
1726 return ret;
1729 bool Iterator::insert_block_after(Prototype *block)
1731 FLAC__ASSERT(0 != block);
1732 FLAC__ASSERT(is_valid());
1733 bool ret = (bool)::FLAC__metadata_iterator_insert_block_after(iterator_, block->object_);
1734 if(ret) {
1735 block->set_reference(true);
1736 delete block;
1738 return ret;