📄 metadata_iterators.c
字号:
return iterator->current->data;
}
FLAC_API FLAC__bool FLAC__metadata_iterator_set_block(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
{
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != block);
return FLAC__metadata_iterator_delete_block(iterator, false) && FLAC__metadata_iterator_insert_block_after(iterator, block);
}
FLAC_API FLAC__bool FLAC__metadata_iterator_delete_block(FLAC__Metadata_Iterator *iterator, FLAC__bool replace_with_padding)
{
FLAC__Metadata_Node *save;
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->current);
if(0 == iterator->current->prev) {
FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
return false;
}
save = iterator->current->prev;
if(replace_with_padding) {
FLAC__metadata_object_delete_data(iterator->current->data);
iterator->current->data->type = FLAC__METADATA_TYPE_PADDING;
}
else {
chain_delete_node_(iterator->chain, iterator->current);
}
iterator->current = save;
return true;
}
FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_before(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
{
FLAC__Metadata_Node *node;
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->current);
FLAC__ASSERT(0 != block);
if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
return false;
if(0 == iterator->current->prev) {
FLAC__ASSERT(iterator->current->data->type == FLAC__METADATA_TYPE_STREAMINFO);
return false;
}
if(0 == (node = node_new_()))
return false;
node->data = block;
iterator_insert_node_(iterator, node);
iterator->current = node;
return true;
}
FLAC_API FLAC__bool FLAC__metadata_iterator_insert_block_after(FLAC__Metadata_Iterator *iterator, FLAC__StreamMetadata *block)
{
FLAC__Metadata_Node *node;
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->current);
FLAC__ASSERT(0 != block);
if(block->type == FLAC__METADATA_TYPE_STREAMINFO)
return false;
if(0 == (node = node_new_()))
return false;
node->data = block;
iterator_insert_node_after_(iterator, node);
iterator->current = node;
return true;
}
/****************************************************************************
*
* Local function definitions
*
***************************************************************************/
void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
{
unsigned i;
b += bytes;
for(i = 0; i < bytes; i++) {
*(--b) = (FLAC__byte)(val & 0xff);
val >>= 8;
}
}
void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes)
{
unsigned i;
for(i = 0; i < bytes; i++) {
*(b++) = (FLAC__byte)(val & 0xff);
val >>= 8;
}
}
void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes)
{
unsigned i;
b += bytes;
for(i = 0; i < bytes; i++) {
*(--b) = (FLAC__byte)(val & 0xff);
val >>= 8;
}
}
FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes)
{
FLAC__uint32 ret = 0;
unsigned i;
for(i = 0; i < bytes; i++)
ret = (ret << 8) | (FLAC__uint32)(*b++);
return ret;
}
FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes)
{
FLAC__uint32 ret = 0;
unsigned i;
b += bytes;
for(i = 0; i < bytes; i++)
ret = (ret << 8) | (FLAC__uint32)(*--b);
return ret;
}
FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes)
{
FLAC__uint64 ret = 0;
unsigned i;
for(i = 0; i < bytes; i++)
ret = (ret << 8) | (FLAC__uint64)(*b++);
return ret;
}
FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator)
{
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->file);
if(!read_metadata_block_header_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, &iterator->is_last, &iterator->type, &iterator->length)) {
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
return false;
}
return true;
}
FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block)
{
FLAC__ASSERT(0 != iterator);
FLAC__ASSERT(0 != iterator->file);
iterator->status = read_metadata_block_data_cb_((FLAC__IOHandle)iterator->file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, block);
return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK);
}
FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length)
{
FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH];
if(read_cb(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, handle) != FLAC__STREAM_METADATA_HEADER_LENGTH)
return false;
*is_last = raw_header[0] & 0x80? true : false;
*type = (FLAC__MetadataType)(raw_header[0] & 0x7f);
*length = unpack_uint32_(raw_header + 1, 3);
/* Note that we don't check:
* if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED)
* we just will read in an opaque block
*/
return true;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block)
{
switch(block->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info);
case FLAC__METADATA_TYPE_PADDING:
return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length);
case FLAC__METADATA_TYPE_APPLICATION:
return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length);
case FLAC__METADATA_TYPE_SEEKTABLE:
return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length);
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment);
case FLAC__METADATA_TYPE_CUESHEET:
return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet);
default:
return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length);
}
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block)
{
FLAC__byte buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH], *b;
if(read_cb(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, handle) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
b = buffer;
/* we are using hardcoded numbers for simplicity but we should
* probably eventually write a bit-level unpacker and use the
* _STREAMINFO_ constants.
*/
block->min_blocksize = unpack_uint32_(b, 2); b += 2;
block->max_blocksize = unpack_uint32_(b, 2); b += 2;
block->min_framesize = unpack_uint32_(b, 3); b += 3;
block->max_framesize = unpack_uint32_(b, 3); b += 3;
block->sample_rate = (unpack_uint32_(b, 2) << 4) | ((unsigned)(b[2] & 0xf0) >> 4);
block->channels = (unsigned)((b[2] & 0x0e) >> 1) + 1;
block->bits_per_sample = ((((unsigned)(b[2] & 0x01)) << 4) | (((unsigned)(b[3] & 0xf0)) >> 4)) + 1;
block->total_samples = (((FLAC__uint64)(b[3] & 0x0f)) << 32) | unpack_uint64_(b+4, 4);
memcpy(block->md5sum, b+8, 16);
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length)
{
(void)block; /* nothing to do; we don't care about reading the padding bytes */
if(0 != seek_cb(handle, block_length, SEEK_CUR))
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR;
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length)
{
const unsigned id_bytes = FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8;
if(read_cb(block->id, 1, id_bytes, handle) != id_bytes)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
block_length -= id_bytes;
if(block_length == 0) {
block->data = 0;
}
else {
if(0 == (block->data = (FLAC__byte*)malloc(block_length)))
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
if(read_cb(block->data, 1, block_length, handle) != block_length)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
}
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length)
{
unsigned i;
FLAC__byte buffer[FLAC__STREAM_METADATA_SEEKPOINT_LENGTH];
FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0);
block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
if(block->num_points == 0)
block->points = 0;
else if(0 == (block->points = (FLAC__StreamMetadata_SeekPoint*)malloc(block->num_points * sizeof(FLAC__StreamMetadata_SeekPoint))))
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
for(i = 0; i < block->num_points; i++) {
if(read_cb(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, handle) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
/* some MAGIC NUMBERs here */
block->points[i].sample_number = unpack_uint64_(buffer, 8);
block->points[i].stream_offset = unpack_uint64_(buffer+8, 8);
block->points[i].frame_samples = unpack_uint32_(buffer+16, 2);
}
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry)
{
const unsigned entry_length_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8;
FLAC__byte buffer[4]; /* magic number is asserted below */
FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN / 8 == 4);
if(read_cb(buffer, 1, entry_length_len, handle) != entry_length_len)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
entry->length = unpack_uint32_little_endian_(buffer, entry_length_len);
if(0 != entry->entry)
free(entry->entry);
if(entry->length == 0) {
entry->entry = 0;
}
else {
if(0 == (entry->entry = (FLAC__byte*)malloc(entry->length+1)))
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
if(read_cb(entry->entry, 1, entry->length, handle) != entry->length)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
entry->entry[entry->length] = '\0';
}
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block)
{
unsigned i;
FLAC__Metadata_SimpleIteratorStatus status;
const unsigned num_comments_len = FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8;
FLAC__byte buffer[4]; /* magic number is asserted below */
FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4);
if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, &(block->vendor_string))))
return status;
if(read_cb(buffer, 1, num_comments_len, handle) != num_comments_len)
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR;
block->num_comments = unpack_uint32_little_endian_(buffer, num_comments_len);
if(block->num_comments == 0) {
block->comments = 0;
}
else if(0 == (block->comments = (FLAC__StreamMetadata_VorbisComment_Entry*)calloc(block->num_comments, sizeof(FLAC__StreamMetadata_VorbisComment_Entry))))
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR;
for(i = 0; i < block->num_comments; i++) {
if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_cb_(handle, read_cb, block->comments + i)))
return status;
}
return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
}
FL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -