~ubuntu-branches/ubuntu/quantal/flac/quantal

« back to all changes in this revision

Viewing changes to src/flac/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-12-06 16:57:20 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20071206165720-ldii5tm8dq6zxg0l
Tags: 1.2.1-1ubuntu1
* Merge from debian unstable, remaining changes:
  - debian/control: xmms-dev dropped to allow xmms to move to universe,
    adjust maintainer field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include <unistd.h> /* for unlink() */
35
35
#endif
36
36
#include "FLAC/all.h"
 
37
#include "share/alloc.h"
37
38
#include "share/grabbag.h"
38
39
#include "analyze.h"
39
40
#include "decode.h"
99
100
        /*
100
101
         * general options
101
102
         */
102
 
        { "help"              , share__no_argument, 0, 'h' },
103
 
        { "explain"           , share__no_argument, 0, 'H' },
104
 
        { "version"           , share__no_argument, 0, 'v' },
105
 
        { "decode"            , share__no_argument, 0, 'd' },
106
 
        { "analyze"           , share__no_argument, 0, 'a' },
107
 
        { "test"              , share__no_argument, 0, 't' },
108
 
        { "stdout"            , share__no_argument, 0, 'c' },
109
 
        { "silent"            , share__no_argument, 0, 's' },
110
 
        { "totally-silent"    , share__no_argument, 0, 0 },
111
 
        { "warnings-as-errors", share__no_argument, 0, 'w' },
112
 
        { "force"             , share__no_argument, 0, 'f' },
113
 
        { "delete-input-file" , share__no_argument, 0, 0 },
114
 
        { "output-prefix"     , share__required_argument, 0, 0 },
115
 
        { "output-name"       , share__required_argument, 0, 'o' },
116
 
        { "skip"              , share__required_argument, 0, 0 },
117
 
        { "until"             , share__required_argument, 0, 0 },
118
 
        { "channel-map"       , share__required_argument, 0, 0 }, /* undocumented */
 
103
        { "help"                  , share__no_argument, 0, 'h' },
 
104
        { "explain"               , share__no_argument, 0, 'H' },
 
105
        { "version"               , share__no_argument, 0, 'v' },
 
106
        { "decode"                , share__no_argument, 0, 'd' },
 
107
        { "analyze"               , share__no_argument, 0, 'a' },
 
108
        { "test"                  , share__no_argument, 0, 't' },
 
109
        { "stdout"                , share__no_argument, 0, 'c' },
 
110
        { "silent"                , share__no_argument, 0, 's' },
 
111
        { "totally-silent"        , share__no_argument, 0, 0 },
 
112
        { "warnings-as-errors"    , share__no_argument, 0, 'w' },
 
113
        { "force"                 , share__no_argument, 0, 'f' },
 
114
        { "delete-input-file"     , share__no_argument, 0, 0 },
 
115
        { "keep-foreign-metadata" , share__no_argument, 0, 0 },
 
116
        { "output-prefix"         , share__required_argument, 0, 0 },
 
117
        { "output-name"           , share__required_argument, 0, 'o' },
 
118
        { "skip"                  , share__required_argument, 0, 0 },
 
119
        { "until"                 , share__required_argument, 0, 0 },
 
120
        { "channel-map"           , share__required_argument, 0, 0 }, /* undocumented */
119
121
 
120
122
        /*
121
123
         * decoding options
149
151
        { "force-raw-format"          , share__no_argument, 0, 0 },
150
152
        { "lax"                       , share__no_argument, 0, 0 },
151
153
        { "replay-gain"               , share__no_argument, 0, 0 },
 
154
        { "ignore-chunk-sizes"        , share__no_argument, 0, 0 },
152
155
        { "sector-align"              , share__no_argument, 0, 0 },
153
156
        { "seekpoint"                 , share__required_argument, 0, 'S' },
154
157
        { "padding"                   , share__required_argument, 0, 'P' },
186
189
        { "no-force"                  , share__no_argument, 0, 0 },
187
190
        { "no-seektable"              , share__no_argument, 0, 0 },
188
191
        { "no-delete-input-file"      , share__no_argument, 0, 0 },
 
192
        { "no-keep-foreign-metadata"  , share__no_argument, 0, 0 },
189
193
        { "no-replay-gain"            , share__no_argument, 0, 0 },
 
194
        { "no-ignore-chunk-sizes"     , share__no_argument, 0, 0 },
190
195
        { "no-sector-align"           , share__no_argument, 0, 0 },
 
196
        { "no-utf8-convert"           , share__no_argument, 0, 0 },
191
197
        { "no-lax"                    , share__no_argument, 0, 0 },
192
198
#if FLAC__HAS_OGG
193
199
        { "no-ogg"                    , share__no_argument, 0, 0 },
207
213
        { "disable-constant-subframes", share__no_argument, 0, 0 },
208
214
        { "disable-fixed-subframes"   , share__no_argument, 0, 0 },
209
215
        { "disable-verbatim-subframes", share__no_argument, 0, 0 },
 
216
        { "no-md5-sum"                , share__no_argument, 0, 0 },
210
217
 
211
218
        {0, 0, 0, 0}
212
219
};
236
243
        FLAC__bool force_aiff_format;
237
244
        FLAC__bool force_raw_format;
238
245
        FLAC__bool delete_input;
 
246
        FLAC__bool keep_foreign_metadata;
239
247
        FLAC__bool replay_gain;
 
248
        FLAC__bool ignore_chunk_sizes;
240
249
        FLAC__bool sector_align;
 
250
        FLAC__bool utf8_convert; /* true by default, to convert tag strings from locale to utf-8, false if --no-utf8-convert used */
241
251
        const char *cmdline_forced_outfilename;
242
252
        const char *output_prefix;
243
253
        analysis_options aopts;
270
280
                FLAC__bool disable_constant_subframes;
271
281
                FLAC__bool disable_fixed_subframes;
272
282
                FLAC__bool disable_verbatim_subframes;
 
283
                FLAC__bool do_md5;
273
284
        } debug;
274
285
} option_values;
275
286
 
292
303
        _wildcard(&argc, &argv);
293
304
#endif
294
305
 
295
 
        srand(time(0));
 
306
        srand((unsigned)time(0));
296
307
        setlocale(LC_ALL, "");
297
308
        if(!init_options()) {
298
309
                flac__utils_printf(stderr, 1, "ERROR: allocating memory\n");
383
394
                                return usage_error("ERROR: --sample-rate not allowed with --decode\n");
384
395
                }
385
396
 
 
397
                if(option_values.ignore_chunk_sizes) {
 
398
                        if(option_values.mode_decode)
 
399
                                return usage_error("ERROR: --ignore-chunk-sizes only allowed for encoding\n");
 
400
                        if(0 != option_values.sector_align)
 
401
                                return usage_error("ERROR: --ignore-chunk-sizes not allowed with --sector-align\n");
 
402
                        if(0 != option_values.until_specification)
 
403
                                return usage_error("ERROR: --ignore-chunk-sizes not allowed with --until\n");
 
404
                        if(0 != option_values.cue_specification)
 
405
                                return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cue\n");
 
406
                        if(0 != option_values.cuesheet_filename)
 
407
                                return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cuesheet\n");
 
408
                }
386
409
                if(option_values.sector_align) {
387
410
                        if(option_values.mode_decode)
388
411
                                return usage_error("ERROR: --sector-align only allowed for encoding\n");
413
436
                         * tags that we will set later, to avoid rewriting the
414
437
                         * whole file.
415
438
                         */
416
 
                        if(option_values.padding <= 0) {
 
439
                        if(
 
440
                                (option_values.padding >= 0 && option_values.padding < (int)GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED) ||
 
441
                                (option_values.padding < 0 && FLAC_ENCODE__DEFAULT_PADDING < (int)GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED)
 
442
                        ) {
417
443
                                flac__utils_printf(stderr, 1, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n");
418
444
                                option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED;
419
445
                        }
430
456
                if(!option_values.mode_decode && 0 != option_values.cuesheet_filename && option_values.num_files > 1) {
431
457
                        return usage_error("ERROR: --cuesheet cannot be used when encoding multiple files\n");
432
458
                }
 
459
                if(option_values.keep_foreign_metadata) {
 
460
                        /* we're not going to try and support the re-creation of broken WAVE files */
 
461
                        if(option_values.ignore_chunk_sizes)
 
462
                                return usage_error("ERROR: using --keep-foreign-metadata cannot be used with --ignore-chunk-sizes\n");
 
463
                        if(option_values.test_only)
 
464
                                return usage_error("ERROR: --keep-foreign-metadata is not allowed in test mode\n");
 
465
                        if(option_values.analyze)
 
466
                                return usage_error("ERROR: --keep-foreign-metadata is not allowed in analyis mode\n");
 
467
                        /*@@@@@@*/
 
468
                        if(option_values.delete_input)
 
469
                                return usage_error("ERROR: using --delete-input-file with --keep-foreign-metadata has been disabled until more testing has been done.\n");
 
470
                        flac__utils_printf(stderr, 1, "NOTE: --keep-foreign-metadata is a new feature; make sure to test the output file before deleting the original.\n");
 
471
                }
433
472
        }
434
473
 
435
474
        flac__utils_printf(stderr, 2, "\n");
458
497
        else { /* encode */
459
498
                FLAC__bool first = true;
460
499
 
 
500
                if(option_values.ignore_chunk_sizes)
 
501
                        flac__utils_printf(stderr, 1, "INFO: Make sure you know what you're doing when using --ignore-chunk-sizes.\n      Improper use can cause flac to encode non-audio data as audio.\n");
 
502
 
461
503
                if(option_values.num_files == 0) {
462
504
                        retval = encode_file("-", first, true);
463
505
                }
522
564
        option_values.force_aiff_format = false;
523
565
        option_values.force_raw_format = false;
524
566
        option_values.delete_input = false;
 
567
        option_values.keep_foreign_metadata = false;
525
568
        option_values.replay_gain = false;
 
569
        option_values.ignore_chunk_sizes = false;
526
570
        option_values.sector_align = false;
 
571
        option_values.utf8_convert = true;
527
572
        option_values.cmdline_forced_outfilename = 0;
528
573
        option_values.output_prefix = 0;
529
574
        option_values.aopts.do_residual_text = false;
545
590
        option_values.num_requested_seek_points = -1;
546
591
        option_values.cuesheet_filename = 0;
547
592
        option_values.cued_seekpoints = true;
548
 
        option_values.channel_map_none = false;;
 
593
        option_values.channel_map_none = false;
549
594
 
550
595
        option_values.num_files = 0;
551
596
        option_values.filenames = 0;
557
602
        option_values.debug.disable_constant_subframes = false;
558
603
        option_values.debug.disable_fixed_subframes = false;
559
604
        option_values.debug.disable_verbatim_subframes = false;
 
605
        option_values.debug.do_md5 = true;
560
606
 
561
607
        return true;
562
608
}
616
662
                else if(0 == strcmp(long_option, "delete-input-file")) {
617
663
                        option_values.delete_input = true;
618
664
                }
 
665
                else if(0 == strcmp(long_option, "keep-foreign-metadata")) {
 
666
                        option_values.keep_foreign_metadata = true;
 
667
                }
619
668
                else if(0 == strcmp(long_option, "output-prefix")) {
620
669
                        FLAC__ASSERT(0 != option_argument);
621
670
                        option_values.output_prefix = option_argument;
697
746
                }
698
747
                else if(0 == strcmp(long_option, "tag-from-file")) {
699
748
                        FLAC__ASSERT(0 != option_argument);
700
 
                        if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/true, &violation))
 
749
                        if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/true, /*raw=*/!option_values.utf8_convert, &violation))
701
750
                                return usage_error("ERROR: (--tag-from-file) %s\n", violation);
702
751
                }
703
752
                else if(0 == strcmp(long_option, "no-cued-seekpoints")) {
715
764
                else if(0 == strcmp(long_option, "replay-gain")) {
716
765
                        option_values.replay_gain = true;
717
766
                }
 
767
                else if(0 == strcmp(long_option, "ignore-chunk-sizes")) {
 
768
                        option_values.ignore_chunk_sizes = true;
 
769
                }
718
770
                else if(0 == strcmp(long_option, "sector-align")) {
719
771
                        option_values.sector_align = true;
720
772
                }
782
834
                else if(0 == strcmp(long_option, "no-delete-input-file")) {
783
835
                        option_values.delete_input = false;
784
836
                }
 
837
                else if(0 == strcmp(long_option, "no-keep-foreign-metadata")) {
 
838
                        option_values.keep_foreign_metadata = false;
 
839
                }
785
840
                else if(0 == strcmp(long_option, "no-replay-gain")) {
786
841
                        option_values.replay_gain = false;
787
842
                }
 
843
                else if(0 == strcmp(long_option, "no-ignore-chunk-sizes")) {
 
844
                        option_values.ignore_chunk_sizes = false;
 
845
                }
788
846
                else if(0 == strcmp(long_option, "no-sector-align")) {
789
847
                        option_values.sector_align = false;
790
848
                }
 
849
                else if(0 == strcmp(long_option, "no-utf8-convert")) {
 
850
                        option_values.utf8_convert = false;
 
851
                }
791
852
                else if(0 == strcmp(long_option, "no-lax")) {
792
853
                        option_values.lax = false;
793
854
                }
834
895
                else if(0 == strcmp(long_option, "disable-verbatim-subframes")) {
835
896
                        option_values.debug.disable_verbatim_subframes = true;
836
897
                }
 
898
                else if(0 == strcmp(long_option, "no-md5-sum")) {
 
899
                        option_values.debug.do_md5 = false;
 
900
                }
837
901
        }
838
902
        else {
839
903
                switch(short_option) {
875
939
                                break;
876
940
                        case 'T':
877
941
                                FLAC__ASSERT(0 != option_argument);
878
 
                                if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/false, &violation))
 
942
                                if(!flac__vorbiscomment_add(option_values.vorbis_comment, option_argument, /*value_from_file=*/false, /*raw=*/!option_values.utf8_convert, &violation))
879
943
                                        return usage_error("ERROR: (-T/--tag) %s\n", violation);
880
944
                                break;
