diff options
author | Josh Coalson <jcoalson@users.sourceforce.net> | 2004-07-10 00:39:01 +0000 |
---|---|---|
committer | Josh Coalson <jcoalson@users.sourceforce.net> | 2004-07-10 00:39:01 +0000 |
commit | ea25cb36150ee32cbbeadab3c3eefe1577476a31 (patch) | |
tree | 129a4b57d0a681725f4d56297704c2ec4c5a3154 /src/libFLAC | |
parent | d8934e21344d51731ed7806ed600de1eeb8757ab (diff) | |
download | flac-ea25cb36150ee32cbbeadab3c3eefe1577476a31.tar.gz |
begin addition of callback-based option to metadata interfaces; start by converting chain reader to callback-based
Diffstat (limited to 'src/libFLAC')
-rw-r--r-- | src/libFLAC/metadata_iterators.c | 346 |
1 files changed, 214 insertions, 132 deletions
diff --git a/src/libFLAC/metadata_iterators.c b/src/libFLAC/metadata_iterators.c index b39ca6f5..f00af247 100644 --- a/src/libFLAC/metadata_iterators.c +++ b/src/libFLAC/metadata_iterators.c @@ -74,15 +74,17 @@ static FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes); static FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator); static FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetadata_Padding *block, unsigned block_length); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_(FILE *file, FLAC__StreamMetadata_Application *block, unsigned block_length); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *file, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetadata_VorbisComment_Entry *entry); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FILE *file, FLAC__StreamMetadata_CueSheet_Track *track); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_(FILE *file, FLAC__StreamMetadata_CueSheet *block); -static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_(FILE *file, FLAC__StreamMetadata_Unknown *block, unsigned block_length); +static FLAC__bool read_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__bool *is_last, FLAC__MetadataType *type, unsigned *length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_StreamInfo *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Application *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_SeekTable *block, unsigned block_length); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment_Entry *entry); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_VorbisComment *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block); +static FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length); static FLAC__bool write_metadata_block_header_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); static FLAC__bool write_metadata_block_data_(FILE *file, FLAC__Metadata_SimpleIteratorStatus *status, const FLAC__StreamMetadata *block); @@ -104,6 +106,7 @@ static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator); static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator); /* return 0 if OK, 1 if read error, 2 if not a FLAC file */ +static unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb); static unsigned seek_to_first_metadata_block_(FILE *f); static FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append); @@ -119,6 +122,9 @@ static void cleanup_tempfile_(FILE **tempfile, char **tempfilename); static FLAC__bool get_file_stats_(const char *filename, struct stat *stats); static void set_file_stats_(const char *filename, struct stat *stats); +static int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence); +static FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle); + static FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status); @@ -356,6 +362,9 @@ static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *it iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; return false; case 2: + iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR; + return false; + case 3: iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE; return false; default: @@ -904,6 +913,92 @@ static FLAC__bool chain_merge_adjacent_padding_(FLAC__Metadata_Chain *chain, FLA return false; } +static FLAC__bool chain_read_cb_(FLAC__Metadata_Chain *chain, FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__IOCallback_Tell tell_cb, FLAC__IOCallback_Close close_cb) +{ + FLAC__Metadata_Node *node; + + FLAC__ASSERT(0 != chain); + + /* we assume we're already at the beginning of the file */ + + switch(seek_to_first_metadata_block_cb_(handle, read_cb, seek_cb)) { + case 0: + break; + case 1: + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + case 2: + chain->status = FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR; + return false; + case 3: + chain->status = FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE; + return false; + default: + FLAC__ASSERT(0); + return false; + } + + { + FLAC__int64 pos = tell_cb(handle); + if(pos < 0) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + chain->first_offset = (long)pos; + } + + { + FLAC__bool is_last; + FLAC__MetadataType type; + unsigned length; + + do { + node = node_new_(); + if(0 == node) { + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + if(!read_metadata_block_header_cb_(handle, read_cb, &is_last, &type, &length)) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + + node->data = FLAC__metadata_object_new(type); + if(0 == node->data) { + node_delete_(node); + chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; + return false; + } + + node->data->is_last = is_last; + node->data->length = length; + + chain->status = get_equivalent_status_(read_metadata_block_data_cb_(handle, read_cb, seek_cb, node->data)); + if(chain->status != FLAC__METADATA_CHAIN_STATUS_OK) { + node_delete_(node); + return false; + } + chain_append_node_(chain, node); + } while(!is_last); + } + + { + FLAC__int64 pos = tell_cb(handle); + if(pos < 0) { + chain->status = FLAC__METADATA_CHAIN_STATUS_READ_ERROR; + return false; + } + chain->last_offset = (long)pos; + } + + close_cb(handle); + + chain->initial_length = chain_calculate_length_(chain); + + return true; +} + FLAC_API FLAC__Metadata_Chain *FLAC__metadata_chain_new() { FLAC__Metadata_Chain *chain = (FLAC__Metadata_Chain*)calloc(1, sizeof(FLAC__Metadata_Chain)); @@ -950,8 +1045,7 @@ FLAC_API FLAC__Metadata_ChainStatus FLAC__metadata_chain_status(FLAC__Metadata_C FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const char *filename) { - FLAC__Metadata_SimpleIterator *iterator; - FLAC__Metadata_Node *node; + FILE *file; FLAC__ASSERT(0 != chain); FLAC__ASSERT(0 != filename); @@ -961,42 +1055,14 @@ FLAC_API FLAC__bool FLAC__metadata_chain_read(FLAC__Metadata_Chain *chain, const return false; } - if(0 == (iterator = FLAC__metadata_simple_iterator_new())) { - chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; - return false; - } - - if(!FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) { - chain->status = get_equivalent_status_(iterator->status); - return false; - } - - chain->first_offset = iterator->offset[iterator->depth]; - - do { - node = node_new_(); - if(0 == node) { - chain->status = FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR; - return false; - } - node->data = FLAC__metadata_simple_iterator_get_block(iterator); - if(0 == node->data) { - node_delete_(node); - chain->status = get_equivalent_status_(iterator->status); - return false; - } - chain_append_node_(chain, node); - } while(FLAC__metadata_simple_iterator_next(iterator)); - - if(!iterator->is_last || iterator->status != FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK) { - chain->status = get_equivalent_status_(iterator->status); + if(0 == (file = fopen(filename, "rb"))) { + chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE; return false; } - chain->last_offset = ftell(iterator->file) + iterator->length; - FLAC__metadata_simple_iterator_delete(iterator); + if(!chain_read_cb_(chain, file, (FLAC__IOCallback_Read)fread, fseek_wrapper_, ftell_wrapper_, (FLAC__IOCallback_Close)fclose)) + return false; /* chain->status is already set by chain_read_cb_ */ - chain->initial_length = chain_calculate_length_(chain); return true; } @@ -1342,19 +1408,37 @@ FLAC__uint64 unpack_uint64_(FLAC__byte *b, unsigned bytes) FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) { - FLAC__byte raw_header[FLAC__STREAM_METADATA_HEADER_LENGTH]; - FLAC__ASSERT(0 != iterator); FLAC__ASSERT(0 != iterator->file); - if(fread(raw_header, 1, FLAC__STREAM_METADATA_HEADER_LENGTH, iterator->file) != FLAC__STREAM_METADATA_HEADER_LENGTH) { + 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; } - iterator->is_last = raw_header[0] & 0x80? true : false; - iterator->type = (FLAC__MetadataType)(raw_header[0] & 0x7f); - iterator->length = unpack_uint32_(raw_header + 1, 3); + 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) @@ -1364,45 +1448,31 @@ FLAC__bool read_metadata_block_header_(FLAC__Metadata_SimpleIterator *iterator) return true; } -FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block) +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata *block) { - FLAC__ASSERT(0 != iterator); - FLAC__ASSERT(0 != iterator->file); - switch(block->type) { case FLAC__METADATA_TYPE_STREAMINFO: - iterator->status = read_metadata_block_data_streaminfo_(iterator->file, &block->data.stream_info); - break; + return read_metadata_block_data_streaminfo_cb_(handle, read_cb, &block->data.stream_info); case FLAC__METADATA_TYPE_PADDING: - iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length); - break; + return read_metadata_block_data_padding_cb_(handle, seek_cb, &block->data.padding, block->length); case FLAC__METADATA_TYPE_APPLICATION: - iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length); - break; + return read_metadata_block_data_application_cb_(handle, read_cb, &block->data.application, block->length); case FLAC__METADATA_TYPE_SEEKTABLE: - iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length); - break; + return read_metadata_block_data_seektable_cb_(handle, read_cb, &block->data.seek_table, block->length); case FLAC__METADATA_TYPE_VORBIS_COMMENT: - iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment); - break; + return read_metadata_block_data_vorbis_comment_cb_(handle, read_cb, &block->data.vorbis_comment); case FLAC__METADATA_TYPE_CUESHEET: - iterator->status = read_metadata_block_data_cuesheet_(iterator->file, &block->data.cue_sheet); - break; + return read_metadata_block_data_cuesheet_cb_(handle, read_cb, &block->data.cue_sheet); default: - iterator->status = read_metadata_block_data_unknown_(iterator->file, &block->data.unknown, block->length); - break; + return read_metadata_block_data_unknown_cb_(handle, read_cb, &block->data.unknown, block->length); } - - return (iterator->status == FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK); } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block) +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; - FLAC__ASSERT(0 != file); - - if(fread(buffer, 1, FLAC__STREAM_METADATA_STREAMINFO_LENGTH, file) != FLAC__STREAM_METADATA_STREAMINFO_LENGTH) + 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; @@ -1425,25 +1495,21 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *f } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_(FILE *file, FLAC__StreamMetadata_Padding *block, unsigned block_length) +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Seek seek_cb, FLAC__StreamMetadata_Padding *block, unsigned block_length) { - FLAC__ASSERT(0 != file); - (void)block; /* nothing to do; we don't care about reading the padding bytes */ - if(0 != fseek(file, block_length, SEEK_CUR)) + 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_(FILE *file, FLAC__StreamMetadata_Application *block, unsigned block_length) +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; - FLAC__ASSERT(0 != file); - - if(fread(block->id, 1, id_bytes, file) != id_bytes) + if(read_cb(block->id, 1, id_bytes, handle) != id_bytes) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; block_length -= id_bytes; @@ -1455,19 +1521,18 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_application_(FILE * if(0 == (block->data = (FLAC__byte*)malloc(block_length))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; - if(fread(block->data, 1, block_length, file) != block_length) + 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_(FILE *file, FLAC__StreamMetadata_SeekTable *block, unsigned block_length) +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(0 != file); FLAC__ASSERT(block_length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH == 0); block->num_points = block_length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; @@ -1478,7 +1543,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *fi return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < block->num_points; i++) { - if(fread(buffer, 1, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH, file) != FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) + 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); @@ -1489,15 +1554,14 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_seektable_(FILE *fi return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entry_(FILE *file, FLAC__StreamMetadata_VorbisComment_Entry *entry) +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); - FLAC__ASSERT(0 != file); - if(fread(buffer, 1, entry_length_len, file) != entry_length_len) + 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); @@ -1511,14 +1575,14 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_entr if(0 == (entry->entry = (FLAC__byte*)malloc(entry->length))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; - if(fread(entry->entry, 1, entry->length, file) != entry->length) + if(read_cb(entry->entry, 1, entry->length, handle) != entry->length) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; } return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FILE *file, FLAC__StreamMetadata_VorbisComment *block) +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; @@ -1526,12 +1590,11 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FIL FLAC__byte buffer[4]; /* magic number is asserted below */ FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN / 8 == 4); - FLAC__ASSERT(0 != file); - if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_vorbis_comment_entry_(file, &(block->vendor_string)))) + 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(fread(buffer, 1, num_comments_len, file) != num_comments_len) + 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); @@ -1542,14 +1605,14 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_vorbis_comment_(FIL 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_(file, block->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; } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FILE *file, FLAC__StreamMetadata_CueSheet_Track *track) +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet_Track *track) { unsigned i, len; FLAC__byte buffer[32]; /* asserted below that this is big enough */ @@ -1558,28 +1621,26 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FIL FLAC__ASSERT(sizeof(buffer) >= FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN/8); FLAC__ASSERT(sizeof(buffer) >= (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8); - FLAC__ASSERT(0 != file); - FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; track->offset = unpack_uint64_(buffer, len); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; track->number = (FLAC__byte)unpack_uint32_(buffer, len); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN / 8; - if(fread(track->isrc, 1, len, file) != len) + if(read_cb(track->isrc, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) % 8 == 0); len = (FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN + FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN) / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN == 1); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN == 1); @@ -1588,7 +1649,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FIL FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; track->num_indices = (FLAC__byte)unpack_uint32_(buffer, len); @@ -1601,55 +1662,54 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_track_(FIL for(i = 0; i < track->num_indices; i++) { FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; track->indices[i].offset = unpack_uint64_(buffer, len); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; track->indices[i].number = (FLAC__byte)unpack_uint32_(buffer, len); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; } return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_(FILE *file, FLAC__StreamMetadata_CueSheet *block) +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_CueSheet *block) { unsigned i, len; FLAC__Metadata_SimpleIteratorStatus status; FLAC__byte buffer[1024]; /* MSVC needs a constant expression so we put a magic number and assert */ - FLAC__ASSERT(0 != file); FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN)/8 <= sizeof(buffer)); FLAC__ASSERT(sizeof(FLAC__uint64) <= sizeof(buffer)); FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN / 8; - if(fread(block->media_catalog_number, 1, len, file) != len) + if(read_cb(block->media_catalog_number, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; block->lead_in = unpack_uint64_(buffer, len); FLAC__ASSERT((FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) % 8 == 0); len = (FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN + FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN) / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; block->is_cd = buffer[0]&0x80? true : false; FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN % 8 == 0); len = FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN / 8; - if(fread(buffer, 1, len, file) != len) + if(read_cb(buffer, 1, len, handle) != len) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; block->num_tracks = unpack_uint32_(buffer, len); @@ -1660,17 +1720,15 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_cuesheet_(FILE *fil return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; for(i = 0; i < block->num_tracks; i++) { - if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_(file, block->tracks + i))) + if(FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK != (status = read_metadata_block_data_cuesheet_track_cb_(handle, read_cb, block->tracks + i))) return status; } return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK; } -FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_(FILE *file, FLAC__StreamMetadata_Unknown *block, unsigned block_length) +FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Unknown *block, unsigned block_length) { - FLAC__ASSERT(0 != file); - if(block_length == 0) { block->data = 0; } @@ -1678,7 +1736,7 @@ FLAC__Metadata_SimpleIteratorStatus read_metadata_block_data_unknown_(FILE *file if(0 == (block->data = (FLAC__byte*)malloc(block_length))) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR; - if(fread(block->data, 1, block_length, file) != block_length) + if(read_cb(block->data, 1, block_length, handle) != block_length) return FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR; } @@ -2191,57 +2249,65 @@ FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator) return read_metadata_block_header_(iterator); } -unsigned seek_to_first_metadata_block_(FILE *f) +/* return meanings: + * 0: ok + * 1: read error + * 2: seek error + * 3: not a FLAC file + */ +unsigned seek_to_first_metadata_block_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Seek seek_cb) { FLAC__byte buffer[4]; size_t n; unsigned i; - FLAC__ASSERT(0 != f); FLAC__ASSERT(FLAC__STREAM_SYNC_LENGTH == 4); /* skip any id3v2 tag */ errno = 0; - n = fread(buffer, 1, 4, f); + n = read_cb(buffer, 1, 4, handle); if(errno) return 1; - else - if(n != 4) - return 2; + else if(n != 4) + return 3; else if(0 == memcmp(buffer, "ID3", 3)) { unsigned tag_length = 0; /* skip to the tag length */ - if(fseek(f, 2, SEEK_CUR) < 0) - return 1; + if(seek_cb(handle, 2, SEEK_CUR) < 0) + return 2; /* read the length */ for(i = 0; i < 4; i++) { - if(fread(buffer, 1, 1, f) < 1 || buffer[0] & 0x80) + if(read_cb(buffer, 1, 1, handle) < 1 || buffer[0] & 0x80) return 1; tag_length <<= 7; tag_length |= (buffer[0] & 0x7f); } /* skip the rest of the tag */ - if(fseek(f, tag_length, SEEK_CUR) < 0) - return 1; + if(seek_cb(handle, tag_length, SEEK_CUR) < 0) + return 2; /* read the stream sync code */ errno = 0; - n = fread(buffer, 1, 4, f); + n = read_cb(buffer, 1, 4, handle); if(errno) return 1; - else - if(n != 4) - return 2; + else if(n != 4) + return 3; } /* check for the fLaC signature */ if(0 == memcmp(FLAC__STREAM_SYNC_STRING, buffer, FLAC__STREAM_SYNC_LENGTH)) return 0; else - return 2; + return 3; +} + +unsigned seek_to_first_metadata_block_(FILE *f) +{ + return seek_to_first_metadata_block_cb_((FLAC__IOHandle)f, (FLAC__IOCallback_Read)fread, fseek_wrapper_); } FLAC__bool simple_iterator_copy_file_prefix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, FLAC__bool append) @@ -2490,6 +2556,22 @@ void set_file_stats_(const char *filename, struct stat *stats) #endif } +/* @@@ WATCHOUT @@@ + * We cast FLAC__int64 to long and use fseek()/ftell() because + * none of our operations on metadata is ever likely to go past + * 2 gigabytes. + */ +int fseek_wrapper_(FLAC__IOHandle handle, FLAC__int64 offset, int whence) +{ + FLAC__ASSERT(offset <= 0x7fffffff); + return fseek((FILE*)handle, (long)offset, whence); +} + +FLAC__int64 ftell_wrapper_(FLAC__IOHandle handle) +{ + return (long)ftell((FILE*)handle); +} + FLAC__Metadata_ChainStatus get_equivalent_status_(FLAC__Metadata_SimpleIteratorStatus status) { switch(status) { |