begin addition of callback-based option to metadata interfaces; start by converting chain reader to callback-based

This commit is contained in:
Josh Coalson 2004-07-10 00:39:01 +00:00
parent d8934e2134
commit ea25cb3615

View File

@ -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;
if(0 == (file = fopen(filename, "rb"))) {
chain->status = FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE;
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;
}
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->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);
return false;
}
chain->last_offset = ftell(iterator->file) + iterator->length;
FLAC__metadata_simple_iterator_delete(iterator);
chain->initial_length = chain_calculate_length_(chain);
return true;
}
@ -1342,25 +1408,14 @@ 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);
/* Note that we don't check:
* if(iterator->type >= FLAC__METADATA_TYPE_UNDEFINED)
* we just will read in an opaque block
*/
return true;
}
@ -1369,40 +1424,55 @@ FLAC__bool read_metadata_block_data_(FLAC__Metadata_SimpleIterator *iterator, FL
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;
case FLAC__METADATA_TYPE_PADDING:
iterator->status = read_metadata_block_data_padding_(iterator->file, &block->data.padding, block->length);
break;
case FLAC__METADATA_TYPE_APPLICATION:
iterator->status = read_metadata_block_data_application_(iterator->file, &block->data.application, block->length);
break;
case FLAC__METADATA_TYPE_SEEKTABLE:
iterator->status = read_metadata_block_data_seektable_(iterator->file, &block->data.seek_table, block->length);
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
iterator->status = read_metadata_block_data_vorbis_comment_(iterator->file, &block->data.vorbis_comment);
break;
case FLAC__METADATA_TYPE_CUESHEET:
iterator->status = read_metadata_block_data_cuesheet_(iterator->file, &block->data.cue_sheet);
break;
default:
iterator->status = read_metadata_block_data_unknown_(iterator->file, &block->data.unknown, block->length);
break;
}
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__Metadata_SimpleIteratorStatus read_metadata_block_data_streaminfo_(FILE *file, FLAC__StreamMetadata_StreamInfo *block)
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;
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) {