1/* flac - Command-line FLAC encoder/decoder 2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19#if HAVE_CONFIG_H 20# include <config.h> 21#endif 22 23#if defined _MSC_VER || defined __MINGW32__ 24#include <sys/types.h> /* for off_t */ 25#if _MSC_VER <= 1600 /* @@@ [2G limit] */ 26#define fseeko fseek 27#define ftello ftell 28#endif 29#endif 30#include <stdio.h> /* for FILE etc. */ 31#include <stdlib.h> /* for calloc() etc. */ 32#include <string.h> /* for memcmp() etc. */ 33#include "FLAC/assert.h" 34#include "FLAC/metadata.h" 35#include "share/alloc.h" 36#include "foreign_metadata.h" 37 38#ifdef min 39#undef min 40#endif 41#define min(x,y) ((x)<(y)?(x):(y)) 42 43 44static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "aiff" , "riff" }; 45 46static FLAC__uint32 unpack32be_(const FLAC__byte *b) 47{ 48 return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3]; 49} 50 51static FLAC__uint32 unpack32le_(const FLAC__byte *b) 52{ 53 return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24); 54} 55 56static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error) 57{ 58 static FLAC__byte buffer[4096]; 59 size_t left; 60 for(left = size; left > 0; ) { 61 size_t need = min(sizeof(buffer), left); 62 if(fread(buffer, 1, need, fin) < need) { 63 if(error) *error = read_error; 64 return false; 65 } 66 if(fwrite(buffer, 1, need, fout) < need) { 67 if(error) *error = write_error; 68 return false; 69 } 70 left -= need; 71 } 72 return true; 73} 74 75static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error) 76{ 77 foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/); 78 if(fb) { 79 fb[fm->num_blocks].offset = offset; 80 fb[fm->num_blocks].size = size; 81 fm->num_blocks++; 82 fm->blocks = fb; 83 return true; 84 } 85 if(error) *error = "out of memory"; 86 return false; 87} 88 89static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error) 90{ 91 FLAC__byte buffer[12]; 92 off_t offset, eof_offset; 93 if((offset = ftello(f)) < 0) { 94 if(error) *error = "ftello() error (001)"; 95 return false; 96 } 97 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) { 98 if(error) *error = "unsupported FORM layout (002)"; 99 return false; 100 } 101 if(!append_block_(fm, offset, 12, error)) 102 return false; 103 eof_offset = 8 + unpack32be_(buffer+4); 104 while(!feof(f)) { 105 FLAC__uint32 size; 106 if((offset = ftello(f)) < 0) { 107 if(error) *error = "ftello() error (003)"; 108 return false; 109 } 110 if((size = fread(buffer, 1, 8, f)) < 8) { 111 if(size == 0 && feof(f)) 112 break; 113 if(error) *error = "invalid AIFF file (004)"; 114 return false; 115 } 116 size = unpack32be_(buffer+4); 117 /* check if pad byte needed */ 118 if(size & 1) 119 size++; 120 if(!memcmp(buffer, "COMM", 4)) { 121 if(fm->format_block) { 122 if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)"; 123 return false; 124 } 125 if(fm->audio_block) { 126 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)"; 127 return false; 128 } 129 fm->format_block = fm->num_blocks; 130 } 131 else if(!memcmp(buffer, "SSND", 4)) { 132 if(fm->audio_block) { 133 if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)"; 134 return false; 135 } 136 if(!fm->format_block) { 137 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)"; 138 return false; 139 } 140 fm->audio_block = fm->num_blocks; 141 /* read #offset bytes */ 142 if(fread(buffer+8, 1, 4, f) < 4) { 143 if(error) *error = "invalid AIFF file (009)"; 144 return false; 145 } 146 fm->ssnd_offset_size = unpack32be_(buffer+8); 147 if(fseeko(f, -4, SEEK_CUR) < 0) { 148 if(error) *error = "invalid AIFF file: seek error (010)"; 149 return false; 150 } 151 } 152 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error)) 153 return false; 154 if(fseeko(f, size, SEEK_CUR) < 0) { 155 if(error) *error = "invalid AIFF file: seek error (011)"; 156 return false; 157 } 158 } 159 if(eof_offset != ftello(f)) { 160 if(error) *error = "invalid AIFF file: unexpected EOF (012)"; 161 return false; 162 } 163 if(!fm->format_block) { 164 if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)"; 165 return false; 166 } 167 if(!fm->audio_block) { 168 if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)"; 169 return false; 170 } 171 return true; 172} 173 174static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error) 175{ 176 FLAC__byte buffer[12]; 177 off_t offset, eof_offset; 178 if((offset = ftello(f)) < 0) { 179 if(error) *error = "ftello() error (001)"; 180 return false; 181 } 182 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) { 183 if(error) *error = "unsupported RIFF layout (002)"; 184 return false; 185 } 186 if(!append_block_(fm, offset, 12, error)) 187 return false; 188 eof_offset = 8 + unpack32le_(buffer+4); 189 while(!feof(f)) { 190 FLAC__uint32 size; 191 if((offset = ftello(f)) < 0) { 192 if(error) *error = "ftello() error (003)"; 193 return false; 194 } 195 if((size = fread(buffer, 1, 8, f)) < 8) { 196 if(size == 0 && feof(f)) 197 break; 198 if(error) *error = "invalid WAVE file (004)"; 199 return false; 200 } 201 size = unpack32le_(buffer+4); 202 /* check if pad byte needed */ 203 if(size & 1) 204 size++; 205 if(!memcmp(buffer, "fmt ", 4)) { 206 if(fm->format_block) { 207 if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)"; 208 return false; 209 } 210 if(fm->audio_block) { 211 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)"; 212 return false; 213 } 214 fm->format_block = fm->num_blocks; 215 } 216 else if(!memcmp(buffer, "data", 4)) { 217 if(fm->audio_block) { 218 if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)"; 219 return false; 220 } 221 if(!fm->format_block) { 222 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)"; 223 return false; 224 } 225 fm->audio_block = fm->num_blocks; 226 } 227 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error)) 228 return false; 229 if(fseeko(f, size, SEEK_CUR) < 0) { 230 if(error) *error = "invalid WAVE file: seek error (009)"; 231 return false; 232 } 233 } 234 if(eof_offset != ftello(f)) { 235 if(error) *error = "invalid WAVE file: unexpected EOF (010)"; 236 return false; 237 } 238 if(!fm->format_block) { 239 if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)"; 240 return false; 241 } 242 if(!fm->audio_block) { 243 if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)"; 244 return false; 245 } 246 return true; 247} 248 249static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error) 250{ 251 FLAC__byte buffer[4]; 252 const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; 253 size_t block_num = 0; 254 FLAC__ASSERT(sizeof(buffer) >= ID_LEN); 255 while(block_num < fm->num_blocks) { 256 /* find next matching padding block */ 257 do { 258 /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */ 259 if(!FLAC__metadata_simple_iterator_next(it)) { 260 if(error) *error = "no matching PADDING block found (004)"; 261 return false; 262 } 263 } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING); 264 if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) { 265 if(error) *error = "PADDING block with wrong size found (005)"; 266 return false; 267 } 268 /* transfer chunk into APPLICATION block */ 269 /* first set up the file pointers */ 270 if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) { 271 if(error) *error = "seek failed in WAVE/AIFF file (006)"; 272 return false; 273 } 274 if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) { 275 if(error) *error = "seek failed in FLAC file (007)"; 276 return false; 277 } 278 /* update the type */ 279 buffer[0] = FLAC__METADATA_TYPE_APPLICATION; 280 if(FLAC__metadata_simple_iterator_is_last(it)) 281 buffer[0] |= 0x80; /*MAGIC number*/ 282 if(fwrite(buffer, 1, 1, fout) < 1) { 283 if(error) *error = "write failed in FLAC file (008)"; 284 return false; 285 } 286 /* length stays the same so skip over it */ 287 if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) { 288 if(error) *error = "seek failed in FLAC file (009)"; 289 return false; 290 } 291 /* write the APPLICATION ID */ 292 memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN); 293 if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) { 294 if(error) *error = "write failed in FLAC file (010)"; 295 return false; 296 } 297 /* transfer the foreign metadata */ 298 if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)")) 299 return false; 300 block_num++; 301 } 302 return true; 303} 304 305static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error) 306{ 307 FLAC__byte id[4], buffer[12]; 308 off_t offset; 309 FLAC__bool type_found = false; 310 311 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8); 312 313 while(FLAC__metadata_simple_iterator_next(it)) { 314 if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION) 315 continue; 316 if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) { 317 if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (003)"; 318 return false; 319 } 320 if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id))) 321 continue; 322 offset = FLAC__metadata_simple_iterator_get_block_offset(it); 323 /* skip over header and app ID */ 324 offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8; 325 offset += sizeof(id); 326 /* look for format or audio blocks */ 327 if(fseek(f, offset, SEEK_SET) < 0) { 328 if(error) *error = "seek error (004)"; 329 return false; 330 } 331 if(fread(buffer, 1, 4, f) != 4) { 332 if(error) *error = "read error (005)"; 333 return false; 334 } 335 if(fm->num_blocks == 0) { 336 if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && 0 == memcmp(buffer, "RIFF", 4)) 337 type_found = true; 338 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) 339 type_found = true; 340 else { 341 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)"; 342 return false; 343 } 344 } 345 else if(!type_found) { 346 FLAC__ASSERT(0); 347 /* double protection: */ 348 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)"; 349 return false; 350 } 351 else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) { 352 if(!memcmp(buffer, "fmt ", 4)) { 353 if(fm->format_block) { 354 if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)"; 355 return false; 356 } 357 if(fm->audio_block) { 358 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)"; 359 return false; 360 } 361 fm->format_block = fm->num_blocks; 362 } 363 else if(!memcmp(buffer, "data", 4)) { 364 if(fm->audio_block) { 365 if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)"; 366 return false; 367 } 368 if(!fm->format_block) { 369 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)"; 370 return false; 371 } 372 fm->audio_block = fm->num_blocks; 373 } 374 } 375 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) { 376 if(!memcmp(buffer, "COMM", 4)) { 377 if(fm->format_block) { 378 if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (011)"; 379 return false; 380 } 381 if(fm->audio_block) { 382 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)"; 383 return false; 384 } 385 fm->format_block = fm->num_blocks; 386 } 387 else if(!memcmp(buffer, "SSND", 4)) { 388 if(fm->audio_block) { 389 if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (013)"; 390 return false; 391 } 392 if(!fm->format_block) { 393 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)"; 394 return false; 395 } 396 fm->audio_block = fm->num_blocks; 397 /* read SSND offset size */ 398 if(fread(buffer+4, 1, 8, f) != 8) { 399 if(error) *error = "read error (015)"; 400 return false; 401 } 402 fm->ssnd_offset_size = unpack32be_(buffer+8); 403 } 404 } 405 else { 406 FLAC__ASSERT(0); 407 /* double protection: */ 408 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (016)"; 409 return false; 410 } 411 if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error)) 412 return false; 413 } 414 if(!type_found) { 415 if(error) *error = "no foreign metadata found (017)"; 416 return false; 417 } 418 if(!fm->format_block) { 419 if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)"; 420 return false; 421 } 422 if(!fm->audio_block) { 423 if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)"; 424 return false; 425 } 426 return true; 427} 428 429static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, off_t offset1, off_t offset2, off_t offset3, const char **error) 430{ 431 size_t i; 432 if(fseeko(fout, offset1, SEEK_SET) < 0) { 433 if(error) *error = "seek failed in WAVE/AIFF file (002)"; 434 return false; 435 } 436 for(i = 1; i < fm->format_block; i++) { 437 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { 438 if(error) *error = "seek failed in FLAC file (003)"; 439 return false; 440 } 441 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)")) 442 return false; 443 } 444 if(fseeko(fout, offset2, SEEK_SET) < 0) { 445 if(error) *error = "seek failed in WAVE/AIFF file (006)"; 446 return false; 447 } 448 for(i = fm->format_block+1; i < fm->audio_block; i++) { 449 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { 450 if(error) *error = "seek failed in FLAC file (007)"; 451 return false; 452 } 453 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)")) 454 return false; 455 } 456 if(fseeko(fout, offset3, SEEK_SET) < 0) { 457 if(error) *error = "seek failed in WAVE/AIFF file (010)"; 458 return false; 459 } 460 for(i = fm->audio_block+1; i < fm->num_blocks; i++) { 461 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) { 462 if(error) *error = "seek failed in FLAC file (011)"; 463 return false; 464 } 465 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)")) 466 return false; 467 } 468 return true; 469} 470 471foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type) 472{ 473 foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1); 474 if(x) 475 x->type = type; 476 return x; 477} 478 479void flac__foreign_metadata_delete(foreign_metadata_t *fm) 480{ 481 if(fm) { 482 if(fm->blocks) 483 free(fm->blocks); 484 free(fm); 485 } 486} 487 488FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error) 489{ 490 FLAC__bool ok; 491 FILE *f = fopen(filename, "rb"); 492 if(!f) { 493 if(error) *error = "can't open AIFF file for reading (000)"; 494 return false; 495 } 496 ok = read_from_aiff_(fm, f, error); 497 fclose(f); 498 return ok; 499} 500 501FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error) 502{ 503 FLAC__bool ok; 504 FILE *f = fopen(filename, "rb"); 505 if(!f) { 506 if(error) *error = "can't open WAVE file for reading (000)"; 507 return false; 508 } 509 ok = read_from_wave_(fm, f, error); 510 fclose(f); 511 return ok; 512} 513 514FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error) 515{ 516 FLAC__bool ok; 517 FILE *fin, *fout; 518 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new(); 519 if(!it) { 520 if(error) *error = "out of memory (000)"; 521 return false; 522 } 523 if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) { 524 if(error) *error = "can't initialize iterator (001)"; 525 FLAC__metadata_simple_iterator_delete(it); 526 return false; 527 } 528 if(0 == (fin = fopen(infilename, "rb"))) { 529 if(error) *error = "can't open WAVE/AIFF file for reading (002)"; 530 FLAC__metadata_simple_iterator_delete(it); 531 return false; 532 } 533 if(0 == (fout = fopen(outfilename, "r+b"))) { 534 if(error) *error = "can't open FLAC file for updating (003)"; 535 FLAC__metadata_simple_iterator_delete(it); 536 fclose(fin); 537 return false; 538 } 539 ok = write_to_flac_(fm, fin, fout, it, error); 540 FLAC__metadata_simple_iterator_delete(it); 541 fclose(fin); 542 fclose(fout); 543 return ok; 544} 545 546FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error) 547{ 548 FLAC__bool ok; 549 FILE *f; 550 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new(); 551 if(!it) { 552 if(error) *error = "out of memory (000)"; 553 return false; 554 } 555 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) { 556 if(error) *error = "can't initialize iterator (001)"; 557 FLAC__metadata_simple_iterator_delete(it); 558 return false; 559 } 560 if(0 == (f = fopen(filename, "rb"))) { 561 if(error) *error = "can't open FLAC file for reading (002)"; 562 FLAC__metadata_simple_iterator_delete(it); 563 return false; 564 } 565 ok = read_from_flac_(fm, f, it, error); 566 FLAC__metadata_simple_iterator_delete(it); 567 fclose(f); 568 return ok; 569} 570 571FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error) 572{ 573 FLAC__bool ok; 574 FILE *fin, *fout; 575 if(0 == (fin = fopen(infilename, "rb"))) { 576 if(error) *error = "can't open FLAC file for reading (000)"; 577 return false; 578 } 579 if(0 == (fout = fopen(outfilename, "r+b"))) { 580 if(error) *error = "can't open WAVE/AIFF file for updating (001)"; 581 fclose(fin); 582 return false; 583 } 584 ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error); 585 fclose(fin); 586 fclose(fout); 587 return ok; 588} 589