📄 metadata_manip.c
字号:
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; /* initialize 'data' to avoid Valgrind errors */ memset(data, 0, sizeof(data)); printf("\n\n++++++ testing level 1 interface\n"); /************************************************************/ printf("simple iterator on read-only file\n"); if(!generate_file_()) return false; if(!change_stats_(flacfile_, /*read_only=*/true))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -