📄 metadata_manip.c
字号:
return true;
}
static FLAC__bool read_chain_(FLAC__Metadata_Chain *chain, const char *filename, FLAC__bool filename_based)
{
if(filename_based)
return FLAC__metadata_chain_read(chain, flacfile_);
else {
FLAC__IOCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.read = (FLAC__IOCallback_Read)fread;
callbacks.seek = chain_seek_cb_;
callbacks.tell = chain_tell_cb_;
{
FLAC__bool ret;
FILE *file = fopen(filename, "rb");
if(0 == file)
return false; /*@@@ chain status still says OK though */
ret = FLAC__metadata_chain_read_with_callbacks(chain, (FLAC__IOHandle)file, callbacks);
fclose(file);
return ret;
}
}
}
/* function for comparing our metadata to a FLAC__Metadata_Chain */
static FLAC__bool compare_chain_(FLAC__Metadata_Chain *chain, unsigned current_position, FLAC__StreamMetadata *current_block)
{
unsigned i;
FLAC__Metadata_Iterator *iterator;
FLAC__StreamMetadata *block;
FLAC__bool next_ok = true;
FLAC__ASSERT(0 != chain);
printf("\tcomparing chain... ");
fflush(stdout);
if(0 == (iterator = FLAC__metadata_iterator_new()))
return die_("allocating memory for iterator");
FLAC__metadata_iterator_init(iterator, chain);
i = 0;
do {
printf("%u... ", i);
fflush(stdout);
if(0 == (block = FLAC__metadata_iterator_get_block(iterator))) {
FLAC__metadata_iterator_delete(iterator);
return die_("getting block from iterator");
}
if(!mutils__compare_block(our_metadata_.blocks[i], block)) {
FLAC__metadata_iterator_delete(iterator);
return die_("metadata block mismatch");
}
i++;
next_ok = FLAC__metadata_iterator_next(iterator);
} while(i < our_metadata_.num_blocks && next_ok);
FLAC__metadata_iterator_delete(iterator);
if(next_ok)
return die_("chain has more blocks than expected");
if(i < our_metadata_.num_blocks)
return die_("short block count in chain");
if(0 != current_block) {
printf("CURRENT_POSITION... ");
fflush(stdout);
if(!mutils__compare_block(our_metadata_.blocks[current_position], current_block))
return die_("metadata block mismatch");
}
printf("PASSED\n");
return true;
}
/* decoder callbacks for checking the file */
static FLAC__StreamDecoderWriteStatus decoder_write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
(void)decoder, (void)buffer, (void)client_data;
if(
(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER && frame->header.number.frame_number == 0) ||
(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER && frame->header.number.sample_number == 0)
) {
printf("content... ");
fflush(stdout);
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
/* this version pays no attention to the metadata */
static void decoder_metadata_callback_null_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
(void)decoder, (void)metadata, (void)client_data;
printf("%d... ", mc_our_block_number_);
fflush(stdout);
mc_our_block_number_++;
}
/* this version is used when we want to compare to our metadata copy */
static void decoder_metadata_callback_compare_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
decoder_client_struct *dcd = (decoder_client_struct*)client_data;
(void)decoder;
/* don't bother checking if we've already hit an error */
if(dcd->error_occurred)
return;
printf("%d... ", mc_our_block_number_);
fflush(stdout);
if(mc_our_block_number_ >= our_metadata_.num_blocks) {
(void)die_("got more metadata blocks than expected");
dcd->error_occurred = true;
}
else {
if(!mutils__compare_block(our_metadata_.blocks[mc_our_block_number_], metadata)) {
(void)die_("metadata block mismatch");
dcd->error_occurred = true;
}
}
mc_our_block_number_++;
}
static void decoder_error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
decoder_client_struct *dcd = (decoder_client_struct*)client_data;
(void)decoder;
dcd->error_occurred = true;
printf("ERROR: got error callback, status = %s (%u)\n", FLAC__StreamDecoderErrorStatusString[status], (unsigned)status);
}
static FLAC__bool generate_file_()
{
FLAC__StreamMetadata streaminfo, vorbiscomment, padding;
FLAC__StreamMetadata *metadata[1];
printf("generating FLAC file for test\n");
while(our_metadata_.num_blocks > 0)
delete_from_our_metadata_(0);
streaminfo.is_last = false;
streaminfo.type = FLAC__METADATA_TYPE_STREAMINFO;
streaminfo.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
streaminfo.data.stream_info.min_blocksize = 576;
streaminfo.data.stream_info.max_blocksize = 576;
streaminfo.data.stream_info.min_framesize = 0;
streaminfo.data.stream_info.max_framesize = 0;
streaminfo.data.stream_info.sample_rate = 44100;
streaminfo.data.stream_info.channels = 1;
streaminfo.data.stream_info.bits_per_sample = 8;
streaminfo.data.stream_info.total_samples = 0;
memset(streaminfo.data.stream_info.md5sum, 0, 16);
{
const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
vorbiscomment.is_last = false;
vorbiscomment.type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
vorbiscomment.length = (4 + vendor_string_length) + 4;
vorbiscomment.data.vorbis_comment.vendor_string.length = vendor_string_length;
vorbiscomment.data.vorbis_comment.vendor_string.entry = malloc_or_die_(vendor_string_length+1);
memcpy(vorbiscomment.data.vorbis_comment.vendor_string.entry, FLAC__VENDOR_STRING, vendor_string_length+1);
vorbiscomment.data.vorbis_comment.num_comments = 0;
vorbiscomment.data.vorbis_comment.comments = 0;
}
padding.is_last = true;
padding.type = FLAC__METADATA_TYPE_PADDING;
padding.length = 1234;
metadata[0] = &padding;
if(
!insert_to_our_metadata_(&streaminfo, 0, /*copy=*/true) ||
!insert_to_our_metadata_(&vorbiscomment, 1, /*copy=*/true) ||
!insert_to_our_metadata_(&padding, 2, /*copy=*/true)
)
return die_("priming our metadata");
if(!file_utils__generate_flacfile(flacfile_, 0, 512 * 1024, &streaminfo, metadata, 1))
return die_("creating the encoded file");
free(vorbiscomment.data.vorbis_comment.vendor_string.entry);
return true;
}
static FLAC__bool test_file_(const char *filename, FLAC__FileDecoderMetadataCallback metadata_callback)
{
FLAC__FileDecoder *decoder;
decoder_client_struct decoder_client_data;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != metadata_callback);
mc_our_block_number_ = 0;
decoder_client_data.error_occurred = false;
printf("\ttesting '%s'... ", filename);
fflush(stdout);
if(0 == (decoder = FLAC__file_decoder_new()))
return die_("couldn't allocate decoder instance");
FLAC__file_decoder_set_md5_checking(decoder, true);
FLAC__file_decoder_set_filename(decoder, filename);
FLAC__file_decoder_set_write_callback(decoder, decoder_write_callback_);
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
FLAC__file_decoder_set_error_callback(decoder, decoder_error_callback_);
FLAC__file_decoder_set_client_data(decoder, &decoder_client_data);
FLAC__file_decoder_set_metadata_respond_all(decoder);
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return die_("initializing decoder\n");
}
if(!FLAC__file_decoder_process_until_end_of_file(decoder)) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
return die_("decoding file\n");
}
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
if(decoder_client_data.error_occurred)
return false;
if(mc_our_block_number_ != our_metadata_.num_blocks)
return die_("short metadata block count");
printf("PASSED\n");
return true;
}
static FLAC__bool change_stats_(const char *filename, FLAC__bool read_only)
{
if(!grabbag__file_change_stats(filename, read_only))
return die_("during grabbag__file_change_stats()");
return true;
}
static FLAC__bool remove_file_(const char *filename)
{
while(our_metadata_.num_blocks > 0)
delete_from_our_metadata_(0);
if(!grabbag__file_remove_file(filename))
return die_("removing file");
return true;
}
static FLAC__bool test_level_0_()
{
FLAC__StreamMetadata streaminfo;
FLAC__StreamMetadata *tags = 0;
printf("\n\n++++++ testing level 0 interface\n");
if(!generate_file_())
return false;
if(!test_file_(flacfile_, decoder_metadata_callback_null_))
return false;
printf("testing FLAC__metadata_get_streaminfo()... ");
if(!FLAC__metadata_get_streaminfo(flacfile_, &streaminfo))
return die_("during FLAC__metadata_get_streaminfo()");
/* check to see if some basic data matches (c.f. generate_file_()) */
if(streaminfo.data.stream_info.channels != 1)
return die_("mismatch in streaminfo.data.stream_info.channels");
if(streaminfo.data.stream_info.bits_per_sample != 8)
return die_("mismatch in streaminfo.data.stream_info.bits_per_sample");
if(streaminfo.data.stream_info.sample_rate != 44100)
return die_("mismatch in streaminfo.data.stream_info.sample_rate");
if(streaminfo.data.stream_info.min_blocksize != 576)
return die_("mismatch in streaminfo.data.stream_info.min_blocksize");
if(streaminfo.data.stream_info.max_blocksize != 576)
return die_("mismatch in streaminfo.data.stream_info.max_blocksize");
printf("OK\n");
printf("testing FLAC__metadata_get_tags()... ");
if(!FLAC__metadata_get_tags(flacfile_, &tags))
return die_("during FLAC__metadata_get_tags()");
/* check to see if some basic data matches (c.f. generate_file_()) */
if(tags->data.vorbis_comment.num_comments != 0)
return die_("mismatch in tags->data.vorbis_comment.num_comments");
printf("OK\n");
FLAC__metadata_object_delete(tags);
if(!remove_file_(flacfile_))
return false;
return true;
}
static FLAC__bool test_level_1_()
{
FLAC__Metadata_SimpleIterator *iterator;
FLAC__StreamMetadata *block, *app, *padding;
FLAC__byte data[1000];
unsigned our_current_position = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -