⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 metadata_iterators.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* write the metadata */
	for(node = chain->head; node; node = node->next) {
		if(!write_metadata_block_header_cb_(temp_handle, temp_write_cb, node->data)) {
			chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
			return false;
		}
		if(!write_metadata_block_data_cb_(temp_handle, temp_write_cb, node->data)) {
			chain->status = FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR;
			return false;
		}
	}
	/*FLAC__ASSERT(fflush(), ftell() == chain->last_offset);*/

	/* copy the file postfix (everything after the metadata) */
	if(0 != seek_cb(handle, chain->last_offset, SEEK_SET)) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
		return false;
	}
	if(!copy_remaining_bytes_from_file_cb_(handle, read_cb, eof_cb, temp_handle, temp_write_cb, &status)) {
		chain->status = get_equivalent_status_(status);
		return false;
	}

	return true;
}

FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new()
{
	FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain));

	if(0 != chain)
		chain_init_(chain);

	return chain;
}

FLAC_API void FLAC__metadata_chain_delete(FLAC__Metadata_Chain *chain)
{
	FLAC__ASSERT(0 != chain);

	chain_clear_(chain);

	free(chain);
}

FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_Chain *chain)
{
	FLAC__Metadata_ChainStatus status;

	FLAC__ASSERT(0 != chain);

	status = chain->status;
	chain->status = FLAC__METADATA_CHAIN_STATUS_OK;
	return status;
}

FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename)
{
	FILE *file;
	FLAC__bool ret;

	FLAC__ASSERT(0 != chain);
	FLAC__ASSERT(0 != filename);

	chain_clear_(chain);

	if(0 == (chain->filename = _strdup(filename))) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR;
		return false;
	}

	if(0 == (file = fopen(filename, "rb"))) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
		return false;
	}

	/* chain_read_cb_() sets chain->status for us */
	ret = chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_);

	fclose(file);

	return ret;
}

FLAC_API FLAC__bool FLAC__metadata_chain_read_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
{
	FLAC__ASSERT(0 != chain);

	chain_clear_(chain);

	if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.tell) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
		return false;
	}

	/* rewind */
	if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
		return false;
	}

	if(!chain_read_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.tell))
		return false; /* chain->status is already set by chain_read_cb_ */

	return true;
}

FLAC_API FLAC__bool FLAC__metadata_chain_check_if_tempfile_needed(FLAC__Metadata_Chain *chain, FLAC__bool use_padding)
{
	/* This does all the same checks that are in chain_prepare_for_write_()
	 * but doesn't actually alter the chain.  Make sure to update the logic
	 * here if chain_prepare_for_write_() changes.
	 */
	const unsigned current_length = chain_calculate_length_(chain);

	FLAC__ASSERT(0 != chain);

	if(use_padding) {
		/* if the metadata shrank and the last block is padding, we just extend the last padding block */
		if(current_length < chain->initial_length && chain->tail->data->type == FLAC__METADATA_TYPE_PADDING)
			return false;
		/* if the metadata shrank more than 4 bytes then there's room to add another padding block */
		else if(current_length + FLAC__STREAM_METADATA_HEADER_LENGTH <= chain->initial_length)
			return false;
		/* if the metadata grew but the last block is padding, try cutting the padding to restore the original length so we don't have to rewrite the whole file */
		else if(current_length > chain->initial_length) {
			const unsigned delta = current_length - chain->initial_length;
			if(chain->tail->data->type == FLAC__METADATA_TYPE_PADDING) {
				/* if the delta is exactly the size of the last padding block, remove the padding block */
				if(chain->tail->data->length + FLAC__STREAM_METADATA_HEADER_LENGTH == delta)
					return false;
				/* if there is at least 'delta' bytes of padding, trim the padding down */
				else if(chain->tail->data->length >= delta)
					return false;
			}
		}
	}

	return (current_length != chain->initial_length);
}

FLAC_API FLAC__bool FLAC__metadata_chain_write(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__bool preserve_file_stats)
{
	const char *tempfile_path_prefix = 0;
	unsigned current_length;

	FLAC__ASSERT(0 != chain);

	if (0 == chain->filename) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
		return false;
	}

	current_length = chain_prepare_for_write_(chain, use_padding);

	/* a return value of 0 means there was an error; chain->status is already set */
	if (0 == current_length)
		return false;

	if(current_length == chain->initial_length) {
		if(!chain_rewrite_metadata_in_place_(chain))
			return false;
	}
	else {
		if(!chain_rewrite_file_(chain, tempfile_path_prefix))
			return false;

		/* recompute lengths and offsets */
		{
			const FLAC__Metadata_Node *node;
			chain->initial_length = current_length;
			chain->last_offset = chain->first_offset;
			for(node = chain->head; node; node = node->next)
				chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
		}
	}

	return true;
}

FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks)
{
	unsigned current_length;

	FLAC__ASSERT(0 != chain);

	if (0 != chain->filename) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
		return false;
	}

	if (0 == callbacks.write || 0 == callbacks.seek) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
		return false;
	}

	if (FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL;
		return false;
	}

	current_length = chain_prepare_for_write_(chain, use_padding);

	/* a return value of 0 means there was an error; chain->status is already set */
	if (0 == current_length)
		return false;

	FLAC__ASSERT(current_length == chain->initial_length);

	return chain_rewrite_metadata_in_place_cb_(chain, handle, callbacks.write, callbacks.seek);
}

