about summary refs log tree commit
path: root/src/flac/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/flac/main.c')
-rw-r--r--src/flac/main.c119
1 files changed, 83 insertions, 36 deletions
diff --git a/src/flac/main.c b/src/flac/main.c
index 14db8daf..07e98647 100644
--- a/src/flac/main.c
+++ b/src/flac/main.c
@@ -56,7 +56,7 @@
 #  include "share/getopt.h"
 #endif
 
-typedef enum { RAW, WAV, AIF } FileFormat;
+typedef enum { RAW, WAV, AIF, FLAC } FileFormat;
 
 static int do_it();
 
@@ -234,7 +234,7 @@ static struct {
         const char *cmdline_forced_outfilename;
         const char *output_prefix;
         analysis_options aopts;
-        int padding;
+        int padding; /* -1 => no -P options were given, 0 => -P- was given, else -P value */
         char apodizations[1000]; /* bad MAGIC NUMBER but buffer overflow is checked */
         unsigned max_lpc_order;
         unsigned qlp_coeff_precision;
@@ -287,6 +287,7 @@ int main(int argc, char *argv[])
         _wildcard(&argc, &argv);
 #endif
 
+        srand(time(0));
         setlocale(LC_ALL, "");
         if(!init_options()) {
                 flac__utils_printf(stderr, 1, "ERROR: allocating memory\n");
@@ -435,7 +436,7 @@ int do_it()
                          * tags that we will set later, to avoid rewriting the
                          * whole file.
                          */
-                        if(option_values.padding < 0) {
+                        if(option_values.padding <= 0) {
                                 flac__utils_printf(stderr, 1, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n");
                                 option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED;
                         }
@@ -461,10 +462,10 @@ int do_it()
 
         if(!option_values.mode_decode) {
                 char padopt[16];
-                if(option_values.padding < 0)
+                if(option_values.padding == 0)
                         strcpy(padopt, "-");
                 else
-                        sprintf(padopt, " %d", option_values.padding);
+                        sprintf(padopt, " %d", option_values.padding > 0? option_values.padding : FLAC_ENCODE__DEFAULT_PADDING);
                 flac__utils_printf(stderr, 2,
                         "options:%s%s%s%s -P%s -b %u%s -l %u%s%s%s -q %u -r %u,%u%s\n",
                         option_values.delete_input?" --delete-input-file":"",
@@ -580,7 +581,7 @@ FLAC__bool init_options()
         option_values.output_prefix = 0;
         option_values.aopts.do_residual_text = false;
         option_values.aopts.do_residual_gnuplot = false;
-        option_values.padding = 4096;
+        option_values.padding = -1;
         option_values.apodizations[0] = '\0';
         option_values.max_lpc_order = 8;
         option_values.qlp_coeff_precision = 0;
@@ -860,7 +861,7 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                         option_values.do_qlp_coeff_prec_search = false;
                 }
                 else if(0 == strcmp(long_option, "no-padding")) {
-                        option_values.padding = -1;
+                        option_values.padding = 0;
                 }
                 else if(0 == strcmp(long_option, "no-verify")) {
                         option_values.verify = false;
@@ -1040,7 +1041,7 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                                 FLAC__ASSERT(0 != option_argument);
                                 option_values.padding = atoi(option_argument);
                                 if(option_values.padding < 0)
-                                        return usage_error("ERROR: argument to -P must be >= 0\n");
+                                        return usage_error("ERROR: argument to -P must be >= 0; for no padding use -P-\n");
                                 break;
                         case 'b':
                                 FLAC__ASSERT(0 != option_argument);
@@ -1552,22 +1553,15 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         int retval;
         off_t infilesize;
         encode_options_t common_options;
-        const char *outfilename = get_encoded_outfilename(infilename);
+        const char *outfilename = get_encoded_outfilename(infilename); /* the final name of the encoded file */
+        /* internal_outfilename is the file we will actually write to; it will be a temporary name if infilename==outfilename */
+        char *internal_outfilename = 0; /* NULL implies 'use outfilename' */
 
         if(0 == outfilename) {
                 flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename);
                 return 1;
         }
 
-        /*
-         * Error if output file already exists (and -f not used).
-         * 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)) {
-                flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename);
-                return 1;
-        }
-
         if(0 == strcmp(infilename, "-")) {
                 infilesize = (off_t)(-1);
                 encode_infile = grabbag__file_get_binary_stdin();
@@ -1588,6 +1582,8 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                         fmt= AIF;
                 else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".aiff"))
                         fmt= AIF;
+                else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".flac"))
+                        fmt= FLAC;
 
                 /* attempt to guess the file type based on the first 12 bytes */
                 if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) {
@@ -1604,6 +1600,8 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                                 fmt= AIF;
                                 is_aifc = true;
                         }
+                        else if(!strncmp((const char *)lookahead, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING)))
+                                fmt= FLAC;
                         else {
                                 if(fmt != RAW)
                                         format_mistake(infilename, fmt == AIF ? "AIFF" : "WAVE", "raw");
@@ -1612,6 +1610,27 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 }
         }
 
+        /*
+         * Error if output file already exists (and -f not used).
+         * Use grabbag__file_get_filesize() as a cheap way to check.
+         */
+        if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
+                if(fmt == FLAC) {
+                        /* need more detailed error message when re-flac'ing to avoid confusing the user */
+                        flac__utils_printf(stderr, 1,
+                                "ERROR: output file %s already exists.\n\n"
+                                "By default flac encodes files to FLAC format; if you meant to decode this file\n"
+                                "from FLAC to something else, use -d.  If you meant to re-encode this file from\n"
+                                "FLAC to FLAC again, use -f to force writing to the same file, or -o to specify\n"
+                                "a different output filename.\n",
+                                outfilename
+                        );
+                }
+                else
+                        flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename);
+                return 1;
+        }
+
         if(option_values.format_input_size >= 0) {
                    if (fmt != RAW || infilesize >= 0) {
                         flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n");
@@ -1622,8 +1641,12 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 }
         }
 
