Changes to update Tomato RAF.
[tomato.git] / release / src / router / flac / src / flac / foreign_metadata.c
blob3fc5310bbf4f707a4792c2a920abab09b1e23d3d
1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
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.
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.
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.
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
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"
38 #ifdef min
39 #undef min
40 #endif
41 #define min(x,y) ((x)<(y)?(x):(y))
44 static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "aiff" , "riff" };
46 static FLAC__uint32 unpack32be_(const FLAC__byte *b)
48 return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
51 static FLAC__uint32 unpack32le_(const FLAC__byte *b)
53 return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
56 static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error)
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;
66 if(fwrite(buffer, 1, need, fout) < need) {
67 if(error) *error = write_error;
68 return false;
70 left -= need;
72 return true;
75 static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error)
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;
85 if(error) *error = "out of memory";
86 return false;
89 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
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;
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;
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;
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;
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;
125 if(fm->audio_block) {
126 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
127 return false;
129 fm->format_block = fm->num_blocks;
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;
136 if(!fm->format_block) {
137 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
138 return false;
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;
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;
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;
159 if(eof_offset != ftello(f)) {
160 if(error) *error = "invalid AIFF file: unexpected EOF (012)";
161 return false;
163 if(!fm->format_block) {
164 if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
165 return false;
167 if(!fm->audio_block) {
168 if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
169 return false;
171 return true;
174 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
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;
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;
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;
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;
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;
210 if(fm->audio_block) {
211 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
212 return false;
214 fm->format_block = fm->num_blocks;
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;
221 if(!fm->format_block) {
222 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
223 return false;
225 fm->audio_block = fm->num_blocks;
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;
234 if(eof_offset != ftello(f)) {
235 if(error) *error = "invalid WAVE file: unexpected EOF (010)";
236 return false;
238 if(!fm->format_block) {
239 if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
240 return false;
242 if(!fm->audio_block) {
243 if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
244 return false;
246 return true;
249 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
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;
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;
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;
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;
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;
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;
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;
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++;
302 return true;
305 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
307 FLAC__byte id[4], buffer[12];
308 off_t offset;
309 FLAC__bool type_found = false;
311 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
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;
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;
331 if(fread(buffer, 1, 4, f) != 4) {
332 if(error) *error = "read error (005)";
333 return false;
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;
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;
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;
357 if(fm->audio_block) {
358 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
359 return false;
361 fm->format_block = fm->num_blocks;
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;
368 if(!fm->format_block) {
369 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
370 return false;
372 fm->audio_block = fm->num_blocks;
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;
381 if(fm->audio_block) {
382 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)";
383 return false;
385 fm->format_block = fm->num_blocks;
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;
392 if(!fm->format_block) {
393 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)";
394 return false;
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;
402 fm->ssnd_offset_size = unpack32be_(buffer+8);
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;
411 if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
412 return false;
414 if(!type_found) {
415 if(error) *error = "no foreign metadata found (017)";
416 return false;
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;
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;
426 return true;
429 static 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)
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;
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;
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;
444 if(fseeko(fout, offset2, SEEK_SET) < 0) {
445 if(error) *error = "seek failed in WAVE/AIFF file (006)";
446 return false;
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;
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;
456 if(fseeko(fout, offset3, SEEK_SET) < 0) {
457 if(error) *error = "seek failed in WAVE/AIFF file (010)";
458 return false;
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;
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;
468 return true;
471 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
473 foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1);
474 if(x)
475 x->type = type;
476 return x;
479 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
481 if(fm) {
482 if(fm->blocks)
483 free(fm->blocks);
484 free(fm);
488 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
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;
496 ok = read_from_aiff_(fm, f, error);
497 fclose(f);
498 return ok;
501 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
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;
509 ok = read_from_wave_(fm, f, error);
510 fclose(f);
511 return ok;
514 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
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;
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;
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;
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;
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;
546 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
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;
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;
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;
565 ok = read_from_flac_(fm, f, it, error);
566 FLAC__metadata_simple_iterator_delete(it);
567 fclose(f);
568 return ok;
571 FLAC__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)
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;
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;
584 ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);
585 fclose(fin);
586 fclose(fout);
587 return ok;