881
945
                        case '0':
1132
1196
        printf("  -c, --stdout                 Write output to stdout\n");
1133
1197
        printf("  -s, --silent                 Do not write runtime encode/decode statistics\n");
1134
1198
        printf("      --totally-silent         Do not print anything, including errors\n");
 
1199
        printf("      --no-utf8-convert        Do not convert tags from local charset to UTF-8\n");
1135
1200
        printf("  -w, --warnings-as-errors     Treat all warnings as errors\n");
1136
1201
        printf("  -f, --force                  Force overwriting of output files\n");
1137
1202
        printf("  -o, --output-name=FILENAME   Force the output file name\n");
1138
1203
        printf("      --output-prefix=STRING   Prepend STRING to output names\n");
1139
1204
        printf("      --delete-input-file      Deletes after a successful encode/decode\n");
 
1205
        printf("      --keep-foreign-metadata  Save/restore WAVE or AIFF non-audio chunks\n");
1140
1206
        printf("      --skip={#|mm:ss.ss}      Skip the given initial samples for each input\n");
1141
1207
        printf("      --until={#|[+|-]mm:ss.ss}  Stop at the given sample for each input file\n");
1142
1208
#if FLAC__HAS_OGG
1152
1218
        printf("encoding options:\n");
1153
1219
        printf("  -V, --verify                 Verify a correct encoding\n");
1154
1220
        printf("      --lax                    Allow encoder to generate non-Subset files\n");
 
1221
#if 0 /*@@@ currently undocumented */
 
1222
        printf("      --ignore-chunk-sizes     Ignore data chunk sizes in WAVE/AIFF files\n");
 
1223
#endif
1155
1224
        printf("      --sector-align           Align multiple files on sector boundaries\n");
1156
1225
        printf("      --replay-gain            Calculate ReplayGain & store in FLAC tags\n");
1157
1226
        printf("      --cuesheet=FILENAME      Import cuesheet and store in CUESHEET block\n");
1191
1260
        printf("      --no-adaptive-mid-side\n");
1192
1261
        printf("      --no-decode-through-errors\n");
1193
1262
        printf("      --no-delete-input-file\n");
 
1263
        printf("      --no-keep-foreign-metadata\n");
1194
1264
        printf("      --no-exhaustive-model-search\n");
1195
1265
        printf("      --no-lax\n");
1196
1266
        printf("      --no-mid-side\n");
1202
1272
        printf("      --no-replay-gain\n");
1203
1273
        printf("      --no-residual-gnuplot\n");
1204
1274
        printf("      --no-residual-text\n");
 
1275
#if 0 /*@@@ currently undocumented */
 
1276
        printf("      --no-ignore-chunk-sizes\n");
 
1277
#endif
1205
1278
        printf("      --no-sector-align\n");
1206
1279
        printf("      --no-seektable\n");
1207
1280
        printf("      --no-silent\n");
1215
1288
        usage_header();
1216
1289
        usage_summary();
1217
1290
        printf("For encoding:\n");
1218
 
        printf("  The input file(s) may be a PCM RIFF WAVE file, AIFF (or uncompressed AIFF-C)\n");
 
1291
        printf("  The input file(s) may be a PCM WAVE file, AIFF (or uncompressed AIFF-C)\n");
1219
1292
        printf("  file, or raw samples.\n");
1220
1293
        printf("  The output file(s) will be in native FLAC or Ogg FLAC format\n");
1221
1294
        printf("For decoding, the reverse is true.\n");
1246
1319
        printf("      --totally-silent         Do not print anything of any kind, including\n");
1247
1320
        printf("                               warnings or errors.  The exit code will be the\n");
1248
1321
        printf("                               only way to determine successful completion.\n");
 
1322
        printf("      --no-utf8-convert        Do not convert tags from local charset to UTF-8.\n");
 
1323
        printf("                               This is useful for scripts, and setting tags in\n");
 
1324
        printf("                               situations where the locale is wrong.  This\n");
 
1325
        printf("                               option must appear before any tag options!\n");
1249
1326
        printf("  -w, --warnings-as-errors     Treat all warnings as errors\n");
1250
1327
        printf("  -f, --force                  Force overwriting of output files\n");
1251
1328
        printf("  -o, --output-name=FILENAME   Force the output file name; usually flac just\n");
1261
1338
        printf("                               successful encode or decode.  If there was an\n");
1262
1339
        printf("                               error (including a verify error) the input file\n");
1263
1340
        printf("                               is left intact.\n");
 
1341
        printf("      --keep-foreign-metadata  If encoding, save WAVE or AIFF non-audio chunks\n");
 
1342
        printf("                               in FLAC metadata.  If decoding, restore any saved\n");
 
1343
        printf("                               non-audio chunks from FLAC metadata when writing\n");
 
1344
        printf("                               the decoded file.  Foreign metadata cannot be\n");
 
1345
        printf("                               transcoded, e.g. WAVE chunks saved in a FLAC file\n");
 
1346
        printf("                               cannot be restored when decoding to AIFF.  Input\n");
 
1347
        printf("                               and output must be regular files, not stdin/out.\n");
1264
1348
        printf("      --skip={#|mm:ss.ss}      Skip the first # samples of each input file; can\n");
1265
1349
        printf("                               be used both for encoding and decoding.  The\n");
1266
1350
        printf("                               alternative form mm:ss.ss can be used to specify\n");
1278
1362
        printf("      --ogg                    When encoding, generate Ogg FLAC output instead\n");
1279
1363
        printf("                               of native FLAC.  Ogg FLAC streams are FLAC\n");
1280
1364
        printf("                               streams wrapped in an Ogg transport layer.  The\n");
1281
 
        printf("                               resulting file should have an '.ogg' extension\n");
 
1365
        printf("                               resulting file should have an '.oga' extension\n");
1282
1366
        printf("                               and will still be decodable by flac.  When\n");
1283
1367
        printf("                               decoding, force the input to be treated as\n");
1284
1368
        printf("                               Ogg FLAC.  This is useful when piping input\n");
1285
1369
        printf("                               from stdin or when the filename does not end in\n");
1286
 
        printf("                               '.ogg'.\n");
 
1370
        printf("                               '.oga' or '.ogg'.\n");
1287
1371
        printf("      --serial-number          Serial number to use for the FLAC stream.  When\n");
1288
1372
        printf("                               encoding and no serial number is given, flac\n");
1289
1373
        printf("                               uses a random one.  If encoding to multiple files\n");
1324
1408
        printf("                               output in parallel and comparing to the\n");
1325
1409
        printf("                               original\n");
1326
1410
        printf("      --lax                    Allow encoder to generate non-Subset files\n");
 
1411
#if 0 /*@@@ currently undocumented */
 
1412
        printf("      --ignore-chunk-sizes     Ignore data chunk sizes in WAVE/AIFF files;\n");
 
1413
        printf("                               useful when piping data from programs which\n");
 
1414
        printf("                               generate bogus data chunk sizes.\n");
 
1415
#endif
1327
1416
        printf("      --sector-align           Align encoding of multiple CD format WAVE files\n");
1328
1417
        printf("                               on sector boundaries.\n");
1329
1418
        printf("      --replay-gain            Calculate ReplayGain values and store them as\n");
1499
1588
        printf("      --no-adaptive-mid-side\n");
1500
1589
        printf("      --no-decode-through-errors\n");
1501
1590
        printf("      --no-delete-input-file\n");
 
1591
        printf("      --no-keep-foreign-metadata\n");
1502
1592
        printf("      --no-exhaustive-model-search\n");
1503
1593
        printf("      --no-lax\n");
1504
1594
        printf("      --no-mid-side\n");
1509
1599
        printf("      --no-qlp-coeff-prec-search\n");
1510
1600
        printf("      --no-residual-gnuplot\n");
1511
1601
        printf("      --no-residual-text\n");
 
1602
#if 0 /*@@@ currently undocumented */
 
1603
        printf("      --no-ignore-chunk-sizes\n");
 
1604
#endif
1512
1605
        printf("      --no-sector-align\n");
1513
1606
        printf("      --no-seektable\n");
1514
1607
        printf("      --no-silent\n");
1529
1622
        FILE *encode_infile;
1530
1623
        FLAC__byte lookahead[12];
1531
1624
        unsigned lookahead_length = 0;
1532
 
        FileFormat fmt = RAW;
 
1625
        FileFormat input_format = RAW;
1533
1626
        FLAC__bool is_aifc = false;
1534
1627
        int retval;
1535
1628
        off_t infilesize;
1558
1651
        if(!option_values.force_raw_format) {
1559
1652
                /* first set format based on name */
1560
1653
                if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".wav"))
1561
 
                        fmt= WAV;
 
1654
                        input_format = WAV;
1562
1655
                else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".aif"))
1563
 
                        fmt= AIF;
 
1656
                        input_format = AIF;
1564
1657
                else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".aiff"))
1565
 
                        fmt= AIF;
 
1658
                        input_format = AIF;
1566
1659
                else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".flac"))
1567
 
                        fmt= FLAC;
 
1660
                        input_format = FLAC;
 
1661
                else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".oga"))
 
1662
                        input_format = OGGFLAC;
1568
1663
                else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".ogg"))
1569
 
                        fmt= OGGFLAC;
 
1664
                        input_format = OGGFLAC;
1570
1665
 
1571
1666
                /* attempt to guess the file type based on the first 12 bytes */
1572
1667
                if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) {
1573
 
                        if(fmt != RAW) {
1574
 
                                format_mistake(infilename, fmt, RAW);
 
1668
                        if(input_format != RAW) {
 
1669
                                format_mistake(infilename, input_format, RAW);
1575
1670
                                if(option_values.treat_warnings_as_errors) {
1576
1671
                                        conditional_fclose(encode_infile);
1577
1672
                                        return 1;
1578
1673
                                }
1579
1674
                        }
1580
 
                        fmt= RAW;
 
1675
                        input_format = RAW;
1581
1676
                }
1582
1677
                else {
1583
1678
                        if(!strncmp((const char *)lookahead, "ID3", 3)) {
1585
1680
                                return 1;
1586
1681
                        }
1587
1682
                        else if(!strncmp((const char *)lookahead, "RIFF", 4) && !strncmp((const char *)lookahead+8, "WAVE", 4))
1588
 
                                fmt= WAV;
 
1683
                                input_format = WAV;
1589
1684
                        else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFF", 4))
1590
 
                                fmt= AIF;
 
1685
                                input_format = AIF;
1591
1686
                        else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFC", 4)) {
1592
 
                                fmt= AIF;
 
1687
                                input_format = AIF;
1593
1688
                                is_aifc = true;
1594
1689
                        }
1595
1690
                        else if(!memcmp(lookahead, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING)))
1596
 
                                fmt= FLAC;
 
1691
                                input_format = FLAC;
1597
1692
                        /* this could be made more accurate by looking at the first packet */
1598
1693
                        else if(!memcmp(lookahead, "OggS", 4))
1599
 
                                fmt= OGGFLAC;
 
1694
                                input_format = OGGFLAC;
1600
1695
                        else {
1601
 
                                if(fmt != RAW) {
1602
 
                                        format_mistake(infilename, fmt, RAW);
 
1696
                                if(input_format != RAW) {
 
1697
                                        format_mistake(infilename, input_format, RAW);
1603
1698
                                        if(option_values.treat_warnings_as_errors) {
1604
1699
                                                conditional_fclose(encode_infile);
1605
1700
                                                return 1;
1606
1701
                                        }
1607
1702
                                }
1608
 
                                fmt= RAW;
 
1703
                                input_format = RAW;
1609
1704
                        }
1610
1705
                }
1611
1706
        }
1612
1707
 
 
1708
        if(option_values.keep_foreign_metadata) {
 
1709
                if(encode_infile == stdin || option_values.force_to_stdout) {
 
1710
                        conditional_fclose(encode_infile);
 
1711
                        return usage_error("ERROR: --keep-foreign-metadata cannot be used when encoding from stdin or to stdout\n");
 
1712
                }
 
1713
                if(input_format != WAV && input_format != AIF) {
 
1714
                        conditional_fclose(encode_infile);
 
1715
                        return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF input\n");
 
1716
                }
 
1717
        }
 
1718
 
1613
1719
        /*
1614
1720
         * Error if output file already exists (and -f not used).
1615
1721
         * Use grabbag__file_get_filesize() as a cheap way to check.
1616
1722
         */
1617
1723
        if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
