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