Add --append option to metaflac
diff --git a/src/metaflac/operations.c b/src/metaflac/operations.c
index c8f5b37..e29311b 100644
--- a/src/metaflac/operations.c
+++ b/src/metaflac/operations.c
@@ -213,9 +213,71 @@
FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options)
{
- (void) chain, (void) options;
- flac_fprintf(stderr, "ERROR: --append not implemented yet\n");
- return false;
+ FLAC__byte header[FLAC__STREAM_METADATA_HEADER_LENGTH];
+ FLAC__byte *buffer;
+ FLAC__uint32 buffer_size, num_objects = 0, i, append_after = UINT32_MAX;
+ FLAC__StreamMetadata *object;
+ FLAC__Metadata_Iterator *iterator;
+
+ /* First, find out after which block appending should take place */
+ for(i = 0; i < options->args.num_arguments; i++) {
+ if(options->args.arguments[i].type == ARG__BLOCK_NUMBER) {
+ if(append_after != UINT32_MAX || options->args.arguments[i].value.block_number.num_entries > 1) {
+ flac_fprintf(stderr, "ERROR: more than one block number specified with --append\n");
+ return false;
+ }
+ append_after = options->args.arguments[i].value.block_number.entries[0];
+ }
+ }
+
+ iterator = FLAC__metadata_iterator_new();
+
+ if(0 == iterator)
+ die("out of memory allocating iterator");
+
+ FLAC__metadata_iterator_init(iterator, chain);
+
+ /* Go to requested block */
+ for(i = 0; i < append_after; i++) {
+ if(!FLAC__metadata_iterator_next(iterator))
+ break;
+ }
+
+ /* Read header from stdin */
+ while(fread(header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, stdin) == FLAC__STREAM_METADATA_HEADER_LENGTH) {
+
+ buffer_size = ((FLAC__uint32)(header[1]) << 16) + ((FLAC__uint32)(header[2]) << 8) + header[3];
+ buffer = safe_malloc_(buffer_size + FLAC__STREAM_METADATA_HEADER_LENGTH);
+ memcpy(buffer, header, FLAC__STREAM_METADATA_HEADER_LENGTH);
+
+ if(fread(buffer+FLAC__STREAM_METADATA_HEADER_LENGTH, 1, buffer_size, stdin) < buffer_size) {
+ flac_fprintf(stderr, "ERROR: couldn't read metadata block #%u from stdin\n",(num_objects+1));
+ free(buffer);
+ break;
+ }
+
+ if((object = FLAC__metadata_object_set_raw(buffer, buffer_size + FLAC__STREAM_METADATA_HEADER_LENGTH)) == NULL) {
+ flac_fprintf(stderr, "ERROR: couldn't parse supplied metadata block #%u\n",(num_objects+1));
+ free(buffer);
+ break;
+ }
+ free(buffer);
+
+ if(!FLAC__metadata_iterator_insert_block_after(iterator, object)) {
+ flac_fprintf(stderr, "ERROR: couldn't add supplied metadata block #%u to file\n",(num_objects+1));
+ FLAC__metadata_object_delete(object);
+ FLAC__metadata_iterator_delete(iterator);
+ break;
+ }
+ num_objects++;
+ }
+
+ if(num_objects == 0)
+ flac_fprintf(stderr, "ERROR: unable to find a metadata block in the supplied input\n");
+
+ FLAC__metadata_iterator_delete(iterator);
+
+ return true;
}
FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options)
diff --git a/src/metaflac/usage.c b/src/metaflac/usage.c
index f9fcf0a..603e328 100644
--- a/src/metaflac/usage.c
+++ b/src/metaflac/usage.c
@@ -280,18 +280,14 @@
fprintf(out, " You may specify --data-format=binary to dump the raw binary form of each\n");
fprintf(out, " metadata block. Specify --data-format=binary-headerless to omit output of\n");
fprintf(out, " metadata block headers, including the id of APPLICATION metadata blocks.\n");
-#if 0
- fprintf(out, " The output can be read in using a subsequent call\n");
- fprintf(out, " to \"metaflac --append --from-file=...\"\n");
-#endif
+ fprintf(out, " The output can be read in using a subsequent call to\n");
+ fprintf(out, " \"metaflac --append\"\n");
fprintf(out, "\n");
fprintf(out, " --application-data-format=hexdump|text\n");
fprintf(out, " If the application block you are displaying contains binary data but your\n");
fprintf(out, " --data-format=text, you can display a hex dump of the application data\n");
fprintf(out, " contents instead using --application-data-format=hexdump\n");
fprintf(out, "\n");
-#if 0
- /*@@@ not implemented yet */
fprintf(out, "--append\n");
fprintf(out, " Insert a metadata block from a file. The input file must be in the same\n");
fprintf(out, " format as generated with --list.\n");
@@ -302,6 +298,8 @@
fprintf(out, " of a block before the first STREAMINFO block. You may not --append another\n");
fprintf(out, " STREAMINFO block.\n");
fprintf(out, "\n");
+#if 0
+ /*@@@ not implemented yet */
fprintf(out, " --from-file=filename\n");
fprintf(out, " Mandatory 'option' to specify the input file containing the block contents.\n");
fprintf(out, "\n");