summaryrefslogtreecommitdiff
path: root/src/libFLAC
diff options
context:
space:
mode:
authorJosh Coalson <jcoalson@users.sourceforce.net>2004-07-10 00:39:01 +0000
committerJosh Coalson <jcoalson@users.sourceforce.net>2004-07-10 00:39:01 +0000
commitea25cb36150ee32cbbeadab3c3eefe1577476a31 (patch)
tree129a4b57d0a681725f4d56297704c2ec4c5a3154 /src/libFLAC
parentd8934e21344d51731ed7806ed600de1eeb8757ab (diff)
downloadflac-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.c346
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) {