fill out more of the shorthand options

This commit is contained in:
Josh Coalson
2002-05-29 06:02:05 +00:00
parent 9fa89294b9
commit 786ddb8907

View File

@@ -65,6 +65,7 @@ static struct option long_options_[] = {
{ "remove-vc-field", 1, 0, 0 },
{ "remove-vc-firstfield", 1, 0, 0 },
{ "set-vc-field", 1, 0, 0 },
{ "add-padding", 1, 0, 0 },
/* major operations */
{ "help", 0, 0, 0 },
{ "list", 0, 0, 0 },
@@ -99,6 +100,7 @@ typedef enum {
OP__REMOVE_VC_FIELD,
OP__REMOVE_VC_FIRSTFIELD,
OP__SET_VC_FIELD,
OP__ADD_PADDING,
OP__LIST,
OP__APPEND,
OP__REMOVE,
@@ -150,6 +152,10 @@ typedef struct {
char *file_name;
} Argument_FromFile;
typedef struct {
unsigned length;
} Argument_AddPadding;
typedef struct {
OperationType type;
union {
@@ -157,6 +163,7 @@ typedef struct {
Argument_VcFieldName remove_vc_field;
Argument_VcFieldName remove_vc_firstfield;
Argument_VcField set_vc_field;
Argument_AddPadding add_padding;
} argument;
} Operation;
@@ -210,6 +217,7 @@ 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_vorbis_comment_field(const char *field, char **name, char **value, unsigned *length);
static FLAC__bool parse_add_padding(const char *in, unsigned *out);
static FLAC__bool parse_block_number(const char *in, Argument_BlockNumber *out);
static FLAC__bool parse_block_type(const char *in, Argument_BlockType *out);
static FLAC__bool parse_data_format(const char *in, Argument_DataFormat *out);
@@ -224,10 +232,17 @@ static FLAC__bool do_major_operation__remove_all(FLAC__MetaData_Chain *chain, co
static FLAC__bool do_shorthand_operations(const CommandLineOptions *options);
static FLAC__bool do_shorthand_operations_on_file(const char *fielname, const CommandLineOptions *options);
static FLAC__bool do_shorthand_operation(const char *filename, FLAC__MetaData_Chain *chain, const Operation *operation, FLAC__bool *needs_write);
static FLAC__bool do_shorthand_operation__add_padding(FLAC__MetaData_Chain *chain, unsigned length, FLAC__bool *needs_write);
static FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__MetaData_Chain *chain, OperationType op);
static FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__MetaData_Chain *chain, OperationType op, FLAC__bool *needs_write);
static FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__MetaData_Chain *chain, const Operation *operation, FLAC__bool *needs_write);
static FLAC__bool passes_filter(const CommandLineOptions *options, const FLAC__StreamMetaData *block, unsigned block_number);
static void write_metadata(const char *filename, FLAC__StreamMetaData *block, unsigned block_number, FLAC__bool hexdump_application);
static void write_vc_field(const char *filename, const FLAC__StreamMetaData_VorbisComment_Entry *entry);
static void write_vc_fields(const char *filename, const char *field_name, const FLAC__StreamMetaData_VorbisComment_Entry entry[], unsigned num_entries);
static FLAC__bool remove_vc_all(FLAC__StreamMetaData *block, FLAC__bool *needs_write);
static FLAC__bool remove_vc_field(FLAC__StreamMetaData *block, const char *field_name, FLAC__bool *needs_write);
static FLAC__bool remove_vc_firstfield(FLAC__StreamMetaData *block, const char *field_name, FLAC__bool *needs_write);
static FLAC__bool set_vc_field(FLAC__StreamMetaData *block, const Argument_VcField *field, FLAC__bool *needs_write);
static void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent);
int main(int argc, char *argv[])
@@ -418,6 +433,14 @@ FLAC__bool parse_option(int option_index, const char *option_argument, CommandLi
ok = false;
}
}
else if(0 == strcmp(opt, "add-padding")) {
op = append_shorthand_operation(options, OP__ADD_PADDING);
FLAC__ASSERT(0 != option_argument);
if(!parse_add_padding(option_argument, &(op->argument.add_padding.length))) {
fprintf(stderr, "ERROR: illegal length \"%s\", length must be >= 0 and < 2^%u\n", option_argument, FLAC__STREAM_METADATA_LENGTH_LEN);
ok = false;
}
}
else if(0 == strcmp(opt, "help")) {
options->show_long_help = true;
}
@@ -723,6 +746,9 @@ 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, "--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, "\n");
fprintf(out, "Major operations:\n");
fprintf(out, "--list\n");
@@ -839,6 +865,12 @@ FLAC__bool parse_vorbis_comment_field(const char *field, char **name, char **val
return true;
}
FLAC__bool parse_add_padding(const char *in, unsigned *out)
{
*out = (unsigned)strtoul(in, 0, 10);
return *out < (1u << FLAC__STREAM_METADATA_LENGTH_LEN);
}
FLAC__bool parse_block_number(const char *in, Argument_BlockNumber *out)
{
char *p, *q, *s, *end;
@@ -1097,6 +1129,7 @@ FLAC__bool do_major_operation__list(const char *filename, FLAC__MetaData_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"); /*@@@*/
return false;
}
@@ -1186,7 +1219,6 @@ FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLi
FLAC__bool do_shorthand_operation(const char *filename, FLAC__MetaData_Chain *chain, const Operation *operation, FLAC__bool *needs_write)
{
unsigned i;
FLAC__bool ok = true;
switch(operation->type) {
@@ -1207,7 +1239,10 @@ 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:
ok = do_shorthand_operation__vorbis_comment(filename, chain, operation->type, needs_write);
ok = do_shorthand_operation__vorbis_comment(filename, chain, operation, needs_write);
break;
case OP__ADD_PADDING:
ok = do_shorthand_operation__add_padding(chain, operation->argument.add_padding.length, needs_write);
break;
default:
ok = false;
@@ -1218,6 +1253,35 @@ FLAC__bool do_shorthand_operation(const char *filename, FLAC__MetaData_Chain *ch
return ok;
}
FLAC__bool do_shorthand_operation__add_padding(FLAC__MetaData_Chain *chain, unsigned length, FLAC__bool *needs_write)
{
FLAC__StreamMetaData *padding = 0;
FLAC__MetaData_Iterator *iterator = FLAC__metadata_iterator_new();
if(0 == iterator)
die("out of memory allocating iterator");
FLAC__metadata_iterator_init(iterator, chain);
while(FLAC__metadata_iterator_next(iterator))
;
padding = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
if(0 == padding)
die("out of memory allocating PADDING block");
padding->length = length;
if(!FLAC__metadata_iterator_insert_block_after(iterator, padding)) {
fprintf(stderr, "ERROR: adding new PADDING block to metadata, status =\"%s\"\n", FLAC__MetaData_ChainStatusString[FLAC__metadata_chain_status(chain)]);
FLAC__metadata_object_delete(padding);
return false;
}
*needs_write = true;
return true;
}
FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__MetaData_Chain *chain, OperationType op)
{
unsigned i;
@@ -1279,7 +1343,7 @@ FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__MetaDa
return ok;
}
FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__MetaData_Chain *chain, OperationType op, FLAC__bool *needs_write)
FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__MetaData_Chain *chain, const Operation *operation, FLAC__bool *needs_write)
{
FLAC__bool ok = true, found_vc_block = false;
FLAC__StreamMetaData *block = 0;
@@ -1297,14 +1361,14 @@ FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__Me
} while(!found_vc_block && FLAC__metadata_iterator_next(iterator));
/* create a new block if necessary */
if(!found_vc_block && op == OP__SET_VC_FIELD) {
if(!found_vc_block && operation->type == OP__SET_VC_FIELD) {
block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
if(0 == block)
die("out of memory allocating VORBIS_COMMENT block");
while(FLAC__metadata_iterator_next(iterator))
;
if(!FLAC__metadata_iterator_insert_block_after(iterator, block)) {
fprintf(stderr, "ERROR: adding new VORBIS_COMMENT block to metadata\n");
fprintf(stderr, "ERROR: adding new VORBIS_COMMENT block to metadata, status =\"%s\"\n", FLAC__MetaData_ChainStatusString[FLAC__metadata_chain_status(chain)]);
return false;
}
/* iterator is left pointing to new block */
@@ -1314,14 +1378,25 @@ FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__Me
FLAC__ASSERT(0 != block);
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
/*@@@@ set needs_write = true where necessary */
switch(op) {
switch(operation->type) {
case OP__SHOW_VC_VENDOR:
write_vc_field(filename, &block->data.vorbis_comment.vendor_string);
break;
case OP__SHOW_VC_FIELD:
write_vc_fields(filename, operation->argument.show_vc_field.field_name, block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments);
break;
case OP__REMOVE_VC_ALL:
ok = remove_vc_all(block, needs_write);
break;
case OP__REMOVE_VC_FIELD:
ok = remove_vc_field(block, operation->argument.remove_vc_field.field_name, needs_write);
break;
case OP__REMOVE_VC_FIRSTFIELD:
ok = remove_vc_firstfield(block, operation->argument.remove_vc_firstfield.field_name, needs_write);
break;
case OP__SET_VC_FIELD:
ok = set_vc_field(block, &operation->argument.set_vc_field, needs_write);
break;
default:
ok = false;
FLAC__ASSERT(0);
@@ -1409,7 +1484,7 @@ void write_metadata(const char *filename, FLAC__StreamMetaData *block, unsigned
if(hexdump_application)
hexdump(filename, block->data.application.data, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, " ");
else
fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout);
(void) fwrite(block->data.application.data, 1, block->length - FLAC__STREAM_METADATA_HEADER_LENGTH, stdout);
}
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
@@ -1427,6 +1502,76 @@ void write_metadata(const char *filename, FLAC__StreamMetaData *block, unsigned
#undef PPR
}
void write_vc_field(const char *filename, const FLAC__StreamMetaData_VorbisComment_Entry *entry)
{
if(filename)
printf("%s:", filename);
(void) fwrite(entry->entry, 1, entry->length, stdout);
printf("\n");
}
void write_vc_fields(const char *filename, const char *field_name, const FLAC__StreamMetaData_VorbisComment_Entry entry[], unsigned num_entries)
{
unsigned i;
const unsigned field_name_length = strlen(field_name);
for(i = 0; i < num_entries; i++) {
if(0 != memchr(entry[i].entry, '=', entry[i].length) && 0 == strncmp(field_name, entry[i].entry, field_name_length))
write_vc_field(filename, entry + i);
}
}
FLAC__bool remove_vc_all(FLAC__StreamMetaData *block, FLAC__bool *needs_write)
{
FLAC__ASSERT(0 != block);
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__ASSERT(0 != needs_write);
if(0 != block->data.vorbis_comment.comments) {
FLAC__ASSERT(block->data.vorbis_comment.num_comments == 0);
if(!FLAC__metadata_object_vorbiscomment_entry_array_resize(&block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, 0))
return false;
*needs_write = true;
}
else {
FLAC__ASSERT(block->data.vorbis_comment.num_comments > 0);
}
return true;
}
FLAC__bool remove_vc_field(FLAC__StreamMetaData *block, const char *field_name, FLAC__bool *needs_write)
{
FLAC__bool ok = true;
FLAC__ASSERT(0 != needs_write);
return ok;
}
FLAC__bool remove_vc_firstfield(FLAC__StreamMetaData *block, const char *field_name, FLAC__bool *needs_write)
{
FLAC__bool ok = true;
FLAC__ASSERT(0 != needs_write);
return ok;
}
FLAC__bool set_vc_field(FLAC__StreamMetaData *block, const Argument_VcField *field, FLAC__bool *needs_write)
{
FLAC__ASSERT(0 != block);
FLAC__ASSERT(block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT);
FLAC__ASSERT(0 != field);
FLAC__ASSERT(0 != needs_write);
if(!FLAC__metadata_object_vorbiscomment_entry_array_resize(&block->data.vorbis_comment.comments, block->data.vorbis_comment.num_comments, block->data.vorbis_comment.num_comments + 1))
return false;
block->data.vorbis_comment.num_comments++;
*needs_write = true;
return true;
}
void hexdump(const char *filename, const FLAC__byte *buf, unsigned bytes, const char *indent)
{
unsigned i, left = bytes;