On WIN32, set stdout/stderr to UTF-8 (#714)

When stderr (flac) or stdout (metaflac) is redirected to a file,
output of non-ASCII characters fails. This commit should fix that.

Fixes https://github.com/xiph/flac/issues/713

NOTE: To enable this change, metaflac no longer outputs
application block data as binary directly, because that would
potentially result in incorrect UTF-8 codepoint. Instead, all
bytes that cannot be represented as printable ASCII are
replaced with the Unicode replacement character
This commit is contained in:
Martijn van Beurden 2024-06-26 09:42:07 +02:00 committed by GitHub
parent 706c061457
commit dda3e77ea2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 450 additions and 414 deletions

View File

@ -223,7 +223,7 @@ FLAC__bool dump_stats(const subframe_stats_t *stats, const char *filename)
outfile = flac_fopen(filename, "w"); outfile = flac_fopen(filename, "w");
if(0 == outfile) { if(0 == outfile) {
fprintf(stderr, "ERROR opening %s: %s\n", filename, strerror(errno)); flac_fprintf(stderr, "ERROR opening %s: %s\n", filename, strerror(errno));
return false; return false;
} }

View File

@ -319,6 +319,8 @@ static int main_to_fuzz(int argc, char *argv[])
fprintf(stderr, "ERROR: failed to convert command line parameters to UTF-8\n"); fprintf(stderr, "ERROR: failed to convert command line parameters to UTF-8\n");
return 1; return 1;
} }
SetConsoleOutputCP(CP_UTF8);
_setmode(fileno(stderr),_O_U8TEXT);
#endif #endif
srand((uint32_t)time(0)); srand((uint32_t)time(0));

View File

@ -235,7 +235,7 @@ void stats_new_file(void)
void stats_clear(void) void stats_clear(void)
{ {
while (stats_char_count > 0 && stats_char_count--) while (stats_char_count > 0 && stats_char_count--)
fprintf(stderr, "\b"); flac_fprintf(stderr, "\b");
} }
void stats_print_name(int level, const char *name) void stats_print_name(int level, const char *name)
@ -267,11 +267,11 @@ void stats_print_info(int level, const char *format, ...)
stats_clear(); stats_clear();
if (len >= console_chars_left) { if (len >= console_chars_left) {
clear_len = console_chars_left; clear_len = console_chars_left;
while (clear_len > 0 && clear_len--) fprintf(stderr, " "); while (clear_len > 0 && clear_len--) flac_fprintf(stderr, " ");
fprintf(stderr, "\n"); flac_fprintf(stderr, "\n");
console_chars_left = console_width; console_chars_left = console_width;
} }
stats_char_count = fprintf(stderr, "%s", tmp); stats_char_count = flac_fprintf(stderr, "%s", tmp);
fflush(stderr); fflush(stderr);
} }
} }

View File

@ -47,7 +47,7 @@
#ifndef NDEBUG #ifndef NDEBUG
#include <stdio.h> #include <stdio.h>
#define dfprintf fprintf #define dfprintf flac_fprintf
#else #else
/* This is bad practice, it should be a static void empty function */ /* This is bad practice, it should be a static void empty function */
#define dfprintf(file, format, ...) #define dfprintf(file, format, ...)

View File

