/* metaflac - Command-line FLAC metadata editor
- * Copyright (C) 2001,2002 Josh Coalson
+ * Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008 Josh Coalson
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include "operations.h"
#include "usage.h"
#include "utils.h"
#include "FLAC/assert.h"
#include "FLAC/metadata.h"
+#include "share/alloc.h"
#include "share/grabbag.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "operations_shorthand.h"
-static void show_version();
+static void show_version(void);
static FLAC__bool do_major_operation(const CommandLineOptions *options);
static FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOptions *options);
static FLAC__bool do_major_operation__list(const char *filename, FLAC__Metadata_Chain *chain, const CommandLineOptions *options);
/* from operations_shorthand_cuesheet.c */
extern FLAC__bool do_shorthand_operation__cuesheet(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write);
+/* from operations_shorthand_picture.c */
+extern FLAC__bool do_shorthand_operation__picture(const char *filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write);
+
FLAC__bool do_operations(const CommandLineOptions *options)
{
* local routines
*/
-void show_version()
+void show_version(void)
{
printf("metaflac %s\n", FLAC__VERSION_STRING);
}
unsigned i;
FLAC__bool ok = true;
- /*@@@ to die after first error, v--- add '&& ok' here */
+ /* to die after first error, v--- add '&& ok' here */
for(i = 0; i < options->num_files; i++)
ok &= do_major_operation_on_file(options->filenames[i], options);
FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOptions *options)
{
- FLAC__bool ok = true, needs_write = false;
+ FLAC__bool ok = true, needs_write = false, is_ogg = false;
FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
if(0 == chain)
die("out of memory allocating chain");
- if(!FLAC__metadata_chain_read(chain, filename)) {
- fprintf(stderr, "%s: ERROR: reading metadata, status = \"%s\"\n", filename, FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]);
+ /*@@@@ lame way of guessing the file type */
+ if(strlen(filename) >= 4 && (0 == strcmp(filename+strlen(filename)-4, ".oga") || 0 == strcmp(filename+strlen(filename)-4, ".ogg")))
+ is_ogg = true;
+
+ if(! (is_ogg? FLAC__metadata_chain_read_ogg(chain, filename) : FLAC__metadata_chain_read(chain, filename)) ) {
+ print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename);
+ FLAC__metadata_chain_delete(chain);
return false;
}
FLAC__metadata_chain_sort_padding(chain);
ok = FLAC__metadata_chain_write(chain, options->use_padding, options->preserve_modtime);
if(!ok)
- fprintf(stderr, "%s: ERROR: writing FLAC file, error = %s\n", filename, FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]);
+ print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename);
}
FLAC__metadata_chain_delete(chain);
FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options)
{
(void) chain, (void) options;
- fprintf(stderr, "ERROR: --append not implemented yet\n"); /*@@@*/
+ fprintf(stderr, "ERROR: --append not implemented yet\n");
return false;
}
die("out of memory allocating chain");
if(!FLAC__metadata_chain_read(chain, filename)) {
- fprintf(stderr, "%s: ERROR: reading metadata, status = \"%s\"\n", filename, FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]);
+ print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename);
return false;
}
FLAC__metadata_chain_sort_padding(chain);
ok = FLAC__metadata_chain_write(chain, use_padding, options->preserve_modtime);
if(!ok)
- fprintf(stderr, "%s: ERROR: writing FLAC file, error = %s\n", filename, FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]);
+ print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename);
}
FLAC__metadata_chain_delete(chain);
case OP__EXPORT_CUESHEET_TO:
ok = do_shorthand_operation__cuesheet(filename, chain, operation, needs_write);
break;
+ case OP__IMPORT_PICTURE_FROM:
+ case OP__EXPORT_PICTURE_TO:
+ ok = do_shorthand_operation__picture(filename, chain, operation, needs_write);
+ break;
case OP__ADD_SEEKPOINT:
ok = do_shorthand_operation__add_seekpoints(filename, chain, operation->argument.add_seekpoint.specification, needs_write);
break;
}
FLAC__ASSERT(bits_per_sample >= FLAC__MIN_BITS_PER_SAMPLE && bits_per_sample <= FLAC__MAX_BITS_PER_SAMPLE);
- if(!grabbag__replaygain_init(sample_rate))
+ if(!grabbag__replaygain_init(sample_rate)) {
FLAC__ASSERT(0);
+ /* double protection */
+ fprintf(stderr, "internal error\n");
+ return false;
+ }
if(
- 0 == (title_gains = (float*)malloc(sizeof(float) * num_files)) ||
- 0 == (title_peaks = (float*)malloc(sizeof(float) * num_files))
+ 0 == (title_gains = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files)) ||
+ 0 == (title_peaks = (float*)safe_malloc_mul_2op_(sizeof(float), /*times*/num_files))
)
die("out of memory allocating space for title gains/peaks");
padding->length = length;
if(!FLAC__metadata_iterator_insert_block_after(iterator, padding)) {
- fprintf(stderr, "%s: ERROR: adding new PADDING block to metadata, status =\"%s\"\n", filename, FLAC__Metadata_ChainStatusString[FLAC__metadata_chain_status(chain)]);
+ print_error_with_chain_status(chain, "%s: ERROR: adding new PADDING block to metadata", filename);
FLAC__metadata_object_delete(padding);
FLAC__metadata_iterator_delete(iterator);
return false;
switch(block->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
- PPR; printf(" minumum blocksize: %u samples\n", block->data.stream_info.min_blocksize);
+ PPR; printf(" minimum blocksize: %u samples\n", block->data.stream_info.min_blocksize);
PPR; printf(" maximum blocksize: %u samples\n", block->data.stream_info.max_blocksize);
PPR; printf(" minimum framesize: %u bytes\n", block->data.stream_info.min_framesize);
PPR; printf(" maximum framesize: %u bytes\n", block->data.stream_info.max_framesize);
PPR; printf(" sample_rate: %u Hz\n", block->data.stream_info.sample_rate);
PPR; printf(" channels: %u\n", block->data.stream_info.channels);
PPR; printf(" bits-per-sample: %u\n", block->data.stream_info.bits_per_sample);
- PPR; printf(" total samples: %llu\n", block->data.stream_info.total_samples);
+#ifdef _MSC_VER
+ PPR; printf(" total samples: %I64u\n", block->data.stream_info.total_samples);
+#else
+ PPR; printf(" total samples: %llu\n", (unsigned long long)block->data.stream_info.total_samples);
+#endif
PPR; printf(" MD5 signature: ");
for(i = 0; i < 16; i++) {
printf("%02x", (unsigned)block->data.stream_info.md5sum[i]);
break;
case FLAC__METADATA_TYPE_APPLICATION:
PPR; printf(" application ID: ");
- for(i = 0; i < 4; i++) {
- PPR; printf("%02x", block->data.application.id[i]);
- }
- PPR; printf("\n");
+ for(i = 0; i < 4; i++)
+ printf("%02x", block->data.application.id[i]);
+ printf("\n");
PPR; printf(" data contents:\n");
if(0 != block->data.application.data) {
if(hexdump_application)
hexdump(filename, block->data.application.data, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, " ");
else
- (void) fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout);
+ (void) local_fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout);
}
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
PPR; printf(" seek points: %u\n", block->data.seek_table.num_points);
for(i = 0; i < block->data.seek_table.num_points; i++) {
if(block->data.seek_table.points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
- PPR; printf(" point %d: sample_number=%llu, stream_offset=%llu, frame_samples=%u\n", i, block->data.seek_table.points[i].sample_number, block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples);
+#ifdef _MSC_VER
+ PPR; printf(" point %u: sample_number=%I64u, stream_offset=%I64u, frame_samples=%u\n", i, block->data.seek_table.points[i].sample_number, block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples);
+#else
+ PPR; printf(" point %u: sample_number=%llu, stream_offset=%llu, frame_samples=%u\n", i, (unsigned long long)block->data.seek_table.points[i].sample_number, (unsigned long long)block->data.seek_table.points[i].stream_offset, block->data.seek_table.points[i].frame_samples);
+#endif
}
else {
- PPR; printf(" point %d: PLACEHOLDER\n", i);
+ PPR; printf(" point %u: PLACEHOLDER\n", i);
}
}
break;
break;
case FLAC__METADATA_TYPE_CUESHEET:
PPR; printf(" media catalog number: %s\n", block->data.cue_sheet.media_catalog_number);
- PPR; printf(" lead-in: %llu\n", block->data.cue_sheet.lead_in);
+#ifdef _MSC_VER
+ PPR; printf(" lead-in: %I64u\n", block->data.cue_sheet.lead_in);
+#else
+ PPR; printf(" lead-in: %llu\n", (unsigned long long)block->data.cue_sheet.lead_in);
+#endif
PPR; printf(" is CD: %s\n", block->data.cue_sheet.is_cd? "true":"false");
PPR; printf(" number of tracks: %u\n", block->data.cue_sheet.num_tracks);
for(i = 0; i < block->data.cue_sheet.num_tracks; i++) {
const FLAC__bool is_last = (i == block->data.cue_sheet.num_tracks-1);
const FLAC__bool is_leadout = is_last && track->num_indices == 0;
PPR; printf(" track[%u]\n", i);
- PPR; printf(" offset: %llu\n", track->offset);
+#ifdef _MSC_VER
+ PPR; printf(" offset: %I64u\n", track->offset);
+#else
+ PPR; printf(" offset: %llu\n", (unsigned long long)track->offset);
+#endif
if(is_last) {
PPR; printf(" number: %u (%s)\n", (unsigned)track->number, is_leadout? "LEAD-OUT" : "INVALID");
}
for(j = 0; j < track->num_indices; j++) {
const FLAC__StreamMetadata_CueSheet_Index *index = track->indices+j;
PPR; printf(" index[%u]\n", j);
- PPR; printf(" offset: %llu\n", index->offset);
+#ifdef _MSC_VER
+ PPR; printf(" offset: %I64u\n", index->offset);
+#else
+ PPR; printf(" offset: %llu\n", (unsigned long long)index->offset);
+#endif
PPR; printf(" number: %u\n", (unsigned)index->number);
}
}
}
break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ PPR; printf(" type: %u (%s)\n", block->data.picture.type, block->data.picture.type < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED? FLAC__StreamMetadata_Picture_TypeString[block->data.picture.type] : "UNDEFINED");
+ PPR; printf(" MIME type: %s\n", block->data.picture.mime_type);
+ PPR; printf(" description: %s\n", block->data.picture.description);
+ PPR; printf(" width: %u\n", (unsigned)block->data.picture.width);
+ PPR; printf(" height: %u\n", (unsigned)block->data.picture.height);
+ PPR; printf(" depth: %u\n", (unsigned)block->data.picture.depth);
+ PPR; printf(" colors: %u%s\n", (unsigned)block->data.picture.colors, block->data.picture.colors? "" : " (unindexed)");
+ PPR; printf(" data length: %u\n", (unsigned)block->data.picture.data_length);
+ PPR; printf(" data:\n");
+ if(0 != block->data.picture.data)
+ hexdump(filename, block->data.picture.data, block->data.picture.data_length, " ");
+ break;
default:
- PPR; printf("SKIPPING block of unknown type\n");
+ PPR; printf(" data contents:\n");
+ if(0 != block->data.unknown.data)
+ hexdump(filename, block->data.unknown.data, block->length, " ");
break;
}
#undef PPR