add --import-vc-from
authorJosh Coalson <jcoalson@users.sourceforce.net>
Thu, 5 Sep 2002 05:38:22 +0000 (05:38 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Thu, 5 Sep 2002 05:38:22 +0000 (05:38 +0000)
src/metaflac/main.c
test/test_metaflac.sh

index f231534..ba3c74b 100644 (file)
@@ -69,6 +69,7 @@ static struct FLAC__share__option long_options_[] = {
        { "remove-vc-field", 1, 0, 0 },
        { "remove-vc-firstfield", 1, 0, 0 },
        { "set-vc-field", 1, 0, 0 },
        { "remove-vc-field", 1, 0, 0 },
        { "remove-vc-firstfield", 1, 0, 0 },
        { "set-vc-field", 1, 0, 0 },
+       { "import-vc-from", 1, 0, 0 },
        { "add-padding", 1, 0, 0 },
        /* major operations */
        { "help", 0, 0, 0 },
        { "add-padding", 1, 0, 0 },
        /* major operations */
        { "help", 0, 0, 0 },
@@ -105,6 +106,7 @@ typedef enum {
        OP__REMOVE_VC_FIELD,
        OP__REMOVE_VC_FIRSTFIELD,
        OP__SET_VC_FIELD,
        OP__REMOVE_VC_FIELD,
        OP__REMOVE_VC_FIRSTFIELD,
        OP__SET_VC_FIELD,
+       OP__IMPORT_VC_FROM,
        OP__ADD_PADDING,
        OP__LIST,
        OP__APPEND,
        OP__ADD_PADDING,
        OP__LIST,
        OP__APPEND,
@@ -135,6 +137,10 @@ typedef struct {
 } Argument_VcField;
 
 typedef struct {
 } Argument_VcField;
 
 typedef struct {
+       char *file_name;
+} Argument_VcImportFile;
+
+typedef struct {
        unsigned num_entries;
        unsigned *entries;
 } Argument_BlockNumber;
        unsigned num_entries;
        unsigned *entries;
 } Argument_BlockNumber;
@@ -169,6 +175,7 @@ typedef struct {
                Argument_VcFieldName remove_vc_field;
                Argument_VcFieldName remove_vc_firstfield;
                Argument_VcField set_vc_field;
                Argument_VcFieldName remove_vc_field;
                Argument_VcFieldName remove_vc_firstfield;
                Argument_VcField set_vc_field;
+               Argument_VcImportFile import_vc_from;
                Argument_AddPadding add_padding;
        } argument;
 } Operation;
                Argument_AddPadding add_padding;
        } argument;
 } Operation;
@@ -225,6 +232,7 @@ static void show_version();
 static int short_usage(const char *message, ...);
 static int long_usage(const char *message, ...);
 static char *local_strdup(const char *source);
 static int short_usage(const char *message, ...);
 static int long_usage(const char *message, ...);
 static char *local_strdup(const char *source);
+static FLAC__bool parse_filename(const char *src, char **dest);
 static FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation);
 static FLAC__bool parse_vorbis_comment_field_name(const char *field_ref, char **name, const char **violation);
 static FLAC__bool parse_add_padding(const char *in, unsigned *out);
 static FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation);
 static FLAC__bool parse_vorbis_comment_field_name(const char *field_ref, char **name, const char **violation);
 static FLAC__bool parse_add_padding(const char *in, unsigned *out);
@@ -253,6 +261,7 @@ static FLAC__bool remove_vc_all(const char *filename, FLAC__StreamMetadata *bloc
 static FLAC__bool remove_vc_field(FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
 static FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
 static FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw);
 static FLAC__bool remove_vc_field(FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
 static FLAC__bool remove_vc_firstfield(const char *filename, FLAC__StreamMetadata *block, const char *field_name, FLAC__bool *needs_write);
 static FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const Argument_VcField *field, FLAC__bool *needs_write, FLAC__bool raw);
+static FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_VcImportFile *file, FLAC__bool *needs_write, FLAC__bool raw);
 static FLAC__bool field_name_matches_entry(const char *field_name, unsigned field_name_length, const FLAC__StreamMetadata_VorbisComment_Entry *entry);
 static void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent);
 
 static FLAC__bool field_name_matches_entry(const char *field_name, unsigned field_name_length, const FLAC__StreamMetadata_VorbisComment_Entry *entry);
 static void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent);
 