+        if(option_values.sector_align && fmt == FLAC) {
+                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC\n");
+                return 1;
+        }
         if(option_values.sector_align && fmt == RAW && infilesize < 0) {
-                flac__utils_printf(stderr, 1, "ERROR: can't --sector-align when the input size is unknown\n");
+                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n");
                 return 1;
         }
 
@@ -1651,7 +1674,6 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         common_options.use_ogg = option_values.use_ogg;
         /* set a random serial number if one has not yet been specified */
         if(!option_values.has_serial_number) {
-                srand(time(0));
                 option_values.serial_number = rand();
                 option_values.has_serial_number = true;
         }
@@ -1686,6 +1708,17 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         common_options.debug.disable_fixed_subframes = option_values.debug.disable_fixed_subframes;
         common_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes;
 
+        /* if infilename==outfilename, we need to write to a temporary file */
+        if(encode_infile != stdin && 0 == strcmp(infilename, outfilename)) { /*@@@@@@ BUG strcmp is not adequate to check if infilename and outfilename are the same file */
+                static const char *tmp_suffix = ".tmp";
+                if(0 == (internal_outfilename = malloc(strlen(outfilename)+strlen(tmp_suffix)+1))) {
+                        flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n");
+                        return 1;
+                }
+                strcpy(internal_outfilename, outfilename);
+                strcat(internal_outfilename, tmp_suffix);
+        }
+
         if(fmt == RAW) {
                 raw_encode_options_t options;
 
@@ -1696,7 +1729,14 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 options.bps = option_values.format_bps;
                 options.sample_rate = option_values.format_sample_rate;
 
-                retval = flac__encode_raw(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options);
+                retval = flac__encode_raw(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
+        }
+        else if(fmt == FLAC) {
+                flac_encode_options_t options;
+
+                options.common = common_options;
+
+                retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
         }
         else {
                 wav_encode_options_t options;
@@ -1704,27 +1744,41 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 options.common = common_options;
 
                 if(fmt == AIF)
-                        retval = flac__encode_aif(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options, is_aifc);
+                        retval = flac__encode_aif(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, is_aifc);
                 else
-                        retval = flac__encode_wav(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options);
+                        retval = flac__encode_wav(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
         }
 
-        if(retval == 0 && strcmp(infilename, "-")) {
+        if(retval == 0) {
                 if(strcmp(outfilename, "-")) {
                         if(option_values.replay_gain) {
                                 float title_gain, title_peak;
                                 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))) {
+                                if(0 != (error = grabbag__replaygain_store_to_file_title(internal_outfilename, title_gain, title_peak, /*preserve_modtime=*/true))) {
                                         flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain title tags\n", outfilename);
                                 }
                         }
-                        grabbag__file_copy_metadata(infilename, outfilename);
+                        if(strcmp(infilename, "-"))
+                                grabbag__file_copy_metadata(infilename, internal_outfilename);
                 }
-                if(option_values.delete_input)
-                        unlink(infilename);
         }
 
+        /* rename temporary file if necessary */
+        if(retval == 0 && internal_outfilename != 0) {
+                if(rename(internal_outfilename, outfilename) < 0) {
+                        flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, keeping both\n", internal_outfilename, outfilename);
+                        retval = 1;
+                }
+        }
+
+        /* handle --delete-input-file, but don't want to delete if piping from stdin, or if input filename and output filename are the same */
+        if(retval == 0 && option_values.delete_input && strcmp(infilename, "-") && internal_outfilename == 0)
+                unlink(infilename);
+
+        if(internal_outfilename != 0)
+                free(internal_outfilename);
+
         return retval;
 }
 
@@ -1870,14 +1924,7 @@ const char *get_outfilename(const char *infilename, const char *suffix)
                                         return 0;
                         }
                         else {
-                                if(0 == strcmp(p, suffix)) {
-                                        *p = '\0';
-                                        if (flac__strlcat(buffer, "_new", sizeof buffer) >= sizeof buffer)
-                                                return 0;
-                                }
-                                else {
-                                        *p = '\0';
-                                }
+                                *p = '\0';
                                 if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer)
                                         return 0;
                         }