1618
 
                if(fmt == FLAC) {
 
1724
                if(input_format == FLAC) {
1619
1725
                        /* need more detailed error message when re-flac'ing to avoid confusing the user */
1620
1726
                        flac__utils_printf(stderr, 1,
1621
1727
                                "ERROR: output file %s already exists.\n\n"
1626
1732
                                outfilename
1627
1733
                        );
1628
1734
                }
1629
 
                else if(fmt == OGGFLAC) {
 
1735
                else if(input_format == OGGFLAC) {
1630
1736
                        /* need more detailed error message when re-flac'ing to avoid confusing the user */
1631
1737
                        flac__utils_printf(stderr, 1,
1632
1738
                                "ERROR: output file %s already exists.\n\n"
1644
1750
        }
1645
1751
 
1646
1752
        if(option_values.format_input_size >= 0) {
1647
 
                if (fmt != RAW || infilesize >= 0) {
 
1753
                if (input_format != RAW || infilesize >= 0) {
1648
1754
                        flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n");
1649
1755
                        conditional_fclose(encode_infile);
1650
1756
                        return 1;
1654
1760
                }
1655
1761
        }
1656
1762
 
1657
 
        if(option_values.sector_align && (fmt == FLAC || fmt == OGGFLAC)) {
 
1763
        if(option_values.sector_align && (input_format == FLAC || input_format == OGGFLAC)) {
1658
1764
                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC or Ogg FLAC\n");
1659
1765
                conditional_fclose(encode_infile);
1660
1766
                return 1;
1661
1767
        }
1662
 
        if(option_values.sector_align && fmt == RAW && infilesize < 0) {
 
1768
        if(option_values.sector_align && input_format == RAW && infilesize < 0) {
1663
1769
                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n");
1664
1770
                conditional_fclose(encode_infile);
1665
1771
                return 1;
1666
1772
        }
1667
1773
 
1668
 
        if(fmt == RAW) {
 
1774
        if(input_format == RAW) {
1669
1775
                if(option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0 || option_values.format_channels < 0 || option_values.format_bps < 0 || option_values.format_sample_rate < 0) {
1670
1776
                        conditional_fclose(encode_infile);
1671
1777
                        return usage_error("ERROR: for encoding a raw file you must specify a value for --endian, --sign, --channels, --bps, and --sample-rate\n");
1672
1778
                }
1673
1779
        }
1674
1780
 
1675
 
        if(encode_infile == stdin || option_values.force_to_stdout) {
 
1781
        if(/*@@@@@@why no stdin?*/encode_infile == stdin || option_values.force_to_stdout) {
1676
1782
                if(option_values.replay_gain) {
1677
1783
                        conditional_fclose(encode_infile);
1678
1784
                        return usage_error("ERROR: --replay-gain cannot be used when encoding to stdout\n");
1723
1829
        common_options.align_reservoir = align_reservoir;
1724
1830
        common_options.align_reservoir_samples = &align_reservoir_samples;
1725
1831
        common_options.replay_gain = option_values.replay_gain;
 
1832
        common_options.ignore_chunk_sizes = option_values.ignore_chunk_sizes;
1726
1833
        common_options.sector_align = option_values.sector_align;
1727
1834
        common_options.vorbis_comment = option_values.vorbis_comment;
1728
1835
        FLAC__ASSERT(sizeof(common_options.pictures) >= sizeof(option_values.pictures));
1731
1838
        common_options.debug.disable_constant_subframes = option_values.debug.disable_constant_subframes;
1732
1839
        common_options.debug.disable_fixed_subframes = option_values.debug.disable_fixed_subframes;
1733
1840
        common_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes;
 
1841
        common_options.debug.do_md5 = option_values.debug.do_md5;
1734
1842
 
1735
1843
        /* if infilename and outfilename point to the same file, we need to write to a temporary file */
1736
1844
        if(encode_infile != stdin && grabbag__file_are_same(infilename, outfilename)) {
1737
1845
                static const char *tmp_suffix = ".tmp,fl-ac+en'c";
1738
1846
                /*@@@@ still a remote possibility that a file with this filename exists */
1739
 
                if(0 == (internal_outfilename = malloc(strlen(outfilename)+strlen(tmp_suffix)+1))) {
 
1847
                if(0 == (internal_outfilename = (char *)safe_malloc_add_3op_(strlen(outfilename), /*+*/strlen(tmp_suffix), /*+*/1))) {
1740
1848
                        flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n");
1741
1849
                        conditional_fclose(encode_infile);
1742
1850
                        return 1;
1745
1853
                strcat(internal_outfilename, tmp_suffix);
1746
1854
        }
1747
1855
 
1748
 
        if(fmt == RAW) {
 
1856
        if(input_format == RAW) {
1749
1857
                raw_encode_options_t options;
1750
1858
 
1751
1859
                options.common = common_options;
1757
1865
 
1758
1866
                retval = flac__encode_raw(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
1759
1867
        }
1760
 
        else if(fmt == FLAC || fmt == OGGFLAC) {
 
1868
        else if(input_format == FLAC || input_format == OGGFLAC) {
1761
1869
                flac_encode_options_t options;
1762
1870
 
1763
1871
                options.common = common_options;
1764
1872
 
1765
 
                retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, fmt==OGGFLAC);
 
1873
                retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, input_format==OGGFLAC);
1766
1874
        }
1767
1875
        else {
1768
1876
                wav_encode_options_t options;
1769
1877
 
1770
1878
                options.common = common_options;
1771
 
 
1772
 
                if(fmt == AIF)
 
1879
                options.foreign_metadata = 0;
 
1880
 
 
1881
                /* read foreign metadata if requested */
 
1882
                if(option_values.keep_foreign_metadata) {
 
1883
                        if(0 == (options.foreign_metadata = flac__foreign_metadata_new(input_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) {
 
1884
                                flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n");
 
1885
                                conditional_fclose(encode_infile);
 
1886
                                return 1;
 
1887
                        }
 
1888
                }
 
1889
 
 
1890
                if(input_format == AIF)
1773
1891
                        retval = flac__encode_aif(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, is_aifc);
1774
1892
                else
1775
1893
                        retval = flac__encode_wav(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
 
1894
 
 
1895
                if(options.foreign_metadata)
 
1896
                        flac__foreign_metadata_delete(options.foreign_metadata);
1776
1897
        }
1777
1898
 
1778
1899
        if(retval == 0) {
1786
1907
                                        0 != (error = grabbag__replaygain_store_to_file_title(internal_outfilename? internal_outfilename : outfilename, title_gain, title_peak, /*preserve_modtime=*/true))
1787
1908
                                ) {
1788
1909
                                        flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain reference/title tags (%s)\n", outfilename, error);
 
1910
                                        retval = 1;
1789
1911
                                }
1790
1912
                        }
1791
1913
                        if(strcmp(infilename, "-"))
1827
1949
{
1828
1950
        int retval;
1829
1951
        FLAC__bool treat_as_ogg = false;
 
1952
        FileFormat output_format = WAV;
1830
1953
        decode_options_t common_options;
1831
1954
        const char *outfilename = get_decoded_outfilename(infilename);
1832
1955
 
1844
1967
                return 1;
1845
1968
        }
1846
1969
 
 
1970
        if(option_values.force_raw_format)
 
1971
                output_format = RAW;
 
1972
        else if(
 
1973
                option_values.force_aiff_format ||
 
1974
                (strlen(outfilename) >= 4 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-4), ".aif")) ||
 
1975
                (strlen(outfilename) >= 5 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-5), ".aiff"))
 
1976
        )
 
1977
                output_format = AIF;
 
1978
        else
 
1979
                output_format = WAV;
 
1980
 
1847
1981
        if(!option_values.test_only && !option_values.analyze) {
1848
 
                if(option_values.force_raw_format && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0))
 
1982
                if(output_format == RAW && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0))
1849
1983
                        return usage_error("ERROR: for decoding to a raw file you must specify a value for --endian and --sign\n");
1850
1984
        }
1851
1985
 
 
1986
        if(option_values.keep_foreign_metadata) {
 
1987
                if(0 == strcmp(infilename, "-") || 0 == strcmp(outfilename, "-"))
 
1988
                        return usage_error("ERROR: --keep-foreign-metadata cannot be used when decoding from stdin or to stdout\n");
 
1989
                if(output_format != WAV && output_format != AIF)
 
1990
                        return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF output\n");
 
1991
        }
 
1992
 
1852
1993
        if(option_values.use_ogg)
1853
1994
                treat_as_ogg = true;
 
1995
        else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".oga"))
 
1996
                treat_as_ogg = true;
1854
1997
        else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".ogg"))
1855
1998
                treat_as_ogg = true;
1856
1999
        else
1890
2033
#endif
1891
2034
        common_options.channel_map_none = option_values.channel_map_none;
1892
2035
 
1893
 
        if(!option_values.force_raw_format) {
 
2036
        if(output_format == RAW) {
 
2037
                raw_decode_options_t options;
 
2038
 
 
2039
                options.common = common_options;
 
2040
                options.is_big_endian = option_values.format_is_big_endian;
 
2041
                options.is_unsigned_samples = option_values.format_is_unsigned_samples;
 
2042
 
 
2043
                retval = flac__decode_raw(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options);
 
2044
        }
 
2045
        else {
1894
2046
                wav_decode_options_t options;
1895
2047
 
1896
2048
                options.common = common_options;
1897
 
 
1898
 
                if(
1899
 
                        option_values.force_aiff_format ||
1900
 
                        (strlen(outfilename) >= 4 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-4), ".aif")) ||
1901
 
                        (strlen(outfilename) >= 5 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-5), ".aiff"))
1902
 
                )
 
2049
                options.foreign_metadata = 0;
 
2050
 
 
2051
                /* read foreign metadata if requested */
 
2052
                if(option_values.keep_foreign_metadata) {
 
2053
                        if(0 == (options.foreign_metadata = flac__foreign_metadata_new(output_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) {
 
2054
                                flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n");
 
2055
                                return 1;
 
2056
                        }
 
2057
                }
 
2058
 
 
2059
                if(output_format == AIF)
1903
2060
                        retval = flac__decode_aiff(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options);
1904
2061
                else
1905
2062
                        retval = flac__decode_wav(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options);
1906
 
        }
1907
 
        else {
1908
 
                raw_decode_options_t options;
1909
 
 
1910
 
                options.common = common_options;
1911
 
                options.is_big_endian = option_values.format_is_big_endian;
1912
 
                options.is_unsigned_samples = option_values.format_is_unsigned_samples;
1913
 
 
1914
 
                retval = flac__decode_raw(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options);
 
2063
 
 
2064
                if(options.foreign_metadata)
 
2065
                        flac__foreign_metadata_delete(options.foreign_metadata);
1915
2066
        }
1916
2067
 
1917
2068
        if(retval == 0 && strcmp(infilename, "-")) {
1926
2077
 
1927
2078
const char *get_encoded_outfilename(const char *infilename)
1928
2079
{
1929
 
        const char *suffix = (option_values.use_ogg? ".ogg" : ".flac");
 
2080
        const char *suffix = (option_values.use_ogg? ".oga" : ".flac");
1930
2081
        return get_outfilename(infilename, suffix);
1931
2082
}
1932
2083