@@ -466,6 +475,14 @@ FLAC__bool parse_option(int option_index, const char *option_argument, CommandLi
                        ok = false;
                }
        }
                        ok = false;
                }
        }
+       else if(0 == strcmp(opt, "import-vc-from")) {
+               op = append_shorthand_operation(options, OP__IMPORT_VC_FROM);
+               FLAC__ASSERT(0 != option_argument);
+               if(!parse_filename(option_argument, &(op->argument.import_vc_from.file_name))) {
+                       fprintf(stderr, "ERROR: missing filename\n");
+                       ok = false;
+               }
+       }
        else if(0 == strcmp(opt, "add-padding")) {
                op = append_shorthand_operation(options, OP__ADD_PADDING);
                FLAC__ASSERT(0 != option_argument);
        else if(0 == strcmp(opt, "add-padding")) {
                op = append_shorthand_operation(options, OP__ADD_PADDING);
                FLAC__ASSERT(0 != option_argument);
@@ -576,6 +593,10 @@ void free_options(CommandLineOptions *options)
                                if(0 != op->argument.set_vc_field.field_value)
                                        free(op->argument.set_vc_field.field_value);
                                break;
                                if(0 != op->argument.set_vc_field.field_value)
                                        free(op->argument.set_vc_field.field_value);
                                break;
+                       case OP__IMPORT_VC_FROM:
+                               if(0 != op->argument.import_vc_from.file_name)
+                                       free(op->argument.import_vc_from.file_name);
+                               break;
                        default:
                                break;
                }
                        default:
                                break;
                }
@@ -791,6 +812,11 @@ int long_usage(const char *message, ...)
        fprintf(out, "                      the Vorbis comment spec, of the form \"NAME=VALUE\".  If\n");
        fprintf(out, "                      there is currently no VORBIS_COMMENT block, one will be\n");
        fprintf(out, "                      created.\n");
        fprintf(out, "                      the Vorbis comment spec, of the form \"NAME=VALUE\".  If\n");
        fprintf(out, "                      there is currently no VORBIS_COMMENT block, one will be\n");
        fprintf(out, "                      created.\n");
+       fprintf(out, "--import-vc-from=file Import Vorbis comments from a file.  Use '-' for stdin.\n");
+       fprintf(out, "                      Each line should be of the form NAME=VALUE.  Multi-\n");
+       fprintf(out, "                      line comments are currently not supported.  Specify\n");
+       fprintf(out, "                      --remove-vc-all and/or --no-utf8-convert before\n");
+       fprintf(out, "                      --import-vc-from if necessary.\n");
        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");
        fprintf(out, "                      the extra 4 bytes is for the metadata block header.\n");
        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");
        fprintf(out, "                      the extra 4 bytes is for the metadata block header.\n");
@@ -895,6 +921,14 @@ char *local_strdup(const char *source)
        return ret;
 }
 
        return ret;
 }
 