@ -268,9 +268,9 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], uint32_t order,
#ifdef FLAC__OVERFLOW_DETECT #ifdef FLAC__OVERFLOW_DETECT
if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */ if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */
fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]); flac_fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]);
else if(q < qmin) else if(q < qmin)
fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmin,*shift,cmax,precision+1,i,lp_coeff[i]); flac_fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmin,*shift,cmax,precision+1,i,lp_coeff[i]);
#endif #endif
if(q > qmax) if(q > qmax)
q = qmax; q = qmax;
@ -289,16 +289,16 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], uint32_t order,
double error = 0.0; double error = 0.0;
FLAC__int32 q; FLAC__int32 q;
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift=%d order=%u cmax=%f\n", *shift, order, cmax); flac_fprintf(stderr,"FLAC__lpc_quantize_coefficients: negative shift=%d order=%u cmax=%f\n", *shift, order, cmax);
#endif #endif
for(i = 0; i < order; i++) { for(i = 0; i < order; i++) {
error += lp_coeff[i] / (1 << nshift); error += lp_coeff[i] / (1 << nshift);
q = lround(error); q = lround(error);
#ifdef FLAC__OVERFLOW_DETECT #ifdef FLAC__OVERFLOW_DETECT
if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */ if(q > qmax+1) /* we expect q==qmax+1 occasionally due to rounding */
fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]); flac_fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q>qmax %d>%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmax,*shift,cmax,precision+1,i,lp_coeff[i]);
else if(q < qmin) else if(q < qmin)
fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmin,*shift,cmax,precision+1,i,lp_coeff[i]); flac_fprintf(stderr,"FLAC__lpc_quantize_coefficients: quantizer overflow: q<qmin %d<%d shift=%d cmax=%f precision=%u lpc[%u]=%f\n",q,qmin,*shift,cmax,precision+1,i,lp_coeff[i]);
#endif #endif
if(q > qmax) if(q > qmax)
q = qmax; q = qmax;
@ -327,10 +327,10 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 * flac_r
const FLAC__int32 *history; const FLAC__int32 *history;
#ifdef FLAC__OVERFLOW_DETECT_VERBOSE #ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); flac_fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
for(i=0;i<order;i++) for(i=0;i<order;i++)
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]); flac_fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
fprintf(stderr,"\n"); flac_fprintf(stderr,"\n");
#endif #endif
FLAC__ASSERT(order > 0); FLAC__ASSERT(order > 0);
@ -342,7 +342,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 * flac_r
sum += qlp_coeff[j] * (*(--history)); sum += qlp_coeff[j] * (*(--history));
sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history);
if(sumo > 2147483647ll || sumo < -2147483648ll) if(sumo > 2147483647ll || sumo < -2147483648ll)
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo); flac_fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo);
} }
*(residual++) = *(data++) - (sum >> lp_quantization); *(residual++) = *(data++) - (sum >> lp_quantization);
} }
@ -587,10 +587,10 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f
const FLAC__int32 *history; const FLAC__int32 *history;
#ifdef FLAC__OVERFLOW_DETECT_VERBOSE #ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); flac_fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
for(i=0;i<order;i++) for(i=0;i<order;i++)
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]); flac_fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
fprintf(stderr,"\n"); flac_fprintf(stderr,"\n");
#endif #endif
FLAC__ASSERT(order > 0); FLAC__ASSERT(order > 0);
@ -600,7 +600,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * f
for(j = 0; j < order; j++) for(j = 0; j < order; j++)
sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history));
if(FLAC__bitmath_silog2((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) { if(FLAC__bitmath_silog2((FLAC__int64)(*data) - (sum >> lp_quantization)) > 32) {
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%" PRId64 ", residual=%" PRId64 "\n", i, *data, (int64_t)(sum >> lp_quantization), ((FLAC__int64)(*data) - (sum >> lp_quantization))); flac_fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients_wide: OVERFLOW, i=%u, data=%d, sum=%" PRId64 ", residual=%" PRId64 "\n", i, *data, (int64_t)(sum >> lp_quantization), ((FLAC__int64)(*data) - (sum >> lp_quantization)));
break; break;
} }
*(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization); *(residual++) = *(data++) - (FLAC__int32)(sum >> lp_quantization);
@ -984,10 +984,10 @@ void FLAC__lpc_restore_signal(const FLAC__int32 * flac_restrict residual, uint32
const FLAC__int32 *r = residual, *history; const FLAC__int32 *r = residual, *history;
#ifdef FLAC__OVERFLOW_DETECT_VERBOSE #ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); flac_fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
for(i=0;i<order;i++) for(i=0;i<order;i++)
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]); flac_fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
fprintf(stderr,"\n"); flac_fprintf(stderr,"\n");
#endif #endif
FLAC__ASSERT(order > 0); FLAC__ASSERT(order > 0);
@ -1000,7 +1000,7 @@ void FLAC__lpc_restore_signal(const FLAC__int32 * flac_restrict residual, uint32
sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history); sumo += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*history);
#ifdef FLAC__OVERFLOW_DETECT #ifdef FLAC__OVERFLOW_DETECT
if(sumo > 2147483647ll || sumo < -2147483648ll) if(sumo > 2147483647ll || sumo < -2147483648ll)
fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo); flac_fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, i=%u, j=%u, c=%d, d=%d, sumo=%" PRId64 "\n",i,j,qlp_coeff[j],*history,sumo);
#endif #endif
} }
*(data++) = *(r++) + (sum >> lp_quantization); *(data++) = *(r++) + (sum >> lp_quantization);
@ -1246,10 +1246,10 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, u
const FLAC__int32 *r = residual, *history; const FLAC__int32 *r = residual, *history;
#ifdef FLAC__OVERFLOW_DETECT_VERBOSE #ifdef FLAC__OVERFLOW_DETECT_VERBOSE
fprintf(stderr,"FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization); flac_fprintf(stderr,"FLAC__lpc_restore_signal_wide: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
for(i=0;i<order;i++) for(i=0;i<order;i++)
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]); flac_fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
fprintf(stderr,"\n"); flac_fprintf(stderr,"\n");
#endif #endif
FLAC__ASSERT(order > 0); FLAC__ASSERT(order > 0);
@ -1260,7 +1260,7 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, u
sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history));
#ifdef FLAC__OVERFLOW_DETECT #ifdef FLAC__OVERFLOW_DETECT
if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 32) { if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 32) {
fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization))); flac_fprintf(stderr,"FLAC__lpc_restore_signal_wide: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization)));
break; break;
} }
#endif #endif
@ -1515,7 +1515,7 @@ void FLAC__lpc_restore_signal_wide_33bit(const FLAC__int32 * flac_restrict resid
sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history)); sum += (FLAC__int64)qlp_coeff[j] * (FLAC__int64)(*(--history));
#ifdef FLAC__OVERFLOW_DETECT #ifdef FLAC__OVERFLOW_DETECT
if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 33) { if(FLAC__bitmath_silog2((FLAC__int64)(*r) + (sum >> lp_quantization)) > 33) {
fprintf(stderr,"FLAC__lpc_restore_signal_33bit: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization))); flac_fprintf(stderr,"FLAC__lpc_restore_signal_33bit: OVERFLOW, i=%u, residual=%d, sum=%" PRId64 ", data=%" PRId64 "\n", i, *r, (sum >> lp_quantization), ((FLAC__int64)(*r) + (sum >> lp_quantization)));
break; break;
} }
#endif #endif

View File

@ -2228,14 +2228,14 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
* isn't checked, if the seek fails the decoder will continue anyway */ * isn't checked, if the seek fails the decoder will continue anyway */
if(!FLAC__bitreader_rewind_to_after_last_seen_framesync(decoder->private_->input)){ if(!FLAC__bitreader_rewind_to_after_last_seen_framesync(decoder->private_->input)){
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "Rewinding, seeking necessary\n"); flac_fprintf(stderr, "Rewinding, seeking necessary\n");
#endif #endif
if(decoder->private_->seek_callback && decoder->private_->last_seen_framesync){ if(decoder->private_->seek_callback && decoder->private_->last_seen_framesync){
/* Last framesync isn't in bitreader anymore, rewind with seek if possible */ /* Last framesync isn't in bitreader anymore, rewind with seek if possible */
#ifndef NDEBUG #ifndef NDEBUG
FLAC__uint64 current_decode_position; FLAC__uint64 current_decode_position;
if(FLAC__stream_decoder_get_decode_position(decoder, &current_decode_position)) if(FLAC__stream_decoder_get_decode_position(decoder, &current_decode_position))
fprintf(stderr, "Bitreader was %" PRIu64 " bytes short\n", current_decode_position-decoder->private_->last_seen_framesync); flac_fprintf(stderr, "Bitreader was %" PRIu64 " bytes short\n", current_decode_position-decoder->private_->last_seen_framesync);
#endif #endif
if(decoder->private_->seek_callback(decoder, decoder->private_->last_seen_framesync, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) { if(decoder->private_->seek_callback(decoder, decoder->private_->last_seen_framesync, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR; decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
@ -2249,7 +2249,7 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
} }
#ifndef NDEBUG #ifndef NDEBUG
else{ else{
fprintf(stderr, "Rewinding, seeking not necessary\n"); flac_fprintf(stderr, "Rewinding, seeking not necessary\n");
} }
#endif #endif
} }

View File

@ -4420,11 +4420,11 @@ static void spotcheck_subframe_estimate_(
FLAC__bool ret; FLAC__bool ret;
FLAC__BitWriter *frame = FLAC__bitwriter_new(); FLAC__BitWriter *frame = FLAC__bitwriter_new();
if(frame == 0) { if(frame == 0) {
fprintf(stderr, "EST: can't allocate frame\n"); flac_fprintf(stderr, "EST: can't allocate frame\n");
return; return;
} }
if(!FLAC__bitwriter_init(frame)) { if(!FLAC__bitwriter_init(frame)) {
fprintf(stderr, "EST: can't init frame\n"); flac_fprintf(stderr, "EST: can't init frame\n");
return; return;
} }
ret = add_subframe_(encoder, blocksize, subframe_bps, subframe, frame); ret = add_subframe_(encoder, blocksize, subframe_bps, subframe, frame);
@ -4432,7 +4432,7 @@ static void spotcheck_subframe_estimate_(
{ {
const uint32_t actual = FLAC__bitwriter_get_input_bits_unconsumed(frame); const uint32_t actual = FLAC__bitwriter_get_input_bits_unconsumed(frame);
if(estimate != actual) if(estimate != actual)
fprintf(stderr, "EST: bad, frame#%u sub#%%d type=%8s est=%u, actual=%u, delta=%d\n", encoder->private_->current_frame_number, FLAC__SubframeTypeString[subframe->type], estimate, actual, (int)actual-(int)estimate); flac_fprintf(stderr, "EST: bad, frame#%u sub#%%d type=%8s est=%u, actual=%u, delta=%d\n", encoder->private_->current_frame_number, FLAC__SubframeTypeString[subframe->type], estimate, actual, (int)actual-(int)estimate);
} }
FLAC__bitwriter_delete(frame); FLAC__bitwriter_delete(frame);
} }
@ -4995,7 +4995,7 @@ FLAC__bool set_partitioned_rice_(
if(rice_parameter >= rice_parameter_limit) { if(rice_parameter >= rice_parameter_limit) {
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1); flac_fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1);
#endif #endif
rice_parameter = rice_parameter_limit - 1; rice_parameter = rice_parameter_limit - 1;
} }
@ -5010,7 +5010,7 @@ FLAC__bool set_partitioned_rice_(
max_rice_parameter = rice_parameter + rice_parameter_search_dist; max_rice_parameter = rice_parameter + rice_parameter_search_dist;
if(max_rice_parameter >= rice_parameter_limit) { if(max_rice_parameter >= rice_parameter_limit) {
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, rice_parameter_limit - 1); flac_fprintf(stderr, "clipping rice_parameter (%u -> %u) @7\n", max_rice_parameter, rice_parameter_limit - 1);
#endif #endif
max_rice_parameter = rice_parameter_limit - 1; max_rice_parameter = rice_parameter_limit - 1;
} }

View File

@ -71,6 +71,13 @@ FLAC__bool do_operations(const CommandLineOptions *options)
{ {
FLAC__bool ok = true; FLAC__bool ok = true;
#ifdef _WIN32
if(options->utf8_convert) {
_setmode(fileno(stdout),_O_U8TEXT);
SetConsoleOutputCP(CP_UTF8);
}
#endif
if(options->show_long_help) { if(options->show_long_help) {
long_usage(0); long_usage(0);
} }
@ -201,6 +208,12 @@ FLAC__bool do_major_operation__list(const char *filename, FLAC__Metadata_Chain *
return false; return false;
} }
write_metadata_binary(block, block_raw, options->data_format_is_binary_headerless); write_metadata_binary(block, block_raw, options->data_format_is_binary_headerless);
#ifdef _WIN32
if(options->utf8_convert)
_setmode(fileno(stdout),_O_U8TEXT);
else
_setmode(fileno(stdin),_O_TEXT);
#endif
free(block_raw); free(block_raw);
} }
} }
@ -323,7 +336,10 @@ FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const Command
} }
#ifdef _WIN32 #ifdef _WIN32
_setmode(fileno(stdin),_O_TEXT); if(options->utf8_convert)
_setmode(fileno(stdout),_O_U8TEXT);
else
_setmode(fileno(stdin),_O_TEXT);
#endif #endif
if(num_objects == 0) if(num_objects == 0)
@ -694,109 +710,125 @@ void write_metadata(const char *filename, FLAC__StreamMetadata *block, unsigned
/*@@@ yuck, should do this with a varargs function or something: */ /*@@@ yuck, should do this with a varargs function or something: */
#define PPR if(filename) { if(raw) printf("%s:",filename); else flac_printf("%s:",filename); } #define PPR if(filename) { if(raw) printf("%s:",filename); else flac_printf("%s:",filename); }
PPR; printf("METADATA block #%u\n", block_number); PPR; flac_printf("METADATA block #%u\n", block_number);
PPR; printf(" type: %u (%s)\n", (unsigned)block->type, block->type < FLAC__METADATA_TYPE_UNDEFINED? FLAC__MetadataTypeString[block->type] : "UNKNOWN"); PPR; flac_printf(" type: %u (%s)\n", (unsigned)block->type, block->type < FLAC__METADATA_TYPE_UNDEFINED? FLAC__MetadataTypeString[block->type] : "UNKNOWN");
PPR; printf(" is last: %s\n", block->is_last? "true":"false"); PPR; flac_printf(" is last: %s\n", block->is_last? "true":"false");
PPR; printf(" length: %u\n", block->length); PPR; flac_printf(" length: %u\n", block->length);
switch(block->type) { switch(block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
PPR; printf(" minimum blocksize: %u samples\n", block->data.stream_info.min_blocksize); PPR; flac_printf(" minimum blocksize: %u samples\n", block->data.stream_info.min_blocksize);
PPR; printf(" maximum blocksize: %u samples\n", block->data.stream_info.max_blocksize); PPR; flac_printf(" maximum blocksize: %u samples\n", block->data.stream_info.max_blocksize);
PPR; printf(" minimum framesize: %u bytes\n", block->data.stream_info.min_framesize); PPR; flac_printf(" minimum framesize: %u bytes\n", block->data.stream_info.min_framesize);
PPR; printf(" maximum framesize: %u bytes\n", block->data.stream_info.max_framesize); PPR; flac_printf(" maximum framesize: %u bytes\n", block->data.stream_info.max_framesize);
PPR; printf(" sample_rate: %u Hz\n", block->data.stream_info.sample_rate); PPR; flac_printf(" sample_rate: %u Hz\n", block->data.stream_info.sample_rate);
PPR; printf(" channels: %u\n", block->data.stream_info.channels); PPR; flac_printf(" channels: %u\n", block->data.stream_info.channels);
PPR; printf(" bits-per-sample: %u\n", block->data.stream_info.bits_per_sample); PPR; flac_printf(" bits-per-sample: %u\n", block->data.stream_info.bits_per_sample);
PPR; printf(" total samples: %" PRIu64 "\n", block->data.stream_info.total_samples); PPR; flac_printf(" total samples: %" PRIu64 "\n", block->data.stream_info.total_samples);
PPR; printf(" MD5 signature: "); PPR; flac_printf(" MD5 signature: ");
for(i = 0; i < 16; i++) { for(i = 0; i < 16; i++) {
printf("%02x", (unsigned)block->data.stream_info.md5sum[i]); if(raw)
printf("%02x", (unsigned)block->data.stream_info.md5sum[i]);
else
flac_printf("%02x", (unsigned)block->data.stream_info.md5sum[i]);
} }
printf("\n"); if(raw)
printf("\n");
else
flac_printf("\n");
break; break;
case FLAC__METADATA_TYPE_PADDING: case FLAC__METADATA_TYPE_PADDING:
/* nothing to print */ /* nothing to print */
break; break;
case FLAC__METADATA_TYPE_APPLICATION: case FLAC__METADATA_TYPE_APPLICATION:
PPR; printf(" application ID: "); PPR; flac_printf(" application ID: ");
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
printf("%02x", block->data.application.id[i]); flac_printf("%02x", block->data.application.id[i]);
printf("\n"); flac_printf("\n");
PPR; printf(" data contents:\n"); PPR; flac_printf(" data contents:\n");
if(0 != block->data.application.data) { if(0 != block->data.application.data) {
if(hexdump_application) if(hexdump_application)
hexdump(filename, block->data.application.data, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, " "); hexdump(filename, block->data.application.data, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, " ");
else else
(void) local_fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout); for(i = 0; i < block->length - FLAC__STREAM_METADATA_HEADER_LENGTH; i++)
if(raw)
(void) local_fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout);
else {
if(block->data.application.data[i] > 32 && block->data.application.data[i] < 127)
flac_printf("%c",block->data.application.data[i]);
else {
char replacement[4] = {0xef, 0xbf, 0xbd, 0}; /* Unicode replacement character */
flac_printf(replacement);
}
}
} }
break; break;
case FLAC__METADATA_TYPE_SEEKTABLE: case FLAC__METADATA_TYPE_SEEKTABLE:
PPR; printf(" seek points: %u\n", block->data.seek_table.num_points); PPR; flac_printf(" seek points: %u\n", block->data.seek_table.num_points);
for(i = 0; i < block->data.seek_table.num_points; i++) { for(i = 0; i < block->data.seek_table.num_points; i++) {
if(block->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) { if(block->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
PPR; printf(" point %u: sample_number=%" PRIu64 ", stream_offset=%" PRIu64 ", frame_samples=%u\n", i, block->data.seek_table.points[i].sample_number, block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples); PPR; flac_printf(" point %u: sample_number=%" PRIu64 ", stream_offset=%" PRIu64 ", frame_samples=%u\n", i, block->data.seek_table.points[i].sample_number, block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples);
} }
else { else {
PPR; printf(" point %u: PLACEHOLDER\n", i); PPR; flac_printf(" point %u: PLACEHOLDER\n", i);
} }
} }
break; break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
PPR; printf(" vendor string: "); PPR; flac_printf(" vendor string: ");
write_vc_field(0, &block->data.vorbis_comment.vendor_string, raw, stdout); write_vc_field(0, &block->data.vorbis_comment.vendor_string, raw, stdout);
PPR; printf(" comments: %u\n", block->data.vorbis_comment.num_comments); PPR; flac_printf(" comments: %u\n", block->data.vorbis_comment.num_comments);
for(i = 0; i < block->data.vorbis_comment.num_comments; i++) { for(i = 0; i < block->data.vorbis_comment.num_comments; i++) {
PPR; printf(" comment[%u]: ", i); PPR; flac_printf(" comment[%u]: ", i);
write_vc_field(0, &block->data.vorbis_comment.comments[i], raw, stdout); write_vc_field(0, &block->data.vorbis_comment.comments[i], raw, stdout);
} }
break; break;
case FLAC__METADATA_TYPE_CUESHEET: case FLAC__METADATA_TYPE_CUESHEET:
PPR; printf(" media catalog number: %s\n", block->data.cue_sheet.media_catalog_number); PPR; flac_printf(" media catalog number: %s\n", block->data.cue_sheet.media_catalog_number);
PPR; printf(" lead-in: %" PRIu64 "\n", block->data.cue_sheet.lead_in); PPR; flac_printf(" lead-in: %" PRIu64 "\n", block->data.cue_sheet.lead_in);
PPR; printf(" is CD: %s\n", block->data.cue_sheet.is_cd? "true":"false"); PPR; flac_printf(" is CD: %s\n", block->data.cue_sheet.is_cd? "true":"false");
PPR; printf(" number of tracks: %u\n", block->data.cue_sheet.num_tracks); PPR; flac_printf(" number of tracks: %u\n", block->data.cue_sheet.num_tracks);
for(i = 0; i < block->data.cue_sheet.num_tracks; i++) { for(i = 0; i < block->data.cue_sheet.num_tracks; i++) {
const FLAC__StreamMetadata_CueSheet_Track *track = block->data.cue_sheet.tracks+i; const FLAC__StreamMetadata_CueSheet_Track *track = block->data.cue_sheet.tracks+i;
const FLAC__bool is_last = (i == block->data.cue_sheet.num_tracks-1); const FLAC__bool is_last = (i == block->data.cue_sheet.num_tracks-1);
const FLAC__bool is_leadout = is_last && track->num_indices == 0; const FLAC__bool is_leadout = is_last && track->num_indices == 0;
PPR; printf(" track[%u]\n", i); PPR; flac_printf(" track[%u]\n", i);
PPR; printf(" offset: %" PRIu64 "\n", track->offset); PPR; flac_printf(" offset: %" PRIu64 "\n", track->offset);
if(is_last) { if(is_last) {
PPR; printf(" number: %u (%s)\n", (unsigned)track->number, is_leadout? "LEAD-OUT" : "INVALID"); PPR; flac_printf(" number: %u (%s)\n", (unsigned)track->number, is_leadout? "LEAD-OUT" : "INVALID");
} }
else { else {
PPR; printf(" number: %u\n", (unsigned)track->number); PPR; flac_printf(" number: %u\n", (unsigned)track->number);
} }
if(!is_leadout) { if(!is_leadout) {
PPR; printf(" ISRC: %s\n", track->isrc); PPR; flac_printf(" ISRC: %s\n", track->isrc);
PPR; printf(" type: %s\n", track->type == 1? "DATA" : "AUDIO"); PPR; flac_printf(" type: %s\n", track->type == 1? "DATA" : "AUDIO");
PPR; printf(" pre-emphasis: %s\n", track->pre_emphasis? "true":"false"); PPR; flac_printf(" pre-emphasis: %s\n", track->pre_emphasis? "true":"false");
PPR; printf(" number of index points: %u\n", track->num_indices); PPR; flac_printf(" number of index points: %u\n", track->num_indices);
for(j = 0; j < track->num_indices; j++) { for(j = 0; j < track->num_indices; j++) {
const FLAC__StreamMetadata_CueSheet_Index *indx = track->indices+j; const FLAC__StreamMetadata_CueSheet_Index *indx = track->indices+j;
PPR; printf(" index[%u]\n", j); PPR; flac_printf(" index[%u]\n", j);
PPR; printf(" offset: %" PRIu64 "\n", indx->offset); PPR; flac_printf(" offset: %" PRIu64 "\n", indx->offset);
PPR; printf(" number: %u\n", (unsigned)indx->number); PPR; flac_printf(" number: %u\n", (unsigned)indx->number);
} }
} }
} }
break; break;
case FLAC__METADATA_TYPE_PICTURE: case FLAC__METADATA_TYPE_PICTURE:
PPR; printf(" type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED"); PPR; flac_printf(" type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED");
PPR; printf(" MIME type: %s\n", block->data.picture.mime_type); PPR; flac_printf(" MIME type: %s\n", block->data.picture.mime_type);
PPR; printf(" description: %s\n", block->data.picture.description); PPR; flac_printf(" description: %s\n", block->data.picture.description);
PPR; printf(" width: %u\n", (unsigned)block->data.picture.width); PPR; flac_printf(" width: %u\n", (unsigned)block->data.picture.width);
PPR; printf(" height: %u\n", (unsigned)block->data.picture.height); PPR; flac_printf(" height: %u\n", (unsigned)block->data.picture.height);
PPR; printf(" depth: %u\n", (unsigned)block->data.picture.depth); PPR; flac_printf(" depth: %u\n", (unsigned)block->data.picture.depth);
PPR; printf(" colors: %u%s\n", (unsigned)block->data.picture.colors, block->data.picture.colors? "" : " (unindexed)"); PPR; flac_printf(" colors: %u%s\n", (unsigned)block->data.picture.colors, block->data.picture.colors? "" : " (unindexed)");
PPR; printf(" data length: %u\n", (unsigned)block->data.picture.data_length); PPR; flac_printf(" data length: %u\n", (unsigned)block->data.picture.data_length);
PPR; printf(" data:\n"); PPR; flac_printf(" data:\n");
if(0 != block->data.picture.data) if(0 != block->data.picture.data)
hexdump(filename, block->data.picture.data, block->data.picture.data_length, " "); hexdump(filename, block->data.picture.data, block->data.picture.data_length, " ");
break; break;
default: default:
PPR; printf(" data contents:\n"); PPR; flac_printf(" data contents:\n");
if(0 != block->data.unknown.data) if(0 != block->data.unknown.data)
hexdump(filename, block->data.unknown.data, block->length, " "); hexdump(filename, block->data.unknown.data, block->length, " ");
break; break;
@ -818,6 +850,5 @@ void write_metadata_binary(FLAC__StreamMetadata *block, FLAC__byte *block_raw, F
local_fwrite(block_raw+FLAC__STREAM_METADATA_HEADER_LENGTH, 1, block->length, stdout); local_fwrite(block_raw+FLAC__STREAM_METADATA_HEADER_LENGTH, 1, block->length, stdout);
#ifdef _WIN32 #ifdef _WIN32
fflush(stdout); fflush(stdout);
_setmode(fileno(stdout),_O_TEXT);
#endif #endif
} }

