Commit f178b143 authored by Josh Coalson's avatar Josh Coalson
Browse files

finish foreign metadata implemetation

parent 02f91ed9
......@@ -70,6 +70,7 @@ typedef struct {
utils__CueSpecification *cue_specification;
const char *inbasefilename;
const char *infilename;
const char *outfilename;
FLAC__uint64 samples_processed;
......@@ -98,6 +99,7 @@ typedef struct {
FILE *fout;
foreign_metadata_t *foreign_metadata; /* NULL unless --keep-foreign-metadata requested */
off_t fm_offset1, fm_offset2, fm_offset3;
} DecoderSession;
......@@ -115,6 +117,8 @@ static int DecoderSession_finish_ok(DecoderSession *d);
static int DecoderSession_finish_error(DecoderSession *d);
static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);
static FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uint64 samples);
static FLAC__bool write_riff_wave_fmt_chunk(FILE *f, FLAC__bool is_waveformatextensible, unsigned bps, unsigned channels, unsigned sample_rate, FLAC__uint32 channel_mask);
static FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, unsigned bps, unsigned channels, unsigned sample_rate);
static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val);
......@@ -291,6 +295,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__
d->cue_specification = cue_specification;
d->inbasefilename = grabbag__file_get_basename(infilename);
d->infilename = infilename;
d->outfilename = outfilename;
d->samples_processed = 0;
......@@ -354,11 +359,13 @@ FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, const ch
is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
if(decoder_session->foreign_metadata) {
const char *error;
if(!flac__foreign_metadata_read_from_flac(decoder_session->foreign_metadata, infilename, &error)) {
flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", decoder_session->inbasefilename, error);
return false;
if(!decoder_session->analysis_mode && !decoder_session->test_only && (decoder_session->is_wave_out || decoder_session->is_aiff_out)) {
if(decoder_session->foreign_metadata) {
const char *error;
if(!flac__foreign_metadata_read_from_flac(decoder_session->foreign_metadata, infilename, &error)) {
flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", decoder_session->inbasefilename, error);
return false;
}
}
}
......@@ -515,9 +522,19 @@ int DecoderSession_finish_ok(DecoderSession *d)
flac__utils_printf(stderr, 2, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done");
}
DecoderSession_destroy(d, /*error_occurred=*/!ok);
if(!d->test_only && (d->is_wave_out || d->is_aiff_out) && (d->iff_headers_need_fixup || (!d->got_stream_info && strcmp(d->outfilename, "-"))))
if(!fixup_iff_headers(d))
return 1;
if(!d->analysis_mode && !d->test_only && (d->is_wave_out || d->is_aiff_out)) {
if(d->iff_headers_need_fixup || (!d->got_stream_info && strcmp(d->outfilename, "-"))) {
if(!fixup_iff_headers(d))
return 1;
}
if(d->foreign_metadata) {
const char *error;
if(!flac__foreign_metadata_write_to_iff(d->foreign_metadata, d->infilename, d->outfilename, d->fm_offset1, d->fm_offset2, d->fm_offset3, &error)) {
flac__utils_printf(stderr, 1, "ERROR updating foreign metadata from %s to %s: %s\n", d->infilename, d->outfilename, error);
return 1;
}
}
}
return ok? 0 : 1;
}
......@@ -584,6 +601,11 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
const FLAC__bool is_waveformatextensible = decoder_session->is_wave_out && (decoder_session->channel_mask == 2 || decoder_session->channel_mask > 3 || decoder_session->bps%8 || decoder_session->channels > 2);
FLAC__uint64 data_size = samples * decoder_session->channels * ((decoder_session->bps+7)/8);
const FLAC__uint32 aligned_data_size = (FLAC__uint32)((data_size+1) & (~1U)); /* we'll check for overflow later */
unsigned foreign_metadata_size = 0; /* size of all non-audio non-fmt/COMM foreign metadata chunks */
foreign_metadata_t *fm = decoder_session->foreign_metadata;
size_t i;
if(samples == 0) {
if(f == stdout) {
flac__utils_printf(stderr, 1, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc);
......@@ -596,54 +618,58 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
decoder_session->iff_headers_need_fixup = true;
}
}
if(data_size >= 0xFFFFFFDC) {
flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc);
if(fm) {
FLAC__ASSERT(fm->format_block);
FLAC__ASSERT(fm->audio_block);
FLAC__ASSERT(fm->format_block < fm->audio_block);
/* calc foreign metadata size; for RIFF/AIFF we always skip the first chunk, format chunk, and sound chunk since we write our own */
for(i = 1; i < fm->num_blocks; i++) {
if(i != fm->format_block && i != fm->audio_block)
foreign_metadata_size += fm->blocks[i].size;
}
}
if(data_size + foreign_metadata_size + 60/*worst-case*/ >= 0xFFFFFFF4) {
flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file\n", decoder_session->inbasefilename, fmt_desc);
return false;
}
if(decoder_session->is_wave_out) {
if(flac__utils_fwrite("RIFF", 1, 4, f) != 4)
return false;
if(!write_little_endian_uint32(f, aligned_data_size+(is_waveformatextensible?60:36))) /* filesize-8 */
return false;
if(flac__utils_fwrite("WAVEfmt ", 1, 8, f) != 8)
return false;
if(!write_little_endian_uint32(f, is_waveformatextensible? 40 : 16)) /* chunk size */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)(is_waveformatextensible? 65534 : 1))) /* compression code */
if(!write_little_endian_uint32(f, foreign_metadata_size + aligned_data_size + (is_waveformatextensible?60:36))) /* filesize-8 */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)(decoder_session->channels)))
if(flac__utils_fwrite("WAVE", 1, 4, f) != 4)
return false;
if(!write_little_endian_uint32(f, decoder_session->sample_rate))
return false;
if(!write_little_endian_uint32(f, decoder_session->sample_rate * decoder_session->channels * ((decoder_session->bps+7) / 8)))
return false;
decoder_session->fm_offset1 = ftello(f);
if(!write_little_endian_uint16(f, (FLAC__uint16)(decoder_session->channels * ((decoder_session->bps+7) / 8)))) /* block align */
return false;
if(fm) {
/* seek forward to {allocate} or {skip over already-written chunks} before "fmt " */
for(i = 1; i < fm->format_block; i++) {
if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata before \"fmt \"\n", decoder_session->inbasefilename);
return false;
}
}
}
if(!write_little_endian_uint16(f, (FLAC__uint16)(((decoder_session->bps+7)/8)*8))) /* bits per sample */
if(!write_riff_wave_fmt_chunk(f, is_waveformatextensible, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate, decoder_session->channel_mask))
return false;
if(is_waveformatextensible) {
if(!write_little_endian_uint16(f, (FLAC__uint16)22)) /* cbSize */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)decoder_session->bps)) /* validBitsPerSample */
return false;
if(!write_little_endian_uint32(f, decoder_session->channel_mask))
return false;
decoder_session->fm_offset2 = ftello(f);
/* GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} */
if(flac__utils_fwrite("\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 1, 16, f) != 16)
return false;
if(fm) {
/* seek forward to {allocate} or {skip over already-written chunks} after "fmt " but before "data" */
for(i = fm->format_block+1; i < fm->audio_block; i++) {
if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata after \"fmt \"\n", decoder_session->inbasefilename);
return false;
}
}
}
if(flac__utils_fwrite("data", 1, 4, f) != 4)
......@@ -651,48 +677,143 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
if(!write_little_endian_uint32(f, (FLAC__uint32)data_size)) /* data size */
return false;
decoder_session->fm_offset3 = ftello(f) + aligned_data_size;
}
else {
FLAC__uint32 ssnd_offset_size = (fm? fm->ssnd_offset_size : 0);
if(flac__utils_fwrite("FORM", 1, 4, f) != 4)
return false;
if(!write_big_endian_uint32(f, aligned_data_size+46)) /* filesize-8 */
if(!write_big_endian_uint32(f, foreign_metadata_size + aligned_data_size + 46 + ssnd_offset_size)) /* filesize-8 */
return false;
if(flac__utils_fwrite("AIFFCOMM", 1, 8, f) != 8)
if(flac__utils_fwrite("AIFF", 1, 4, f) != 4)
return false;
if(flac__utils_fwrite("\000\000\000\022", 1, 4, f) != 4) /* chunk size = 18 */
decoder_session->fm_offset1 = ftello(f);
if(fm) {
/* seek forward to {allocate} or {skip over already-written chunks} before "COMM" */
for(i = 1; i < fm->format_block; i++) {
if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata before \"COMM\"\n", decoder_session->inbasefilename);
return false;
}
}
}
if(!write_aiff_form_comm_chunk(f, samples, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate))
return false;
if(!write_big_endian_uint16(f, (FLAC__uint16)(decoder_session->channels)))
decoder_session->fm_offset2 = ftello(f);
if(fm) {
/* seek forward to {allocate} or {skip over already-written chunks} after "COMM" but before "SSND" */
for(i = fm->format_block+1; i < fm->audio_block; i++) {
if(fseeko(f, fm->blocks[i].size, SEEK_CUR) < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping foreign metadata after \"COMM\"\n", decoder_session->inbasefilename);
return false;
}
}
}
if(flac__utils_fwrite("SSND", 1, 4, f) != 4)
return false;
if(!write_big_endian_uint32(f, (FLAC__uint32)samples))
if(!write_big_endian_uint32(f, (FLAC__uint32)data_size + 8 + ssnd_offset_size)) /* data size */
return false;
if(!write_big_endian_uint16(f, (FLAC__uint16)(decoder_session->bps)))
if(!write_big_endian_uint32(f, ssnd_offset_size))
return false;
if(!write_sane_extended(f, decoder_session->sample_rate))
if(!write_big_endian_uint32(f, 0/*block_size*/))
return false;
if(flac__utils_fwrite("SSND", 1, 4, f) != 4)
if(ssnd_offset_size) {
/* seek forward to {allocate} or {skip over already-written} SSND offset */
if(fseeko(f, ssnd_offset_size, SEEK_CUR) < 0) {
flac__utils_printf(stderr, 1, "%s: ERROR: allocating/skipping \"SSND\" offset\n", decoder_session->inbasefilename);
return false;
}
}
decoder_session->fm_offset3 = ftello(f) + aligned_data_size;
}
return true;
}
FLAC__bool write_riff_wave_fmt_chunk(FILE *f, FLAC__bool is_waveformatextensible, unsigned bps, unsigned channels, unsigned sample_rate, FLAC__uint32 channel_mask)
{
if(flac__utils_fwrite("fmt ", 1, 4, f) != 4)
return false;
if(!write_little_endian_uint32(f, is_waveformatextensible? 40 : 16)) /* chunk size */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)(is_waveformatextensible? 65534 : 1))) /* compression code */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)channels))
return false;
if(!write_little_endian_uint32(f, sample_rate))
return false;
if(!write_little_endian_uint32(f, sample_rate * channels * ((bps+7) / 8)))
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)(channels * ((bps+7) / 8)))) /* block align */
return false;
if(!write_little_endian_uint16(f, (FLAC__uint16)(((bps+7)/8)*8))) /* bits per sample */
return false;
if(is_waveformatextensible) {
if(!write_little_endian_uint16(f, (FLAC__uint16)22)) /* cbSize */
return false;
if(!write_big_endian_uint32(f, (FLAC__uint32)data_size+8)) /* data size */
if(!write_little_endian_uint16(f, (FLAC__uint16)bps)) /* validBitsPerSample */
return false;
if(!write_big_endian_uint32(f, 0/*offset*/))
if(!write_little_endian_uint32(f, channel_mask))
return false;
if(!write_big_endian_uint32(f, 0/*block_size*/))
/* GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} */
if(flac__utils_fwrite("\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 1, 16, f) != 16)
return false;
}
return true;
}
FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, unsigned bps, unsigned channels, unsigned sample_rate)
{
FLAC__ASSERT(samples <= 0xffffffff);
if(flac__utils_fwrite("COMM", 1, 4, f) != 4)
return false;
if(!write_big_endian_uint32(f, 18)) /* chunk size = 18 */
return false;
if(!write_big_endian_uint16(f, (FLAC__uint16)channels))
return false;
if(!write_big_endian_uint32(f, (FLAC__uint32)samples))
return false;
if(!write_big_endian_uint16(f, (FLAC__uint16)bps))
return false;
if(!write_sane_extended(f, sample_rate))
return false;
return true;
}
FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val)
{
FLAC__byte *b = (FLAC__byte*)(&val);
......
......@@ -2098,7 +2098,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
}
static_metadata_append(&static_metadata, p, /*needs_delete=*/true);
static_metadata.metadata[static_metadata.num_metadata-1]->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8 + foreign_metadata->blocks[i].size;
fprintf(stderr,"@@@@@@ add PADDING=%u\n",static_metadata.metadata[static_metadata.num_metadata-1]->length);
/*fprintf(stderr,"@@@@@@ add PADDING=%u\n",static_metadata.metadata[static_metadata.num_metadata-1]->length);*/
}
}
if(options.padding != 0) {
......
......@@ -101,6 +101,10 @@ SOURCE=.\encode.c
# End Source File
# Begin Source File
SOURCE=.\foreign_metadata.c
# End Source File
# Begin Source File
SOURCE=.\main.c
# End Source File
# Begin Source File
......@@ -133,6 +137,10 @@ SOURCE=.\encode.h
# End Source File
# Begin Source File
SOURCE=.\foreign_metadata.h
# End Source File
# Begin Source File
SOURCE=.\local_string_utils.h
# End Source File
# Begin Source File
......
......@@ -199,6 +199,10 @@
RelativePath=".\encode.h"
>
</File>
<File
RelativePath=".\foreign_metadata.h"
>
</File>
<File
RelativePath=".\local_string_utils.h"
>
......@@ -229,6 +233,10 @@
RelativePath=".\encode.c"
>
</File>
<File
RelativePath=".\foreign_metadata.c"
>
</File>
<File
RelativePath=".\local_string_utils.c"
>
......
......@@ -40,7 +40,7 @@
#define min(x,y) ((x)<(y)?(x):(y))
static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID = "FFMB";/*@@@@@@ settle on an ID */
static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "AIFF" , "RIFF" };
static FLAC__uint32 unpack32be_(const FLAC__byte *b)
{
......@@ -52,6 +52,25 @@ static FLAC__uint32 unpack32le_(const FLAC__byte *b)
return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
}
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)
{
static FLAC__byte buffer[4096];
size_t left;
for(left = size; left > 0; ) {
size_t need = min(sizeof(buffer), left);
if(fread(buffer, 1, need, fin) < need) {
if(error) *error = read_error;
return false;
}
if(fwrite(buffer, 1, need, fout) < need) {
if(error) *error = write_error;
return false;
}
left -= need;
}
return true;
}
static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error)
{
foreign_block_t *fb = realloc(fm->blocks, sizeof(foreign_block_t) * (fm->num_blocks+1));
......@@ -60,6 +79,7 @@ static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint
fb[fm->num_blocks].size = size;
fm->num_blocks++;
fm->blocks = fb;
/*fprintf(stderr,"@@@@@@ appended: block#%u offset=%d size=%u\n",fm->num_blocks-1,(int)fm->blocks[fm->num_blocks-1].offset,(unsigned)fm->blocks[fm->num_blocks-1].size);*/
return true;
}
if(error) *error = "out of memory";
......@@ -81,8 +101,9 @@ static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **
if(!append_block_(fm, offset, 12, error))
return false;
eof_offset = 8 + unpack32be_(buffer+4);
/*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/
while(!feof(f)) {
FLAC__uint32 size, ssnd_offset_size = 0;
FLAC__uint32 size;
if((offset = ftello(f)) < 0) {
if(error) *error = "ftello() error (003)";
return false;
......@@ -102,43 +123,51 @@ static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **
if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
return false;
}
if(fm->audio_block) {
if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
return false;
}
fm->format_block = fm->num_blocks;
}
else if(!memcmp(buffer, "SSND", 4)) {
if(fm->audio_block) {
if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (006)";
if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
return false;
}
if(!fm->format_block) {
if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
return false;
}
fm->audio_block = fm->num_blocks;
/* read #offset bytes */
if(fread(buffer+8, 1, 4, f) < 4) {
if(error) *error = "invalid AIFF file (007)";
if(error) *error = "invalid AIFF file (009)";
return false;
}
ssnd_offset_size = unpack32be_(buffer+8);
fm->ssnd_offset_size = unpack32be_(buffer+8);
if(fseeko(f, -4, SEEK_CUR) < 0) {
if(error) *error = "invalid AIFF file: seek error (008)";
if(error) *error = "invalid AIFF file: seek error (010)";
return false;
}
}
if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + ssnd_offset_size), error))
if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
return false;
fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);
/*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/
if(fseeko(f, size, SEEK_CUR) < 0) {
if(error) *error = "invalid AIFF file: seek error (009)";
if(error) *error = "invalid AIFF file: seek error (011)";
return false;
}
}
if(eof_offset != ftello(f)) {
if(error) *error = "invalid AIFF file: unexpected EOF (010)";
if(error) *error = "invalid AIFF file: unexpected EOF (012)";
return false;
}
if(!fm->format_block) {
if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (011)";
if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
return false;
}
if(!fm->audio_block) {
if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (012)";
if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
return false;
}
return true;
......@@ -159,7 +188,7 @@ static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **
if(!append_block_(fm, offset, 12, error))
return false;
eof_offset = 8 + unpack32le_(buffer+4);
fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);
/*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/
while(!feof(f)) {
FLAC__uint32 size;
if((offset = ftello(f)) < 0) {
......@@ -181,33 +210,41 @@ fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);
if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
return false;
}
if(fm->audio_block) {
if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
return false;
}
fm->format_block = fm->num_blocks;
}
else if(!memcmp(buffer, "data", 4)) {
if(fm->audio_block) {
if(error) *error = "invalid WAVE file: multiple \"data\" chunks (006)";
if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
return false;
}
if(!fm->format_block) {
if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
return false;
}
fm->audio_block = fm->num_blocks;
}
if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
return false;
fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);
/*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/
if(fseeko(f, size, SEEK_CUR) < 0) {
if(error) *error = "invalid WAVE file: seek error (007)";
if(error) *error = "invalid WAVE file: seek error (009)";
return false;
}
}
if(eof_offset != ftello(f)) {
if(error) *error = "invalid WAVE file: unexpected EOF (008)";
if(error) *error = "invalid WAVE file: unexpected EOF (010)";
return false;
}
if(!fm->format_block) {
if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (009)";
if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
return false;
}
if(!fm->audio_block) {
if(error) *error = "invalid WAVE file: missing \"data\" chunk (010)";
if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
return false;
}
return true;
......@@ -215,9 +252,9 @@ fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],b
static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
{
static FLAC__byte buffer[4096];
FLAC__byte buffer[4];
const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
size_t left, block_num = 0;
size_t block_num = 0;
FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
while(block_num < fm->num_blocks) {
/* find next matching padding block */
......@@ -232,14 +269,14 @@ static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout,
if(error) *error = "PADDING block with wrong size found (005)";
return false;
}
fprintf(stderr,"@@@@@@ flac offset = %d\n",(int)FLAC__metadata_simple_iterator_get_block_offset(it));
/*fprintf(stderr,"@@@@@@ flac offset = %d\n",(int)FLAC__metadata_simple_iterator_get_block_offset(it));*/
/* transfer chunk into APPLICATION block */
/* first set up the file pointers */
if(fseek(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in WAVE/AIFF file (006)";
return false;
}
if(fseek(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (007)";
return false;
}
......@@ -248,41 +285,200 @@ fprintf(stderr,"@@@@@@ flac offset = %d\n",(int)FLAC__metadata_simple_iterator_g
if(FLAC__metadata_simple_iterator_is_last(it))
buffer[0] |= 0x80; /*MAGIC number*/
if(fwrite(buffer, 1, 1, fout) < 1) {
if(error) *error = "write failed in FLAC/AIFF file (008)";
if(error) *error = "write failed in FLAC file (008)";
return false;
}
/* length stays the same so skip over it */
if(fseek(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
if(error) *error = "seek failed in FLAC file (009)";
return false;
}
/* write the APPLICATION ID */
memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID, ID_LEN);