+FLAC__bool parse_filename(const char *src, char **dest)
+{
+       if(0 == src || strlen(src) == 0)
+               return false;
+       *dest = strdup(src);
+       return true;
+}
+
 FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation)
 {
        static const char * const violations[] = {
 FLAC__bool parse_vorbis_comment_field(const char *field_ref, char **field, char **name, char **value, unsigned *length, const char **violation)
 {
        static const char * const violations[] = {
@@ -1338,6 +1372,7 @@ FLAC__bool do_shorthand_operation(const char *filename, FLAC__Metadata_Chain *ch
                case OP__REMOVE_VC_FIELD:
                case OP__REMOVE_VC_FIRSTFIELD:
                case OP__SET_VC_FIELD:
                case OP__REMOVE_VC_FIELD:
                case OP__REMOVE_VC_FIRSTFIELD:
                case OP__SET_VC_FIELD:
+               case OP__IMPORT_VC_FROM:
                        ok = do_shorthand_operation__vorbis_comment(filename, chain, operation, needs_write, !utf8_convert);
                        break;
                case OP__ADD_PADDING:
                        ok = do_shorthand_operation__vorbis_comment(filename, chain, operation, needs_write, !utf8_convert);
                        break;
                case OP__ADD_PADDING:
@@ -1496,6 +1531,9 @@ FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__Me
                case OP__SET_VC_FIELD:
                        ok = set_vc_field(filename, block, &operation->argument.set_vc_field, needs_write, raw);
                        break;
                case OP__SET_VC_FIELD:
                        ok = set_vc_field(filename, block, &operation->argument.set_vc_field, needs_write, raw);
                        break;
+               case OP__IMPORT_VC_FROM:
+                       ok = import_vc_from(filename, block, &operation->argument.import_vc_from, needs_write, raw);
+                       break;
                default:
                        ok = false;
                        FLAC__ASSERT(0);
                default:
                        ok = false;
                        FLAC__ASSERT(0);
@@ -1754,6 +1792,63 @@ FLAC__bool set_vc_field(const char *filename, FLAC__StreamMetadata *block, const
        }
 }
 
        }
 }
 
+FLAC__bool import_vc_from(const char *filename, FLAC__StreamMetadata *block, const Argument_VcImportFile *file, FLAC__bool *needs_write, FLAC__bool raw)
+{
+       FILE *f;
+       char line[65536];
+       FLAC__bool ret;
+
+       if(0 == file->file_name || strlen(file->file_name) == 0) {
+               fprintf(stderr, "%s: ERROR: empty import file name\n", filename);
+               return false;
+       }
+       if(0 == strcmp(file->file_name, "-"))
+               f = stdin;
+       else
+               f = fopen(file->file_name, "r");
+
+       if(0 == f) {
+               fprintf(stderr, "%s: ERROR: can't open import file %s\n", filename, file->file_name);
+               return false;
+       }
+
+       ret = true;
+       while(ret && !feof(f)) {
+               fgets(line, sizeof(line), f);
+               if(!feof(f)) {
+                       char *p = strchr(line, '\n');
+                       if(0 == p) {
+                               fprintf(stderr, "%s: ERROR: line too long, aborting\n", file->file_name);
+                               ret = false;
+                       }
+                       else {
+                               const char *violation;
+                               Argument_VcField field;
+                               *p = '\0';
+                               memset(&field, 0, sizeof(Argument_VcField));
+                               if(!parse_vorbis_comment_field(line, &field.field, &field.field_name, &field.field_value, &field.field_value_length, &violation)) {
+                                       FLAC__ASSERT(0 != violation);
+                                       fprintf(stderr, "%s: ERROR: malformed vorbis comment field \"%s\",\n       %s\n", file->file_name, line, violation);
+                                       ret = false;
+                               }
+                               else {
+                                       ret = set_vc_field(filename, block, &field, needs_write, raw);
+                               }
+                               if(0 != field.field)
+                                       free(field.field);
+                               if(0 != field.field_name)
+                                       free(field.field_name);
+                               if(0 != field.field_value)
+                                       free(field.field_value);
+                       }
+               }
+       };
+
+       if(f != stdin)
+               fclose(f);
+       return ret;
+}
+
 FLAC__bool field_name_matches_entry(const char *field_name, unsigned field_name_length, const FLAC__StreamMetadata_VorbisComment_Entry *entry)
 {
        const FLAC__byte *eq = memchr(entry->entry, '=', entry->length);
 FLAC__bool field_name_matches_entry(const char *field_name, unsigned field_name_length, const FLAC__StreamMetadata_VorbisComment_Entry *entry)
 {
        const FLAC__byte *eq = memchr(entry->entry, '=', entry->length);
index cb89107..2d32ed2 100755 (executable)
@@ -231,4 +231,22 @@ check_flac
 (set -x && metaflac --list --except-block-type=STREAMINFO $flacfile)
 check_exit
 
 (set -x && metaflac --list --except-block-type=STREAMINFO $flacfile)
 check_exit
 
+(set -x && echo "TITLE=Tittle" | metaflac --import-vc-from=- $flacfile)
+check_exit
+check_flac
+(set -x && metaflac --list --block-type=VORBIS_COMMENT $flacfile)
+check_exit
+
+cat > vc.txt << EOF
+artist=Fartist
+artist=artits
+EOF
+(set -x && metaflac --import-vc-from=vc.txt $flacfile)
+check_exit
+check_flac
+(set -x && metaflac --list --block-type=VORBIS_COMMENT $flacfile)
+check_exit
+
+rm vc.txt
+
 exit 0
 exit 0