FLAC_API FLAC__bool FLAC__metadata_chain_write_with_callbacks_and_tempfile(FLAC__Metadata_Chain *chain, FLAC__bool use_padding, FLAC__IOHandle handle, FLAC__IOCallbacks callbacks, FLAC__IOHandle temp_handle, FLAC__IOCallbacks temp_callbacks)
{
	unsigned current_length;

	FLAC__ASSERT(0 != chain);

	if (0 != chain->filename) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_READ_WRITE_MISMATCH;
		return false;
	}

	if (0 == callbacks.read || 0 == callbacks.seek || 0 == callbacks.eof) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
		return false;
	}
	if (0 == temp_callbacks.write) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_INVALID_CALLBACKS;
		return false;
	}

	if (!FLAC__metadata_chain_check_if_tempfile_needed(chain, use_padding)) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_WRONG_WRITE_CALL;
		return false;
	}

	current_length = chain_prepare_for_write_(chain, use_padding);

	/* a return value of 0 means there was an error; chain->status is already set */
	if (0 == current_length)
		return false;

	FLAC__ASSERT(current_length != chain->initial_length);

	/* rewind */
	if(0 != callbacks.seek(handle, 0, SEEK_SET)) {
		chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR;
		return false;
	}

	if(!chain_rewrite_file_cb_(chain, handle, callbacks.read, callbacks.seek, callbacks.eof, temp_handle, temp_callbacks.write))
		return false;

	/* recompute lengths and offsets */
	{
		const FLAC__Metadata_Node *node;
		chain->initial_length = current_length;
		chain->last_offset = chain->first_offset;
		for(node = chain->head; node; node = node->next)
			chain->last_offset += (FLAC__STREAM_METADATA_HEADER_LENGTH + node->data->length);
	}

	return true;
}

FLAC_API void FLAC__metadata_chain_merge_padding(FLAC__Metadata_Chain *chain)
{
	FLAC__Metadata_Node *node;

	FLAC__ASSERT(0 != chain);

	for(node = chain->head; node; ) {
		if(!chain_merge_adjacent_padding_(chain, node))
			node = node->next;
	}
}

FLAC_API void FLAC__metadata_chain_sort_padding(FLAC__Metadata_Chain *chain)
{
	FLAC__Metadata_Node *node, *save;
	unsigned i;

	FLAC__ASSERT(0 != chain);

	/*
	 * Don't try and be too smart... this simple algo is good enough for
	 * the small number of nodes that we deal with.
	 */
	for(i = 0, node = chain->head; i < chain->nodes; i++) {
		if(node->data->type == FLAC__METADATA_TYPE_PADDING) {
			save = node->next;
			chain_remove_node_(chain, node);
			chain_append_node_(chain, node);
			node = save;
		}
		else {
			node = node->next;
		}
	}

	FLAC__metadata_chain_merge_padding(chain);
}


FLAC_API FLAC__Metadata_Iterator *FLAC__metadata_iterator_new()
{
	FLAC__Metadata_Iterator *iterator = (FLAC__Metadata_Iterator*)calloc(1, sizeof(FLAC__Metadata_Iterator));

	/* calloc() implies:
		iterator->current = 0;
		iterator->chain = 0;
	*/

	return iterator;
}

FLAC_API void FLAC__metadata_iterator_delete(FLAC__Metadata_Iterator *iterator)
{
	FLAC__ASSERT(0 != iterator);

	free(iterator);
}

FLAC_API void FLAC__metadata_iterator_init(FLAC__Metadata_Iterator *iterator, FLAC__Metadata_Chain *chain)
{
	FLAC__ASSERT(0 != iterator);
	FLAC__ASSERT(0 != chain);
	FLAC__ASSERT(0 != chain->head);

	iterator->chain = chain;
	iterator->current = chain->head;
}

FLAC_API FLAC__bool FLAC__metadata_iterator_next(FLAC__Metadata_Iterator *iterator)
{
	FLAC__ASSERT(0 != iterator);

	if(0 == iterator->current || 0 == iterator->current->next)
		return false;

	iterator->current = iterator->current->next;
	return true;
}

FLAC_API FLAC__bool FLAC__metadata_iterator_prev(FLAC__Metadata_Iterator *iterator)
{
	FLAC__ASSERT(0 != iterator);

	if(0 == iterator->current || 0 == iterator->current->prev)
		return false;

	iterator->current = iterator->current->prev;
	return true;
}

FLAC_API FLAC__MetadataType FLAC__metadata_iterator_get_block_type(const FLAC__Metadata_Iterator *iterator)
{
	FLAC__ASSERT(0 != iterator);
	FLAC__ASSERT(0 != iterator->current);
	FLAC__ASSERT(0 != iterator->current->data);

	return iterator->current->data->type;
}

FLAC_API FLAC__StreamMetadata *FLAC__metadata_iterator_get_block(FLAC__Metadata_Iterator *iterator)
{
	FLAC__ASSERT(0 != iterator);
	FLAC__ASSERT(0 != iterator->current);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -