~ubuntu-branches/ubuntu/precise/flac/precise-updates

« back to all changes in this revision

Viewing changes to src/metaflac/options.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-05-29 22:56:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070529225636-ljeff8xxip09qaap
Tags: 1.1.4-1
* New upstream release. closes: #405167, #411311
  - libOggFLAC and libOggFLAC++ have been merged into libFLAC, so
    remove their corresponding packages.
  - Because of the API changes required to effect the above, there has
    been yet another soname bump. libflac7 -> libflac8 and
    libflac++5 -> libflac++6. Emails have been dispatched to the
    maintainers of dependent packages.
* Some notes on patches that were removed:
  - 02_stdin_stdout, 06_manpage_mention_utf8_convert: merged upstream
  - 08_manpage_warnings: Upstream has changed the manpage so it defintely
    can't fit in in 80 cols, so just forget about it. We'll live.
  - 05_eof_warnings_are_errors: Upstream decided to add a -w option to
    flac to treat all warnings as errors. I am going to defer to that
    for now, but if people think it's stupid let me know and I'll port
    the patch forward.
  - 04_stack_smasher: was a backport from 1.1.3, so it's obsolete.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* metaflac - Command-line FLAC metadata editor
2
 
 * Copyright (C) 2001,2002,2003,2004,2005  Josh Coalson
 
2
 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007  Josh Coalson
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public License
16
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
17
 */
18
18
 
 
19
#if HAVE_CONFIG_H
 
20
#  include <config.h>
 
21
#endif
 
22
 
19
23
#include "options.h"
20
24
#include "usage.h"
21
25
#include "utils.h"
22
26
#include "FLAC/assert.h"
 
27
#include "share/grabbag/replaygain.h"
23
28
#include <ctype.h>
24
29
#include <stdio.h>
25
30
#include <stdlib.h>
62
67
        { "remove-tag", 1, 0, 0 }, 
63
68
        { "remove-first-tag", 1, 0, 0 }, 
64
69
        { "set-tag", 1, 0, 0 }, 
 
70
        { "set-tag-from-file", 1, 0, 0 }, 
65
71
        { "import-tags-from", 1, 0, 0 }, 
66
72
        { "export-tags-to", 1, 0, 0 }, 
67
 
        { "show-vc-vendor", 0, 0, 0 }, /* deprecated */
68
 
        { "show-vc-field", 1, 0, 0 }, /* deprecated */
69
 
        { "remove-vc-all", 0, 0, 0 }, /* deprecated */
70
 
        { "remove-vc-field", 1, 0, 0 }, /* deprecated */
71
 
        { "remove-vc-firstfield", 1, 0, 0 }, /* deprecated */
72
 
        { "set-vc-field", 1, 0, 0 }, /* deprecated */
73
 
        { "import-vc-from", 1, 0, 0 }, /* deprecated */
74
 
        { "export-vc-to", 1, 0, 0 }, /* deprecated */
75
73
        { "import-cuesheet-from", 1, 0, 0 },
76
74
        { "export-cuesheet-to", 1, 0, 0 },
 
75
        { "import-picture-from", 1, 0, 0 },
 
76
        { "export-picture-to", 1, 0, 0 },
77
77
        { "add-seekpoint", 1, 0, 0 },
78
78
        { "add-replay-gain", 0, 0, 0 },
 
79
        { "remove-replay-gain", 0, 0, 0 },
79
80
        { "add-padding", 1, 0, 0 },
80
81
        /* major operations */
81
82
        { "help", 0, 0, 0 },
101
102
static void append_new_argument(CommandLineOptions *options, Argument argument);
102
103
static Operation *append_major_operation(CommandLineOptions *options, OperationType type);
103
104
static Operation *append_shorthand_operation(CommandLineOptions *options, OperationType type);
 
105
static Argument *find_argument(CommandLineOptions *options, ArgumentType type);
104
106
static Operation *find_shorthand_operation(CommandLineOptions *options, OperationType type);
105
107
static Argument *append_argument(CommandLineOptions *options, ArgumentType type);
106
108
static FLAC__bool parse_md5(const char *src, FLAC__byte dest[16]);
107
109
static FLAC__bool parse_uint32(const char *src, FLAC__uint32 *dest);
108
110
static FLAC__bool parse_uint64(const char *src, FLAC__uint64 *dest);
109
 
static FLAC__bool parse_filename(const char *src, char **dest);
 
111
static FLAC__bool parse_string(const char *src, char **dest);
110
112
static FLAC__bool parse_vorbis_comment_field_name(const char *field_ref, char **name, const char **violation);
111
113
static FLAC__bool parse_add_seekpoint(const char *in, char **out, const char **violation);
112
114
static FLAC__bool parse_add_padding(const char *in, unsigned *out);
200
202
                }
201
203
        }
202
204
 
203
 
        /* check for only one FLAC file used with --import-cuesheet-from/--export-cuesheet-to */
204
 
        if((0 != find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM) || 0 != find_shorthand_operation(options, OP__EXPORT_CUESHEET_TO)) && options->num_files > 1) {
205
 
                fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--import-cuesheet-from' or '--export-cuesheet-to'\n");
206
 
                had_error = true;
 
205
        /* check for only one FLAC file used with certain options */
 
206
        if(options->num_files > 1) {
 
207
                if(0 != find_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM)) {
 
208
                        fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--import-cuesheet-from'\n");
 
209
                        had_error = true;
 
210
                }
 
211
                if(0 != find_shorthand_operation(options, OP__EXPORT_CUESHEET_TO)) {
 
212
                        fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--export-cuesheet-to'\n");
 
213
                        had_error = true;
 
214
                }
 
215
                if(0 != find_shorthand_operation(options, OP__EXPORT_PICTURE_TO)) {
 
216
                        fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--export-picture-to'\n");
 
217
                        had_error = true;
 
218
                }
 
219
                if(
 
220
                        0 != find_shorthand_operation(options, OP__IMPORT_VC_FROM) &&
 
221
                        0 == strcmp(find_shorthand_operation(options, OP__IMPORT_VC_FROM)->argument.filename.value, "-")
 
222
                ) {
 
223
                        fprintf(stderr, "ERROR: you may only specify one FLAC file when using '--import-tags-from=-'\n");
 
224
                        had_error = true;
 
225
                }
207
226
        }
208
227
 
209
228
        if(options->args.checks.has_block_type && options->args.checks.has_except_block_type) {
267
286
                                if(0 != op->argument.import_cuesheet_from.filename)
268
287
                                        free(op->argument.import_cuesheet_from.filename);
269
288
                                break;
 
289
                        case OP__IMPORT_PICTURE_FROM:
 
290
                                if(0 != op->argument.specification.value)
 
291
                                        free(op->argument.specification.value);
 
292
                                break;
 
293
                        case OP__EXPORT_PICTURE_TO:
 
294
                                if(0 != op->argument.export_picture_to.filename)
 
295
                                        free(op->argument.export_picture_to.filename);
 
296
                                break;
270
297
                        case OP__ADD_SEEKPOINT:
271
298
                                if(0 != op->argument.add_seekpoint.specification)
272
299
                                        free(op->argument.add_seekpoint.specification);
449
476
                else
450
477
                        undocumented_warning(opt);
451
478
        }
452
 
        else if(0 == strcmp(opt, "show-vendor-tag") || 0 == strcmp(opt, "show-vc-vendor")) {
453
 
                if(0 == strcmp(opt, "show-vc-vendor"))
454
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --show-vendor-tag\n", opt);
 
479
        else if(0 == strcmp(opt, "show-vendor-tag")) {
455
480
                (void) append_shorthand_operation(options, OP__SHOW_VC_VENDOR);
456
481
        }
457
 
        else if(0 == strcmp(opt, "show-tag") || 0 == strcmp(opt, "show-vc-field")) {
 
482
        else if(0 == strcmp(opt, "show-tag")) {
458
483
                const char *violation;
459
 
                if(0 == strcmp(opt, "show-vc-field"))
460
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --show-tag\n", opt);
461
484
                op = append_shorthand_operation(options, OP__SHOW_VC_FIELD);
462
485
                FLAC__ASSERT(0 != option_argument);
463
486
                if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
466
489
                        ok = false;
467
490
                }
468
491
        }
469
 
        else if(0 == strcmp(opt, "remove-all-tags") || 0 == strcmp(opt, "remove-vc-all")) {
470
 
                if(0 == strcmp(opt, "remove-vc-all"))
471
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --remove-all-tags\n", opt);
 
492
        else if(0 == strcmp(opt, "remove-all-tags")) {
472
493
                (void) append_shorthand_operation(options, OP__REMOVE_VC_ALL);
473
494
        }
474
 
        else if(0 == strcmp(opt, "remove-tag") || 0 == strcmp(opt, "remove-vc-field")) {
 
495
        else if(0 == strcmp(opt, "remove-tag")) {
475
496
                const char *violation;
476
 
                if(0 == strcmp(opt, "remove-vc-field"))
477
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --remove-tag\n", opt);
478
497
                op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD);
479
498
                FLAC__ASSERT(0 != option_argument);
480
499
                if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
483
502
                        ok = false;
484
503
                }
485
504
        }
486
 
        else if(0 == strcmp(opt, "remove-first-tag") || 0 == strcmp(opt, "remove-vc-firstfield")) {
 
505
        else if(0 == strcmp(opt, "remove-first-tag")) {
487
506
                const char *violation;
488
 
                if(0 == strcmp(opt, "remove-vc-firstfield"))
489
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --remove-first-tag\n", opt);
490
507
                op = append_shorthand_operation(options, OP__REMOVE_VC_FIRSTFIELD);
491
508
                FLAC__ASSERT(0 != option_argument);
492
509
                if(!parse_vorbis_comment_field_name(option_argument, &(op->argument.vc_field_name.value), &violation)) {
495
512
                        ok = false;
496
513
                }
497
514
        }
498
 
        else if(0 == strcmp(opt, "set-tag") || 0 == strcmp(opt, "set-vc-field")) {
499
 
                const char *violation;
500
 
                if(0 == strcmp(opt, "set-vc-field"))
501
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --set-tag\n", opt);
502
 
                op = append_shorthand_operation(options, OP__SET_VC_FIELD);
503
 
                FLAC__ASSERT(0 != option_argument);
504
 
                if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
505
 
                        FLAC__ASSERT(0 != violation);
506
 
                        fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
507
 
                        ok = false;
508
 
                }
509
 
        }
510
 
        else if(0 == strcmp(opt, "import-tags-from") || 0 == strcmp(opt, "import-vc-from")) {
511
 
                if(0 == strcmp(opt, "import-vc-from"))
512
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --import-tags-from\n", opt);
 
515
        else if(0 == strcmp(opt, "set-tag")) {
 
516
                const char *violation;
 
517
                op = append_shorthand_operation(options, OP__SET_VC_FIELD);
 
518
                FLAC__ASSERT(0 != option_argument);
 
519
                op->argument.vc_field.field_value_from_file = false;
 
520
                if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
 
521
                        FLAC__ASSERT(0 != violation);
 
522
                        fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
 
523
                        ok = false;
 
524
                }
 
525
        }
 
526
        else if(0 == strcmp(opt, "set-tag-from-file")) {
 
527
                const char *violation;
 
528
                op = append_shorthand_operation(options, OP__SET_VC_FIELD);
 
529
                FLAC__ASSERT(0 != option_argument);
 
530
                op->argument.vc_field.field_value_from_file = true;
 
531
                if(!parse_vorbis_comment_field(option_argument, &(op->argument.vc_field.field), &(op->argument.vc_field.field_name), &(op->argument.vc_field.field_value), &(op->argument.vc_field.field_value_length), &violation)) {
 
532
                        FLAC__ASSERT(0 != violation);
 
533
                        fprintf(stderr, "ERROR (--%s): malformed vorbis comment field \"%s\",\n       %s\n", opt, option_argument, violation);
 
534
                        ok = false;
 
535
                }
 
536
        }
 
537
        else if(0 == strcmp(opt, "import-tags-from")) {
513
538
                op = append_shorthand_operation(options, OP__IMPORT_VC_FROM);
514
539
                FLAC__ASSERT(0 != option_argument);
515
 
                if(!parse_filename(option_argument, &(op->argument.filename.value))) {
 
540
                if(!parse_string(option_argument, &(op->argument.filename.value))) {
516
541
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
517
542
                        ok = false;
518
543
                }
519
544
        }
520
 
        else if(0 == strcmp(opt, "export-tags-to") || 0 == strcmp(opt, "export-vc-to")) {
521
 
                if(0 == strcmp(opt, "export-vc-to"))
522
 
                        fprintf(stderr, "WARNING: --%s is deprecated, the new name is --export-tags-to\n", opt);
 
545
        else if(0 == strcmp(opt, "export-tags-to")) {
523
546
                op = append_shorthand_operation(options, OP__EXPORT_VC_TO);
524
547
                FLAC__ASSERT(0 != option_argument);
525
 
                if(!parse_filename(option_argument, &(op->argument.filename.value))) {
 
548
                if(!parse_string(option_argument, &(op->argument.filename.value))) {
526
549
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
527
550
                        ok = false;
528
551
                }
534
557
                }
535
558
                op = append_shorthand_operation(options, OP__IMPORT_CUESHEET_FROM);
536
559
                FLAC__ASSERT(0 != option_argument);
537
 
                if(!parse_filename(option_argument, &(op->argument.import_cuesheet_from.filename))) {
 
560
                if(!parse_string(option_argument, &(op->argument.import_cuesheet_from.filename))) {
538
561
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
539
562
                        ok = false;
540
563
                }
542
565
        else if(0 == strcmp(opt, "export-cuesheet-to")) {
543
566
                op = append_shorthand_operation(options, OP__EXPORT_CUESHEET_TO);
544
567
                FLAC__ASSERT(0 != option_argument);
545
 
                if(!parse_filename(option_argument, &(op->argument.filename.value))) {
546
 
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
547
 
                        ok = false;
548
 
                }
 
568
                if(!parse_string(option_argument, &(op->argument.filename.value))) {
 
569
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
 
570
                        ok = false;
 
571
                }
 
572
        }
 
573
        else if(0 == strcmp(opt, "import-picture-from")) {
 
574
                op = append_shorthand_operation(options, OP__IMPORT_PICTURE_FROM);
 
575
                FLAC__ASSERT(0 != option_argument);
 
576
                if(!parse_string(option_argument, &(op->argument.specification.value))) {
 
577
                        fprintf(stderr, "ERROR (--%s): missing specification\n", opt);
 
578
                        ok = false;
 
579
                }
 
580
        }
 
581
        else if(0 == strcmp(opt, "export-picture-to")) {
 
582
                const Argument *arg = find_argument(options, ARG__BLOCK_NUMBER);
 
583
                op = append_shorthand_operation(options, OP__EXPORT_PICTURE_TO);
 
584
                FLAC__ASSERT(0 != option_argument);
 
585
                if(!parse_string(option_argument, &(op->argument.export_picture_to.filename))) {
 
586
                        fprintf(stderr, "ERROR (--%s): missing filename\n", opt);
 
587
                        ok = false;
 
588
                }
 
589
                op->argument.export_picture_to.block_number_link = arg? &(arg->value.block_number) : 0;
549
590
        }
550
591
        else if(0 == strcmp(opt, "add-seekpoint")) {
551
592
                const char *violation;
556
597
                        fprintf(stderr, "ERROR (--%s): malformed seekpoint specification \"%s\",\n       %s\n", opt, option_argument, violation);
557
598
                        ok = false;
558
599
                }
559
 
                op = find_shorthand_operation(options, OP__ADD_SEEKPOINT);
560
 
                if(0 == op)
561
 
                        op = append_shorthand_operation(options, OP__ADD_SEEKPOINT);
562
 
                local_strcat(&(op->argument.add_seekpoint.specification), spec);
563
 
                local_strcat(&(op->argument.add_seekpoint.specification), ";");
564
 
                free(spec);
 
600
                else {
 
601
                        op = find_shorthand_operation(options, OP__ADD_SEEKPOINT);
 
602
                        if(0 == op)
 
603
                                op = append_shorthand_operation(options, OP__ADD_SEEKPOINT);
 
604
                        local_strcat(&(op->argument.add_seekpoint.specification), spec);
 
605
                        local_strcat(&(op->argument.add_seekpoint.specification), ";");
 
606
                        free(spec);
 
607
                }
565
608
        }
566
609
        else if(0 == strcmp(opt, "add-replay-gain")) {
567
610
                (void) append_shorthand_operation(options, OP__ADD_REPLAY_GAIN);
568
611
        }
 
612
        else if(0 == strcmp(opt, "remove-replay-gain")) {
 
613
                const FLAC__byte * const tags[5] = {
 
614
                        GRABBAG__REPLAYGAIN_TAG_REFERENCE_LOUDNESS,
 
615
                        GRABBAG__REPLAYGAIN_TAG_TITLE_GAIN,
 
616
                        GRABBAG__REPLAYGAIN_TAG_TITLE_PEAK,
 
617
                        GRABBAG__REPLAYGAIN_TAG_ALBUM_GAIN,
 
618
                        GRABBAG__REPLAYGAIN_TAG_ALBUM_PEAK
 
619
                };
 
620
                size_t i;
 
621
                for(i = 0; i < sizeof(tags)/sizeof(tags[0]); i++) {
 
622
                        op = append_shorthand_operation(options, OP__REMOVE_VC_FIELD);
 
623
                        op->argument.vc_field_name.value = local_strdup((const char *)tags[i]);
 
624
                }
 
625
        }
569
626
        else if(0 == strcmp(opt, "add-padding")) {
570
627
                op = append_shorthand_operation(options, OP__ADD_PADDING);
571
628
                FLAC__ASSERT(0 != option_argument);
709
766
        return options->ops.operations + (options->ops.num_operations - 1);
710
767
}
711
768
 
 
769
Argument *find_argument(CommandLineOptions *options, ArgumentType type)
 
770
{
 
771
        unsigned i;
 
772
        for(i = 0; i < options->args.num_arguments; i++)
 
773
                if(options->args.arguments[i].type == type)
 
774
                        return &options->args.arguments[i];
 
775
        return 0;
 
776
}
 
777
 
712
778
Operation *find_shorthand_operation(CommandLineOptions *options, OperationType type)
713
779
{
714
780
        unsigned i;
769
835
        return true;
770
836
}
771
837
 
772
 
/* There's no stroull() in MSVC6 so we just write a specialized one */
 
838
#ifdef _MSC_VER
 
839
/* There's no strtoull() in MSVC6 so we just write a specialized one */
773
840
static FLAC__uint64 local__strtoull(const char *src)
774
841
{
775
842
        FLAC__uint64 ret = 0;
784
851
        }
785
852
        return ret;
786
853
}
 
854
#endif
787
855
 
788
856
FLAC__bool parse_uint64(const char *src, FLAC__uint64 *dest)
789
857
{
790
858
        FLAC__ASSERT(0 != src);
791
859
        if(strlen(src) == 0 || strspn(src, "0123456789") != strlen(src))
792
860
                return false;
 
861
#ifdef _MSC_VER
793
862
        *dest = local__strtoull(src);
 
863
#else
 
864
        *dest = strtoull(src, 0, 10);
 
865
#endif
794
866
        return true;
795
867
}
796
868
 
797
 
FLAC__bool parse_filename(const char *src, char **dest)
 
869
FLAC__bool parse_string(const char *src, char **dest)
798
870
{
799
871
        if(0 == src || strlen(src) == 0)
800
872
                return false;
989
1061
                else if(0 == strcmp(q, "CUESHEET")) {
990
1062
                        out->entries[entry++].type = FLAC__METADATA_TYPE_CUESHEET;
991
1063
                }
 
1064
                else if(0 == strcmp(q, "PICTURE")) {
 
1065
                        out->entries[entry++].type = FLAC__METADATA_TYPE_PICTURE;
 
1066
                }
992
1067
                else {
993
1068
                        free(s);
994
1069
                        return false;