diff --git a/doc/html/documentation.html b/doc/html/documentation.html index f8a8a373..db3e2512 100644 --- a/doc/html/documentation.html +++ b/doc/html/documentation.html @@ -349,6 +349,14 @@ Silent: do not show encoding/decoding statistics. + + + --totally-silent + + + Do not print anything of any kind, including warnings or errors. The exit code will be the only way to determine successful completion. + + -f, --force diff --git a/man/flac.sgml b/man/flac.sgml index 796cfdbf..477cd73a 100644 --- a/man/flac.sgml +++ b/man/flac.sgml @@ -153,6 +153,17 @@ + + + + + Do not print anything of any kind, + including warnings or errors. The exit + code will be the only way to determine + successful completion. + + + , diff --git a/src/flac/decode.c b/src/flac/decode.c index 0ec61340..7a6d2bae 100644 --- a/src/flac/decode.c +++ b/src/flac/decode.c @@ -44,6 +44,7 @@ typedef struct { #endif FLAC__bool verbose; + FLAC__bool silent; FLAC__bool is_aiff_out; FLAC__bool is_wave_out; FLAC__bool continue_through_decode_errors; @@ -105,20 +106,20 @@ static FLAC__bool is_big_endian_host_; /* * local routines */ -static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename); +static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool silent, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename); static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred); static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, decode_options_t decode_options, const char *infilename); static FLAC__bool DecoderSession_process(DecoderSession *d); 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 canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input, FLAC__bool silent); static FLAC__bool write_necessary_headers(DecoderSession *decoder_session); 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); static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val); static FLAC__bool write_sane_extended(FILE *f, unsigned val); -static FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps); +static FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps, FLAC__bool silent); /* * We use 'void *' so that we can use the same callbacks for the * FLAC__StreamDecoder and FLAC__FileDecoder. The 'decoder' argument is @@ -147,6 +148,7 @@ int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__boo /*is_ogg=*/false, #endif options.common.verbose, + options.common.silent, /*is_aiff_out=*/true, /*is_wave_out=*/false, options.common.continue_through_decode_errors, @@ -184,6 +186,7 @@ int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool /*is_ogg=*/false, #endif options.common.verbose, + options.common.silent, /*is_aiff_out=*/false, /*is_wave_out=*/true, options.common.continue_through_decode_errors, @@ -224,6 +227,7 @@ int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool /*is_ogg=*/false, #endif options.common.verbose, + options.common.silent, /*is_aiff_out=*/false, /*is_wave_out=*/false, options.common.continue_through_decode_errors, @@ -248,7 +252,7 @@ int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool return DecoderSession_finish_ok(&decoder_session); } -FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename) +FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool silent, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, const char *infilename, const char *outfilename) { #ifdef FLAC__HAS_OGG d->is_ogg = is_ogg; @@ -257,6 +261,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__ #endif d->verbose = verbose; + d->silent = silent; d->is_aiff_out = is_aiff_out; d->is_wave_out = is_wave_out; d->continue_through_decode_errors = continue_through_decode_errors; @@ -296,7 +301,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__ } else { if(0 == (d->fout = fopen(outfilename, "wb"))) { - fprintf(stderr, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename); + if(!d->silent) fprintf(stderr, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename); DecoderSession_destroy(d, /*error_occurred=*/true); return false; } @@ -329,7 +334,7 @@ FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_o decoder_session->decoder.ogg.file = OggFLAC__file_decoder_new(); if(0 == decoder_session->decoder.ogg.file) { - fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); return false; } @@ -365,7 +370,7 @@ FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_o decoder_session->decoder.flac.file = FLAC__file_decoder_new(); if(0 == decoder_session->decoder.flac.file) { - fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename); return false; } @@ -534,15 +539,14 @@ int DecoderSession_finish_ok(DecoderSession *d) if(d->analysis_mode) flac__analyze_finish(d->aopts); if(md5_failure) { - fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename); + if(!d->silent) fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename); } else { - if(d->verbose) - fprintf(stderr, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done"); + if(d->verbose) fprintf(stderr, "\r%s: %s \n", d->inbasefilename, d->test_only? "ok ":d->analysis_mode?"done ":"done"); } DecoderSession_destroy(d, /*error_occurred=*/false); if((d->is_wave_out || d->is_aiff_out) && d->wave_chunk_size_fixup.needs_fixup) - if(!fixup_wave_chunk_size(d->outfilename, d->is_wave_out, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, d->wave_chunk_size_fixup.frames_offset, (FLAC__uint32)d->samples_processed, d->channels, d->bps)) + if(!fixup_wave_chunk_size(d->outfilename, d->is_wave_out, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, d->wave_chunk_size_fixup.frames_offset, (FLAC__uint32)d->samples_processed, d->channels, d->bps, d->silent)) return 1; return 0; } @@ -570,7 +574,7 @@ int DecoderSession_finish_error(DecoderSession *d) return 1; } -FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input, FLAC__bool silent) { /* convert from mm:ss.sss to sample number if necessary */ flac__utils_canonicalize_skip_until_specification(spec, sample_rate); @@ -583,7 +587,7 @@ FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, /* in any other case the total samples in the input must be known */ if(total_samples_in_input == 0) { - fprintf(stderr, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename); return false; } @@ -600,15 +604,15 @@ FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, /* error check */ if(spec->value.samples < 0) { - fprintf(stderr, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); return false; } if((FLAC__uint64)spec->value.samples <= skip) { - fprintf(stderr, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is before --skip point\n", inbasefilename); return false; } if((FLAC__uint64)spec->value.samples > total_samples_in_input) { - fprintf(stderr, "%s: ERROR, --until value is after end of input\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is after end of input\n", inbasefilename); return false; } @@ -623,16 +627,16 @@ FLAC__bool write_necessary_headers(DecoderSession *decoder_session) FLAC__uint64 data_size = decoder_session->total_samples * decoder_session->channels * ((decoder_session->bps+7)/8); if(decoder_session->total_samples == 0) { if(decoder_session->fout == stdout) { - fprintf(stderr, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc); - fprintf(stderr, " Generated %s file will have a data chunk size of 0. Try\n", fmt_desc); - fprintf(stderr, " decoding directly to a file instead.\n"); + if(!decoder_session->silent) fprintf(stderr, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc); + if(!decoder_session->silent) fprintf(stderr, " Generated %s file will have a data chunk size of 0. Try\n", fmt_desc); + if(!decoder_session->silent) fprintf(stderr, " decoding directly to a file instead.\n"); } else { decoder_session->wave_chunk_size_fixup.needs_fixup = true; } } if(data_size >= 0xFFFFFFDC) { - fprintf(stderr, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc); return false; } if(decoder_session->is_wave_out) { @@ -804,7 +808,7 @@ FLAC__bool write_sane_extended(FILE *f, unsigned val) return true; } -FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps) +FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps, FLAC__bool silent) { const char *fmt_desc = (is_wave_out? "WAVE" : "AIFF"); FLAC__bool (*write_it)(FILE *, FLAC__uint32) = (is_wave_out? write_little_endian_uint32 : write_big_endian_uint32); @@ -812,7 +816,7 @@ FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out FLAC__uint32 data_size, aligned_data_size; if(0 == f) { - fprintf(stderr, "ERROR, couldn't open file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't open file %s while fixing up %s chunk size\n", outfilename, fmt_desc); return false; } @@ -821,34 +825,34 @@ FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out aligned_data_size++; if(fseek(f, riff_offset, SEEK_SET) < 0) { - fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } if(!write_it(f, aligned_data_size + (is_wave_out? 36 : 46))) { - fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } if(!is_wave_out) { if(fseek(f, frames_offset, SEEK_SET) < 0) { - fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } if(!write_it(f, total_samples)) { - fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } } if(fseek(f, data_offset, SEEK_SET) < 0) { - fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } if(!write_it(f, data_size + (is_wave_out? 0 : 8))) { - fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); + if(!silent) fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc); fclose(f); return false; } @@ -877,15 +881,15 @@ FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__F return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; if(bps != decoder_session->bps) { - fprintf(stderr, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } if(channels != decoder_session->channels) { - fprintf(stderr, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } if(frame->header.sample_rate != decoder_session->sample_rate) { - fprintf(stderr, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } @@ -1046,12 +1050,12 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */ if(metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) { - fprintf(stderr, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename); decoder_session->abort_flag = true; return; } else if(metadata->data.stream_info.total_samples == 0 && skip > 0) { - fprintf(stderr, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); decoder_session->abort_flag = true; return; } @@ -1059,7 +1063,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata decoder_session->total_samples = metadata->data.stream_info.total_samples - skip; /* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */ - if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples)) { + if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples, decoder_session->silent)) { decoder_session->abort_flag = true; return; } @@ -1073,7 +1077,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata } if(decoder_session->bps != 8 && decoder_session->bps != 16 && decoder_session->bps != 24) { - fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename); decoder_session->abort_flag = true; return; } @@ -1081,7 +1085,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata else if(metadata->type == FLAC__METADATA_TYPE_CUESHEET) { /* remember, at this point, decoder_session->total_samples can be 0, meaning 'unknown' */ if(decoder_session->total_samples == 0) { - fprintf(stderr, "%s: ERROR can't use --cue when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: ERROR can't use --cue when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename); decoder_session->abort_flag = true; return; } @@ -1105,7 +1109,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata if (decoder_session->replaygain.spec.apply) { double gain, peak; if (!(decoder_session->replaygain.apply = grabbag__replaygain_load_from_vorbiscomment(metadata, decoder_session->replaygain.spec.use_album_gain, &gain, &peak))) { - fprintf(stderr, "%s: WARNING: can't get %s ReplayGain tag\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track"); + if(!decoder_session->silent) fprintf(stderr, "%s: WARNING: can't get %s ReplayGain tag\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track"); } else { const char *ls[] = { "no", "peak", "hard" }; @@ -1113,8 +1117,8 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata decoder_session->replaygain.scale = grabbag__replaygain_compute_scale_factor(peak, gain, decoder_session->replaygain.spec.preamp, decoder_session->replaygain.spec.limiter == RGSS_LIMIT__PEAK); FLAC__ASSERT(decoder_session->bps > 0 && decoder_session->bps <= 32); FLAC__replaygain_synthesis__init_dither_context(&decoder_session->replaygain.dither_context, decoder_session->bps, decoder_session->replaygain.spec.noise_shaping); - fprintf(stderr, "%s: INFO: applying %s ReplayGain (gain=%0.2fdB+preamp=%0.1fdB, %s noise shaping, %s limiting) to output\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track", gain, decoder_session->replaygain.spec.preamp, ns[decoder_session->replaygain.spec.noise_shaping], ls[decoder_session->replaygain.spec.limiter]); - fprintf(stderr, "%s: WARNING: applying ReplayGain is not lossless\n", decoder_session->inbasefilename); + if(!decoder_session->silent) fprintf(stderr, "%s: INFO: applying %s ReplayGain (gain=%0.2fdB+preamp=%0.1fdB, %s noise shaping, %s limiting) to output\n", decoder_session->inbasefilename, decoder_session->replaygain.spec.use_album_gain? "album":"track", gain, decoder_session->replaygain.spec.preamp, ns[decoder_session->replaygain.spec.noise_shaping], ls[decoder_session->replaygain.spec.limiter]); + if(!decoder_session->silent) fprintf(stderr, "%s: WARNING: applying ReplayGain is not lossless\n", decoder_session->inbasefilename); } } } @@ -1124,7 +1128,7 @@ void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, { DecoderSession *decoder_session = (DecoderSession*)client_data; (void)decoder; - fprintf(stderr, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]); + if(!decoder_session->silent) fprintf(stderr, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]); if(!decoder_session->continue_through_decode_errors) decoder_session->abort_flag = true; } @@ -1133,6 +1137,9 @@ void print_error_with_state(const DecoderSession *d, const char *message) { const int ilen = strlen(d->inbasefilename) + 1; + if(d->silent) + return; + fprintf(stderr, "\n%s: %s\n", d->inbasefilename, message); #ifdef FLAC__HAS_OGG diff --git a/src/flac/decode.h b/src/flac/decode.h index 2e455f7a..92bf0120 100644 --- a/src/flac/decode.h +++ b/src/flac/decode.h @@ -37,6 +37,7 @@ typedef struct { typedef struct { FLAC__bool verbose; + FLAC__bool silent; FLAC__bool continue_through_decode_errors; replaygain_synthesis_spec_t replaygain_synthesis_spec; #ifdef FLAC__HAS_OGG diff --git a/src/flac/encode.c b/src/flac/encode.c index b19336b8..41192c91 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -59,6 +59,7 @@ typedef struct { #endif FLAC__bool verify; FLAC__bool verbose; + FLAC__bool silent; FLAC__bool is_stdout; const char *inbasefilename; const char *outfilename; @@ -131,14 +132,14 @@ extern FLAC__bool OggFLAC__file_encoder_disable_verbatim_subframes(OggFLAC__File /* * local routines */ -static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FILE *infile, const char *infilename, const char *outfilename); +static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FLAC__bool silent, FILE *infile, const char *infilename, const char *outfilename); static void EncoderSession_destroy(EncoderSession *e); static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero); static int EncoderSession_finish_error(EncoderSession *e); static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate); static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples); static FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e); -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 canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input, FLAC__bool silent); static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps); #ifdef FLAC__HAS_OGG static FLAC__StreamEncoderWriteStatus ogg_stream_encoder_write_callback(const OggFLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); @@ -148,15 +149,15 @@ static void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encod static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data); static void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data); -static FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset); +static FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool silent); static void print_stats(const EncoderSession *encoder_session); static void print_error_with_state(const EncoderSession *e, const char *message); static void print_verify_error(EncoderSession *e); -static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent); +static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent); +static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent); +static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent); +static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent); /* * public routines @@ -186,6 +187,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch #endif options.common.verify, options.common.verbose, + options.common.silent, infile, infilename, outfilename @@ -203,7 +205,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch if(feof(infile) || ((c= fread(chunk_id, 1U, 4U, infile)), c==0U && feof(infile))) break; else if(c<4U || feof(infile)) { - fprintf(stderr, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } @@ -211,56 +213,57 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch unsigned long skip; /* COMM chunk size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); else if(xx<18U) { - fprintf(stderr, "%s: ERROR: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); return EncoderSession_finish_error(&encoder_session); } - else if(xx!=18U) - fprintf(stderr, "%s: WARNING: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); + else if(xx!=18U) { + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: non-standard 'COMM' chunk has length = %u\n", encoder_session.inbasefilename, (unsigned int)xx); + } skip= (xx-18U)+(xx & 1U); /* number of channels */ - if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); else if(x==0U || x>FLAC__MAX_CHANNELS) { - fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && x!=2U) { - fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } channels= x; /* number of sample frames */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); sample_frames= xx; /* bits per sample */ - if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); else if(x!=8U && x!=16U && x!=24U) { - fprintf(stderr, "%s: ERROR: unsupported bits per sample %u\n", encoder_session.inbasefilename, (unsigned int)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported bits per sample %u\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && x!=16U) { - fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } bps= x; /* sample rate */ - if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); else if(!FLAC__format_sample_rate_is_valid(xx)) { - fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && xx!=44100U) { - fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx); return EncoderSession_finish_error(&encoder_session); } sample_rate= xx; @@ -270,7 +273,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch while(skip>0U && fseek(infile, skip, SEEK_CUR)<0) { unsigned int need= min(skip, sizeof ucbuffer_); if(fread(ucbuffer_, 1U, need, infile)0 && fseek(infile, skip, SEEK_CUR)<0) { unsigned int need= min(skip, sizeof ucbuffer_); if(fread(ucbuffer_, 1U, need, infile)0 && fseek(infile, skip, SEEK_CUR)<0) { unsigned int need= min(skip, sizeof ucbuffer_); if(fread(ucbuffer_, 1U, need, infile)=588U); if(bytes_read==0U && ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } - else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame) - fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame) { + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); + } else { info_align_carry= *options.common.align_reservoir_samples; format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, true, false, channels, bps); @@ -504,7 +508,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch unsigned char tmp; if(fread(&tmp, 1U, 1U, infile)<1U) { - fprintf(stderr, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } @@ -512,15 +516,18 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch got_ssnd_chunk= true; } else { /* other chunk */ - if(!strncmp(chunk_id, "COMM", 4)) - fprintf(stderr, "%s: WARNING: skipping extra 'COMM' chunk\n", encoder_session.inbasefilename); - else if(!strncmp(chunk_id, "SSND", 4)) - fprintf(stderr, "%s: WARNING: skipping extra 'SSND' chunk\n", encoder_session.inbasefilename); - else - fprintf(stderr, "%s: WARNING: skipping unknown chunk '%s'\n", encoder_session.inbasefilename, chunk_id); + if(!strncmp(chunk_id, "COMM", 4)) { + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping extra 'COMM' chunk\n", encoder_session.inbasefilename); + } + else if(!strncmp(chunk_id, "SSND", 4)) { + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping extra 'SSND' chunk\n", encoder_session.inbasefilename); + } + else { + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping unknown chunk '%s'\n", encoder_session.inbasefilename, chunk_id); + } /* chunk size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); else { unsigned long skip= xx+(xx & 1U); @@ -539,7 +546,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch } if(got_ssnd_chunk==false && sample_frames!=0U) { - fprintf(stderr, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } @@ -572,6 +579,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons #endif options.common.verify, options.common.verbose, + options.common.silent, infile, infilename, outfilename @@ -583,7 +591,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons * lookahead[] already has "RIFFxxxxWAVE", do sub-chunks */ while(!feof(infile)) { - if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(feof(infile)) break; @@ -591,68 +599,68 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons unsigned block_align; /* fmt sub-chunk size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(xx < 16) { - fprintf(stderr, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); return EncoderSession_finish_error(&encoder_session); } else if(xx != 16 && xx != 18) { - fprintf(stderr, "%s: WARNING: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, (unsigned)xx); } data_bytes = xx; /* compression code */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(x != 1) { - fprintf(stderr, "%s: ERROR: unsupported compression type %u\n", encoder_session.inbasefilename, (unsigned)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported compression type %u\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } /* number of channels */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(x == 0 || x > FLAC__MAX_CHANNELS) { - fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && x != 2) { - fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } channels = x; /* sample rate */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(!FLAC__format_sample_rate_is_valid(xx)) { - fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned)xx); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && xx != 44100) { - fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned)xx); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned)xx); return EncoderSession_finish_error(&encoder_session); } sample_rate = xx; /* avg bytes per second (ignored) */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); /* block align */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); block_align = x; /* bits per sample */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(x != 8 && x != 16 && x != 24) { - fprintf(stderr, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, (unsigned)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } else if(options.common.sector_align && x != 16) { - fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: file has %u bits per sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } bps = x; if(bps * channels != block_align * 8) { - fprintf(stderr, "%s: ERROR: unsupported block alignment (%u), for bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, block_align, bps, channels); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: unsupported block alignment (%u), for bits-per-sample=%u, channels=%u\n", encoder_session.inbasefilename, block_align, bps, channels); return EncoderSession_finish_error(&encoder_session); } is_unsigned_samples = (x == 8); @@ -664,7 +672,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons for(left = data_bytes; left > 0; ) { need = min(left, CHUNK_OF_SAMPLES); if(fread(ucbuffer_, 1U, need, infile) < need) { - fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; @@ -686,7 +694,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons FLAC__uint64 total_samples_in_input, trim = 0; /* data size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); data_bytes = xx; @@ -700,7 +708,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons * now that we know the input size, canonicalize the * --until string to an absolute sample number: */ - if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input)) + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, sample_rate, encoder_session.skip, total_samples_in_input, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); @@ -712,7 +720,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons for(left = (unsigned)encoder_session.skip; left > 0; ) { /*@@@ WATCHOUT: 4GB limit */ need = min(left, CHUNK_OF_SAMPLES); if(fread(ucbuffer_, bytes_per_wide_sample, need, infile) < need) { - fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; @@ -773,17 +781,17 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); if(bytes_read == 0) { if(ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(feof(infile)) { - fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); data_bytes = 0; } } else { if(bytes_read % bytes_per_wide_sample != 0) { - fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { @@ -806,7 +814,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons for(left = (unsigned)trim; left > 0; ) { /*@@@ WATCHOUT: 4GB limit */ need = min(left, CHUNK_OF_SAMPLES); if(fread(ucbuffer_, bytes_per_wide_sample, need, infile) < need) { - fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; @@ -839,11 +847,11 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); if(bytes_read == 0 && ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { - fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); data_bytes = 0; } else { @@ -858,14 +866,14 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons } else { if(xx == 0x20746d66 && got_fmt_chunk) { /* "fmt " */ - fprintf(stderr, "%s: WARNING: skipping extra 'fmt ' sub-chunk\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping extra 'fmt ' sub-chunk\n", encoder_session.inbasefilename); } else if(xx == 0x61746164) { /* "data" */ if(got_data_chunk) { - fprintf(stderr, "%s: WARNING: skipping extra 'data' sub-chunk\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping extra 'data' sub-chunk\n", encoder_session.inbasefilename); } else if(!got_fmt_chunk) { - fprintf(stderr, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { @@ -873,10 +881,10 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons } } else { - fprintf(stderr, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); } /* sub-chunk size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); if(fseek(infile, xx, SEEK_CUR) < 0) { /* can't seek input, read ahead manually... */ @@ -885,7 +893,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons for(left = xx; left > 0; ) { need = min(left, chunk); if(fread(ucbuffer_, 1, need, infile) < need) { - fprintf(stderr, "%s: ERROR during read while skipping unsupported sub-chunk\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read while skipping unsupported sub-chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; @@ -923,6 +931,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons #endif options.common.verify, options.common.verbose, + options.common.silent, infile, infilename, outfilename @@ -951,7 +960,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons * now that we know the input size, canonicalize the * --until strings to a number of samples: */ - if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, options.sample_rate, encoder_session.skip, total_samples_in_input)) + if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, options.sample_rate, encoder_session.skip, total_samples_in_input, encoder_session.silent)) return EncoderSession_finish_error(&encoder_session); encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); @@ -988,7 +997,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons for(left = skip_bytes; left > 0; ) { need = min(left, chunk); if(fread(ucbuffer_, 1, need, infile) < need) { - fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } left -= need; @@ -1039,7 +1048,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons memcpy(ucbuffer_, lookahead, lookahead_length); bytes_read = fread(ucbuffer_+lookahead_length, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample - lookahead_length, infile) + lookahead_length; if(ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } lookahead_length = 0; @@ -1049,12 +1058,12 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons if(bytes_read == 0) { if(ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } else if(bytes_read % bytes_per_wide_sample != 0) { - fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { @@ -1084,7 +1093,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons if(wanted > 0) { bytes_read += fread(ucbuffer_+lookahead_length, sizeof(unsigned char), wanted, infile); if(ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } @@ -1096,17 +1105,17 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons if(bytes_read == 0) { if(ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(feof(infile)) { - fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); total_input_bytes_read = max_input_bytes; } } else { if(bytes_read % bytes_per_wide_sample != 0) { - fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { @@ -1148,11 +1157,11 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); if(bytes_read == 0 && ferror(infile)) { - fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); + if(!encoder_session.silent) fprintf(stderr, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { - fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); + if(!encoder_session.silent) fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); } else { info_align_carry = *options.common.align_reservoir_samples; @@ -1165,7 +1174,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero); } -FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FILE *infile, const char *infilename, const char *outfilename) +FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FLAC__bool verbose, FLAC__bool silent, FILE *infile, const char *infilename, const char *outfilename) { unsigned i; FLAC__uint32 test = 1; @@ -1191,6 +1200,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ #endif e->verify = verify; e->verbose = verbose; + e->silent = silent; e->is_stdout = (0 == strcmp(outfilename, "-")); @@ -1221,7 +1231,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ } if(0 == (e->seek_table_template = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE))) { - fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); return false; } @@ -1230,7 +1240,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ if(e->is_stdout) { e->encoder.ogg.stream = OggFLAC__stream_encoder_new(); if(0 == e->encoder.ogg.stream) { - fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); EncoderSession_destroy(e); return false; } @@ -1238,7 +1248,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ else { e->encoder.ogg.file = OggFLAC__file_encoder_new(); if(0 == e->encoder.ogg.file) { - fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); EncoderSession_destroy(e); return false; } @@ -1249,7 +1259,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ if(e->is_stdout) { e->encoder.flac.stream = FLAC__stream_encoder_new(); if(0 == e->encoder.flac.stream) { - fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); EncoderSession_destroy(e); return false; } @@ -1257,7 +1267,7 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ else { e->encoder.flac.file = FLAC__file_encoder_new(); if(0 == e->encoder.flac.file) { - fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR creating the encoder instance\n", e->inbasefilename); EncoderSession_destroy(e); return false; } @@ -1354,10 +1364,12 @@ int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_a ret = 1; } else { - if(info_align_carry >= 0) - fprintf(stderr, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry); - if(info_align_zero >= 0) - fprintf(stderr, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero); + if(info_align_carry >= 0) { + if(!e->silent) fprintf(stderr, "%s: INFO: sector alignment causing %d samples to be carried over\n", e->inbasefilename, info_align_carry); + } + if(info_align_zero >= 0) { + if(!e->silent) fprintf(stderr, "%s: INFO: sector alignment causing %d zero samples to be appended\n", e->inbasefilename, info_align_zero); + } } EncoderSession_destroy(e); @@ -1414,16 +1426,16 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio if(e->replay_gain) { if(channels != 1 && channels != 2) { - fprintf(stderr, "%s: ERROR, number of channels (%u) must be 1 or 2 for --replay-gain\n", e->inbasefilename, channels); + if(!e->silent) fprintf(stderr, "%s: ERROR, number of channels (%u) must be 1 or 2 for --replay-gain\n", e->inbasefilename, channels); return false; } if(!grabbag__replaygain_is_valid_sample_frequency(sample_rate)) { - fprintf(stderr, "%s: ERROR, invalid sample rate (%u) for --replay-gain\n", e->inbasefilename, sample_rate); + if(!e->silent) fprintf(stderr, "%s: ERROR, invalid sample rate (%u) for --replay-gain\n", e->inbasefilename, sample_rate); return false; } if(options.is_first_file) { if(!grabbag__replaygain_init(sample_rate)) { - fprintf(stderr, "%s: ERROR initializing ReplayGain stage\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR initializing ReplayGain stage\n", e->inbasefilename); return false; } } @@ -1432,11 +1444,11 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio if(channels != 2) options.do_mid_side = options.loose_mid_side = false; - if(!parse_cuesheet_(&cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode)) + if(!parse_cuesheet_(&cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode, e->silent)) return false; if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? cuesheet : 0, e)) { - fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); + if(!e->silent) fprintf(stderr, "%s: ERROR allocating memory for seek table\n", e->inbasefilename); if(0 != cuesheet) free(cuesheet); return false; @@ -1613,8 +1625,9 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples) { if(e->replay_gain) { - if(!grabbag__replaygain_analyze(buffer, e->channels==2, e->bits_per_sample, samples)) - fprintf(stderr, "%s: WARNING, error while calculating ReplayGain\n", e->inbasefilename); + if(!grabbag__replaygain_analyze(buffer, e->channels==2, e->bits_per_sample, samples)) { + if(!e->silent) fprintf(stderr, "%s: WARNING, error while calculating ReplayGain\n", e->inbasefilename); + } } #ifdef FLAC__HAS_OGG @@ -1671,14 +1684,15 @@ FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int } if(has_real_points) { - if(e->is_stdout) - fprintf(stderr, "%s: WARNING, cannot write back seekpoints when encoding to stdout\n", e->inbasefilename); + if(e->is_stdout) { + if(!e->silent) fprintf(stderr, "%s: WARNING, cannot write back seekpoints when encoding to stdout\n", e->inbasefilename); + } } return true; } -FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input) +FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input, FLAC__bool silent) { /* convert from mm:ss.sss to sample number if necessary */ flac__utils_canonicalize_skip_until_specification(spec, sample_rate); @@ -1691,7 +1705,7 @@ FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, /* in any other case the total samples in the input must be known */ if(total_samples_in_input == 0) { - fprintf(stderr, "%s: ERROR, cannot use --until when input length is unknown\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, cannot use --until when input length is unknown\n", inbasefilename); return false; } @@ -1708,15 +1722,15 @@ FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, /* error check */ if(spec->value.samples < 0) { - fprintf(stderr, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is before beginning of input\n", inbasefilename); return false; } if((FLAC__uint64)spec->value.samples <= skip) { - fprintf(stderr, "%s: ERROR, --until value is before --skip point\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is before --skip point\n", inbasefilename); return false; } if((FLAC__uint64)spec->value.samples > total_samples_in_input) { - fprintf(stderr, "%s: ERROR, --until value is after end of input\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR, --until value is after end of input\n", inbasefilename); return false; } @@ -1882,7 +1896,7 @@ void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC_ print_stats(encoder_session); } -FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset) +FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool silent) { FILE *f; unsigned last_line_read; @@ -1892,12 +1906,12 @@ FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet return true; if(lead_out_offset == 0) { - fprintf(stderr, "%s: ERROR cannot import cuesheet when the number of input samples to encode is unknown\n", inbasefilename); + if(!silent) fprintf(stderr, "%s: ERROR cannot import cuesheet when the number of input samples to encode is unknown\n", inbasefilename); return false; } if(0 == (f = fopen(cuesheet_filename, "r"))) { - fprintf(stderr, "%s: ERROR opening cuesheet \"%s\" for reading\n", inbasefilename, cuesheet_filename); + if(!silent) fprintf(stderr, "%s: ERROR opening cuesheet \"%s\" for reading\n", inbasefilename, cuesheet_filename); return false; } @@ -1906,7 +1920,7 @@ FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet fclose(f); if(0 == *cuesheet) { - fprintf(stderr, "%s: ERROR parsing cuesheet \"%s\" on line %u: %s\n", inbasefilename, cuesheet_filename, last_line_read, error_message); + if(!silent) fprintf(stderr, "%s: ERROR parsing cuesheet \"%s\" on line %u: %s\n", inbasefilename, cuesheet_filename, last_line_read, error_message); return false; } @@ -1925,6 +1939,9 @@ void print_stats(const EncoderSession *encoder_session) const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * max(1.0, progress)); #endif + if(encoder_session->silent) + return; + if(samples_written == encoder_session->total_samples_to_encode) { fprintf(stderr, "\r%s:%s wrote %u bytes, ratio=%0.3f", encoder_session->inbasefilename, @@ -1943,6 +1960,9 @@ void print_error_with_state(const EncoderSession *e, const char *message) const int ilen = strlen(e->inbasefilename) + 1; const char *state_string; + if(e->silent) + return; + fprintf(stderr, "\n%s: %s\n", e->inbasefilename, message); #ifdef FLAC__HAS_OGG @@ -1975,6 +1995,9 @@ void print_verify_error(EncoderSession *e) FLAC__int32 expected; FLAC__int32 got; + if(e->silent) + return; + #ifdef FLAC__HAS_OGG if(e->use_ogg) { if(e->is_stdout) { @@ -2002,20 +2025,20 @@ void print_verify_error(EncoderSession *e) fprintf(stderr, "Verify FAILED! Do not trust %s\n", e->outfilename); } -FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent) { size_t bytes_read = fread(val, 1, 2, f); if(bytes_read == 0) { if(!eof_ok) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } else return true; } else if(bytes_read < 2) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } else { @@ -2027,20 +2050,20 @@ FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ } } -FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent) { size_t bytes_read = fread(val, 1, 4, f); if(bytes_read == 0) { if(!eof_ok) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } else return true; } else if(bytes_read < 4) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } else { @@ -2053,8 +2076,7 @@ FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ } } -FLAC__bool -read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent) { unsigned char buf[4]; size_t bytes_read= fread(buf, 1, 2, f); @@ -2062,7 +2084,7 @@ read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char if(bytes_read==0U && eof_ok) return true; else if(bytes_read<2U) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } @@ -2072,8 +2094,7 @@ read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char return true; } -FLAC__bool -read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent) { unsigned char buf[4]; size_t bytes_read= fread(buf, 1, 4, f); @@ -2081,7 +2102,7 @@ read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char if(bytes_read==0U && eof_ok) return true; else if(bytes_read<4U) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } @@ -2092,8 +2113,7 @@ read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char return true; } -FLAC__bool -read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn, FLAC__bool silent) /* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f', * convert it into an integral value and store in 'val'. Return false if only * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f' and 'eof_ok' is @@ -2111,11 +2131,11 @@ read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn if(bytes_read==0U && eof_ok) return true; else if(bytes_read<10U) { - fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: unexpected EOF\n", fn); return false; } else if((buf[0]>>7)==1U || e<0 || e>63) { - fprintf(stderr, "%s: ERROR: invalid floating-point value\n", fn); + if(!silent) fprintf(stderr, "%s: ERROR: invalid floating-point value\n", fn); return false; } diff --git a/src/flac/encode.h b/src/flac/encode.h index 1f7e5a2a..5a2f7562 100644 --- a/src/flac/encode.h +++ b/src/flac/encode.h @@ -28,6 +28,7 @@ typedef struct { FLAC__bool verbose; + FLAC__bool silent; utils__SkipUntilSpecification skip_specification; utils__SkipUntilSpecification until_specification; FLAC__bool verify; diff --git a/src/flac/main.c b/src/flac/main.c index 93bde52d..c1fb517e 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -94,6 +94,7 @@ static struct share__option long_options_[] = { { "test" , share__no_argument, 0, 't' }, { "stdout" , share__no_argument, 0, 'c' }, { "silent" , share__no_argument, 0, 's' }, + { "totally-silent" , share__no_argument, 0, 0 }, { "force" , share__no_argument, 0, 'f' }, { "delete-input-file", share__no_argument, 0, 0 }, { "output-prefix" , share__required_argument, 0, 0 }, @@ -203,6 +204,7 @@ static struct { FLAC__bool mode_decode; FLAC__bool verify; FLAC__bool verbose; + FLAC__bool silent; FLAC__bool force_file_overwrite; FLAC__bool continue_through_decode_errors; replaygain_synthesis_spec_t replaygain_synthesis_spec; @@ -274,7 +276,7 @@ int main(int argc, char *argv[]) setlocale(LC_ALL, ""); if(!init_options()) { - fprintf(stderr, "ERROR: allocating memory\n"); + if(!option_values.silent) fprintf(stderr, "ERROR: allocating memory\n"); retval = 1; } else { @@ -305,7 +307,7 @@ int do_it() } else { if(option_values.num_files == 0) { - short_usage(); + if(!option_values.silent) short_usage(); return 0; } @@ -418,7 +420,7 @@ int do_it() * whole file. */ if(option_values.padding < 0) { - fprintf(stderr, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n"); + if(!option_values.silent) fprintf(stderr, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n"); option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED; } else { @@ -508,17 +510,17 @@ int do_it() for(i = 0; i < option_values.num_files; i++) { const char *error, *outfilename = get_encoded_outfilename(option_values.filenames[i]); if(0 == outfilename) { - fprintf(stderr, "ERROR: filename too long: %s", option_values.filenames[i]); + if(!option_values.silent) fprintf(stderr, "ERROR: filename too long: %s", option_values.filenames[i]); return 1; } if(0 == strcmp(option_values.filenames[i], "-")) { FLAC__ASSERT(0); /* double protection */ - fprintf(stderr, "internal error\n"); + if(!option_values.silent) fprintf(stderr, "internal error\n"); return 2; } if(0 != (error = grabbag__replaygain_store_to_file_album(outfilename, album_gain, album_peak, /*preserve_modtime=*/true))) { - fprintf(stderr, "%s: ERROR writing ReplayGain album tags\n", outfilename); + if(!option_values.silent) fprintf(stderr, "%s: ERROR writing ReplayGain album tags\n", outfilename); retval = 1; } } @@ -536,6 +538,7 @@ FLAC__bool init_options() option_values.mode_decode = false; option_values.verify = false; option_values.verbose = true; + option_values.silent = false; option_values.force_file_overwrite = false; option_values.continue_through_decode_errors = false; option_values.replaygain_synthesis_spec.apply = false; @@ -644,7 +647,11 @@ int parse_option(int short_option, const char *long_option, const char *option_a if(short_option == 0) { FLAC__ASSERT(0 != long_option); - if(0 == strcmp(long_option, "delete-input-file")) { + if(0 == strcmp(long_option, "totally-silent")) { + option_values.verbose = false; + option_values.silent = true; + } + else if(0 == strcmp(long_option, "delete-input-file")) { option_values.delete_input = true; } else if(0 == strcmp(long_option, "output-prefix")) { @@ -775,6 +782,7 @@ int parse_option(int short_option, const char *long_option, const char *option_a } else if(0 == strcmp(long_option, "no-silent")) { option_values.verbose = true; + option_values.silent = false; } else if(0 == strcmp(long_option, "no-force")) { option_values.force_file_overwrite = false; @@ -1064,17 +1072,19 @@ void free_options() int usage_error(const char *message, ...) { - va_list args; + if(!option_values.silent) { + va_list args; - FLAC__ASSERT(0 != message); + FLAC__ASSERT(0 != message); - va_start(args, message); + va_start(args, message); - (void) vfprintf(stderr, message, args); + (void) vfprintf(stderr, message, args); - va_end(args); + va_end(args); - printf("Type \"flac\" for a usage summary or \"flac --help\" for all options\n"); + printf("Type \"flac\" for a usage summary or \"flac --help\" for all options\n"); + } return 1; } @@ -1149,6 +1159,7 @@ void show_help() printf(" -a, --analyze Same as -d except an analysis file is written\n"); printf(" -c, --stdout Write output to stdout\n"); printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything, including errors\n"); printf(" -f, --force Force overwriting of output files\n"); printf(" -o, --output-name=FILENAME Force the output file name\n"); printf(" --output-prefix=STRING Prepend STRING to output names\n"); @@ -1253,6 +1264,9 @@ void show_explain() printf(" -a, --analyze Same as -d except an analysis file is written\n"); printf(" -c, --stdout Write output to stdout\n"); printf(" -s, --silent Do not write runtime encode/decode statistics\n"); + printf(" --totally-silent Do not print anything of any kind, including\n"); + printf(" warnings or errors. The exit code will be the\n"); + printf(" only way to determine successful completion.\n"); printf(" -f, --force Force overwriting of output files\n"); printf(" -o, --output-name=FILENAME Force the output file name; usually flac just\n"); printf(" changes the extension. May only be used when\n"); @@ -1440,10 +1454,9 @@ void show_explain() printf(" --no-verify\n"); } -void -format_mistake(const char *infilename, const char *wrong, const char *right) +void format_mistake(const char *infilename, const char *wrong, const char *right) { - fprintf(stderr, "WARNING: %s is not a %s file; treating as a %s file\n", infilename, wrong, right); + if(!option_values.silent) fprintf(stderr, "WARNING: %s is not a %s file; treating as a %s file\n", infilename, wrong, right); } int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file) @@ -1458,7 +1471,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ const char *outfilename = get_encoded_outfilename(infilename); if(0 == outfilename) { - fprintf(stderr, "ERROR: filename too long: %s", infilename); + if(!option_values.silent) fprintf(stderr, "ERROR: filename too long: %s", infilename); return 1; } @@ -1467,7 +1480,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ * Use grabbag__file_get_filesize() as a cheap way to check. */ if(!option_values.test_only && !option_values.force_file_overwrite && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { - fprintf(stderr, "ERROR: output file %s already exists, use -f to override\n", outfilename); + if(!option_values.silent) fprintf(stderr, "ERROR: output file %s already exists, use -f to override\n", outfilename); return 1; } @@ -1478,7 +1491,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ else { infilesize = grabbag__file_get_filesize(infilename); if(0 == (encode_infile = fopen(infilename, "rb"))) { - fprintf(stderr, "ERROR: can't open input file %s\n", infilename); + if(!option_values.silent) fprintf(stderr, "ERROR: can't open input file %s\n", infilename); return 1; } } @@ -1512,7 +1525,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ } if(option_values.sector_align && fmt == RAW && infilesize < 0) { - fprintf(stderr, "ERROR: can't --sector-align when the input size is unknown\n"); + if(!option_values.silent) fprintf(stderr, "ERROR: can't --sector-align when the input size is unknown\n"); return 1; } @@ -1536,6 +1549,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ common_options.until_specification.is_relative = true; common_options.verbose = option_values.verbose; + common_options.silent = option_values.silent; common_options.verify = option_values.verify; #ifdef FLAC__HAS_OGG common_options.use_ogg = option_values.use_ogg; @@ -1605,7 +1619,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ const char *error; grabbag__replaygain_get_title(&title_gain, &title_peak); if(0 != (error = grabbag__replaygain_store_to_file_title(outfilename, title_gain, title_peak, /*preserve_modtime=*/true))) { - fprintf(stderr, "%s: ERROR writing ReplayGain title tags\n", outfilename); + if(!option_values.silent) fprintf(stderr, "%s: ERROR writing ReplayGain title tags\n", outfilename); } } grabbag__file_copy_metadata(infilename, outfilename); @@ -1625,7 +1639,7 @@ int decode_file(const char *infilename) const char *outfilename = get_decoded_outfilename(infilename); if(0 == outfilename) { - fprintf(stderr, "ERROR: filename too long: %s", infilename); + if(!option_values.silent) fprintf(stderr, "ERROR: filename too long: %s", infilename); return 1; } @@ -1634,7 +1648,7 @@ int decode_file(const char *infilename) * Use grabbag__file_get_filesize() as a cheap way to check. */ if(!option_values.test_only && !option_values.force_file_overwrite && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { - fprintf(stderr, "ERROR: output file %s already exists, use -f to override\n", outfilename); + if(!option_values.silent) fprintf(stderr, "ERROR: output file %s already exists, use -f to override\n", outfilename); return 1; } @@ -1652,7 +1666,7 @@ int decode_file(const char *infilename) #ifndef FLAC__HAS_OGG if(treat_as_ogg) { - fprintf(stderr, "%s: Ogg support has not been built into this copy of flac\n", infilename); + if(!option_values.silent) fprintf(stderr, "%s: Ogg support has not been built into this copy of flac\n", infilename); return 1; } #endif @@ -1675,6 +1689,7 @@ int decode_file(const char *infilename) common_options.has_cue_specification = false; common_options.verbose = option_values.verbose; + common_options.silent = option_values.silent; common_options.continue_through_decode_errors = option_values.continue_through_decode_errors; common_options.replaygain_synthesis_spec = option_values.replaygain_synthesis_spec; #ifdef FLAC__HAS_OGG @@ -1781,7 +1796,7 @@ const char *get_outfilename(const char *infilename, const char *suffix) void die(const char *message) { FLAC__ASSERT(0 != message); - fprintf(stderr, "ERROR: %s\n", message); + if(!option_values.silent) fprintf(stderr, "ERROR: %s\n", message); exit(1); } diff --git a/test/test_flac.sh b/test/test_flac.sh index a52fbcb0..f1b6c6fc 100755 --- a/test/test_flac.sh +++ b/test/test_flac.sh @@ -60,28 +60,28 @@ fi echo "Try encoding to a file that exists; should fail" cp wacky1.wav exist.wav touch exist.flac -if run_flac -s -0 exist.wav ; then +if run_flac --totally-silent -0 exist.wav ; then die "ERROR: it should have failed but didn't" else echo "OK, it failed as it should" fi echo "Try encoding with -f to a file that exists; should succeed" -if run_flac -s -0 --force exist.wav ; then +if run_flac --totally-silent -0 --force exist.wav ; then echo "OK, it succeeded as it should" else die "ERROR: it should have succeeded but didn't" fi echo "Try decoding to a file that exists; should fail" -if run_flac -s -d exist.flac ; then +if run_flac --totally-silent -d exist.flac ; then die "ERROR: it should have failed but didn't" else echo "OK, it failed as it should" fi echo "Try decoding with -f to a file that exists; should succeed" -if run_flac -s -d -f exist.flac ; then +if run_flac --totally-silent -d -f exist.flac ; then echo "OK, it succeeded as it should" else die "ERROR: it should have succeeded but didn't"