1 /* libFLAC++ - Free Lossless Audio Codec library 2 * Copyright (C) 2002-2009 Josh Coalson 3 * Copyright (C) 2011-2016 Xiph.Org Foundation 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 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. 15 * 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. 19 * 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. 31 */ 32 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 37 38 #include "share/alloc.h" 39 #include "FLAC++/metadata.h" 40 #include "FLAC/assert.h" 41 #include <cstdlib> // for malloc(), free() 42 #include <cstring> // for memcpy() etc. 43 44 #ifdef _MSC_VER 45 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning) 46 #pragma warning ( disable : 4800 ) 47 #endif 48 49 namespace FLAC { 50 namespace Metadata { 51 52 // local utility routines 53 54 namespace local { 55 construct_block(::FLAC__StreamMetadata * object)56 Prototype *construct_block(::FLAC__StreamMetadata *object) 57 { 58 if (0 == object) 59 return 0; 60 61 Prototype *ret = 0; 62 switch(object->type) { 63 case FLAC__METADATA_TYPE_STREAMINFO: 64 ret = new StreamInfo(object, /*copy=*/false); 65 break; 66 case FLAC__METADATA_TYPE_PADDING: 67 ret = new Padding(object, /*copy=*/false); 68 break; 69 case FLAC__METADATA_TYPE_APPLICATION: 70 ret = new Application(object, /*copy=*/false); 71 break; 72 case FLAC__METADATA_TYPE_SEEKTABLE: 73 ret = new SeekTable(object, /*copy=*/false); 74 break; 75 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 76 ret = new VorbisComment(object, /*copy=*/false); 77 break; 78 case FLAC__METADATA_TYPE_CUESHEET: 79 ret = new CueSheet(object, /*copy=*/false); 80 break; 81 case FLAC__METADATA_TYPE_PICTURE: 82 ret = new Picture(object, /*copy=*/false); 83 break; 84 default: 85 ret = new Unknown(object, /*copy=*/false); 86 break; 87 } 88 return ret; 89 } 90 91 } // namespace local 92 clone(const Prototype * object)93 FLACPP_API Prototype *clone(const Prototype *object) 94 { 95 FLAC__ASSERT(0 != object); 96 97 const StreamInfo *streaminfo = dynamic_cast<const StreamInfo *>(object); 98 const Padding *padding = dynamic_cast<const Padding *>(object); 99 const Application *application = dynamic_cast<const Application *>(object); 100 const SeekTable *seektable = dynamic_cast<const SeekTable *>(object); 101 const VorbisComment *vorbiscomment = dynamic_cast<const VorbisComment *>(object); 102 const CueSheet *cuesheet = dynamic_cast<const CueSheet *>(object); 103 const Picture *picture = dynamic_cast<const Picture *>(object); 104 const Unknown *unknown = dynamic_cast<const Unknown *>(object); 105 106 if(0 != streaminfo) 107 return new StreamInfo(*streaminfo); 108 if(0 != padding) 109 return new Padding(*padding); 110 if(0 != application) 111 return new Application(*application); 112 if(0 != seektable) 113 return new SeekTable(*seektable); 114 if(0 != vorbiscomment) 115 return new VorbisComment(*vorbiscomment); 116 if(0 != cuesheet) 117 return new CueSheet(*cuesheet); 118 if(0 != picture) 119 return new Picture(*picture); 120 if(0 != unknown) 121 return new Unknown(*unknown); 122 123 FLAC__ASSERT(0); 124 return 0; 125 } 126 127 // 128 // Prototype 129 // 130 Prototype(const Prototype & object)131 Prototype::Prototype(const Prototype &object): 132 object_(::FLAC__metadata_object_clone(object.object_)), 133 is_reference_(false) 134 { 135 FLAC__ASSERT(object.is_valid()); 136 } 137 Prototype(const::FLAC__StreamMetadata & object)138 Prototype::Prototype(const ::FLAC__StreamMetadata &object): 139 object_(::FLAC__metadata_object_clone(&object)), 140 is_reference_(false) 141 { 142 } 143 Prototype(const::FLAC__StreamMetadata * object)144 Prototype::Prototype(const ::FLAC__StreamMetadata *object): 145 object_(::FLAC__metadata_object_clone(object)), 146 is_reference_(false) 147 { 148 FLAC__ASSERT(0 != object); 149 } 150 Prototype(::FLAC__StreamMetadata * object,bool copy)151 Prototype::Prototype(::FLAC__StreamMetadata *object, bool copy): 152 object_(copy? ::FLAC__metadata_object_clone(object) : object), 153 is_reference_(false) 154 { 155 FLAC__ASSERT(0 != object); 156 } 157 ~Prototype()158 Prototype::~Prototype() 159 { 160 clear(); 161 } 162 clear()163 void Prototype::clear() 164 { 165 if(0 != object_ && !is_reference_) 166 FLAC__metadata_object_delete(object_); 167 object_ = 0; 168 } 169 operator =(const Prototype & object)170 Prototype &Prototype::operator=(const Prototype &object) 171 { 172 FLAC__ASSERT(object.is_valid()); 173 clear(); 174 is_reference_ = false; 175 object_ = ::FLAC__metadata_object_clone(object.object_); 176 return *this; 177 } 178 operator =(const::FLAC__StreamMetadata & object)179 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata &object) 180 { 181 clear(); 182 is_reference_ = false; 183 object_ = ::FLAC__metadata_object_clone(&object); 184 return *this; 185 } 186 operator =(const::FLAC__StreamMetadata * object)187 Prototype &Prototype::operator=(const ::FLAC__StreamMetadata *object) 188 { 189 FLAC__ASSERT(0 != object); 190 clear(); 191 is_reference_ = false; 192 object_ = ::FLAC__metadata_object_clone(object); 193 return *this; 194 } 195 assign_object(::FLAC__StreamMetadata * object,bool copy)196 Prototype &Prototype::assign_object(::FLAC__StreamMetadata *object, bool copy) 197 { 198 FLAC__ASSERT(0 != object); 199 clear(); 200 object_ = (copy? ::FLAC__metadata_object_clone(object) : object); 201 is_reference_ = false; 202 return *this; 203 } 204 get_is_last() const205 bool Prototype::get_is_last() const 206 { 207 FLAC__ASSERT(is_valid()); 208 return static_cast<bool>(object_->is_last); 209 } 210 get_type() const211 FLAC__MetadataType Prototype::get_type() const 212 { 213 FLAC__ASSERT(is_valid()); 214 return object_->type; 215 } 216 get_length() const217 uint32_t Prototype::get_length() const 218 { 219 FLAC__ASSERT(is_valid()); 220 return object_->length; 221 } 222 set_is_last(bool value)223 void Prototype::set_is_last(bool value) 224 { 225 FLAC__ASSERT(is_valid()); 226 object_->is_last = value; 227 } 228 229 230 // 231 // StreamInfo 232 // 233 StreamInfo()234 StreamInfo::StreamInfo(): 235 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO), /*copy=*/false) 236 { } 237 ~StreamInfo()238 StreamInfo::~StreamInfo() 239 { } 240 get_min_blocksize() const241 uint32_t StreamInfo::get_min_blocksize() const 242 { 243 FLAC__ASSERT(is_valid()); 244 return object_->data.stream_info.min_blocksize; 245 } 246 get_max_blocksize() const247 uint32_t StreamInfo::get_max_blocksize() const 248 { 249 FLAC__ASSERT(is_valid()); 250 return object_->data.stream_info.max_blocksize; 251 } 252 get_min_framesize() const253 uint32_t StreamInfo::get_min_framesize() const 254 { 255 FLAC__ASSERT(is_valid()); 256 return object_->data.stream_info.min_framesize; 257 } 258 get_max_framesize() const259 uint32_t StreamInfo::get_max_framesize() const 260 { 261 FLAC__ASSERT(is_valid()); 262 return object_->data.stream_info.max_framesize; 263 } 264 get_sample_rate() const265 uint32_t StreamInfo::get_sample_rate() const 266 { 267 FLAC__ASSERT(is_valid()); 268 return object_->data.stream_info.sample_rate; 269 } 270 get_channels() const271 uint32_t StreamInfo::get_channels() const 272 { 273 FLAC__ASSERT(is_valid()); 274 return object_->data.stream_info.channels; 275 } 276 get_bits_per_sample() const277 uint32_t StreamInfo::get_bits_per_sample() const 278 { 279 FLAC__ASSERT(is_valid()); 280 return object_->data.stream_info.bits_per_sample; 281 } 282 get_total_samples() const283 FLAC__uint64 StreamInfo::get_total_samples() const 284 { 285 FLAC__ASSERT(is_valid()); 286 return object_->data.stream_info.total_samples; 287 } 288 get_md5sum() const289 const FLAC__byte *StreamInfo::get_md5sum() const 290 { 291 FLAC__ASSERT(is_valid()); 292 return object_->data.stream_info.md5sum; 293 } 294 set_min_blocksize(uint32_t value)295 void StreamInfo::set_min_blocksize(uint32_t value) 296 { 297 FLAC__ASSERT(is_valid()); 298 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE); 299 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE); 300 object_->data.stream_info.min_blocksize = value; 301 } 302 set_max_blocksize(uint32_t value)303 void StreamInfo::set_max_blocksize(uint32_t value) 304 { 305 FLAC__ASSERT(is_valid()); 306 FLAC__ASSERT(value >= FLAC__MIN_BLOCK_SIZE); 307 FLAC__ASSERT(value <= FLAC__MAX_BLOCK_SIZE); 308 object_->data.stream_info.max_blocksize = value; 309 } 310 set_min_framesize(uint32_t value)311 void StreamInfo::set_min_framesize(uint32_t value) 312 { 313 FLAC__ASSERT(is_valid()); 314 FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN)); 315 object_->data.stream_info.min_framesize = value; 316 } 317 set_max_framesize(uint32_t value)318 void StreamInfo::set_max_framesize(uint32_t value) 319 { 320 FLAC__ASSERT(is_valid()); 321 FLAC__ASSERT(value < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN)); 322 object_->data.stream_info.max_framesize = value; 323 } 324 set_sample_rate(uint32_t value)325 void StreamInfo::set_sample_rate(uint32_t value) 326 { 327 FLAC__ASSERT(is_valid()); 328 FLAC__ASSERT(FLAC__format_sample_rate_is_valid(value)); 329 object_->data.stream_info.sample_rate = value; 330 } 331 set_channels(uint32_t value)332 void StreamInfo::set_channels(uint32_t value) 333 { 334 FLAC__ASSERT(is_valid()); 335 FLAC__ASSERT(value > 0); 336 FLAC__ASSERT(value <= FLAC__MAX_CHANNELS); 337 object_->data.stream_info.channels = value; 338 } 339 set_bits_per_sample(uint32_t value)340 void StreamInfo::set_bits_per_sample(uint32_t value) 341 { 342 FLAC__ASSERT(is_valid()); 343 FLAC__ASSERT(value >= FLAC__MIN_BITS_PER_SAMPLE); 344 FLAC__ASSERT(value <= FLAC__MAX_BITS_PER_SAMPLE); 345 object_->data.stream_info.bits_per_sample = value; 346 } 347 set_total_samples(FLAC__uint64 value)348 void StreamInfo::set_total_samples(FLAC__uint64 value) 349 { 350 FLAC__ASSERT(is_valid()); 351 FLAC__ASSERT(value < (((FLAC__uint64)1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)); 352 object_->data.stream_info.total_samples = value; 353 } 354 set_md5sum(const FLAC__byte value[16])355 void StreamInfo::set_md5sum(const FLAC__byte value[16]) 356 { 357 FLAC__ASSERT(is_valid()); 358 FLAC__ASSERT(0 != value); 359 std::memcpy(object_->data.stream_info.md5sum, value, 16); 360 } 361 362 363 // 364 // Padding 365 // 366 Padding()367 Padding::Padding(): 368 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false) 369 { } 370 Padding(uint32_t length)371 Padding::Padding(uint32_t length): 372 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING), /*copy=*/false) 373 { 374 set_length(length); 375 } 376 ~Padding()377 Padding::~Padding() 378 { } 379 set_length(uint32_t length)380 void Padding::set_length(uint32_t length) 381 { 382 FLAC__ASSERT(is_valid()); 383 object_->length = length; 384 } 385 386 387 // 388 // Application 389 // 390 Application()391 Application::Application(): 392 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false) 393 { } 394 ~Application()395 Application::~Application() 396 { } 397 get_id() const398 const FLAC__byte *Application::get_id() const 399 { 400 FLAC__ASSERT(is_valid()); 401 return object_->data.application.id; 402 } 403 get_data() const404 const FLAC__byte *Application::get_data() const 405 { 406 FLAC__ASSERT(is_valid()); 407 return object_->data.application.data; 408 } 409 set_id(const FLAC__byte value[4])410 void Application::set_id(const FLAC__byte value[4]) 411 { 412 FLAC__ASSERT(is_valid()); 413 FLAC__ASSERT(0 != value); 414 std::memcpy(object_->data.application.id, value, 4); 415 } 416 set_data(const FLAC__byte * data,uint32_t length)417 bool Application::set_data(const FLAC__byte *data, uint32_t length) 418 { 419 FLAC__ASSERT(is_valid()); 420 return static_cast<bool>(::FLAC__metadata_object_application_set_data(object_, const_cast<FLAC__byte*>(data), length, true)); 421 } 422 set_data(FLAC__byte * data,uint32_t length,bool copy)423 bool Application::set_data(FLAC__byte *data, uint32_t length, bool copy) 424 { 425 FLAC__ASSERT(is_valid()); 426 return static_cast<bool>(::FLAC__metadata_object_application_set_data(object_, data, length, copy)); 427 } 428 429 430 // 431 // SeekTable 432 // 433 SeekTable()434 SeekTable::SeekTable(): 435 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE), /*copy=*/false) 436 { } 437 ~SeekTable()438 SeekTable::~SeekTable() 439 { } 440 get_num_points() const441 uint32_t SeekTable::get_num_points() const 442 { 443 FLAC__ASSERT(is_valid()); 444 return object_->data.seek_table.num_points; 445 } 446 get_point(uint32_t indx) const447 ::FLAC__StreamMetadata_SeekPoint SeekTable::get_point(uint32_t indx) const 448 { 449 FLAC__ASSERT(is_valid()); 450 FLAC__ASSERT(indx < object_->data.seek_table.num_points); 451 return object_->data.seek_table.points[indx]; 452 } 453 resize_points(uint32_t new_num_points)454 bool SeekTable::resize_points(uint32_t new_num_points) 455 { 456 FLAC__ASSERT(is_valid()); 457 return static_cast<bool>(::FLAC__metadata_object_seektable_resize_points(object_, new_num_points)); 458 } 459 set_point(uint32_t indx,const::FLAC__StreamMetadata_SeekPoint & point)460 void SeekTable::set_point(uint32_t indx, const ::FLAC__StreamMetadata_SeekPoint &point) 461 { 462 FLAC__ASSERT(is_valid()); 463 FLAC__ASSERT(indx < object_->data.seek_table.num_points); 464 ::FLAC__metadata_object_seektable_set_point(object_, indx, point); 465 } 466 insert_point(uint32_t indx,const::FLAC__StreamMetadata_SeekPoint & point)467 bool SeekTable::insert_point(uint32_t indx, const ::FLAC__StreamMetadata_SeekPoint &point) 468 { 469 FLAC__ASSERT(is_valid()); 470 FLAC__ASSERT(indx <= object_->data.seek_table.num_points); 471 return static_cast<bool>(::FLAC__metadata_object_seektable_insert_point(object_, indx, point)); 472 } 473 delete_point(uint32_t indx)474 bool SeekTable::delete_point(uint32_t indx) 475 { 476 FLAC__ASSERT(is_valid()); 477 FLAC__ASSERT(indx < object_->data.seek_table.num_points); 478 return static_cast<bool>(::FLAC__metadata_object_seektable_delete_point(object_, indx)); 479 } 480 is_legal() const481 bool SeekTable::is_legal() const 482 { 483 FLAC__ASSERT(is_valid()); 484 return static_cast<bool>(::FLAC__metadata_object_seektable_is_legal(object_)); 485 } 486 template_append_placeholders(uint32_t num)487 bool SeekTable::template_append_placeholders(uint32_t num) 488 { 489 FLAC__ASSERT(is_valid()); 490 return static_cast<bool>(::FLAC__metadata_object_seektable_template_append_placeholders(object_, num)); 491 } 492 template_append_point(FLAC__uint64 sample_number)493 bool SeekTable::template_append_point(FLAC__uint64 sample_number) 494 { 495 FLAC__ASSERT(is_valid()); 496 return static_cast<bool>(::FLAC__metadata_object_seektable_template_append_point(object_, sample_number)); 497 } 498 template_append_points(FLAC__uint64 sample_numbers[],uint32_t num)499 bool SeekTable::template_append_points(FLAC__uint64 sample_numbers[], uint32_t num) 500 { 501 FLAC__ASSERT(is_valid()); 502 return static_cast<bool>(::FLAC__metadata_object_seektable_template_append_points(object_, sample_numbers, num)); 503 } 504 template_append_spaced_points(uint32_t num,FLAC__uint64 total_samples)505 bool SeekTable::template_append_spaced_points(uint32_t num, FLAC__uint64 total_samples) 506 { 507 FLAC__ASSERT(is_valid()); 508 return static_cast<bool>(::FLAC__metadata_object_seektable_template_append_spaced_points(object_, num, total_samples)); 509 } 510 template_append_spaced_points_by_samples(uint32_t samples,FLAC__uint64 total_samples)511 bool SeekTable::template_append_spaced_points_by_samples(uint32_t samples, FLAC__uint64 total_samples) 512 { 513 FLAC__ASSERT(is_valid()); 514 return static_cast<bool>(::FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(object_, samples, total_samples)); 515 } 516 template_sort(bool compact)517 bool SeekTable::template_sort(bool compact) 518 { 519 FLAC__ASSERT(is_valid()); 520 return static_cast<bool>(::FLAC__metadata_object_seektable_template_sort(object_, compact)); 521 } 522 523 524 // 525 // VorbisComment::Entry 526 // 527 Entry()528 VorbisComment::Entry::Entry() : 529 is_valid_(true), 530 entry_(), 531 field_name_(0), 532 field_name_length_(0), 533 field_value_(0), 534 field_value_length_(0) 535 { 536 zero(); 537 } 538 Entry(const char * field,uint32_t field_length)539 VorbisComment::Entry::Entry(const char *field, uint32_t field_length) : 540 is_valid_(true), 541 entry_(), 542 field_name_(0), 543 field_name_length_(0), 544 field_value_(0), 545 field_value_length_(0) 546 { 547 zero(); 548 construct(field, field_length); 549 } 550 Entry(const char * field)551 VorbisComment::Entry::Entry(const char *field) : 552 is_valid_(true), 553 entry_(), 554 field_name_(0), 555 field_name_length_(0), 556 field_value_(0), 557 field_value_length_(0) 558 { 559 zero(); 560 construct(field); 561 } 562 Entry(const char * field_name,const char * field_value,uint32_t field_value_length)563 VorbisComment::Entry::Entry(const char *field_name, const char *field_value, uint32_t field_value_length) : 564 is_valid_(true), 565 entry_(), 566 field_name_(0), 567 field_name_length_(0), 568 field_value_(0), 569 field_value_length_(0) 570 { 571 zero(); 572 construct(field_name, field_value, field_value_length); 573 } 574 Entry(const char * field_name,const char * field_value)575 VorbisComment::Entry::Entry(const char *field_name, const char *field_value) : 576 is_valid_(true), 577 entry_(), 578 field_name_(0), 579 field_name_length_(0), 580 field_value_(0), 581 field_value_length_(0) 582 { 583 zero(); 584 construct(field_name, field_value); 585 } 586 Entry(const Entry & entry)587 VorbisComment::Entry::Entry(const Entry &entry) : 588 is_valid_(true), 589 entry_(), 590 field_name_(0), 591 field_name_length_(0), 592 field_value_(0), 593 field_value_length_(0) 594 { 595 FLAC__ASSERT(entry.is_valid()); 596 zero(); 597 construct(reinterpret_cast<const char *>(entry.entry_.entry), entry.entry_.length); 598 } 599 operator =(const Entry & entry)600 VorbisComment::Entry &VorbisComment::Entry::operator=(const Entry &entry) 601 { 602 FLAC__ASSERT(entry.is_valid()); 603 clear(); 604 construct(reinterpret_cast<const char *>(entry.entry_.entry), entry.entry_.length); 605 return *this; 606 } 607 ~Entry()608 VorbisComment::Entry::~Entry() 609 { 610 clear(); 611 } 612 is_valid() const613 bool VorbisComment::Entry::is_valid() const 614 { 615 return is_valid_; 616 } 617 get_field_length() const618 uint32_t VorbisComment::Entry::get_field_length() const 619 { 620 FLAC__ASSERT(is_valid()); 621 return entry_.length; 622 } 623 get_field_name_length() const624 uint32_t VorbisComment::Entry::get_field_name_length() const 625 { 626 FLAC__ASSERT(is_valid()); 627 return field_name_length_; 628 } 629 get_field_value_length() const630 uint32_t VorbisComment::Entry::get_field_value_length() const 631 { 632 FLAC__ASSERT(is_valid()); 633 return field_value_length_; 634 } 635 get_entry() const636 ::FLAC__StreamMetadata_VorbisComment_Entry VorbisComment::Entry::get_entry() const 637 { 638 FLAC__ASSERT(is_valid()); 639 return entry_; 640 } 641 get_field() const642 const char *VorbisComment::Entry::get_field() const 643 { 644 FLAC__ASSERT(is_valid()); 645 return reinterpret_cast<const char *>(entry_.entry); 646 } 647 get_field_name() const648 const char *VorbisComment::Entry::get_field_name() const 649 { 650 FLAC__ASSERT(is_valid()); 651 return field_name_; 652 } 653 get_field_value() const654 const char *VorbisComment::Entry::get_field_value() const 655 { 656 FLAC__ASSERT(is_valid()); 657 return field_value_; 658 } 659 set_field(const char * field,uint32_t field_length)660 bool VorbisComment::Entry::set_field(const char *field, uint32_t field_length) 661 { 662 FLAC__ASSERT(is_valid()); 663 FLAC__ASSERT(0 != field); 664 665 if(!::FLAC__format_vorbiscomment_entry_is_legal(reinterpret_cast<const ::FLAC__byte*>(field), field_length)) 666 return is_valid_ = false; 667 668 clear_entry(); 669 670 if(0 == (entry_.entry = static_cast<FLAC__byte*>(safe_malloc_add_2op_(field_length, /*+*/1)))) { 671 is_valid_ = false; 672 } 673 else { 674 entry_.length = field_length; 675 std::memcpy(entry_.entry, field, field_length); 676 entry_.entry[field_length] = '\0'; 677 (void) parse_field(); 678 } 679 680 return is_valid_; 681 } 682 set_field(const char * field)683 bool VorbisComment::Entry::set_field(const char *field) 684 { 685 return set_field(field, std::strlen(field)); 686 } 687 set_field_name(const char * field_name)688 bool VorbisComment::Entry::set_field_name(const char *field_name) 689 { 690 FLAC__ASSERT(is_valid()); 691 FLAC__ASSERT(0 != field_name); 692 693 if(!::FLAC__format_vorbiscomment_entry_name_is_legal(field_name)) 694 return is_valid_ = false; 695 696 clear_field_name(); 697 698 if(0 == (field_name_ = strdup(field_name))) { 699 is_valid_ = false; 700 } 701 else { 702 field_name_length_ = std::strlen(field_name_); 703 compose_field(); 704 } 705 706 return is_valid_; 707 } 708 set_field_value(const char * field_value,uint32_t field_value_length)709 bool VorbisComment::Entry::set_field_value(const char *field_value, uint32_t field_value_length) 710 { 711 FLAC__ASSERT(is_valid()); 712 FLAC__ASSERT(0 != field_value); 713 714 if(!::FLAC__format_vorbiscomment_entry_value_is_legal(reinterpret_cast<const FLAC__byte*>(field_value), field_value_length)) 715 return is_valid_ = false; 716 717 clear_field_value(); 718 719 if(0 == (field_value_ = static_cast<char *>(safe_malloc_add_2op_(field_value_length, /*+*/1)))) { 720 is_valid_ = false; 721 } 722 else { 723 field_value_length_ = field_value_length; 724 std::memcpy(field_value_, field_value, field_value_length); 725 field_value_[field_value_length] = '\0'; 726 compose_field(); 727 } 728 729 return is_valid_; 730 } 731 set_field_value(const char * field_value)732 bool VorbisComment::Entry::set_field_value(const char *field_value) 733 { 734 return set_field_value(field_value, std::strlen(field_value)); 735 } 736 zero()737 void VorbisComment::Entry::zero() 738 { 739 is_valid_ = true; 740 entry_.length = 0; 741 entry_.entry = 0; 742 field_name_ = 0; 743 field_name_length_ = 0; 744 field_value_ = 0; 745 field_value_length_ = 0; 746 } 747 clear()748 void VorbisComment::Entry::clear() 749 { 750 clear_entry(); 751 clear_field_name(); 752 clear_field_value(); 753 is_valid_ = true; 754 } 755 clear_entry()756 void VorbisComment::Entry::clear_entry() 757 { 758 if(0 != entry_.entry) { 759 std::free(entry_.entry); 760 entry_.entry = 0; 761 entry_.length = 0; 762 } 763 } 764 clear_field_name()765 void VorbisComment::Entry::clear_field_name() 766 { 767 if(0 != field_name_) { 768 std::free(field_name_); 769 field_name_ = 0; 770 field_name_length_ = 0; 771 } 772 } 773 clear_field_value()774 void VorbisComment::Entry::clear_field_value() 775 { 776 if(0 != field_value_) { 777 std::free(field_value_); 778 field_value_ = 0; 779 field_value_length_ = 0; 780 } 781 } 782 construct(const char * field,uint32_t field_length)783 void VorbisComment::Entry::construct(const char *field, uint32_t field_length) 784 { 785 if(set_field(field, field_length)) 786 parse_field(); 787 } 788 construct(const char * field)789 void VorbisComment::Entry::construct(const char *field) 790 { 791 construct(field, std::strlen(field)); 792 } 793 construct(const char * field_name,const char * field_value,uint32_t field_value_length)794 void VorbisComment::Entry::construct(const char *field_name, const char *field_value, uint32_t field_value_length) 795 { 796 if(set_field_name(field_name) && set_field_value(field_value, field_value_length)) 797 compose_field(); 798 } 799 construct(const char * field_name,const char * field_value)800 void VorbisComment::Entry::construct(const char *field_name, const char *field_value) 801 { 802 construct(field_name, field_value, std::strlen(field_value)); 803 } 804 compose_field()805 void VorbisComment::Entry::compose_field() 806 { 807 clear_entry(); 808 809 if(0 == (entry_.entry = static_cast<FLAC__byte*>(safe_malloc_add_4op_(field_name_length_, /*+*/1, /*+*/field_value_length_, /*+*/1)))) { 810 is_valid_ = false; 811 } 812 else { 813 std::memcpy(entry_.entry, field_name_, field_name_length_); 814 entry_.length += field_name_length_; 815 std::memcpy(entry_.entry + entry_.length, "=", 1); 816 entry_.length += 1; 817 if (field_value_length_ > 0) 818 std::memcpy(entry_.entry + entry_.length, field_value_, field_value_length_); 819 entry_.length += field_value_length_; 820 entry_.entry[entry_.length] = '\0'; 821 is_valid_ = true; 822 } 823 } 824 parse_field()825 void VorbisComment::Entry::parse_field() 826 { 827 clear_field_name(); 828 clear_field_value(); 829 830 const char *p = static_cast<const char *>(std::memchr(entry_.entry, '=', entry_.length)); 831 832 if(0 == p) 833 p = reinterpret_cast<const char *>(entry_.entry) + entry_.length; 834 835 field_name_length_ = static_cast<uint32_t>(p - reinterpret_cast<const char *>(entry_.entry)); 836 if(0 == (field_name_ = static_cast<char *>(safe_malloc_add_2op_(field_name_length_, /*+*/1)))) { // +1 for the trailing \0 837 is_valid_ = false; 838 return; 839 } 840 std::memcpy(field_name_, entry_.entry, field_name_length_); 841 field_name_[field_name_length_] = '\0'; 842 843 if(entry_.length - field_name_length_ == 0) { 844 field_value_length_ = 0; 845 if(0 == (field_value_ = static_cast<char *>(safe_malloc_(0)))) { 846 is_valid_ = false; 847 return; 848 } 849 } 850 else { 851 field_value_length_ = entry_.length - field_name_length_ - 1; 852 if(0 == (field_value_ = static_cast<char *>(safe_malloc_add_2op_(field_value_length_, /*+*/1)))) { // +1 for the trailing \0 853 is_valid_ = false; 854 return; 855 } 856 std::memcpy(field_value_, ++p, field_value_length_); 857 field_value_[field_value_length_] = '\0'; 858 } 859 860 is_valid_ = true; 861 } 862 863 864 // 865 // VorbisComment 866 // 867 VorbisComment()868 VorbisComment::VorbisComment(): 869 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT), /*copy=*/false) 870 { } 871 ~VorbisComment()872 VorbisComment::~VorbisComment() 873 { } 874 get_num_comments() const875 uint32_t VorbisComment::get_num_comments() const 876 { 877 FLAC__ASSERT(is_valid()); 878 return object_->data.vorbis_comment.num_comments; 879 } 880 get_vendor_string() const881 const FLAC__byte *VorbisComment::get_vendor_string() const 882 { 883 FLAC__ASSERT(is_valid()); 884 return object_->data.vorbis_comment.vendor_string.entry; 885 } 886 get_comment(uint32_t indx) const887 VorbisComment::Entry VorbisComment::get_comment(uint32_t indx) const 888 { 889 FLAC__ASSERT(is_valid()); 890 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments); 891 return Entry(reinterpret_cast<const char *>(object_->data.vorbis_comment.comments[indx].entry), object_->data.vorbis_comment.comments[indx].length); 892 } 893 set_vendor_string(const FLAC__byte * string)894 bool VorbisComment::set_vendor_string(const FLAC__byte *string) 895 { 896 FLAC__ASSERT(is_valid()); 897 // vendor_string is a special kind of entry 898 const ::FLAC__StreamMetadata_VorbisComment_Entry vendor_string = { static_cast<FLAC__uint32>(std::strlen(reinterpret_cast<const char *>(string))), const_cast<FLAC__byte*>(string) }; // we can cheat on const-ness because we make a copy below: 899 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_set_vendor_string(object_, vendor_string, /*copy=*/true)); 900 } 901 resize_comments(uint32_t new_num_comments)902 bool VorbisComment::resize_comments(uint32_t new_num_comments) 903 { 904 FLAC__ASSERT(is_valid()); 905 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_resize_comments(object_, new_num_comments)); 906 } 907 set_comment(uint32_t indx,const VorbisComment::Entry & entry)908 bool VorbisComment::set_comment(uint32_t indx, const VorbisComment::Entry &entry) 909 { 910 FLAC__ASSERT(is_valid()); 911 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments); 912 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_set_comment(object_, indx, entry.get_entry(), /*copy=*/true)); 913 } 914 insert_comment(uint32_t indx,const VorbisComment::Entry & entry)915 bool VorbisComment::insert_comment(uint32_t indx, const VorbisComment::Entry &entry) 916 { 917 FLAC__ASSERT(is_valid()); 918 FLAC__ASSERT(indx <= object_->data.vorbis_comment.num_comments); 919 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_insert_comment(object_, indx, entry.get_entry(), /*copy=*/true)); 920 } 921 append_comment(const VorbisComment::Entry & entry)922 bool VorbisComment::append_comment(const VorbisComment::Entry &entry) 923 { 924 FLAC__ASSERT(is_valid()); 925 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_append_comment(object_, entry.get_entry(), /*copy=*/true)); 926 } 927 replace_comment(const VorbisComment::Entry & entry,bool all)928 bool VorbisComment::replace_comment(const VorbisComment::Entry &entry, bool all) 929 { 930 FLAC__ASSERT(is_valid()); 931 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_replace_comment(object_, entry.get_entry(), static_cast<FLAC__bool>(all), /*copy=*/true)); 932 } 933 delete_comment(uint32_t indx)934 bool VorbisComment::delete_comment(uint32_t indx) 935 { 936 FLAC__ASSERT(is_valid()); 937 FLAC__ASSERT(indx < object_->data.vorbis_comment.num_comments); 938 return static_cast<bool>(::FLAC__metadata_object_vorbiscomment_delete_comment(object_, indx)); 939 } 940 find_entry_from(uint32_t offset,const char * field_name)941 int VorbisComment::find_entry_from(uint32_t offset, const char *field_name) 942 { 943 FLAC__ASSERT(is_valid()); 944 return ::FLAC__metadata_object_vorbiscomment_find_entry_from(object_, offset, field_name); 945 } 946 remove_entry_matching(const char * field_name)947 int VorbisComment::remove_entry_matching(const char *field_name) 948 { 949 FLAC__ASSERT(is_valid()); 950 return ::FLAC__metadata_object_vorbiscomment_remove_entry_matching(object_, field_name); 951 } 952 remove_entries_matching(const char * field_name)953 int VorbisComment::remove_entries_matching(const char *field_name) 954 { 955 FLAC__ASSERT(is_valid()); 956 return ::FLAC__metadata_object_vorbiscomment_remove_entries_matching(object_, field_name); 957 } 958 959 960 // 961 // CueSheet::Track 962 // 963 Track()964 CueSheet::Track::Track(): 965 object_(::FLAC__metadata_object_cuesheet_track_new()) 966 { } 967 Track(const::FLAC__StreamMetadata_CueSheet_Track * track)968 CueSheet::Track::Track(const ::FLAC__StreamMetadata_CueSheet_Track *track): 969 object_(::FLAC__metadata_object_cuesheet_track_clone(track)) 970 { } 971 Track(const Track & track)972 CueSheet::Track::Track(const Track &track): 973 object_(::FLAC__metadata_object_cuesheet_track_clone(track.object_)) 974 { } 975 operator =(const Track & track)976 CueSheet::Track &CueSheet::Track::operator=(const Track &track) 977 { 978 if(0 != object_) 979 ::FLAC__metadata_object_cuesheet_track_delete(object_); 980 object_ = ::FLAC__metadata_object_cuesheet_track_clone(track.object_); 981 return *this; 982 } 983 ~Track()984 CueSheet::Track::~Track() 985 { 986 if(0 != object_) 987 ::FLAC__metadata_object_cuesheet_track_delete(object_); 988 } 989 is_valid() const990 bool CueSheet::Track::is_valid() const 991 { 992 return(0 != object_); 993 } 994 get_index(uint32_t i) const995 ::FLAC__StreamMetadata_CueSheet_Index CueSheet::Track::get_index(uint32_t i) const 996 { 997 FLAC__ASSERT(is_valid()); 998 FLAC__ASSERT(i < object_->num_indices); 999 return object_->indices[i]; 1000 } 1001 set_isrc(const char value[12])1002 void CueSheet::Track::set_isrc(const char value[12]) 1003 { 1004 FLAC__ASSERT(is_valid()); 1005 FLAC__ASSERT(0 != value); 1006 std::memcpy(object_->isrc, value, 12); 1007 object_->isrc[12] = '\0'; 1008 } 1009 set_type(uint32_t value)1010 void CueSheet::Track::set_type(uint32_t value) 1011 { 1012 FLAC__ASSERT(is_valid()); 1013 FLAC__ASSERT(value <= 1); 1014 object_->type = value; 1015 } 1016 set_index(uint32_t i,const::FLAC__StreamMetadata_CueSheet_Index & indx)1017 void CueSheet::Track::set_index(uint32_t i, const ::FLAC__StreamMetadata_CueSheet_Index &indx) 1018 { 1019 FLAC__ASSERT(is_valid()); 1020 FLAC__ASSERT(i < object_->num_indices); 1021 object_->indices[i] = indx; 1022 } 1023 1024 1025 // 1026 // CueSheet 1027 // 1028 CueSheet()1029 CueSheet::CueSheet(): 1030 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET), /*copy=*/false) 1031 { } 1032 ~CueSheet()1033 CueSheet::~CueSheet() 1034 { } 1035 get_media_catalog_number() const1036 const char *CueSheet::get_media_catalog_number() const 1037 { 1038 FLAC__ASSERT(is_valid()); 1039 return object_->data.cue_sheet.media_catalog_number; 1040 } 1041 get_lead_in() const1042 FLAC__uint64 CueSheet::get_lead_in() const 1043 { 1044 FLAC__ASSERT(is_valid()); 1045 return object_->data.cue_sheet.lead_in; 1046 } 1047 get_is_cd() const1048 bool CueSheet::get_is_cd() const 1049 { 1050 FLAC__ASSERT(is_valid()); 1051 return object_->data.cue_sheet.is_cd? true : false; 1052 } 1053 get_num_tracks() const1054 uint32_t CueSheet::get_num_tracks() const 1055 { 1056 FLAC__ASSERT(is_valid()); 1057 return object_->data.cue_sheet.num_tracks; 1058 } 1059 get_track(uint32_t i) const1060 CueSheet::Track CueSheet::get_track(uint32_t i) const 1061 { 1062 FLAC__ASSERT(is_valid()); 1063 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks); 1064 return Track(object_->data.cue_sheet.tracks + i); 1065 } 1066 set_media_catalog_number(const char value[128])1067 void CueSheet::set_media_catalog_number(const char value[128]) 1068 { 1069 FLAC__ASSERT(is_valid()); 1070 FLAC__ASSERT(0 != value); 1071 std::memcpy(object_->data.cue_sheet.media_catalog_number, value, 128); 1072 object_->data.cue_sheet.media_catalog_number[128] = '\0'; 1073 } 1074 set_lead_in(FLAC__uint64 value)1075 void CueSheet::set_lead_in(FLAC__uint64 value) 1076 { 1077 FLAC__ASSERT(is_valid()); 1078 object_->data.cue_sheet.lead_in = value; 1079 } 1080 set_is_cd(bool value)1081 void CueSheet::set_is_cd(bool value) 1082 { 1083 FLAC__ASSERT(is_valid()); 1084 object_->data.cue_sheet.is_cd = value; 1085 } 1086 set_index(uint32_t track_num,uint32_t index_num,const::FLAC__StreamMetadata_CueSheet_Index & indx)1087 void CueSheet::set_index(uint32_t track_num, uint32_t index_num, const ::FLAC__StreamMetadata_CueSheet_Index &indx) 1088 { 1089 FLAC__ASSERT(is_valid()); 1090 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks); 1091 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices); 1092 object_->data.cue_sheet.tracks[track_num].indices[index_num] = indx; 1093 } 1094 resize_indices(uint32_t track_num,uint32_t new_num_indices)1095 bool CueSheet::resize_indices(uint32_t track_num, uint32_t new_num_indices) 1096 { 1097 FLAC__ASSERT(is_valid()); 1098 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks); 1099 return static_cast<bool>(::FLAC__metadata_object_cuesheet_track_resize_indices(object_, track_num, new_num_indices)); 1100 } 1101 insert_index(uint32_t track_num,uint32_t index_num,const::FLAC__StreamMetadata_CueSheet_Index & indx)1102 bool CueSheet::insert_index(uint32_t track_num, uint32_t index_num, const ::FLAC__StreamMetadata_CueSheet_Index &indx) 1103 { 1104 FLAC__ASSERT(is_valid()); 1105 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks); 1106 FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices); 1107 return static_cast<bool>(::FLAC__metadata_object_cuesheet_track_insert_index(object_, track_num, index_num, indx)); 1108 } 1109 insert_blank_index(uint32_t track_num,uint32_t index_num)1110 bool CueSheet::insert_blank_index(uint32_t track_num, uint32_t index_num) 1111 { 1112 FLAC__ASSERT(is_valid()); 1113 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks); 1114 FLAC__ASSERT(index_num <= object_->data.cue_sheet.tracks[track_num].num_indices); 1115 return static_cast<bool>(::FLAC__metadata_object_cuesheet_track_insert_blank_index(object_, track_num, index_num)); 1116 } 1117 delete_index(uint32_t track_num,uint32_t index_num)1118 bool CueSheet::delete_index(uint32_t track_num, uint32_t index_num) 1119 { 1120 FLAC__ASSERT(is_valid()); 1121 FLAC__ASSERT(track_num < object_->data.cue_sheet.num_tracks); 1122 FLAC__ASSERT(index_num < object_->data.cue_sheet.tracks[track_num].num_indices); 1123 return static_cast<bool>(::FLAC__metadata_object_cuesheet_track_delete_index(object_, track_num, index_num)); 1124 } 1125 resize_tracks(uint32_t new_num_tracks)1126 bool CueSheet::resize_tracks(uint32_t new_num_tracks) 1127 { 1128 FLAC__ASSERT(is_valid()); 1129 return static_cast<bool>(::FLAC__metadata_object_cuesheet_resize_tracks(object_, new_num_tracks)); 1130 } 1131 set_track(uint32_t i,const CueSheet::Track & track)1132 bool CueSheet::set_track(uint32_t i, const CueSheet::Track &track) 1133 { 1134 FLAC__ASSERT(is_valid()); 1135 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks); 1136 // We can safely const_cast since copy=true 1137 return static_cast<bool>(::FLAC__metadata_object_cuesheet_set_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true)); 1138 } 1139 insert_track(uint32_t i,const CueSheet::Track & track)1140 bool CueSheet::insert_track(uint32_t i, const CueSheet::Track &track) 1141 { 1142 FLAC__ASSERT(is_valid()); 1143 FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks); 1144 // We can safely const_cast since copy=true 1145 return static_cast<bool>(::FLAC__metadata_object_cuesheet_insert_track(object_, i, const_cast< ::FLAC__StreamMetadata_CueSheet_Track*>(track.get_track()), /*copy=*/true)); 1146 } 1147 insert_blank_track(uint32_t i)1148 bool CueSheet::insert_blank_track(uint32_t i) 1149 { 1150 FLAC__ASSERT(is_valid()); 1151 FLAC__ASSERT(i <= object_->data.cue_sheet.num_tracks); 1152 return static_cast<bool>(::FLAC__metadata_object_cuesheet_insert_blank_track(object_, i)); 1153 } 1154 delete_track(uint32_t i)1155 bool CueSheet::delete_track(uint32_t i) 1156 { 1157 FLAC__ASSERT(is_valid()); 1158 FLAC__ASSERT(i < object_->data.cue_sheet.num_tracks); 1159 return static_cast<bool>(::FLAC__metadata_object_cuesheet_delete_track(object_, i)); 1160 } 1161 is_legal(bool check_cd_da_subset,const char ** violation) const1162 bool CueSheet::is_legal(bool check_cd_da_subset, const char **violation) const 1163 { 1164 FLAC__ASSERT(is_valid()); 1165 return static_cast<bool>(::FLAC__metadata_object_cuesheet_is_legal(object_, check_cd_da_subset, violation)); 1166 } 1167 calculate_cddb_id() const1168 FLAC__uint32 CueSheet::calculate_cddb_id() const 1169 { 1170 FLAC__ASSERT(is_valid()); 1171 return ::FLAC__metadata_object_cuesheet_calculate_cddb_id(object_); 1172 } 1173 1174 1175 // 1176 // Picture 1177 // 1178 Picture()1179 Picture::Picture(): 1180 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE), /*copy=*/false) 1181 { } 1182 ~Picture()1183 Picture::~Picture() 1184 { } 1185 get_type() const1186 ::FLAC__StreamMetadata_Picture_Type Picture::get_type() const 1187 { 1188 FLAC__ASSERT(is_valid()); 1189 return object_->data.picture.type; 1190 } 1191 get_mime_type() const1192 const char *Picture::get_mime_type() const 1193 { 1194 FLAC__ASSERT(is_valid()); 1195 return object_->data.picture.mime_type; 1196 } 1197 get_description() const1198 const FLAC__byte *Picture::get_description() const 1199 { 1200 FLAC__ASSERT(is_valid()); 1201 return object_->data.picture.description; 1202 } 1203 get_width() const1204 FLAC__uint32 Picture::get_width() const 1205 { 1206 FLAC__ASSERT(is_valid()); 1207 return object_->data.picture.width; 1208 } 1209 get_height() const1210 FLAC__uint32 Picture::get_height() const 1211 { 1212 FLAC__ASSERT(is_valid()); 1213 return object_->data.picture.height; 1214 } 1215 get_depth() const1216 FLAC__uint32 Picture::get_depth() const 1217 { 1218 FLAC__ASSERT(is_valid()); 1219 return object_->data.picture.depth; 1220 } 1221 get_colors() const1222 FLAC__uint32 Picture::get_colors() const 1223 { 1224 FLAC__ASSERT(is_valid()); 1225 return object_->data.picture.colors; 1226 } 1227 get_data_length() const1228 FLAC__uint32 Picture::get_data_length() const 1229 { 1230 FLAC__ASSERT(is_valid()); 1231 return object_->data.picture.data_length; 1232 } 1233 get_data() const1234 const FLAC__byte *Picture::get_data() const 1235 { 1236 FLAC__ASSERT(is_valid()); 1237 return object_->data.picture.data; 1238 } 1239 set_type(::FLAC__StreamMetadata_Picture_Type type)1240 void Picture::set_type(::FLAC__StreamMetadata_Picture_Type type) 1241 { 1242 FLAC__ASSERT(is_valid()); 1243 object_->data.picture.type = type; 1244 } 1245 set_mime_type(const char * string)1246 bool Picture::set_mime_type(const char *string) 1247 { 1248 FLAC__ASSERT(is_valid()); 1249 // We can safely const_cast since copy=true 1250 return static_cast<bool>(::FLAC__metadata_object_picture_set_mime_type(object_, const_cast<char*>(string), /*copy=*/true)); 1251 } 1252 set_description(const FLAC__byte * string)1253 bool Picture::set_description(const FLAC__byte *string) 1254 { 1255 FLAC__ASSERT(is_valid()); 1256 // We can safely const_cast since copy=true 1257 return static_cast<bool>(::FLAC__metadata_object_picture_set_description(object_, const_cast<FLAC__byte*>(string), /*copy=*/true)); 1258 } 1259 set_width(FLAC__uint32 value) const1260 void Picture::set_width(FLAC__uint32 value) const 1261 { 1262 FLAC__ASSERT(is_valid()); 1263 object_->data.picture.width = value; 1264 } 1265 set_height(FLAC__uint32 value) const1266 void Picture::set_height(FLAC__uint32 value) const 1267 { 1268 FLAC__ASSERT(is_valid()); 1269 object_->data.picture.height = value; 1270 } 1271 set_depth(FLAC__uint32 value) const1272 void Picture::set_depth(FLAC__uint32 value) const 1273 { 1274 FLAC__ASSERT(is_valid()); 1275 object_->data.picture.depth = value; 1276 } 1277 set_colors(FLAC__uint32 value) const1278 void Picture::set_colors(FLAC__uint32 value) const 1279 { 1280 FLAC__ASSERT(is_valid()); 1281 object_->data.picture.colors = value; 1282 } 1283 set_data(const FLAC__byte * data,FLAC__uint32 data_length)1284 bool Picture::set_data(const FLAC__byte *data, FLAC__uint32 data_length) 1285 { 1286 FLAC__ASSERT(is_valid()); 1287 // We can safely const_cast since copy=true 1288 return static_cast<bool>(::FLAC__metadata_object_picture_set_data(object_, const_cast<FLAC__byte*>(data), data_length, /*copy=*/true)); 1289 } 1290 is_legal(const char ** violation)1291 bool Picture::is_legal(const char **violation) 1292 { 1293 FLAC__ASSERT(is_valid()); 1294 return static_cast<bool>(::FLAC__metadata_object_picture_is_legal(object_, violation)); 1295 } 1296 1297 1298 // 1299 // Unknown 1300 // 1301 Unknown()1302 Unknown::Unknown(): 1303 Prototype(FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION), /*copy=*/false) 1304 { } 1305 ~Unknown()1306 Unknown::~Unknown() 1307 { } 1308 get_data() const1309 const FLAC__byte *Unknown::get_data() const 1310 { 1311 FLAC__ASSERT(is_valid()); 1312 return object_->data.application.data; 1313 } 1314 set_data(const FLAC__byte * data,uint32_t length)1315 bool Unknown::set_data(const FLAC__byte *data, uint32_t length) 1316 { 1317 FLAC__ASSERT(is_valid()); 1318 return static_cast<bool>(::FLAC__metadata_object_application_set_data(object_, const_cast<FLAC__byte*>(data), length, true)); 1319 } 1320 set_data(FLAC__byte * data,uint32_t length,bool copy)1321 bool Unknown::set_data(FLAC__byte *data, uint32_t length, bool copy) 1322 { 1323 FLAC__ASSERT(is_valid()); 1324 return static_cast<bool>(::FLAC__metadata_object_application_set_data(object_, data, length, copy)); 1325 } 1326 1327 1328 // ============================================================ 1329 // 1330 // Level 0 1331 // 1332 // ============================================================ 1333 get_streaminfo(const char * filename,StreamInfo & streaminfo)1334 FLACPP_API bool get_streaminfo(const char *filename, StreamInfo &streaminfo) 1335 { 1336 FLAC__ASSERT(0 != filename); 1337 1338 ::FLAC__StreamMetadata object; 1339 1340 if(::FLAC__metadata_get_streaminfo(filename, &object)) { 1341 streaminfo = object; 1342 return true; 1343 } 1344 else 1345 return false; 1346 } 1347 get_tags(const char * filename,VorbisComment * & tags)1348 FLACPP_API bool get_tags(const char *filename, VorbisComment *&tags) 1349 { 1350 FLAC__ASSERT(0 != filename); 1351 1352 ::FLAC__StreamMetadata *object; 1353 1354 tags = 0; 1355 1356 if(::FLAC__metadata_get_tags(filename, &object)) { 1357 tags = new VorbisComment(object, /*copy=*/false); 1358 return true; 1359 } 1360 else 1361 return false; 1362 } 1363 get_tags(const char * filename,VorbisComment & tags)1364 FLACPP_API bool get_tags(const char *filename, VorbisComment &tags) 1365 { 1366 FLAC__ASSERT(0 != filename); 1367 1368 ::FLAC__StreamMetadata *object; 1369 1370 if(::FLAC__metadata_get_tags(filename, &object)) { 1371 tags.assign(object, /*copy=*/false); 1372 return true; 1373 } 1374 else 1375 return false; 1376 } 1377 get_cuesheet(const char * filename,CueSheet * & cuesheet)1378 FLACPP_API bool get_cuesheet(const char *filename, CueSheet *&cuesheet) 1379 { 1380 FLAC__ASSERT(0 != filename); 1381 1382 ::FLAC__StreamMetadata *object; 1383 1384 cuesheet = 0; 1385 1386 if(::FLAC__metadata_get_cuesheet(filename, &object)) { 1387 cuesheet = new CueSheet(object, /*copy=*/false); 1388 return true; 1389 } 1390 else 1391 return false; 1392 } 1393 get_cuesheet(const char * filename,CueSheet & cuesheet)1394 FLACPP_API bool get_cuesheet(const char *filename, CueSheet &cuesheet) 1395 { 1396 FLAC__ASSERT(0 != filename); 1397 1398 ::FLAC__StreamMetadata *object; 1399 1400 if(::FLAC__metadata_get_cuesheet(filename, &object)) { 1401 cuesheet.assign(object, /*copy=*/false); 1402 return true; 1403 } 1404 else 1405 return false; 1406 } 1407 get_picture(const char * filename,Picture * & picture,::FLAC__StreamMetadata_Picture_Type type,const char * mime_type,const FLAC__byte * description,uint32_t max_width,uint32_t max_height,uint32_t max_depth,uint32_t max_colors)1408 FLACPP_API bool get_picture(const char *filename, Picture *&picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, uint32_t max_width, uint32_t max_height, uint32_t max_depth, uint32_t max_colors) 1409 { 1410 FLAC__ASSERT(0 != filename); 1411 1412 ::FLAC__StreamMetadata *object; 1413 1414 picture = 0; 1415 1416 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) { 1417 picture = new Picture(object, /*copy=*/false); 1418 return true; 1419 } 1420 else 1421 return false; 1422 } 1423 get_picture(const char * filename,Picture & picture,::FLAC__StreamMetadata_Picture_Type type,const char * mime_type,const FLAC__byte * description,uint32_t max_width,uint32_t max_height,uint32_t max_depth,uint32_t max_colors)1424 FLACPP_API bool get_picture(const char *filename, Picture &picture, ::FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, uint32_t max_width, uint32_t max_height, uint32_t max_depth, uint32_t max_colors) 1425 { 1426 FLAC__ASSERT(0 != filename); 1427 1428 ::FLAC__StreamMetadata *object; 1429 1430 if(::FLAC__metadata_get_picture(filename, &object, type, mime_type, description, max_width, max_height, max_depth, max_colors)) { 1431 picture.assign(object, /*copy=*/false); 1432 return true; 1433 } 1434 else 1435 return false; 1436 } 1437 1438 1439 // ============================================================ 1440 // 1441 // Level 1 1442 // 1443 // ============================================================ 1444 SimpleIterator()1445 SimpleIterator::SimpleIterator(): 1446 iterator_(::FLAC__metadata_simple_iterator_new()) 1447 { } 1448 ~SimpleIterator()1449 SimpleIterator::~SimpleIterator() 1450 { 1451 clear(); 1452 } 1453 clear()1454 void SimpleIterator::clear() 1455 { 1456 if(0 != iterator_) 1457 FLAC__metadata_simple_iterator_delete(iterator_); 1458 iterator_ = 0; 1459 } 1460 init(const char * filename,bool read_only,bool preserve_file_stats)1461 bool SimpleIterator::init(const char *filename, bool read_only, bool preserve_file_stats) 1462 { 1463 FLAC__ASSERT(0 != filename); 1464 FLAC__ASSERT(is_valid()); 1465 return static_cast<bool>(::FLAC__metadata_simple_iterator_init(iterator_, filename, read_only, preserve_file_stats)); 1466 } 1467 is_valid() const1468 bool SimpleIterator::is_valid() const 1469 { 1470 return 0 != iterator_; 1471 } 1472 status()1473 SimpleIterator::Status SimpleIterator::status() 1474 { 1475 FLAC__ASSERT(is_valid()); 1476 return Status(::FLAC__metadata_simple_iterator_status(iterator_)); 1477 } 1478 is_writable() const1479 bool SimpleIterator::is_writable() const 1480 { 1481 FLAC__ASSERT(is_valid()); 1482 return static_cast<bool>(::FLAC__metadata_simple_iterator_is_writable(iterator_)); 1483 } 1484 next()1485 bool SimpleIterator::next() 1486 { 1487 FLAC__ASSERT(is_valid()); 1488 return static_cast<bool>(::FLAC__metadata_simple_iterator_next(iterator_)); 1489 } 1490 prev()1491 bool SimpleIterator::prev() 1492 { 1493 FLAC__ASSERT(is_valid()); 1494 return static_cast<bool>(::FLAC__metadata_simple_iterator_prev(iterator_)); 1495 } 1496 1497 //@@@@ add to tests is_last() const1498 bool SimpleIterator::is_last() const 1499 { 1500 FLAC__ASSERT(is_valid()); 1501 return static_cast<bool>(::FLAC__metadata_simple_iterator_is_last(iterator_)); 1502 } 1503 1504 //@@@@ add to tests get_block_offset() const1505 off_t SimpleIterator::get_block_offset() const 1506 { 1507 FLAC__ASSERT(is_valid()); 1508 return ::FLAC__metadata_simple_iterator_get_block_offset(iterator_); 1509 } 1510 get_block_type() const1511 ::FLAC__MetadataType SimpleIterator::get_block_type() const 1512 { 1513 FLAC__ASSERT(is_valid()); 1514 return ::FLAC__metadata_simple_iterator_get_block_type(iterator_); 1515 } 1516 1517 //@@@@ add to tests get_block_length() const1518 uint32_t SimpleIterator::get_block_length() const 1519 { 1520 FLAC__ASSERT(is_valid()); 1521 return ::FLAC__metadata_simple_iterator_get_block_length(iterator_); 1522 } 1523 1524 //@@@@ add to tests get_application_id(FLAC__byte * id)1525 bool SimpleIterator::get_application_id(FLAC__byte *id) 1526 { 1527 FLAC__ASSERT(is_valid()); 1528 return static_cast<bool>(::FLAC__metadata_simple_iterator_get_application_id(iterator_, id)); 1529 } 1530 get_block()1531 Prototype *SimpleIterator::get_block() 1532 { 1533 FLAC__ASSERT(is_valid()); 1534 return local::construct_block(::FLAC__metadata_simple_iterator_get_block(iterator_)); 1535 } 1536 set_block(Prototype * block,bool use_padding)1537 bool SimpleIterator::set_block(Prototype *block, bool use_padding) 1538 { 1539 FLAC__ASSERT(0 != block); 1540 FLAC__ASSERT(is_valid()); 1541 return static_cast<bool>(::FLAC__metadata_simple_iterator_set_block(iterator_, block->object_, use_padding)); 1542 } 1543 insert_block_after(Prototype * block,bool use_padding)1544 bool SimpleIterator::insert_block_after(Prototype *block, bool use_padding) 1545 { 1546 FLAC__ASSERT(0 != block); 1547 FLAC__ASSERT(is_valid()); 1548 return static_cast<bool>(::FLAC__metadata_simple_iterator_insert_block_after(iterator_, block->object_, use_padding)); 1549 } 1550 delete_block(bool use_padding)1551 bool SimpleIterator::delete_block(bool use_padding) 1552 { 1553 FLAC__ASSERT(is_valid()); 1554 return static_cast<bool>(::FLAC__metadata_simple_iterator_delete_block(iterator_, use_padding)); 1555 } 1556 1557 1558 // ============================================================ 1559 // 1560 // Level 2 1561 // 1562 // ============================================================ 1563 Chain()1564 Chain::Chain(): 1565 chain_(::FLAC__metadata_chain_new()) 1566 { } 1567 ~Chain()1568 Chain::~Chain() 1569 { 1570 clear(); 1571 } 1572 clear()1573 void Chain::clear() 1574 { 1575 if(0 != chain_) 1576 FLAC__metadata_chain_delete(chain_); 1577 chain_ = 0; 1578 } 1579 is_valid() const1580 bool Chain::is_valid() const 1581 { 1582 return 0 != chain_; 1583 } 1584 status()1585 Chain::Status Chain::status() 1586 { 1587 FLAC__ASSERT(is_valid()); 1588 return Status(::FLAC__metadata_chain_status(chain_)); 1589 } 1590 read(const char * filename,bool is_ogg)1591 bool Chain::read(const char *filename, bool is_ogg) 1592 { 1593 FLAC__ASSERT(0 != filename); 1594 FLAC__ASSERT(is_valid()); 1595 return is_ogg? 1596 static_cast<bool>(::FLAC__metadata_chain_read_ogg(chain_, filename)) : 1597 static_cast<bool>(::FLAC__metadata_chain_read(chain_, filename)) 1598 ; 1599 } 1600 read(FLAC__IOHandle handle,::FLAC__IOCallbacks callbacks,bool is_ogg)1601 bool Chain::read(FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, bool is_ogg) 1602 { 1603 FLAC__ASSERT(is_valid()); 1604 return is_ogg? 1605 static_cast<bool>(::FLAC__metadata_chain_read_ogg_with_callbacks(chain_, handle, callbacks)) : 1606 static_cast<bool>(::FLAC__metadata_chain_read_with_callbacks(chain_, handle, callbacks)) 1607 ; 1608 } 1609 check_if_tempfile_needed(bool use_padding)1610 bool Chain::check_if_tempfile_needed(bool use_padding) 1611 { 1612 FLAC__ASSERT(is_valid()); 1613 return static_cast<bool>(::FLAC__metadata_chain_check_if_tempfile_needed(chain_, use_padding)); 1614 } 1615 write(bool use_padding,bool preserve_file_stats)1616 bool Chain::write(bool use_padding, bool preserve_file_stats) 1617 { 1618 FLAC__ASSERT(is_valid()); 1619 return static_cast<bool>(::FLAC__metadata_chain_write(chain_, use_padding, preserve_file_stats)); 1620 } 1621 write(bool use_padding,::FLAC__IOHandle handle,::FLAC__IOCallbacks callbacks)1622 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks) 1623 { 1624 FLAC__ASSERT(is_valid()); 1625 return static_cast<bool>(::FLAC__metadata_chain_write_with_callbacks(chain_, use_padding, handle, callbacks)); 1626 } 1627 write(bool use_padding,::FLAC__IOHandle handle,::FLAC__IOCallbacks callbacks,::FLAC__IOHandle temp_handle,::FLAC__IOCallbacks temp_callbacks)1628 bool Chain::write(bool use_padding, ::FLAC__IOHandle handle, ::FLAC__IOCallbacks callbacks, ::FLAC__IOHandle temp_handle, ::FLAC__IOCallbacks temp_callbacks) 1629 { 1630 FLAC__ASSERT(is_valid()); 1631 return static_cast<bool>(::FLAC__metadata_chain_write_with_callbacks_and_tempfile(chain_, use_padding, handle, callbacks, temp_handle, temp_callbacks)); 1632 } 1633 merge_padding()1634 void Chain::merge_padding() 1635 { 1636 FLAC__ASSERT(is_valid()); 1637 ::FLAC__metadata_chain_merge_padding(chain_); 1638 } 1639 sort_padding()1640 void Chain::sort_padding() 1641 { 1642 FLAC__ASSERT(is_valid()); 1643 ::FLAC__metadata_chain_sort_padding(chain_); 1644 } 1645 1646 Iterator()1647 Iterator::Iterator(): 1648 iterator_(::FLAC__metadata_iterator_new()) 1649 { } 1650 ~Iterator()1651 Iterator::~Iterator() 1652 { 1653 clear(); 1654 } 1655 clear()1656 void Iterator::clear() 1657 { 1658 if(0 != iterator_) 1659 FLAC__metadata_iterator_delete(iterator_); 1660 iterator_ = 0; 1661 } 1662 is_valid() const1663 bool Iterator::is_valid() const 1664 { 1665 return 0 != iterator_; 1666 } 1667 init(Chain & chain)1668 void Iterator::init(Chain &chain) 1669 { 1670 FLAC__ASSERT(is_valid()); 1671 FLAC__ASSERT(chain.is_valid()); 1672 ::FLAC__metadata_iterator_init(iterator_, chain.chain_); 1673 } 1674 next()1675 bool Iterator::next() 1676 { 1677 FLAC__ASSERT(is_valid()); 1678 return static_cast<bool>(::FLAC__metadata_iterator_next(iterator_)); 1679 } 1680 prev()1681 bool Iterator::prev() 1682 { 1683 FLAC__ASSERT(is_valid()); 1684 return static_cast<bool>(::FLAC__metadata_iterator_prev(iterator_)); 1685 } 1686 get_block_type() const1687 ::FLAC__MetadataType Iterator::get_block_type() const 1688 { 1689 FLAC__ASSERT(is_valid()); 1690 return ::FLAC__metadata_iterator_get_block_type(iterator_); 1691 } 1692 get_block()1693 Prototype *Iterator::get_block() 1694 { 1695 FLAC__ASSERT(is_valid()); 1696 Prototype *block = local::construct_block(::FLAC__metadata_iterator_get_block(iterator_)); 1697 if(0 != block) 1698 block->set_reference(true); 1699 return block; 1700 } 1701 set_block(Prototype * block)1702 bool Iterator::set_block(Prototype *block) 1703 { 1704 FLAC__ASSERT(0 != block); 1705 FLAC__ASSERT(is_valid()); 1706 bool ret = static_cast<bool>(::FLAC__metadata_iterator_set_block(iterator_, block->object_)); 1707 if(ret) { 1708 block->set_reference(true); 1709 delete block; 1710 } 1711 return ret; 1712 } 1713 delete_block(bool replace_with_padding)1714 bool Iterator::delete_block(bool replace_with_padding) 1715 { 1716 FLAC__ASSERT(is_valid()); 1717 return static_cast<bool>(::FLAC__metadata_iterator_delete_block(iterator_, replace_with_padding)); 1718 } 1719 insert_block_before(Prototype * block)1720 bool Iterator::insert_block_before(Prototype *block) 1721 { 1722 FLAC__ASSERT(0 != block); 1723 FLAC__ASSERT(is_valid()); 1724 bool ret = static_cast<bool>(::FLAC__metadata_iterator_insert_block_before(iterator_, block->object_)); 1725 if(ret) { 1726 block->set_reference(true); 1727 delete block; 1728 } 1729 return ret; 1730 } 1731 insert_block_after(Prototype * block)1732 bool Iterator::insert_block_after(Prototype *block) 1733 { 1734 FLAC__ASSERT(0 != block); 1735 FLAC__ASSERT(is_valid()); 1736 bool ret = static_cast<bool>(::FLAC__metadata_iterator_insert_block_after(iterator_, block->object_)); 1737 if(ret) { 1738 block->set_reference(true); 1739 delete block; 1740 } 1741 return ret; 1742 } 1743 1744 } // namespace Metadata 1745 } // namespace FLAC 1746