View File

@ -52,32 +52,32 @@ FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__bool p
switch(operation->type) { switch(operation->type) {
case OP__SHOW_MD5SUM: case OP__SHOW_MD5SUM:
for(i = 0; i < 16; i++) for(i = 0; i < 16; i++)
printf("%02x", block->data.stream_info.md5sum[i]); flac_printf("%02x", block->data.stream_info.md5sum[i]);
printf("\n"); flac_printf("\n");
break; break;
case OP__SHOW_MIN_BLOCKSIZE: case OP__SHOW_MIN_BLOCKSIZE:
printf("%u\n", block->data.stream_info.min_blocksize); flac_printf("%u\n", block->data.stream_info.min_blocksize);
break; break;
case OP__SHOW_MAX_BLOCKSIZE: case OP__SHOW_MAX_BLOCKSIZE:
printf("%u\n", block->data.stream_info.max_blocksize); flac_printf("%u\n", block->data.stream_info.max_blocksize);
break; break;
case OP__SHOW_MIN_FRAMESIZE: case OP__SHOW_MIN_FRAMESIZE:
printf("%u\n", block->data.stream_info.min_framesize); flac_printf("%u\n", block->data.stream_info.min_framesize);
break; break;
case OP__SHOW_MAX_FRAMESIZE: case OP__SHOW_MAX_FRAMESIZE:
printf("%u\n", block->data.stream_info.max_framesize); flac_printf("%u\n", block->data.stream_info.max_framesize);
break; break;
case OP__SHOW_SAMPLE_RATE: case OP__SHOW_SAMPLE_RATE:
printf("%u\n", block->data.stream_info.sample_rate); flac_printf("%u\n", block->data.stream_info.sample_rate);
break; break;
case OP__SHOW_CHANNELS: case OP__SHOW_CHANNELS:
printf("%u\n", block->data.stream_info.channels); flac_printf("%u\n", block->data.stream_info.channels);
break; break;
case OP__SHOW_BPS: case OP__SHOW_BPS:
printf("%u\n", block->data.stream_info.bits_per_sample); flac_printf("%u\n", block->data.stream_info.bits_per_sample);
break; break;
case OP__SHOW_TOTAL_SAMPLES: case OP__SHOW_TOTAL_SAMPLES:
printf("%" PRIu64 "\n", block->data.stream_info.total_samples); flac_printf("%" PRIu64 "\n", block->data.stream_info.total_samples);
break; break;
case OP__SET_MD5SUM: case OP__SET_MD5SUM:
memcpy(block->data.stream_info.md5sum, operation->argument.streaminfo_md5.value, 16); memcpy(block->data.stream_info.md5sum, operation->argument.streaminfo_md5.value, 16);

View File

@ -30,50 +30,50 @@
static void usage_header(FILE *out) static void usage_header(FILE *out)
{ {
fprintf(out, "==============================================================================\n"); flac_fprintf(out, "==============================================================================\n");
fprintf(out, "metaflac - Command-line FLAC metadata editor version %s\n", FLAC__VERSION_STRING); flac_fprintf(out, "metaflac - Command-line FLAC metadata editor version %s\n", FLAC__VERSION_STRING);
fprintf(out, "Copyright (C) 2001-2009 Josh Coalson\n"); flac_fprintf(out, "Copyright (C) 2001-2009 Josh Coalson\n");
fprintf(out, "Copyright (C) 2011-2023 Xiph.Org Foundation\n"); flac_fprintf(out, "Copyright (C) 2011-2023 Xiph.Org Foundation\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "This program is free software; you can redistribute it and/or\n"); flac_fprintf(out, "This program is free software; you can redistribute it and/or\n");
fprintf(out, "modify it under the terms of the GNU General Public License\n"); flac_fprintf(out, "modify it under the terms of the GNU General Public License\n");
fprintf(out, "as published by the Free Software Foundation; either version 2\n"); flac_fprintf(out, "as published by the Free Software Foundation; either version 2\n");
fprintf(out, "of the License, or (at your option) any later version.\n"); flac_fprintf(out, "of the License, or (at your option) any later version.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "This program is distributed in the hope that it will be useful,\n"); flac_fprintf(out, "This program is distributed in the hope that it will be useful,\n");
fprintf(out, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); flac_fprintf(out, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
fprintf(out, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); flac_fprintf(out, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
fprintf(out, "GNU General Public License for more details.\n"); flac_fprintf(out, "GNU General Public License for more details.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "You should have received a copy of the GNU General Public License along\n"); flac_fprintf(out, "You should have received a copy of the GNU General Public License along\n");
fprintf(out, "with this program; if not, write to the Free Software Foundation, Inc.,\n"); flac_fprintf(out, "with this program; if not, write to the Free Software Foundation, Inc.,\n");
fprintf(out, "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n"); flac_fprintf(out, "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n");
fprintf(out, "==============================================================================\n"); flac_fprintf(out, "==============================================================================\n");
} }
static void usage_summary(FILE *out) static void usage_summary(FILE *out)
{ {
fprintf(out, "Usage:\n"); flac_fprintf(out, "Usage:\n");
fprintf(out, " metaflac [options] [operations] FLACfile [FLACfile ...]\n"); flac_fprintf(out, " metaflac [options] [operations] FLACfile [FLACfile ...]\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "Use metaflac to list, add, remove, or edit metadata in one or more FLAC files.\n"); flac_fprintf(out, "Use metaflac to list, add, remove, or edit metadata in one or more FLAC files.\n");
fprintf(out, "You may perform one major operation, or many shorthand operations at a time.\n"); flac_fprintf(out, "You may perform one major operation, or many shorthand operations at a time.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "Options:\n"); flac_fprintf(out, "Options:\n");
fprintf(out, "--preserve-modtime Preserve the original modification time in spite of edits\n"); flac_fprintf(out, "--preserve-modtime Preserve the original modification time in spite of edits\n");
fprintf(out, "--with-filename Prefix each output line with the FLAC file name\n"); flac_fprintf(out, "--with-filename Prefix each output line with the FLAC file name\n");
fprintf(out, " (the default if more than one FLAC file is specified).\n"); flac_fprintf(out, " (the default if more than one FLAC file is specified).\n");
fprintf(out, " This option has no effect for options exporting to a\n"); flac_fprintf(out, " This option has no effect for options exporting to a\n");
fprintf(out, " file, like --export-tags-to.\n"); flac_fprintf(out, " file, like --export-tags-to.\n");
fprintf(out, "--no-filename Do not prefix each output line with the FLAC file name\n"); flac_fprintf(out, "--no-filename Do not prefix each output line with the FLAC file name\n");
fprintf(out, " (the default if only one FLAC file is specified)\n"); flac_fprintf(out, " (the default if only one FLAC file is specified)\n");
fprintf(out, "--no-utf8-convert Do not convert tags from UTF-8 to local charset,\n"); flac_fprintf(out, "--no-utf8-convert Do not convert tags from UTF-8 to local charset,\n");
fprintf(out, " or vice versa. This is useful for scripts, and setting\n"); flac_fprintf(out, " or vice versa. This is useful for scripts, and setting\n");
fprintf(out, " tags in situations where the locale is wrong.\n"); flac_fprintf(out, " tags in situations where the locale is wrong.\n");
fprintf(out, "--dont-use-padding By default metaflac tries to use padding where possible\n"); flac_fprintf(out, "--dont-use-padding By default metaflac tries to use padding where possible\n");
fprintf(out, " to avoid rewriting the entire file if the metadata size\n"); flac_fprintf(out, " to avoid rewriting the entire file if the metadata size\n");
fprintf(out, " changes. Use this option to tell metaflac to not take\n"); flac_fprintf(out, " changes. Use this option to tell metaflac to not take\n");
fprintf(out, " advantage of padding this way.\n"); flac_fprintf(out, " advantage of padding this way.\n");
} }
int short_usage(const char *message, ...) int short_usage(const char *message, ...)
@ -83,7 +83,7 @@ int short_usage(const char *message, ...)
if(message) { if(message) {
va_start(args, message); va_start(args, message);
(void) vfprintf(stderr, message, args); (void) flac_vfprintf(stderr, message, args);
va_end(args); va_end(args);
@ -105,245 +105,245 @@ int long_usage(const char *message, ...)
if(message) { if(message) {
va_start(args, message); va_start(args, message);
(void) vfprintf(stderr, message, args); (void) flac_vfprintf(stderr, message, args);
va_end(args); va_end(args);
} }
usage_header(out); usage_header(out);
fprintf(out, "\n"); flac_fprintf(out, "\n");
usage_summary(out); usage_summary(out);
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "Shorthand operations:\n"); flac_fprintf(out, "Shorthand operations:\n");
fprintf(out, "--show-md5sum Show the MD5 signature from the STREAMINFO block.\n"); flac_fprintf(out, "--show-md5sum Show the MD5 signature from the STREAMINFO block.\n");
fprintf(out, "--show-min-blocksize Show the minimum block size from the STREAMINFO block.\n"); flac_fprintf(out, "--show-min-blocksize Show the minimum block size from the STREAMINFO block.\n");
fprintf(out, "--show-max-blocksize Show the maximum block size from the STREAMINFO block.\n"); flac_fprintf(out, "--show-max-blocksize Show the maximum block size from the STREAMINFO block.\n");
fprintf(out, "--show-min-framesize Show the minimum frame size from the STREAMINFO block.\n"); flac_fprintf(out, "--show-min-framesize Show the minimum frame size from the STREAMINFO block.\n");
fprintf(out, "--show-max-framesize Show the maximum frame size from the STREAMINFO block.\n"); flac_fprintf(out, "--show-max-framesize Show the maximum frame size from the STREAMINFO block.\n");
fprintf(out, "--show-sample-rate Show the sample rate from the STREAMINFO block.\n"); flac_fprintf(out, "--show-sample-rate Show the sample rate from the STREAMINFO block.\n");
fprintf(out, "--show-channels Show the number of channels from the STREAMINFO block.\n"); flac_fprintf(out, "--show-channels Show the number of channels from the STREAMINFO block.\n");
fprintf(out, "--show-bps Show the # of bits per sample from the STREAMINFO block.\n"); flac_fprintf(out, "--show-bps Show the # of bits per sample from the STREAMINFO block.\n");
fprintf(out, "--show-total-samples Show the total # of samples from the STREAMINFO block.\n"); flac_fprintf(out, "--show-total-samples Show the total # of samples from the STREAMINFO block.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "--show-vendor-tag Show the vendor string from the VORBIS_COMMENT block.\n"); flac_fprintf(out, "--show-vendor-tag Show the vendor string from the VORBIS_COMMENT block.\n");
fprintf(out, "--show-tag=NAME Show all tags where the field name matches 'NAME'.\n"); flac_fprintf(out, "--show-tag=NAME Show all tags where the field name matches 'NAME'.\n");
fprintf(out, "--show-all-tags Show all tags. This is an alias for --export-tags-to=-.\n"); flac_fprintf(out, "--show-all-tags Show all tags. This is an alias for --export-tags-to=-.\n");
fprintf(out, "--remove-tag=NAME Remove all tags whose field name is 'NAME'.\n"); flac_fprintf(out, "--remove-tag=NAME Remove all tags whose field name is 'NAME'.\n");
fprintf(out, "--remove-first-tag=NAME Remove first tag whose field name is 'NAME'.\n"); flac_fprintf(out, "--remove-first-tag=NAME Remove first tag whose field name is 'NAME'.\n");
fprintf(out, "--remove-all-tags Remove all tags, leaving only the vendor string.\n"); flac_fprintf(out, "--remove-all-tags Remove all tags, leaving only the vendor string.\n");
fprintf(out, "--remove-all-tags-except=NAME1[=NAME2[=...]] Remove all tags, except the vendor\n"); flac_fprintf(out, "--remove-all-tags-except=NAME1[=NAME2[=...]] Remove all tags, except the vendor\n");
fprintf(out, " string and the tag names specified. Tag names must be\n"); flac_fprintf(out, " string and the tag names specified. Tag names must be\n");
fprintf(out, " separated by an = character.\n"); flac_fprintf(out, " separated by an = character.\n");
fprintf(out, "--set-tag=FIELD Add a tag. The FIELD must comply with the Vorbis comment\n"); flac_fprintf(out, "--set-tag=FIELD Add a tag. The FIELD must comply with the Vorbis comment\n");
fprintf(out, " spec, of the form \"NAME=VALUE\". If there is currently\n"); flac_fprintf(out, " spec, of the form \"NAME=VALUE\". If there is currently\n");
fprintf(out, " no tag block, one will be created.\n"); flac_fprintf(out, " no tag block, one will be created.\n");
fprintf(out, "--set-tag-from-file=FIELD Like --set-tag, except the VALUE is a filename\n"); flac_fprintf(out, "--set-tag-from-file=FIELD Like --set-tag, except the VALUE is a filename\n");
fprintf(out, " whose contents will be read verbatim to set the tag value.\n"); flac_fprintf(out, " whose contents will be read verbatim to set the tag value.\n");
fprintf(out, " Unless --no-utf8-convert is specified, the contents will\n"); flac_fprintf(out, " Unless --no-utf8-convert is specified, the contents will\n");
fprintf(out, " be converted to UTF-8 from the local charset. This can\n"); flac_fprintf(out, " be converted to UTF-8 from the local charset. This can\n");
fprintf(out, " be used to store a cuesheet in a tag (e.g.\n"); flac_fprintf(out, " be used to store a cuesheet in a tag (e.g.\n");
fprintf(out, " --set-tag-from-file=\"CUESHEET=image.cue\"). Do not try\n"); flac_fprintf(out, " --set-tag-from-file=\"CUESHEET=image.cue\"). Do not try\n");
fprintf(out, " to store binary data in tag fields! Use APPLICATION\n"); flac_fprintf(out, " to store binary data in tag fields! Use APPLICATION\n");
fprintf(out, " blocks for that.\n"); flac_fprintf(out, " blocks for that.\n");
fprintf(out, "--import-tags-from=FILE Import tags from a file. Use '-' for stdin. Each line\n"); flac_fprintf(out, "--import-tags-from=FILE Import tags from a file. Use '-' for stdin. Each line\n");
fprintf(out, " should be of the form NAME=VALUE. Multi-line comments\n"); flac_fprintf(out, " should be of the form NAME=VALUE. Multi-line comments\n");
fprintf(out, " are currently not supported. Specify --remove-all-tags\n"); flac_fprintf(out, " are currently not supported. Specify --remove-all-tags\n");
fprintf(out, " and/or --no-utf8-convert before --import-tags-from if\n"); flac_fprintf(out, " and/or --no-utf8-convert before --import-tags-from if\n");
fprintf(out, " necessary. If FILE is '-' (stdin), only one FLAC file\n"); flac_fprintf(out, " necessary. If FILE is '-' (stdin), only one FLAC file\n");
fprintf(out, " may be specified.\n"); flac_fprintf(out, " may be specified.\n");
fprintf(out, "--export-tags-to=FILE Export tags to a file. Use '-' for stdout. Each line\n"); flac_fprintf(out, "--export-tags-to=FILE Export tags to a file. Use '-' for stdout. Each line\n");
fprintf(out, " will be of the form NAME=VALUE. Specify\n"); flac_fprintf(out, " will be of the form NAME=VALUE. Specify\n");
fprintf(out, " --no-utf8-convert if necessary.\n"); flac_fprintf(out, " --no-utf8-convert if necessary.\n");
fprintf(out, "--import-cuesheet-from=FILE Import a cuesheet from a file. Use '-' for stdin.\n"); flac_fprintf(out, "--import-cuesheet-from=FILE Import a cuesheet from a file. Use '-' for stdin.\n");
fprintf(out, " Only one FLAC file may be specified. A seekpoint will be\n"); flac_fprintf(out, " Only one FLAC file may be specified. A seekpoint will be\n");
fprintf(out, " added for each index point in the cuesheet to the\n"); flac_fprintf(out, " added for each index point in the cuesheet to the\n");
fprintf(out, " SEEKTABLE unless --no-cued-seekpoints is specified.\n"); flac_fprintf(out, " SEEKTABLE unless --no-cued-seekpoints is specified.\n");
fprintf(out, "--export-cuesheet-to=FILE Export CUESHEET block to a cuesheet file, suitable\n"); flac_fprintf(out, "--export-cuesheet-to=FILE Export CUESHEET block to a cuesheet file, suitable\n");
fprintf(out, " for use by CD authoring software. Use '-' for stdout.\n"); flac_fprintf(out, " for use by CD authoring software. Use '-' for stdout.\n");
fprintf(out, " Only one FLAC file may be specified on the command line.\n"); flac_fprintf(out, " Only one FLAC file may be specified on the command line.\n");
fprintf(out, "--import-picture-from=FILENAME|SPECIFICATION Import a picture and store it in a\n"); flac_fprintf(out, "--import-picture-from=FILENAME|SPECIFICATION Import a picture and store it in a\n");
fprintf(out, " PICTURE block. Either a filename for the picture file or\n"); flac_fprintf(out, " PICTURE block. Either a filename for the picture file or\n");
fprintf(out, " a more complete specification form can be used. The\n"); flac_fprintf(out, " a more complete specification form can be used. The\n");
fprintf(out, " SPECIFICATION is a string whose parts are separated by |\n"); flac_fprintf(out, " SPECIFICATION is a string whose parts are separated by |\n");
fprintf(out, " characters. Some parts may be left empty to invoke\n"); flac_fprintf(out, " characters. Some parts may be left empty to invoke\n");
fprintf(out, " default values. FILENAME is just shorthand for\n"); flac_fprintf(out, " default values. FILENAME is just shorthand for\n");
fprintf(out, " \"||||FILENAME\". The format of SPECIFICATION is:\n"); flac_fprintf(out, " \"||||FILENAME\". The format of SPECIFICATION is:\n");
fprintf(out, " [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE\n"); flac_fprintf(out, " [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE\n");
fprintf(out, " TYPE is optional; it is a number from one of:\n"); flac_fprintf(out, " TYPE is optional; it is a number from one of:\n");
fprintf(out, " 0: Other\n"); flac_fprintf(out, " 0: Other\n");
fprintf(out, " 1: 32x32 pixels 'file icon' (PNG only)\n"); flac_fprintf(out, " 1: 32x32 pixels 'file icon' (PNG only)\n");
fprintf(out, " 2: Other file icon\n"); flac_fprintf(out, " 2: Other file icon\n");
fprintf(out, " 3: Cover (front)\n"); flac_fprintf(out, " 3: Cover (front)\n");
fprintf(out, " 4: Cover (back)\n"); flac_fprintf(out, " 4: Cover (back)\n");
fprintf(out, " 5: Leaflet page\n"); flac_fprintf(out, " 5: Leaflet page\n");
fprintf(out, " 6: Media (e.g. label side of CD)\n"); flac_fprintf(out, " 6: Media (e.g. label side of CD)\n");
fprintf(out, " 7: Lead artist/lead performer/soloist\n"); flac_fprintf(out, " 7: Lead artist/lead performer/soloist\n");
fprintf(out, " 8: Artist/performer\n"); flac_fprintf(out, " 8: Artist/performer\n");
fprintf(out, " 9: Conductor\n"); flac_fprintf(out, " 9: Conductor\n");
fprintf(out, " 10: Band/Orchestra\n"); flac_fprintf(out, " 10: Band/Orchestra\n");
fprintf(out, " 11: Composer\n"); flac_fprintf(out, " 11: Composer\n");
fprintf(out, " 12: Lyricist/text writer\n"); flac_fprintf(out, " 12: Lyricist/text writer\n");
fprintf(out, " 13: Recording Location\n"); flac_fprintf(out, " 13: Recording Location\n");
fprintf(out, " 14: During recording\n"); flac_fprintf(out, " 14: During recording\n");
fprintf(out, " 15: During performance\n"); flac_fprintf(out, " 15: During performance\n");
fprintf(out, " 16: Movie/video screen capture\n"); flac_fprintf(out, " 16: Movie/video screen capture\n");
fprintf(out, " 17: A bright coloured fish\n"); flac_fprintf(out, " 17: A bright coloured fish\n");
fprintf(out, " 18: Illustration\n"); flac_fprintf(out, " 18: Illustration\n");
fprintf(out, " 19: Band/artist logotype\n"); flac_fprintf(out, " 19: Band/artist logotype\n");
fprintf(out, " 20: Publisher/Studio logotype\n"); flac_fprintf(out, " 20: Publisher/Studio logotype\n");
fprintf(out, " The default is 3 (front cover). There may only be one picture each\n"); flac_fprintf(out, " The default is 3 (front cover). There may only be one picture each\n");
fprintf(out, " of type 1 and 2 in a file.\n"); flac_fprintf(out, " of type 1 and 2 in a file.\n");
fprintf(out, " MIME-TYPE is optional; if left blank, it will be detected from the\n"); flac_fprintf(out, " MIME-TYPE is optional; if left blank, it will be detected from the\n");
fprintf(out, " file. For best compatibility with players, use pictures with MIME\n"); flac_fprintf(out, " file. For best compatibility with players, use pictures with MIME\n");
fprintf(out, " type image/jpeg or image/png. The MIME type can also be --> to\n"); flac_fprintf(out, " type image/jpeg or image/png. The MIME type can also be --> to\n");
fprintf(out, " mean that FILE is actually a URL to an image, though this use is\n"); flac_fprintf(out, " mean that FILE is actually a URL to an image, though this use is\n");
fprintf(out, " discouraged.\n"); flac_fprintf(out, " discouraged.\n");
fprintf(out, " DESCRIPTION is optional; the default is an empty string\n"); flac_fprintf(out, " DESCRIPTION is optional; the default is an empty string\n");
fprintf(out, " The next part specifies the resolution and color information. If\n"); flac_fprintf(out, " The next part specifies the resolution and color information. If\n");
fprintf(out, " the MIME-TYPE is image/jpeg, image/png, or image/gif, you can\n"); flac_fprintf(out, " the MIME-TYPE is image/jpeg, image/png, or image/gif, you can\n");
fprintf(out, " usually leave this empty and they can be detected from the file.\n"); flac_fprintf(out, " usually leave this empty and they can be detected from the file.\n");
fprintf(out, " Otherwise, you must specify the width in pixels, height in pixels,\n"); flac_fprintf(out, " Otherwise, you must specify the width in pixels, height in pixels,\n");
fprintf(out, " and color depth in bits-per-pixel. If the image has indexed colors\n"); flac_fprintf(out, " and color depth in bits-per-pixel. If the image has indexed colors\n");
fprintf(out, " you should also specify the number of colors used.\n"); flac_fprintf(out, " you should also specify the number of colors used.\n");
fprintf(out, " FILE is the path to the picture file to be imported, or the URL if\n"); flac_fprintf(out, " FILE is the path to the picture file to be imported, or the URL if\n");
fprintf(out, " MIME type is -->\n"); flac_fprintf(out, " MIME type is -->\n");
fprintf(out, "--export-picture-to=FILE Export PICTURE block to a file. Use '-' for stdout.\n"); flac_fprintf(out, "--export-picture-to=FILE Export PICTURE block to a file. Use '-' for stdout.\n");
fprintf(out, " Only one FLAC file may be specified. The first PICTURE\n"); flac_fprintf(out, " Only one FLAC file may be specified. The first PICTURE\n");
fprintf(out, " block will be exported unless --export-picture-to is\n"); flac_fprintf(out, " block will be exported unless --export-picture-to is\n");
fprintf(out, " preceded by a --block-number=# option to specify the exact\n"); flac_fprintf(out, " preceded by a --block-number=# option to specify the exact\n");
fprintf(out, " metadata block to extract. Note that the block number is\n"); flac_fprintf(out, " metadata block to extract. Note that the block number is\n");
fprintf(out, " the one shown by --list.\n"); flac_fprintf(out, " the one shown by --list.\n");
fprintf(out, "--add-replay-gain Calculates the title and album gains/peaks of the given\n"); flac_fprintf(out, "--add-replay-gain Calculates the title and album gains/peaks of the given\n");
fprintf(out, " FLAC files as if all the files were part of one album,\n"); flac_fprintf(out, " FLAC files as if all the files were part of one album,\n");
fprintf(out, " then stores them in the VORBIS_COMMENT block. The tags\n"); flac_fprintf(out, " then stores them in the VORBIS_COMMENT block. The tags\n");
fprintf(out, " are the same as those used by vorbisgain. Existing\n"); flac_fprintf(out, " are the same as those used by vorbisgain. Existing\n");
fprintf(out, " ReplayGain tags will be replaced. If only one FLAC file\n"); flac_fprintf(out, " ReplayGain tags will be replaced. If only one FLAC file\n");
fprintf(out, " is given, the album and title gains will be the same.\n"); flac_fprintf(out, " is given, the album and title gains will be the same.\n");
fprintf(out, " Since this operation requires two passes, it is always\n"); flac_fprintf(out, " Since this operation requires two passes, it is always\n");
fprintf(out, " executed last, after all other operations have been\n"); flac_fprintf(out, " executed last, after all other operations have been\n");
fprintf(out, " completed and written to disk. All FLAC files specified\n"); flac_fprintf(out, " completed and written to disk. All FLAC files specified\n");
fprintf(out, " must have the same resolution, sample rate, and number\n"); flac_fprintf(out, " must have the same resolution, sample rate, and number\n");
fprintf(out, " of channels. Only mono and stereo files are allowed,\n"); flac_fprintf(out, " of channels. Only mono and stereo files are allowed,\n");
fprintf(out, " and the sample rate must be 8, 11.025, 12, 16, 18.9,\n"); flac_fprintf(out, " and the sample rate must be 8, 11.025, 12, 16, 18.9,\n");
fprintf(out, " 22.05, 24, 28, 32, 36, 37.8, 44.1, 48, 56, 64, 72, 75.6,\n"); flac_fprintf(out, " 22.05, 24, 28, 32, 36, 37.8, 44.1, 48, 56, 64, 72, 75.6,\n");
fprintf(out, " 88.2, 96, 112, 128, 144, 151.2, 176.4, 192, 224, 256,\n"); flac_fprintf(out, " 88.2, 96, 112, 128, 144, 151.2, 176.4, 192, 224, 256,\n");
fprintf(out, " 288, 302.4, 352.8, 384, 448, 512, 576, or 604.8 kHz.\n"); flac_fprintf(out, " 288, 302.4, 352.8, 384, 448, 512, 576, or 604.8 kHz.\n");
fprintf(out, "--scan-replay-gain Like --add-replay-gain, but only analyzes the files\n"); flac_fprintf(out, "--scan-replay-gain Like --add-replay-gain, but only analyzes the files\n");
fprintf(out, " rather than writing them to tags.\n"); flac_fprintf(out, " rather than writing them to tags.\n");
fprintf(out, "--remove-replay-gain Removes the ReplayGain tags.\n"); flac_fprintf(out, "--remove-replay-gain Removes the ReplayGain tags.\n");
fprintf(out, "--add-seekpoint={#|X|#x|#s} Add seek points to a SEEKTABLE block\n"); flac_fprintf(out, "--add-seekpoint={#|X|#x|#s} Add seek points to a SEEKTABLE block\n");
fprintf(out, " # : a specific sample number for a seek point\n"); flac_fprintf(out, " # : a specific sample number for a seek point\n");
fprintf(out, " X : a placeholder point (always goes at the end of the SEEKTABLE)\n"); flac_fprintf(out, " X : a placeholder point (always goes at the end of the SEEKTABLE)\n");
fprintf(out, " #x : # evenly spaced seekpoints, the first being at sample 0\n"); flac_fprintf(out, " #x : # evenly spaced seekpoints, the first being at sample 0\n");
fprintf(out, " #s : a seekpoint every # seconds; # does not have to be a whole number\n"); flac_fprintf(out, " #s : a seekpoint every # seconds; # does not have to be a whole number\n");
fprintf(out, " If no SEEKTABLE block exists, one will be created. If\n"); flac_fprintf(out, " If no SEEKTABLE block exists, one will be created. If\n");
fprintf(out, " one already exists, points will be added to the existing\n"); flac_fprintf(out, " one already exists, points will be added to the existing\n");
fprintf(out, " table, and any duplicates will be turned into placeholder\n"); flac_fprintf(out, " table, and any duplicates will be turned into placeholder\n");
fprintf(out, " points. You may use many --add-seekpoint options; the\n"); flac_fprintf(out, " points. You may use many --add-seekpoint options; the\n");
fprintf(out, " resulting SEEKTABLE will be the unique-ified union of\n"); flac_fprintf(out, " resulting SEEKTABLE will be the unique-ified union of\n");
fprintf(out, " all such values. Example: --add-seekpoint=100x\n"); flac_fprintf(out, " all such values. Example: --add-seekpoint=100x\n");
fprintf(out, " --add-seekpoint=3.5s will add 100 evenly spaced\n"); flac_fprintf(out, " --add-seekpoint=3.5s will add 100 evenly spaced\n");
fprintf(out, " seekpoints and a seekpoint every 3.5 seconds.\n"); flac_fprintf(out, " seekpoints and a seekpoint every 3.5 seconds.\n");
fprintf(out, "--add-padding=length Add a padding block of the given length (in bytes).\n"); flac_fprintf(out, "--add-padding=length Add a padding block of the given length (in bytes).\n");
fprintf(out, " The overall length of the new block will be 4 + length;\n"); flac_fprintf(out, " The overall length of the new block will be 4 + length;\n");
fprintf(out, " the extra 4 bytes is for the metadata block header.\n"); flac_fprintf(out, " the extra 4 bytes is for the metadata block header.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "Major operations:\n"); flac_fprintf(out, "Major operations:\n");
fprintf(out, "--version\n"); flac_fprintf(out, "--version\n");
fprintf(out, " Show the metaflac version number.\n"); flac_fprintf(out, " Show the metaflac version number.\n");
fprintf(out, "--list\n"); flac_fprintf(out, "--list\n");
fprintf(out, " List the contents of one or more metadata blocks to stdout. By default,\n"); flac_fprintf(out, " List the contents of one or more metadata blocks to stdout. By default,\n");
fprintf(out, " all metadata blocks are listed in text format. Use the following options\n"); flac_fprintf(out, " all metadata blocks are listed in text format. Use the following options\n");
fprintf(out, " to change this behavior:\n"); flac_fprintf(out, " to change this behavior:\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --block-number=#[,#[...]]\n"); flac_fprintf(out, " --block-number=#[,#[...]]\n");
fprintf(out, " An optional comma-separated list of block numbers to display. The first\n"); flac_fprintf(out, " An optional comma-separated list of block numbers to display. The first\n");
fprintf(out, " block, the STREAMINFO block, is block 0.\n"); flac_fprintf(out, " block, the STREAMINFO block, is block 0.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --block-type=type[,type[...]]\n"); flac_fprintf(out, " --block-type=type[,type[...]]\n");
fprintf(out, " --except-block-type=type[,type[...]]\n"); flac_fprintf(out, " --except-block-type=type[,type[...]]\n");
fprintf(out, " An optional comma-separated list of block types to be included or ignored\n"); flac_fprintf(out, " An optional comma-separated list of block types to be included or ignored\n");
fprintf(out, " with this option. Use only one of --block-type or --except-block-type.\n"); flac_fprintf(out, " with this option. Use only one of --block-type or --except-block-type.\n");
fprintf(out, " The valid block types are: STREAMINFO, PADDING, APPLICATION, SEEKTABLE,\n"); flac_fprintf(out, " The valid block types are: STREAMINFO, PADDING, APPLICATION, SEEKTABLE,\n");
fprintf(out, " VORBIS_COMMENT. You may narrow down the types of APPLICATION blocks\n"); flac_fprintf(out, " VORBIS_COMMENT. You may narrow down the types of APPLICATION blocks\n");
fprintf(out, " displayed as follows:\n"); flac_fprintf(out, " displayed as follows:\n");
fprintf(out, " APPLICATION:abcd The APPLICATION block(s) whose textual repre-\n"); flac_fprintf(out, " APPLICATION:abcd The APPLICATION block(s) whose textual repre-\n");
fprintf(out, " sentation of the 4-byte ID is \"abcd\"\n"); flac_fprintf(out, " sentation of the 4-byte ID is \"abcd\"\n");
fprintf(out, " APPLICATION:0xXXXXXXXX The APPLICATION block(s) whose hexadecimal big-\n"); flac_fprintf(out, " APPLICATION:0xXXXXXXXX The APPLICATION block(s) whose hexadecimal big-\n");
fprintf(out, " endian representation of the 4-byte ID is\n"); flac_fprintf(out, " endian representation of the 4-byte ID is\n");
fprintf(out, " \"0xXXXXXXXX\". For the example \"abcd\" above the\n"); flac_fprintf(out, " \"0xXXXXXXXX\". For the example \"abcd\" above the\n");
fprintf(out, " hexadecimal equivalalent is 0x61626364\n"); flac_fprintf(out, " hexadecimal equivalalent is 0x61626364\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); flac_fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n");
fprintf(out, " the result is the logical AND of both arguments.\n"); flac_fprintf(out, " the result is the logical AND of both arguments.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --data-format=binary|binary-headerless|text\n"); flac_fprintf(out, " --data-format=binary|binary-headerless|text\n");
fprintf(out, " By default a human-readable text representation of the data is displayed.\n"); flac_fprintf(out, " By default a human-readable text representation of the data is displayed.\n");
fprintf(out, " You may specify --data-format=binary to dump the raw binary form of each\n"); flac_fprintf(out, " You may specify --data-format=binary to dump the raw binary form of each\n");
fprintf(out, " metadata block. Specify --data-format=binary-headerless to omit output of\n"); flac_fprintf(out, " metadata block. Specify --data-format=binary-headerless to omit output of\n");
fprintf(out, " metadata block headers, including the id of APPLICATION metadata blocks.\n"); flac_fprintf(out, " metadata block headers, including the id of APPLICATION metadata blocks.\n");
fprintf(out, " The output can be read in using a subsequent call to\n"); flac_fprintf(out, " The output can be read in using a subsequent call to\n");
fprintf(out, " \"metaflac --append\"\n"); flac_fprintf(out, " \"metaflac --append\"\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --application-data-format=hexdump|text\n"); flac_fprintf(out, " --application-data-format=hexdump|text\n");
fprintf(out, " If the application block you are displaying contains binary data but your\n"); flac_fprintf(out, " If the application block you are displaying contains binary data but your\n");
fprintf(out, " --data-format=text, you can display a hex dump of the application data\n"); flac_fprintf(out, " --data-format=text, you can display a hex dump of the application data\n");
fprintf(out, " contents instead using --application-data-format=hexdump\n"); flac_fprintf(out, " contents instead using --application-data-format=hexdump\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "--append\n"); flac_fprintf(out, "--append\n");
fprintf(out, " Insert a metadata block from a file. This must be a binary block as\n"); flac_fprintf(out, " Insert a metadata block from a file. This must be a binary block as\n");
fprintf(out, " exported with --list --data-format=binary. The insertion point is\n"); flac_fprintf(out, " exported with --list --data-format=binary. The insertion point is\n");
fprintf(out, " defined with --block-number=#. The new block will be added after the\n"); flac_fprintf(out, " defined with --block-number=#. The new block will be added after the\n");
fprintf(out, " given block number. This prevents the illegal insertion of a block\n"); flac_fprintf(out, " given block number. This prevents the illegal insertion of a block\n");
fprintf(out, " before the first STREAMINFO block. You may not --append another\n"); flac_fprintf(out, " before the first STREAMINFO block. You may not --append another\n");
fprintf(out, " STREAMINFO block. It is possible to copy a metadata block from one\n"); flac_fprintf(out, " STREAMINFO block. It is possible to copy a metadata block from one\n");
fprintf(out, " file to another with this option. For example use\n"); flac_fprintf(out, " file to another with this option. For example use\n");
fprintf(out, " metaflac --list --data-format=binary --block-number=6 file.flac > block\n"); flac_fprintf(out, " metaflac --list --data-format=binary --block-number=6 file.flac > block\n");
fprintf(out, " to export the block, and then import it with\n"); flac_fprintf(out, " to export the block, and then import it with\n");
fprintf(out, " metaflac --append anotherfile.flac < block\n"); flac_fprintf(out, " metaflac --append anotherfile.flac < block\n");
fprintf(out, " Insert a metadata block from a file. The input file must be in the same\n"); flac_fprintf(out, " Insert a metadata block from a file. The input file must be in the same\n");
fprintf(out, " format as generated with --list.\n"); flac_fprintf(out, " format as generated with --list.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --block-number=#\n"); flac_fprintf(out, " --block-number=#\n");
fprintf(out, " Specify the insertion point (defaults to last block). The new block will\n"); flac_fprintf(out, " Specify the insertion point (defaults to last block). The new block will\n");
fprintf(out, " be added after the given block number. This prevents the illegal insertion\n"); flac_fprintf(out, " be added after the given block number. This prevents the illegal insertion\n");
fprintf(out, " of a block before the first STREAMINFO block. You may not --append another\n"); flac_fprintf(out, " of a block before the first STREAMINFO block. You may not --append another\n");
fprintf(out, " STREAMINFO block.\n"); flac_fprintf(out, " STREAMINFO block.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
#if 0 #if 0
/*@@@ not implemented yet */ /*@@@ not implemented yet */
fprintf(out, " --from-file=filename\n"); flac_fprintf(out, " --from-file=filename\n");
fprintf(out, " Mandatory 'option' to specify the input file containing the block contents.\n"); flac_fprintf(out, " Mandatory 'option' to specify the input file containing the block contents.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --data-format=binary|text\n"); flac_fprintf(out, " --data-format=binary|text\n");
fprintf(out, " By default the block contents are assumed to be in binary format. You can\n"); flac_fprintf(out, " By default the block contents are assumed to be in binary format. You can\n");
fprintf(out, " override this by specifying --data-format=text\n"); flac_fprintf(out, " override this by specifying --data-format=text\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
#endif #endif
fprintf(out, "--remove\n"); flac_fprintf(out, "--remove\n");
fprintf(out, " Remove one or more metadata blocks from the metadata. Unless\n"); flac_fprintf(out, " Remove one or more metadata blocks from the metadata. Unless\n");
fprintf(out, " --dont-use-padding is specified, the blocks will be replaced with padding.\n"); flac_fprintf(out, " --dont-use-padding is specified, the blocks will be replaced with padding.\n");
fprintf(out, " You may not remove the STREAMINFO block.\n"); flac_fprintf(out, " You may not remove the STREAMINFO block.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " --block-number=#[,#[...]]\n"); flac_fprintf(out, " --block-number=#[,#[...]]\n");
fprintf(out, " --block-type=type[,type[...]]\n"); flac_fprintf(out, " --block-type=type[,type[...]]\n");
fprintf(out, " --except-block-type=type[,type[...]]\n"); flac_fprintf(out, " --except-block-type=type[,type[...]]\n");
fprintf(out, " See --list above for usage.\n"); flac_fprintf(out, " See --list above for usage.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n"); flac_fprintf(out, " NOTE: if both --block-number and --[except-]block-type are specified,\n");
fprintf(out, " the result is the logical AND of both arguments.\n"); flac_fprintf(out, " the result is the logical AND of both arguments.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "--remove-all\n"); flac_fprintf(out, "--remove-all\n");
fprintf(out, " Remove all metadata blocks (except the STREAMINFO block) from the\n"); flac_fprintf(out, " Remove all metadata blocks (except the STREAMINFO block) from the\n");
fprintf(out, " metadata. Unless --dont-use-padding is specified, the blocks will be\n"); flac_fprintf(out, " metadata. Unless --dont-use-padding is specified, the blocks will be\n");
fprintf(out, " replaced with padding.\n"); flac_fprintf(out, " replaced with padding.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "--merge-padding\n"); flac_fprintf(out, "--merge-padding\n");
fprintf(out, " Merge adjacent PADDING blocks into single blocks.\n"); flac_fprintf(out, " Merge adjacent PADDING blocks into single blocks.\n");
fprintf(out, "\n"); flac_fprintf(out, "\n");
fprintf(out, "--sort-padding\n"); flac_fprintf(out, "--sort-padding\n");
fprintf(out, " Move all PADDING blocks to the end of the metadata and merge them into a\n"); flac_fprintf(out, " Move all PADDING blocks to the end of the metadata and merge them into a\n");
fprintf(out, " single block.\n"); flac_fprintf(out, " single block.\n");
return message? 1 : 0; return message? 1 : 0;
} }

View File

@ -98,7 +98,7 @@ void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const
for(i = 0; i < bytes; i += 16) { for(i = 0; i < bytes; i += 16) {
flac_printf("%s%s", filename? filename:"", filename? ":":""); flac_printf("%s%s", filename? filename:"", filename? ":":"");
printf("%s%08X: " flac_printf("%s%08X: "
"%02X %02X %02X %02X %02X %02X %02X %02X " "%02X %02X %02X %02X %02X %02X %02X %02X "
"%02X %02X %02X %02X %02X %02X %02X %02X " "%02X %02X %02X %02X %02X %02X %02X %02X "
"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
@ -244,11 +244,9 @@ void write_vc_field(const char *filename, const FLAC__StreamMetadata_VorbisComme
* WATCHOUT: comments that contain an embedded null will * WATCHOUT: comments that contain an embedded null will
* be truncated by utf_decode(). * be truncated by utf_decode().
*/ */
#ifdef _WIN32 /* if we are outputting to console, we need to use proper print functions to show unicode characters */ #ifdef _WIN32
if (f == stdout || f == stderr) { flac_fprintf(f, "%s", entry->entry);
flac_fprintf(f, "%s", entry->entry); #else
} else {
#endif
char *converted; char *converted;
if(utf8_decode((const char *)entry->entry, &converted) >= 0) { if(utf8_decode((const char *)entry->entry, &converted) >= 0) {
@ -258,16 +256,17 @@ void write_vc_field(const char *filename, const FLAC__StreamMetadata_VorbisComme
else { else {
(void) local_fwrite(entry->entry, 1, entry->length, f); (void) local_fwrite(entry->entry, 1, entry->length, f);
} }
#ifdef _WIN32
}
#endif #endif
} }
else { else {
(void) local_fwrite(entry->entry, 1, entry->length, f); (void) local_fwrite(entry->entry, 1, entry->length, f);
} }
} }
#ifdef _WIN32
flac_fprintf(f,"\n");
#else
putc('\n', f); putc('\n', f);
#endif
} }
void write_vc_fields(const char *filename, const char *field_name, const FLAC__StreamMetadata_VorbisComment_Entry entry[], unsigned num_entries, FLAC__bool raw, FILE *f) void write_vc_fields(const char *filename, const char *field_name, const FLAC__StreamMetadata_VorbisComment_Entry entry[], unsigned num_entries, FLAC__bool raw, FILE *f)

View File

@ -45,6 +45,8 @@
# include <config.h> # include <config.h>
#endif #endif
#include "share/compat.h"
#if !defined __STDC__ || !__STDC__ #if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems /* This is a separate conditional since some stdc systems
reject `defined (const)'. */ reject `defined (const)'. */
@ -681,7 +683,7 @@ share___getopt_internal (
if (ambig && !exact) if (ambig && !exact)
{ {
if (share__opterr) if (share__opterr)
fprintf (stderr, _("%s: option `%s' is ambiguous\n"), flac_fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[share__optind]); argv[0], argv[share__optind]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
share__optind++; share__optind++;
@ -705,12 +707,12 @@ share___getopt_internal (
{ {
if (argv[share__optind - 1][1] == '-') if (argv[share__optind - 1][1] == '-')
/* --option */ /* --option */
fprintf (stderr, flac_fprintf (stderr,
_("%s: option `--%s' doesn't allow an argument\n"), _("%s: option `--%s' doesn't allow an argument\n"),
argv[0], pfound->name); argv[0], pfound->name);
else else
/* +option or -option */ /* +option or -option */
fprintf (stderr, flac_fprintf (stderr,
_("%s: option `%c%s' doesn't allow an argument\n"), _("%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[share__optind - 1][0], pfound->name); argv[0], argv[share__optind - 1][0], pfound->name);
} }
@ -728,7 +730,7 @@ share___getopt_internal (
else else
{ {
if (share__opterr) if (share__opterr)
fprintf (stderr, flac_fprintf (stderr,
_("%s: option `%s' requires an argument\n"), _("%s: option `%s' requires an argument\n"),
argv[0], argv[share__optind - 1]); argv[0], argv[share__optind - 1]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
@ -758,11 +760,11 @@ share___getopt_internal (
{ {
if (argv[share__optind][1] == '-') if (argv[share__optind][1] == '-')
/* --option */ /* --option */
fprintf (stderr, _("%s: unrecognized option `--%s'\n"), flac_fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar); argv[0], nextchar);
else else
/* +option or -option */ /* +option or -option */
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), flac_fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[share__optind][0], nextchar); argv[0], argv[share__optind][0], nextchar);
} }
nextchar = (char *) ""; nextchar = (char *) "";
@ -788,10 +790,10 @@ share___getopt_internal (
{ {
if (posixly_correct) if (posixly_correct)
/* 1003.2 specifies the format of this message. */ /* 1003.2 specifies the format of this message. */
fprintf (stderr, _("%s: illegal option -- %c\n"), flac_fprintf (stderr, _("%s: illegal option -- %c\n"),
argv[0], c); argv[0], c);
else else
fprintf (stderr, _("%s: invalid option -- %c\n"), flac_fprintf (stderr, _("%s: invalid option -- %c\n"),
argv[0], c); argv[0], c);
} }
share__optopt = c; share__optopt = c;
@ -821,7 +823,7 @@ share___getopt_internal (
if (share__opterr) if (share__opterr)
{ {
/* 1003.2 specifies the format of this message. */ /* 1003.2 specifies the format of this message. */
fprintf (stderr, _("%s: option requires an argument -- %c\n"), flac_fprintf (stderr, _("%s: option requires an argument -- %c\n"),
argv[0], c); argv[0], c);
} }
share__optopt = c; share__optopt = c;
@ -868,7 +870,7 @@ share___getopt_internal (
if (ambig && !exact) if (ambig && !exact)
{ {
if (share__opterr) if (share__opterr)
fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), flac_fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[share__optind]); argv[0], argv[share__optind]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
share__optind++; share__optind++;
@ -886,7 +888,7 @@ share___getopt_internal (
else else
{ {
if (share__opterr) if (share__opterr)
fprintf (stderr, _("\ flac_fprintf (stderr, _("\
%s: option `-W %s' doesn't allow an argument\n"), %s: option `-W %s' doesn't allow an argument\n"),
argv[0], pfound->name); argv[0], pfound->name);
@ -901,7 +903,7 @@ share___getopt_internal (
else else
{ {
if (share__opterr) if (share__opterr)
fprintf (stderr, flac_fprintf (stderr,
_("%s: option `%s' requires an argument\n"), _("%s: option `%s' requires an argument\n"),
argv[0], argv[share__optind - 1]); argv[0], argv[share__optind - 1]);
nextchar += strlen (nextchar); nextchar += strlen (nextchar);
@ -950,7 +952,7 @@ share___getopt_internal (
if (share__opterr) if (share__opterr)
{ {
/* 1003.2 specifies the format of this message. */ /* 1003.2 specifies the format of this message. */
fprintf (stderr, flac_fprintf (stderr,
_("%s: option requires an argument -- %c\n"), _("%s: option requires an argument -- %c\n"),
argv[0], c); argv[0], c);
} }
@ -1014,37 +1016,37 @@ main (int argc, char **argv)
case '8': case '8':
case '9': case '9':
if (digit_optind != 0 && digit_optind != this_option_optind) if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n"); flac_printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind; digit_optind = this_option_optind;
printf ("option %c\n", c); flac_printf ("option %c\n", c);
break; break;
case 'a': case 'a':
printf ("option a\n"); flac_printf ("option a\n");
break; break;
case 'b': case 'b':
printf ("option b\n"); flac_printf ("option b\n");
break; break;
case 'c': case 'c':
printf ("option c with value `%s'\n", share__optarg); flac_printf ("option c with value `%s'\n", share__optarg);
break; break;
case '?': case '?':
break; break;
default: default:
printf ("?? getopt returned character code 0%o ??\n", c); flac_printf ("?? getopt returned character code 0%o ??\n", c);
} }
} }
if (share__optind < argc) if (share__optind < argc)
{ {
printf ("non-option ARGV-elements: "); flac_printf ("non-option ARGV-elements: ");
while (share__optind < argc) while (share__optind < argc)
printf ("%s ", argv[share__optind++]); flac_printf ("%s ", argv[share__optind++]);
printf ("\n"); flac_printf ("\n");
} }
exit (0); exit (0);

View File

@ -36,6 +36,8 @@
# include <config.h> # include <config.h>
#endif #endif
#include "share/compat.h"
#if !defined __STDC__ || !__STDC__ #if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems /* This is a separate conditional since some stdc systems
reject `defined (const)'. */ reject `defined (const)'. */
@ -129,10 +131,10 @@ int main(int argc, char **argv)
switch (c) switch (c)
{ {
case 0: case 0:
printf ("option %s", long_options[option_index].name); flac_printf ("option %s", long_options[option_index].name);
if (share__optarg) if (share__optarg)
printf (" with arg %s", share__optarg); flac_printf (" with arg %s", share__optarg);
printf ("\n"); flac_printf ("\n");
break; break;
case '0': case '0':
@ -146,41 +148,41 @@ int main(int argc, char **argv)
case '8': case '8':
case '9': case '9':
if (digit_optind != 0 && digit_optind != this_option_optind) if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n"); flac_printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind; digit_optind = this_option_optind;
printf ("option %c\n", c); flac_printf ("option %c\n", c);
break; break;
case 'a': case 'a':
printf ("option a\n"); flac_printf ("option a\n");
break; break;
case 'b': case 'b':
printf ("option b\n"); flac_printf ("option b\n");
break; break;
case 'c': case 'c':
printf ("option c with value `%s'\n", share__optarg); flac_printf ("option c with value `%s'\n", share__optarg);
break; break;
case 'd': case 'd':
printf ("option d with value `%s'\n", share__optarg); flac_printf ("option d with value `%s'\n", share__optarg);
break; break;
case '?': case '?':
break; break;
default: default:
printf ("?? getopt returned character code 0%o ??\n", c); flac_printf ("?? getopt returned character code 0%o ??\n", c);
} }
} }
if (share__optind < argc) if (share__optind < argc)
{ {
printf ("non-option ARGV-elements: "); flac_printf ("non-option ARGV-elements: ");
while (share__optind < argc) while (share__optind < argc)
printf ("%s ", argv[share__optind++]); flac_printf ("%s ", argv[share__optind++]);
printf ("\n"); flac_printf ("\n");
} }
exit (0); exit (0);