1 /* libFLAC++ - Free Lossless Audio Codec library
2 * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "FLAC++/metadata.h"
33 #include "FLAC/assert.h"
34 #include <stdlib.h> // for malloc(), free()
35 #include <string.h> // for memcpy() etc.
38 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
39 #pragma warning ( disable : 4800 )
45 // local utility routines
49 Prototype *construct_block(::FLAC__StreamMetadata *object)
52 switch(object->type) {
53 case FLAC__METADATA_TYPE_STREAMINFO:
54 ret = new StreamInfo(object, /*copy=*/false);
56 case FLAC__METADATA_TYPE_PADDING:
57 ret = new Padding(object, /*copy=*/false);
59 case FLAC__METADATA_TYPE_APPLICATION:
60 ret = new Application(object, /*copy=*/false);
62 case FLAC__METADATA_TYPE_SEEKTABLE:
63 ret = new SeekTable(object, /*copy=*/false);
65 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
66 ret = new VorbisComment(object, /*copy=*/false);
68 case FLAC__METADATA_TYPE_CUESHEET:
69 ret = new CueSheet(object, /*copy=*/false);
71 case FLAC__METADATA_TYPE_PICTURE:
72 ret = new Picture(object, /*copy=*/false);
75 ret = new Unknown(object, /*copy=*/false);
83 FLACPP_API Prototype *clone(const Prototype *object)
85 FLAC__ASSERT(0 != object);
87 const StreamInfo *streaminfo = dynamic_cast<const StreamInfo *>(object);
88 const Padding *padding = dynamic_cast<const Padding *>(object);
89 const Application *application = dynamic_cast<const Application *>(object);
90 const SeekTable *seektable = dynamic_cast<const SeekTable *>(object);
91 const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object);
92 const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object);
93 const Picture *picture = dynamic_cast<const Picture *>(object);
94 const Unknown *unknown = dynamic_cast<const Unknown *>(object);
97 return new StreamInfo(*streaminfo);
99 return new Padding(*padding);
100 else if(0 != application)
101 return new Application(*application);
102 else if(0 != seektable)
103 return new SeekTable(*seektable);
104 else if(0 != vorbiscomment)
105 return new VorbisComment(*vorbiscomment);
106 else if(0 != cuesheet)
107 return new CueSheet(*cuesheet);
108 else if(0 != picture)
109 return new Picture(*picture);
110 else if(0 != unknown)
111 return new Unknown(*unknown);
122 Prototype::Prototype(const Prototype &object):
123 object_(::FLAC__metadata_object_clone(object.object_)),
126 FLAC__ASSERT(object.is_valid());
129 Prototype::Prototype(const ::FLAC__StreamMetadata &object):
130 object_(::FLAC__metadata_object_clone(&object)),
135 Prototype::Prototype(const ::FLAC__StreamMetadata *object):
136 object_(::FLAC__metadata_object_clone(object)),
139 FLAC__ASSERT(0 != object);
142 Prototype::Prototype(::FLAC__StreamMetadata *object, bool copy):
143 object_(copy? ::FLAC__metadata_object_clone(object) : object),
146 FLAC__ASSERT(0 != object);
149 Prototype::~Prototype()
154 void Prototype::clear()
156 if(0 != object_ && !is_reference_)
157 FLAC__metadata_object_delete(object_);
161 Prototype &Prototype::operator=(const Prototype &object)
163 FLAC__ASSERT(object.is_valid());
165 is_reference_ = false;
166 object_ = ::FLAC__metadata_object_clone(object.object_);
170 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata &object)
173 is_reference_ = false;
174 object_ = ::FLAC__metadata_object_clone(&object);
178 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata *object)
180 FLAC__ASSERT(0 != object);
182 is_reference_ = false;
183 object_ = ::FLAC__metadata_object_clone(object);
187 Prototype &Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy)
189 FLAC__ASSERT(0 != object);
191 object_ = (copy? ::FLAC__metadata_object_clone(object) : object);
192 is_reference_ = false;
196 bool Prototype::get_is_last() const
198 FLAC__ASSERT(is_valid());
199 return (bool)object_->is_last;
202 FLAC__MetadataType Prototype::get_type() const
204 FLAC__ASSERT(is_valid());
205 return object_->type;
208 unsigned Prototype::get_length() const
210 FLAC__ASSERT(is_valid());
211 return object_->length;
214 void Prototype::set_is_last(bool value)
216 FLAC__ASSERT(is_valid());
217 object_->is_last = value;
225 StreamInfo::StreamInfo():
226 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false)
229 StreamInfo::~StreamInfo()
232 unsigned StreamInfo::get_min_blocksize() const
234 FLAC__ASSERT(is_valid());
235 return object_->data.stream_info.min_blocksize;
238 unsigned StreamInfo::get_max_blocksize() const
240 FLAC__ASSERT(is_valid());
241 return object_->data.stream_info.max_blocksize;
244 unsigned StreamInfo::get_min_framesize() const
246 FLAC__ASSERT(is_valid());
247 return object_->data.stream_info.min_framesize;
250 unsigned StreamInfo::get_max_framesize() const
252 FLAC__ASSERT(is_valid());
253 return object_->data.stream_info.max_framesize;
256 unsigned StreamInfo::get_sample_rate() const
258 FLAC__ASSERT(is_valid());
259 return object_->data.stream_info.sample_rate;
262 unsigned StreamInfo::get_channels() const
264 FLAC__ASSERT(is_valid());
265 return object_->data.stream_info.channels;
268 unsigned StreamInfo::get_bits_per_sample() const
270 FLAC__ASSERT(is_valid());
271 return object_->data.stream_info.bits_per_sample;
274 FLAC__uint64 StreamInfo::get_total_samples() const
276 FLAC__ASSERT(is_valid());
277 return object_->data.stream_info.total_samples;
280 const FLAC__byte *StreamInfo::get_md5sum() const
282 FLAC__ASSERT(is_valid());
283 return object_->data.stream_info.md5sum;
286 void StreamInfo::set_min_blocksize(unsigned value)
288 FLAC__ASSERT(is_valid());
289 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
290 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
291 object_->data.stream_info.min_blocksize = value;
294 void StreamInfo::set_max_blocksize(unsigned value)
296 FLAC__ASSERT(is_valid());
297 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE);
298 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE);
299 object_->data.stream_info.max_blocksize = value;
302 void StreamInfo::set_min_framesize(unsigned value)
304 FLAC__ASSERT(is_valid());
305 FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
306 object_->data.stream_info.min_framesize = value;
309 void StreamInfo::set_max_framesize(unsigned value)
311 FLAC__ASSERT(is_valid());
312 FLAC__ASSERT(value < (1u < FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
313 object_->data.stream_info.max_framesize = value;
316 void StreamInfo::set_sample_rate(unsigned value)
318 FLAC__ASSERT(is_valid());
319 FLAC__ASSERT(FLAC__format_sample_rate_is_valid(value));
320 object_->data.stream_info.sample_rate = value;
323 void StreamInfo::set_channels(unsigned value)
325 FLAC__ASSERT(is_valid());
326 FLAC__ASSERT(value > 0);
327 FLAC__ASSERT(value <= FLAC__MAX_CHANNELS);
328 object_->data.stream_info.channels = value;
331 void StreamInfo::set_bits_per_sample(unsigned value)
333 FLAC__ASSERT(is_valid());
334 FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE);
335 FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE);
336 object_->data.stream_info.bits_per_sample = value;
339 void StreamInfo::set_total_samples(FLAC__uint64 value)
341 FLAC__ASSERT(is_valid());
342 FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN));
343 object_->data.stream_info.total_samples = value;
346 void StreamInfo::set_md5sum(const FLAC__byte value[16])
348 FLAC__ASSERT(is_valid());
349 FLAC__ASSERT(0 != value);
350 memcpy(object_->data.stream_info.md5sum, value, 16);
359 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false)
365 void Padding::set_length(unsigned length)
367 FLAC__ASSERT(is_valid());
368 object_->length = length;
376 Application::Application():
377 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
380 Application::~Application()
383 const FLAC__byte *Application::get_id() const
385 FLAC__ASSERT(is_valid());
386 return object_->data.application.id;
389 const FLAC__byte *Application::get_data() const
391 FLAC__ASSERT(is_valid());
392 return object_->data.application.data;
395 void Application::set_id(const FLAC__byte value[4])
397 FLAC__ASSERT(is_valid());
398 FLAC__ASSERT(0 != value);
399 memcpy(object_->data.application.id, value, 4);
402 bool Application::set_data(const FLAC__byte *data, unsigned length)
404 FLAC__ASSERT(is_valid());
405 return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
408 bool Application::set_data(FLAC__byte *data, unsigned length, bool copy)
410 FLAC__ASSERT(is_valid());
411 return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
419 SeekTable::SeekTable():
420 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false)
423 SeekTable::~SeekTable()
426 unsigned SeekTable::get_num_points() const
428 FLAC__ASSERT(is_valid());
429 return object_->data.seek_table.num_points;
432 ::FLAC__StreamMetadata_SeekPoint SeekTable::get_point(unsigned index) const
434 FLAC__ASSERT(is_valid());
435 FLAC__ASSERT(index < object_->data.seek_table.num_points);
436 return object_->data.seek_table.points[index];
439 void SeekTable::set_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
441 FLAC__ASSERT(is_valid());
442 FLAC__ASSERT(index < object_->data.seek_table.num_points);
443 ::FLAC__metadata_object_seektable_set_point(object_, index, point);
446 bool SeekTable::insert_point(unsigned index, const ::FLAC__StreamMetadata_SeekPoint &point)
448 FLAC__ASSERT(is_valid());
449 FLAC__ASSERT(index <= object_->data.seek_table.num_points);
450 return (bool)::FLAC__metadata_object_seektable_insert_point(object_, index, point);
453 bool SeekTable::delete_point(unsigned index)
455 FLAC__ASSERT(is_valid());
456 FLAC__ASSERT(index < object_->data.seek_table.num_points);
457 return (bool)::FLAC__metadata_object_seektable_delete_point(object_, index);
460 bool SeekTable::is_legal() const
462 FLAC__ASSERT(is_valid());
463 return (bool)::FLAC__metadata_object_seektable_is_legal(object_);
468 // VorbisComment::Entry
471 VorbisComment::Entry::Entry()
476 VorbisComment::Entry::Entry(const char *field, unsigned field_length)
479 construct(field, field_length);
482 VorbisComment::Entry::Entry(const char *field)
488 VorbisComment::Entry::Entry(const char *field_name, const char *field_value, unsigned field_value_length)
491 construct(field_name, field_value, field_value_length);
494 VorbisComment::Entry::Entry(const char *field_name, const char *field_value)
497 construct(field_name, field_value);
500 VorbisComment::Entry::Entry(const Entry &entry)
502 FLAC__ASSERT(entry.is_valid());
504 construct((const char *)entry.entry_.entry, entry.entry_.length);
507 VorbisComment::Entry &VorbisComment::Entry::operator=(const Entry &entry)
509 FLAC__ASSERT(entry.is_valid());
511 construct((const char *)entry.entry_.entry, entry.entry_.length);
515 VorbisComment::Entry::~Entry()
520 bool VorbisComment::Entry::is_valid() const
525 unsigned VorbisComment::Entry::get_field_length() const
527 FLAC__ASSERT(is_valid());
528 return entry_.length;
531 unsigned VorbisComment::Entry::get_field_name_length() const
533 FLAC__ASSERT(is_valid());
534 return field_name_length_;
537 unsigned VorbisComment::Entry::get_field_value_length() const
539 FLAC__ASSERT(is_valid());
540 return field_value_length_;
543 ::FLAC__StreamMetadata_VorbisComment_Entry VorbisComment::Entry::get_entry() const
545 FLAC__ASSERT(is_valid());
549 const char *VorbisComment::Entry::get_field() const
551 FLAC__ASSERT(is_valid());
552 return (const char *)entry_.entry;
555 const char *VorbisComment::Entry::get_field_name() const
557 FLAC__ASSERT(is_valid());
561 const char *VorbisComment::Entry::get_field_value() const
563 FLAC__ASSERT(is_valid());
567 bool VorbisComment::Entry::set_field(const char *field, unsigned field_length)
569 FLAC__ASSERT(is_valid());
570 FLAC__ASSERT(0 != field);
572 if(!::FLAC__format_vorbiscomment_entry_is_legal((const ::FLAC__byte*)field, field_length))
573 return is_valid_ = false;
577 if(0 == (entry_.entry = (FLAC__byte*)malloc(field_length+1))) {
581 entry_.length = field_length;
582 memcpy(entry_.entry, field, field_length);
583 entry_.entry[field_length] = '\0';
584 (void) parse_field();
590 bool VorbisComment::Entry::set_field(const char *field)
592 return set_field(field, strlen(field));
595 bool VorbisComment::Entry::set_field_name(const char *field_name)
597 FLAC__ASSERT(is_valid());
598 FLAC__ASSERT(0 != field_name);
600 if(!::FLAC__format_vorbiscomment_entry_name_is_legal(field_name))
601 return is_valid_ = false;
605 if(0 == (field_name_ = strdup(field_name))) {
609 field_name_length_ = strlen(field_name_);
616 bool VorbisComment::Entry::set_field_value(const char *field_value, unsigned field_value_length)
618 FLAC__ASSERT(is_valid());
619 FLAC__ASSERT(0 != field_value);
621 if(!::FLAC__format_vorbiscomment_entry_value_is_legal((const FLAC__byte*)field_value, field_value_length))
622 return is_valid_ = false;
626 if(0 == (field_value_ = (char *)malloc(field_value_length+1))) {
630 field_value_length_ = field_value_length;
631 memcpy(field_value_, field_value, field_value_length);
632 field_value_[field_value_length] = '\0';
639 bool VorbisComment::Entry::set_field_value(const char *field_value)
641 return set_field_value(field_value, strlen(field_value));
644 void VorbisComment::Entry::zero()
650 field_name_length_ = 0;
652 field_value_length_ = 0;
655 void VorbisComment::Entry::clear()
663 void VorbisComment::Entry::clear_entry()
665 if(0 != entry_.entry) {
672 void VorbisComment::Entry::clear_field_name()
674 if(0 != field_name_) {
677 field_name_length_ = 0;
681 void VorbisComment::Entry::clear_field_value()
683 if(0 != field_value_) {
686 field_value_length_ = 0;
690 void VorbisComment::Entry::construct(const char *field, unsigned field_length)
692 if(set_field(field, field_length))
696 void VorbisComment::Entry::construct(const char *field)
698 construct(field, strlen(field));
701 void VorbisComment::Entry::construct(const char *field_name, const char *field_value, unsigned field_value_length)
703 if(set_field_name(field_name) && set_field_value(field_value, field_value_length))
707 void VorbisComment::Entry::construct(const char *field_name, const char *field_value)
709 construct(field_name, field_value, strlen(field_value));
712 void VorbisComment::Entry::compose_field()
716 if(0 == (entry_.entry = (FLAC__byte*)malloc(field_name_length_ + 1 + field_value_length_ + 1))) {
720 memcpy(entry_.entry, field_name_, field_name_length_);
721 entry_.length += field_name_length_;
722 memcpy(entry_.entry + entry_.length, "=", 1);
724 memcpy(entry_.entry + entry_.length, field_value_, field_value_length_);
725 entry_.length += field_value_length_;
726 entry_.entry[entry_.length] = '\0';
731 void VorbisComment::Entry::parse_field()
736 const char *p = (const char *)memchr(entry_.entry, '=', entry_.length);
739 p = (const char *)entry_.entry + entry_.length;
741 field_name_length_ = p - (const char *)entry_.entry;
742 if(0 == (field_name_ = (char *)malloc(field_name_length_ + 1))) { // +1 for the trailing \0
746 memcpy(field_name_, entry_.entry, field_name_length_);
747 field_name_[field_name_length_] = '\0';
749 if(entry_.length - field_name_length_ == 0) {
750 field_value_length_ = 0;
751 if(0 == (field_value_ = (char *)malloc(0))) {
757 field_value_length_ = entry_.length - field_name_length_ - 1;
758 if(0 == (field_value_ = (char *)malloc(field_value_length_ + 1))) { // +1 for the trailing \0
762 memcpy(field_value_, ++p, field_value_length_);
763 field_value_[field_value_length_] = '\0';
774 VorbisComment::VorbisComment():
775 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false)
778 VorbisComment::~VorbisComment()
781 unsigned VorbisComment::get_num_comments() const
783 FLAC__ASSERT(is_valid());
784 return object_->data.vorbis_comment.num_comments;
787 const FLAC__byte *VorbisComment::get_vendor_string() const
789 FLAC__ASSERT(is_valid());
790 return object_->data.vorbis_comment.vendor_string.entry;
793 VorbisComment::Entry VorbisComment::get_comment(unsigned index) const
795 FLAC__ASSERT(is_valid());
796 FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
797 return Entry((const char *)object_->data.vorbis_comment.comments[index].entry, object_->data.vorbis_comment.comments[index].length);
800 bool VorbisComment::set_vendor_string(const FLAC__byte *string)
802 FLAC__ASSERT(is_valid());
803 // vendor_string is a special kind of entry
804 const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { strlen((const char *)string), (FLAC__byte*)string }; // we can cheat on const-ness because we make a copy below:
805 return (bool)::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true);
808 bool VorbisComment::set_comment(unsigned index, const VorbisComment::Entry &entry)
810 FLAC__ASSERT(is_valid());
811 FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
812 return (bool)::FLAC__metadata_object_vorbiscomment_set_comment(object_, index, entry.get_entry(), /*copy=*/true);
815 bool VorbisComment::insert_comment(unsigned index, const VorbisComment::Entry &entry)
817 FLAC__ASSERT(is_valid());
818 FLAC__ASSERT(index <= object_->data.vorbis_comment.num_comments);
819 return (bool)::FLAC__metadata_object_vorbiscomment_insert_comment(object_, index, entry.get_entry(), /*copy=*/true);
822 bool VorbisComment::append_comment(const VorbisComment::Entry &entry)
824 FLAC__ASSERT(is_valid());
825 return (bool)::FLAC__metadata_object_vorbiscomment_append_comment(object_, entry.get_entry(), /*copy=*/true);
828 bool VorbisComment::delete_comment(unsigned index)
830 FLAC__ASSERT(is_valid());
831 FLAC__ASSERT(index < object_->data.vorbis_comment.num_comments);
832 return (bool)::FLAC__metadata_object_vorbiscomment_delete_comment(object_, index);
840 CueSheet::Track::Track():
841 object_(::FLAC__metadata_object_cuesheet_track_new())
844 CueSheet::Track::Track(const ::FLAC__StreamMetadata_CueSheet_Track *track):
845 object_(::FLAC__metadata_object_cuesheet_track_clone(track))
848 CueSheet::Track::Track(const Track &track):
849 object_(::FLAC__metadata_object_cuesheet_track_clone(track.object_))
852 CueSheet::Track &CueSheet::Track::operator=(const Track &track)
855 ::FLAC__metadata_object_cuesheet_track_delete(object_);
856 object_ = ::FLAC__metadata_object_cuesheet_track_clone(track.object_);
860 CueSheet::Track::~Track()
863 ::FLAC__metadata_object_cuesheet_track_delete(object_);
866 bool CueSheet::Track::is_valid() const
868 return(0 != object_);
871 ::FLAC__StreamMetadata_CueSheet_Index CueSheet::Track::get_index(unsigned i) const
873 FLAC__ASSERT(is_valid());
874 FLAC__ASSERT(i < object_->num_indices);
875 return object_->indices[i];
878 void CueSheet::Track::set_isrc(const char value[12])
880 FLAC__ASSERT(is_valid());
881 FLAC__ASSERT(0 != value);
882 memcpy(object_->isrc, value, 12);
883 object_->isrc[12] = '\0';
886 void CueSheet::Track::set_type(unsigned value)
888 FLAC__ASSERT(is_valid());
889 FLAC__ASSERT(value <= 1);
890 object_->type = value;
893 void CueSheet::Track::set_index(unsigned i, const ::FLAC__StreamMetadata_CueSheet_Index &index)
895 FLAC__ASSERT(is_valid());
896 FLAC__ASSERT(i < object_->num_indices);
897 object_->indices[i] = index;
905 CueSheet::CueSheet():
906 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET), /*copy=*/false)
909 CueSheet::~CueSheet()
912 const char *CueSheet::get_media_catalog_number() const
914 FLAC__ASSERT(is_valid());
915 return object_->data.cue_sheet.media_catalog_number;
918 FLAC__uint64 CueSheet::get_lead_in() const
920 FLAC__ASSERT(is_valid());
921 return object_->data.cue_sheet.lead_in;
924 bool CueSheet::get_is_cd() const
926 FLAC__ASSERT(is_valid());
927 return object_->data.cue_sheet.is_cd? true : false;
930 unsigned CueSheet::get_num_tracks() const
932 FLAC__ASSERT(is_valid());
933 return object_->data.cue_sheet.num_tracks;
936 CueSheet::Track CueSheet::get_track(unsigned i) const
938 FLAC__ASSERT(is_valid());
939 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
940 return Track(object_->data.cue_sheet.tracks + i);
943 void CueSheet::set_media_catalog_number(const char value[128])
945 FLAC__ASSERT(is_valid());
946 FLAC__ASSERT(0 != value);
947 memcpy(object_->data.cue_sheet.media_catalog_number, value, 128);
948 object_->data.cue_sheet.media_catalog_number[128] = '\0';
951 void CueSheet::set_lead_in(FLAC__uint64 value)
953 FLAC__ASSERT(is_valid());
954 object_->data.cue_sheet.lead_in = value;
957 void CueSheet::set_is_cd(bool value)
959 FLAC__ASSERT(is_valid());
960 object_->data.cue_sheet.is_cd = value;
963 void CueSheet::set_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index)
965 FLAC__ASSERT(is_valid());
966 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
967 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
968 object_->data.cue_sheet.tracks[track_num].indices[index_num] = index;
971 bool CueSheet::insert_index(unsigned track_num, unsigned index_num, const ::FLAC__StreamMetadata_CueSheet_Index &index)
973 FLAC__ASSERT(is_valid());
974 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
975 FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices);
976 return (bool)::FLAC__metadata_object_cuesheet_track_insert_index(object_, track_num, index_num, index);
979 bool CueSheet::delete_index(unsigned track_num, unsigned index_num)
981 FLAC__ASSERT(is_valid());
982 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks);
983 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices);
984 return (bool)::FLAC__metadata_object_cuesheet_track_delete_index(object_, track_num, index_num);
987 bool CueSheet::set_track(unsigned i, const CueSheet::Track &track)
989 FLAC__ASSERT(is_valid());
990 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
991 // We can safely const_cast since copy=true
992 return (bool)::FLAC__metadata_object_cuesheet_set_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
995 bool CueSheet::insert_track(unsigned i, const CueSheet::Track &track)
997 FLAC__ASSERT(is_valid());
998 FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks);
999 // We can safely const_cast since copy=true
1000 return (bool)::FLAC__metadata_object_cuesheet_insert_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true);
1003 bool CueSheet::delete_track(unsigned i)
1005 FLAC__ASSERT(is_valid());
1006 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks);
1007 return (bool)::FLAC__metadata_object_cuesheet_delete_track(object_, i);
1010 bool CueSheet::is_legal(bool check_cd_da_subset, const char **violation) const
1012 FLAC__ASSERT(is_valid());
1013 return (bool)::FLAC__metadata_object_cuesheet_is_legal(object_, check_cd_da_subset, violation);
1016 FLAC__uint32 CueSheet::calculate_cddb_id() const
1018 FLAC__ASSERT(is_valid());
1019 return ::FLAC__metadata_object_cuesheet_calculate_cddb_id(object_);
1028 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE), /*copy=*/false)
1034 ::FLAC__StreamMetadata_Picture_Type Picture::get_type() const
1036 FLAC__ASSERT(is_valid());
1037 return object_->data.picture.type;
1040 const char *Picture::get_mime_type() const
1042 FLAC__ASSERT(is_valid());
1043 return object_->data.picture.mime_type;
1046 const FLAC__byte *Picture::get_description() const
1048 FLAC__ASSERT(is_valid());
1049 return object_->data.picture.description;
1052 FLAC__uint32 Picture::get_width() const
1054 FLAC__ASSERT(is_valid());
1055 return object_->data.picture.width;
1058 FLAC__uint32 Picture::get_height() const
1060 FLAC__ASSERT(is_valid());
1061 return object_->data.picture.height;
1064 FLAC__uint32 Picture::get_depth() const
1066 FLAC__ASSERT(is_valid());
1067 return object_->data.picture.depth;
1070 FLAC__uint32 Picture::get_colors() const
1072 FLAC__ASSERT(is_valid());
1073 return object_->data.picture.colors;
1076 FLAC__uint32 Picture::get_data_length() const
1078 FLAC__ASSERT(is_valid());
1079 return object_->data.picture.data_length;
1082 const FLAC__byte *Picture::get_data() const
1084 FLAC__ASSERT(is_valid());
1085 return object_->data.picture.data;
1088 void Picture::set_type(::FLAC__StreamMetadata_Picture_Type type)
1090 FLAC__ASSERT(is_valid());
1091 object_->data.picture.type = type;
1094 bool Picture::set_mime_type(const char *string)
1096 FLAC__ASSERT(is_valid());
1097 // We can safely const_cast since copy=true
1098 return (bool)::FLAC__metadata_object_picture_set_mime_type(object_, const_cast<char*>(string), /*copy=*/true);
1101 bool Picture::set_description(const FLAC__byte *string)
1103 FLAC__ASSERT(is_valid());
1104 // We can safely const_cast since copy=true
1105 return (bool)::FLAC__metadata_object_picture_set_description(object_, const_cast<FLAC__byte*>(string), /*copy=*/true);
1108 void Picture::set_width(FLAC__uint32 value) const
1110 FLAC__ASSERT(is_valid());
1111 object_->data.picture.width = value;
1114 void Picture::set_height(FLAC__uint32 value) const
1116 FLAC__ASSERT(is_valid());
1117 object_->data.picture.height = value;
1120 void Picture::set_depth(FLAC__uint32 value) const
1122 FLAC__ASSERT(is_valid());
1123 object_->data.picture.depth = value;
1126 void Picture::set_colors(FLAC__uint32 value) const
1128 FLAC__ASSERT(is_valid());
1129 object_->data.picture.colors = value;
1132 bool Picture::set_data(const FLAC__byte *data, FLAC__uint32 data_length)
1134 FLAC__ASSERT(is_valid());
1135 // We can safely const_cast since copy=true
1136 return (bool)::FLAC__metadata_object_picture_set_data(object_, const_cast<FLAC__byte*>(data), data_length, /*copy=*/true);
1145 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false)
1151 const FLAC__byte *Unknown::get_data() const
1153 FLAC__ASSERT(is_valid());
1154 return object_->data.application.data;
1157 bool Unknown::set_data(const FLAC__byte *data, unsigned length)
1159 FLAC__ASSERT(is_valid());
1160 return (bool)::FLAC__metadata_object_application_set_data(object_, (FLAC__byte*)data, length, true);
1163 bool Unknown::set_data(FLAC__byte *data, unsigned length, bool copy)
1165 FLAC__ASSERT(is_valid());
1166 return (bool)::FLAC__metadata_object_application_set_data(object_, data, length, copy);
1170 // ============================================================
1174 // ============================================================
1176 FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo)
1178 FLAC__ASSERT(0 != filename);
1180 ::FLAC__StreamMetadata object;
1182 if(::FLAC__metadata_get_streaminfo(filename, &object)) {
1183 streaminfo = object;
1190 FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags)
1192 FLAC__ASSERT(0 != filename);
1194 ::FLAC__StreamMetadata *object;
1198 if(::FLAC__metadata_get_tags(filename, &object)) {
1199 tags = new VorbisComment(object, /*copy=*/false);
1206 FLACPP_API bool get_tags(const char *filename, VorbisComment &tags)
1208 FLAC__ASSERT(0 != filename);
1210 ::FLAC__StreamMetadata *object;
1212 if(::FLAC__metadata_get_tags(filename, &object)) {
1213 tags.assign(object, /*copy=*/false);
1220 FLACPP_API bool get_cuesheet(const char *filename, CueSheet *&cuesheet)
1222 FLAC__ASSERT(0 != filename);
1224 ::FLAC__StreamMetadata *object;
1228 if(::FLAC__metadata_get_cuesheet(filename, &object)) {
1229 cuesheet = new CueSheet(object, /*copy=*/false);
1236 FLACPP_API bool get_cuesheet(const char *filename, CueSheet &cuesheet)
1238 FLAC__ASSERT(0 != filename);
1240 ::FLAC__StreamMetadata *object;
1242 if(::FLAC__metadata_get_cuesheet(filename, &object)) {
1243 cuesheet.assign(object, /*copy=*/false);
1250 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)
1252 FLAC__ASSERT(0 != filename);
1254 ::FLAC__StreamMetadata *object;
1258 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) {
1259 picture = new Picture(object, /*copy=*/false);
1266 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)
1268 FLAC__ASSERT(0 != filename);
1270 ::FLAC__StreamMetadata *object;
1272 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) {
1273 picture.assign(object, /*copy=*/false);
1281 // ============================================================
1285 // ============================================================
1287 SimpleIterator::SimpleIterator():
1288 iterator_(::FLAC__metadata_simple_iterator_new())
1291 SimpleIterator::~SimpleIterator()
1296 void SimpleIterator::clear()
1299 FLAC__metadata_simple_iterator_delete(iterator_);
1303 bool SimpleIterator::init(const char *filename, bool read_only, bool preserve_file_stats)
1305 FLAC__ASSERT(0 != filename);
1306 FLAC__ASSERT(is_valid());
1307 return (bool)::FLAC__metadata_simple_iterator_init(iterator_, filename, read_only, preserve_file_stats);
1310 bool SimpleIterator::is_valid() const
1312 return 0 != iterator_;
1315 SimpleIterator::Status SimpleIterator::status()
1317 FLAC__ASSERT(is_valid());
1318 return Status(::FLAC__metadata_simple_iterator_status(iterator_));
1321 bool SimpleIterator::is_writable() const
1323 FLAC__ASSERT(is_valid());
1324 return (bool)::FLAC__metadata_simple_iterator_is_writable(iterator_);
1327 bool SimpleIterator::next()
1329 FLAC__ASSERT(is_valid());
1330 return (bool)::FLAC__metadata_simple_iterator_next(iterator_);
1333 bool SimpleIterator::prev()
1335 FLAC__ASSERT(is_valid());
1336 return (bool)::FLAC__metadata_simple_iterator_prev(iterator_);
1339 ::FLAC__MetadataType SimpleIterator::get_block_type() const
1341 FLAC__ASSERT(is_valid());
1342 return ::FLAC__metadata_simple_iterator_get_block_type(iterator_);
1345 Prototype *SimpleIterator::get_block()
1347 FLAC__ASSERT(is_valid());
1348 return local::construct_block(::FLAC__metadata_simple_iterator_get_block(iterator_));
1351 bool SimpleIterator::set_block(Prototype *block, bool use_padding)
1353 FLAC__ASSERT(0 != block);
1354 FLAC__ASSERT(is_valid());
1355 return (bool)::FLAC__metadata_simple_iterator_set_block(iterator_, block->object_, use_padding);
1358 bool SimpleIterator::insert_block_after(Prototype *block, bool use_padding)
1360 FLAC__ASSERT(0 != block);
1361 FLAC__ASSERT(is_valid());
1362 return (bool)::FLAC__metadata_simple_iterator_insert_block_after(iterator_, block->object_, use_padding);
1365 bool SimpleIterator::delete_block(bool use_padding)
1367 FLAC__ASSERT(is_valid());
1368 return (bool)::FLAC__metadata_simple_iterator_delete_block(iterator_, use_padding);
1372 // ============================================================
1376 // ============================================================
1379 chain_(::FLAC__metadata_chain_new())
1390 FLAC__metadata_chain_delete(chain_);
1394 bool Chain::is_valid() const
1399 Chain::Status Chain::status()
1401 FLAC__ASSERT(is_valid());
1402 return Status(::FLAC__metadata_chain_status(chain_));
1405 bool Chain::read(const char *filename, bool is_ogg)
1407 FLAC__ASSERT(0 != filename);
1408 FLAC__ASSERT(is_valid());
1410 (bool)::FLAC__metadata_chain_read_ogg(chain_, filename) :
1411 (bool)::FLAC__metadata_chain_read(chain_, filename)
1415 bool Chain::read(FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, bool is_ogg)
1417 FLAC__ASSERT(is_valid());
1419 (bool)::FLAC__metadata_chain_read_ogg_with_callbacks(chain_, handle, callbacks) :
1420 (bool)::FLAC__metadata_chain_read_with_callbacks(chain_, handle, callbacks)
1424 bool Chain::check_if_tempfile_needed(bool use_padding)
1426 FLAC__ASSERT(is_valid());
1427 return (bool)::FLAC__metadata_chain_check_if_tempfile_needed(chain_, use_padding);
1430 bool Chain::write(bool use_padding, bool preserve_file_stats)
1432 FLAC__ASSERT(is_valid());
1433 return (bool)::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats);
1436 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks)
1438 FLAC__ASSERT(is_valid());
1439 return (bool)::FLAC__metadata_chain_write_with_callbacks(chain_, use_padding, handle, callbacks);
1442 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks)
1444 FLAC__ASSERT(is_valid());
1445 return (bool)::FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain_, use_padding, handle, callbacks, temp_handle, temp_callbacks);
1448 void Chain::merge_padding()
1450 FLAC__ASSERT(is_valid());
1451 ::FLAC__metadata_chain_merge_padding(chain_);
1454 void Chain::sort_padding()
1456 FLAC__ASSERT(is_valid());
1457 ::FLAC__metadata_chain_sort_padding(chain_);
1461 Iterator::Iterator():
1462 iterator_(::FLAC__metadata_iterator_new())
1465 Iterator::~Iterator()
1470 void Iterator::clear()
1473 FLAC__metadata_iterator_delete(iterator_);
1477 bool Iterator::is_valid() const
1479 return 0 != iterator_;
1482 void Iterator::init(Chain &chain)
1484 FLAC__ASSERT(is_valid());
1485 FLAC__ASSERT(chain.is_valid());
1486 ::FLAC__metadata_iterator_init(iterator_, chain.chain_);
1489 bool Iterator::next()
1491 FLAC__ASSERT(is_valid());
1492 return (bool)::FLAC__metadata_iterator_next(iterator_);
1495 bool Iterator::prev()
1497 FLAC__ASSERT(is_valid());
1498 return (bool)::FLAC__metadata_iterator_prev(iterator_);
1501 ::FLAC__MetadataType Iterator::get_block_type() const
1503 FLAC__ASSERT(is_valid());
1504 return ::FLAC__metadata_iterator_get_block_type(iterator_);
1507 Prototype *Iterator::get_block()
1509 FLAC__ASSERT(is_valid());
1510 Prototype *block = local::construct_block(::FLAC__metadata_iterator_get_block(iterator_));
1512 block->set_reference(true);
1516 bool Iterator::set_block(Prototype *block)
1518 FLAC__ASSERT(0 != block);
1519 FLAC__ASSERT(is_valid());
1520 bool ret = (bool)::FLAC__metadata_iterator_set_block(iterator_, block->object_);
1522 block->set_reference(true);
1528 bool Iterator::delete_block(bool replace_with_padding)
1530 FLAC__ASSERT(is_valid());
1531 return (bool)::FLAC__metadata_iterator_delete_block(iterator_, replace_with_padding);
1534 bool Iterator::insert_block_before(Prototype *block)
1536 FLAC__ASSERT(0 != block);
1537 FLAC__ASSERT(is_valid());
1538 bool ret = (bool)::FLAC__metadata_iterator_insert_block_before(iterator_, block->object_);
1540 block->set_reference(true);
1546 bool Iterator::insert_block_after(Prototype *block)
1548 FLAC__ASSERT(0 != block);
1549 FLAC__ASSERT(is_valid());
1550 bool ret = (bool)::FLAC__metadata_iterator_insert_block_after(iterator_, block->object_);
1552 block->set_reference(true);