📄 operations.c
字号:
/* metaflac - Command-line FLAC metadata editor * Copyright (C) 2001,2002,2003,2004,2005 Josh Coalson * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "operations.h"#include "usage.h"#include "utils.h"#include "FLAC/assert.h"#include "FLAC/metadata.h"#include "share/grabbag.h"#include <stdio.h>#include <stdlib.h>#include <string.h>static void show_version();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);static FLAC__bool do_major_operation__append(FLAC__Metadata_Chain *chain, const CommandLineOptions *options);static FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options);static FLAC__bool do_major_operation__remove_all(FLAC__Metadata_Chain *chain, const CommandLineOptions *options);static FLAC__bool do_shorthand_operations(const CommandLineOptions *options);static FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLineOptions *options);static FLAC__bool do_shorthand_operation(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool utf8_convert);static FLAC__bool do_shorthand_operation__add_replay_gain(char **filenames, unsigned num_files, FLAC__bool preserve_modtime);static FLAC__bool do_shorthand_operation__add_padding(const char *filename, FLAC__Metadata_Chain *chain, unsigned length, 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 raw, FLAC__bool hexdump_application);/* from operations_shorthand_seektable.c */extern FLAC__bool do_shorthand_operation__add_seekpoints(const char *filename, FLAC__Metadata_Chain *chain, const char *specification, FLAC__bool *needs_write);/* from operations_shorthand_streaminfo.c */extern FLAC__bool do_shorthand_operation__streaminfo(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write);/* from operations_shorthand_vorbiscomment.c */extern FLAC__bool do_shorthand_operation__vorbis_comment(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool raw);/* 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);FLAC__bool do_operations(const CommandLineOptions *options){ FLAC__bool ok = true; if(options->show_long_help) { long_usage(0); } if(options->show_version) { show_version(); } else if(options->args.checks.num_major_ops > 0) { FLAC__ASSERT(options->args.checks.num_shorthand_ops == 0); FLAC__ASSERT(options->args.checks.num_major_ops == 1); FLAC__ASSERT(options->args.checks.num_major_ops == options->ops.num_operations); ok = do_major_operation(options); } else if(options->args.checks.num_shorthand_ops > 0) { FLAC__ASSERT(options->args.checks.num_shorthand_ops == options->ops.num_operations); ok = do_shorthand_operations(options); } return ok;}/* * local routines */void show_version(){ printf("metaflac %s\n", FLAC__VERSION_STRING);}FLAC__bool do_major_operation(const CommandLineOptions *options){ unsigned i; FLAC__bool ok = true; /*@@@ 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); return ok;}FLAC__bool do_major_operation_on_file(const char *filename, const CommandLineOptions *options){ FLAC__bool ok = true, needs_write = 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)) { print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename); FLAC__metadata_chain_delete(chain); return false; } switch(options->ops.operations[0].type) { case OP__LIST: ok = do_major_operation__list(options->prefix_with_filename? filename : 0, chain, options); break; case OP__APPEND: ok = do_major_operation__append(chain, options); needs_write = true; break; case OP__REMOVE: ok = do_major_operation__remove(chain, options); needs_write = true; break; case OP__REMOVE_ALL: ok = do_major_operation__remove_all(chain, options); needs_write = true; break; case OP__MERGE_PADDING: FLAC__metadata_chain_merge_padding(chain); needs_write = true; break; case OP__SORT_PADDING: FLAC__metadata_chain_sort_padding(chain); needs_write = true; break; default: FLAC__ASSERT(0); return false; } if(ok && needs_write) { if(options->use_padding) FLAC__metadata_chain_sort_padding(chain); ok = FLAC__metadata_chain_write(chain, options->use_padding, options->preserve_modtime); if(!ok) print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename); } FLAC__metadata_chain_delete(chain); return ok;}FLAC__bool do_major_operation__list(const char *filename, FLAC__Metadata_Chain *chain, const CommandLineOptions *options){ FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); FLAC__StreamMetadata *block; FLAC__bool ok = true; unsigned block_number; if(0 == iterator) die("out of memory allocating iterator"); FLAC__metadata_iterator_init(iterator, chain); block_number = 0; do { block = FLAC__metadata_iterator_get_block(iterator); ok &= (0 != block); if(!ok) fprintf(stderr, "%s: ERROR: couldn't get block from chain\n", filename); else if(passes_filter(options, FLAC__metadata_iterator_get_block(iterator), block_number)) write_metadata(filename, block, block_number, !options->utf8_convert, options->application_data_format_is_hexdump); block_number++; } while(ok && FLAC__metadata_iterator_next(iterator)); FLAC__metadata_iterator_delete(iterator); return ok;}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;}FLAC__bool do_major_operation__remove(FLAC__Metadata_Chain *chain, const CommandLineOptions *options){ FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); FLAC__bool ok = true; unsigned block_number; if(0 == iterator) die("out of memory allocating iterator"); FLAC__metadata_iterator_init(iterator, chain); block_number = 0; while(ok && FLAC__metadata_iterator_next(iterator)) { block_number++; if(passes_filter(options, FLAC__metadata_iterator_get_block(iterator), block_number)) { ok &= FLAC__metadata_iterator_delete_block(iterator, options->use_padding); if(options->use_padding) ok &= FLAC__metadata_iterator_next(iterator); } } FLAC__metadata_iterator_delete(iterator); return ok;}FLAC__bool do_major_operation__remove_all(FLAC__Metadata_Chain *chain, const CommandLineOptions *options){ FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new(); FLAC__bool ok = true; if(0 == iterator) die("out of memory allocating iterator"); FLAC__metadata_iterator_init(iterator, chain); while(ok && FLAC__metadata_iterator_next(iterator)) { ok &= FLAC__metadata_iterator_delete_block(iterator, options->use_padding); if(options->use_padding) ok &= FLAC__metadata_iterator_next(iterator); } FLAC__metadata_iterator_delete(iterator); return ok;}FLAC__bool do_shorthand_operations(const CommandLineOptions *options){ unsigned i; FLAC__bool ok = true; /* to die after first error, v--- add '&& ok' here */ for(i = 0; i < options->num_files; i++) ok &= do_shorthand_operations_on_file(options->filenames[i], options); /* check if OP__ADD_REPLAY_GAIN requested */ if(ok && options->num_files > 0) { for(i = 0; i < options->ops.num_operations; i++) { if(options->ops.operations[i].type == OP__ADD_REPLAY_GAIN) ok = do_shorthand_operation__add_replay_gain(options->filenames, options->num_files, options->preserve_modtime); } } return ok;}FLAC__bool do_shorthand_operations_on_file(const char *filename, const CommandLineOptions *options){ unsigned i; FLAC__bool ok = true, needs_write = false, use_padding = options->use_padding; FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); if(0 == chain) die("out of memory allocating chain"); if(!FLAC__metadata_chain_read(chain, filename)) { print_error_with_chain_status(chain, "%s: ERROR: reading metadata", filename); return false; } for(i = 0; i < options->ops.num_operations && ok; i++) { /* * Do OP__ADD_SEEKPOINT last to avoid decoding twice if both * --add-seekpoint and --import-cuesheet-from are used. */ if(options->ops.operations[i].type != OP__ADD_SEEKPOINT) ok &= do_shorthand_operation(filename, options->prefix_with_filename, chain, &options->ops.operations[i], &needs_write, options->utf8_convert); /* The following seems counterintuitive but the meaning * of 'use_padding' is 'try to keep the overall metadata * to its original size, adding or truncating extra * padding if necessary' which is why we need to turn it * off in this case. If we don't, the extra padding block * will just be truncated. */ if(options->ops.operations[i].type == OP__ADD_PADDING) use_padding = false; } /* * Do OP__ADD_SEEKPOINT last to avoid decoding twice if both * --add-seekpoint and --import-cuesheet-from are used. */ for(i = 0; i < options->ops.num_operations && ok; i++) { if(options->ops.operations[i].type == OP__ADD_SEEKPOINT) ok &= do_shorthand_operation(filename, options->prefix_with_filename, chain, &options->ops.operations[i], &needs_write, options->utf8_convert); } if(ok && needs_write) { if(use_padding) FLAC__metadata_chain_sort_padding(chain); ok = FLAC__metadata_chain_write(chain, use_padding, options->preserve_modtime); if(!ok) print_error_with_chain_status(chain, "%s: ERROR: writing FLAC file", filename); } FLAC__metadata_chain_delete(chain); return ok;}FLAC__bool do_shorthand_operation(const char *filename, FLAC__bool prefix_with_filename, FLAC__Metadata_Chain *chain, const Operation *operation, FLAC__bool *needs_write, FLAC__bool utf8_convert){ FLAC__bool ok = true; switch(operation->type) { case OP__SHOW_MD5SUM: case OP__SHOW_MIN_BLOCKSIZE: case OP__SHOW_MAX_BLOCKSIZE: case OP__SHOW_MIN_FRAMESIZE: case OP__SHOW_MAX_FRAMESIZE: case OP__SHOW_SAMPLE_RATE: case OP__SHOW_CHANNELS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -