Commit f6271747 authored by Libretro-Admin's avatar Libretro-Admin
Browse files

Further slim down on libflac

parent 4a65bd11
Pipeline #39750 passed with stages
in 14 minutes and 22 seconds
......@@ -135,7 +135,7 @@ endif
ifeq ($(USE_CODEC_FLAC),1)
INCFLAGS += -I$(LIBFLAC_DIR)/include
SOURCES_C += $(LIBFLAC_DIR)/bitmath.c \
SOURCES_C += \
$(LIBFLAC_DIR)/bitreader.c \
$(LIBFLAC_DIR)/cpu.c \
$(LIBFLAC_DIR)/crc.c \
......@@ -145,10 +145,7 @@ SOURCES_C += $(LIBFLAC_DIR)/bitmath.c \
$(LIBFLAC_DIR)/lpc.c \
$(LIBFLAC_DIR)/md5.c \
$(LIBFLAC_DIR)/memory.c \
$(LIBFLAC_DIR)/metadata_iterators.c \
$(LIBFLAC_DIR)/metadata_object.c \
$(LIBFLAC_DIR)/ogg_decoder_aspect.c \
$(LIBFLAC_DIR)/ogg_helper.c \
$(LIBFLAC_DIR)/ogg_mapping.c \
$(LIBFLAC_DIR)/stream_decoder.c \
$(LIBFLAC_DIR)/window.c
......
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001-2009 Josh Coalson
* Copyright (C) 2011-2013 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "private/bitmath.h"
#include "FLAC/assert.h"
/* An example of what FLAC__bitmath_silog2() computes:
*
* silog2(-10) = 5
* silog2(- 9) = 5
* silog2(- 8) = 4
* silog2(- 7) = 4
* silog2(- 6) = 4
* silog2(- 5) = 4
* silog2(- 4) = 3
* silog2(- 3) = 3
* silog2(- 2) = 2
* silog2(- 1) = 2
* silog2( 0) = 0
* silog2( 1) = 2
* silog2( 2) = 3
* silog2( 3) = 3
* silog2( 4) = 4
* silog2( 5) = 4
* silog2( 6) = 4
* silog2( 7) = 4
* silog2( 8) = 5
* silog2( 9) = 5
* silog2( 10) = 5
*/
unsigned FLAC__bitmath_silog2(int v)
{
while(1) {
if(v == 0) {
return 0;
}
else if(v > 0) {
unsigned l = 0;
while(v) {
l++;
v >>= 1;
}
return l+1;
}
else if(v == -1) {
return 2;
}
else {
v++;
v = -v;
}
}
}
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v)
{
while(1) {
if(v == 0) {
return 0;
}
else if(v > 0) {
unsigned l = 0;
while(v) {
l++;
v >>= 1;
}
return l+1;
}
else if(v == -1) {
return 2;
}
else {
v++;
v = -v;
}
}
}
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001-2009 Josh Coalson
* Copyright (C) 2011-2013 Xiph.Org Foundation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/stat.h> /* for stat(), maybe chmod() */
#include "private/metadata.h"
#include "FLAC/assert.h"
#include "FLAC/stream_decoder.h"
#include "share/alloc.h"
#include "share/compat.h"
#include "share/macros.h"
#include "share/safe_str.h"
#include "private/macros.h"
#include "private/memory.h"
#include <retro_miscellaneous.h>
/* Alias the first (in share/alloc.h) to the second (in src/libFLAC/memory.c). */
#define safe_malloc_mul_2op_ safe_malloc_mul_2op_p
/****************************************************************************
*
* Local function declarations
*
***************************************************************************/
static void pack_uint32_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
static void pack_uint32_little_endian_(FLAC__uint32 val, FLAC__byte *b, unsigned bytes);
static void pack_uint64_(FLAC__uint64 val, FLAC__byte *b, unsigned bytes);
static FLAC__uint32 unpack_uint32_(FLAC__byte *b, unsigned bytes);
static FLAC__uint32 unpack_uint32_little_endian_(FLAC__byte *b, unsigned bytes);
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__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_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__StreamMetadata_Picture *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);
static FLAC__bool write_metadata_block_header_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block);
static FLAC__bool write_metadata_block_data_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata *block);
static FLAC__bool write_metadata_block_data_streaminfo_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_StreamInfo *block);
static FLAC__bool write_metadata_block_data_padding_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Padding *block, unsigned block_length);
static FLAC__bool write_metadata_block_data_application_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Application *block, unsigned block_length);
static FLAC__bool write_metadata_block_data_seektable_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_SeekTable *block);
static FLAC__bool write_metadata_block_data_vorbis_comment_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_VorbisComment *block);
static FLAC__bool write_metadata_block_data_cuesheet_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_CueSheet *block);
static FLAC__bool write_metadata_block_data_picture_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Picture *block);
static FLAC__bool write_metadata_block_data_unknown_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Write write_cb, const FLAC__StreamMetadata_Unknown *block, unsigned block_length);
static FLAC__bool write_metadata_block_stationary_(FLAC__Metadata_SimpleIterator *iterator, const FLAC__StreamMetadata *block);
static FLAC__bool write_metadata_block_stationary_with_padding_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, unsigned padding_length, FLAC__bool padding_is_last);
static FLAC__bool rewrite_whole_file_(FLAC__Metadata_SimpleIterator *iterator, FLAC__StreamMetadata *block, FLAC__bool append);
static void simple_iterator_push_(FLAC__Metadata_SimpleIterator *iterator);
static FLAC__bool simple_iterator_pop_(FLAC__Metadata_SimpleIterator *iterator);
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);
static FLAC__bool simple_iterator_copy_file_postfix_(FLAC__Metadata_SimpleIterator *iterator, FILE **tempfile, char **tempfilename, int fixup_is_last_code, FLAC__off_t fixup_is_last_flag_offset, FLAC__bool backup);
static FLAC__bool copy_n_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
static FLAC__bool copy_n_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__off_t bytes, FLAC__Metadata_SimpleIteratorStatus *status);
static FLAC__bool copy_remaining_bytes_from_file_(FILE *file, FILE *tempfile, FLAC__Metadata_SimpleIteratorStatus *status);
static FLAC__bool copy_remaining_bytes_from_file_cb_(FLAC__IOHandle handle, FLAC__IOCallback_Read read_cb, FLAC__IOCallback_Eof eof_cb, FLAC__IOHandle temp_handle, FLAC__IOCallback_Write temp_write_cb, FLAC__Metadata_SimpleIteratorStatus *status);
static FLAC__bool open_tempfile_(const char *filename, const char *tempfile_path_prefix, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
static FLAC__bool transport_tempfile_(const char *filename, FILE **tempfile, char **tempfilename, FLAC__Metadata_SimpleIteratorStatus *status);
static void cleanup_tempfile_(FILE **tempfile, char **tempfilename);
static FLAC__bool get_file_stats_(const char *filename, struct flac_stat_s *stats);
static void set_file_stats_(const char *filename, struct flac_stat_s *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);
#ifdef FLAC__VALGRIND_TESTING
static size_t local__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t ret = fwrite(ptr, size, nmemb, stream);
if(!ferror(stream))
fflush(stream);
return ret;
}
#else
#define local__fwrite fwrite
#endif
/****************************************************************************
*
* Level 0 implementation
*
***************************************************************************/
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
typedef struct {
FLAC__bool got_error;
FLAC__StreamMetadata *object;
} level0_client_data;
static FLAC__StreamMetadata *get_one_metadata_block_(const char *filename, FLAC__MetadataType type)
{
level0_client_data cd;
FLAC__StreamDecoder *decoder;
FLAC__ASSERT(0 != filename);
cd.got_error = false;
cd.object = 0;
decoder = FLAC__stream_decoder_new();
if(0 == decoder)
return 0;
FLAC__stream_decoder_set_md5_checking(decoder, false);
FLAC__stream_decoder_set_metadata_ignore_all(decoder);
FLAC__stream_decoder_set_metadata_respond(decoder, type);
if(FLAC__stream_decoder_init_file(decoder, filename, write_callback_, metadata_callback_, error_callback_, &cd) != FLAC__STREAM_DECODER_INIT_STATUS_OK || cd.got_error) {
(void)FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
return 0;
}
if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder) || cd.got_error) {
(void)FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
if(0 != cd.object)
FLAC__metadata_object_delete(cd.object);
return 0;
}
(void)FLAC__stream_decoder_finish(decoder);
FLAC__stream_decoder_delete(decoder);
return cd.object;
}
FLAC_API FLAC__bool FLAC__metadata_get_streaminfo(const char *filename, FLAC__StreamMetadata *streaminfo)
{
FLAC__StreamMetadata *object;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != streaminfo);
object = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_STREAMINFO);
if (object) {
/* can just copy the contents since STREAMINFO has no internal structure */
*streaminfo = *object;
FLAC__metadata_object_delete(object);
return true;
}
else {
return false;
}
}
FLAC_API FLAC__bool FLAC__metadata_get_tags(const char *filename, FLAC__StreamMetadata **tags)
{
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != tags);
*tags = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_VORBIS_COMMENT);
return 0 != *tags;
}
FLAC_API FLAC__bool FLAC__metadata_get_cuesheet(const char *filename, FLAC__StreamMetadata **cuesheet)
{
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != cuesheet);
*cuesheet = get_one_metadata_block_(filename, FLAC__METADATA_TYPE_CUESHEET);
return 0 != *cuesheet;
}
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
(void)decoder, (void)frame, (void)buffer, (void)client_data;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
{
level0_client_data *cd = (level0_client_data *)client_data;
(void)decoder;
/*
* we assume we only get here when the one metadata block we were
* looking for was passed to us
*/
if(!cd->got_error && 0 == cd->object) {
if(0 == (cd->object = FLAC__metadata_object_clone(metadata)))
cd->got_error = true;
}
}
void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
level0_client_data *cd = (level0_client_data *)client_data;
(void)decoder;
if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
cd->got_error = true;
}
FLAC_API FLAC__bool FLAC__metadata_get_picture(const char *filename, FLAC__StreamMetadata **picture, FLAC__StreamMetadata_Picture_Type type, const char *mime_type, const FLAC__byte *description, unsigned max_width, unsigned max_height, unsigned max_depth, unsigned max_colors)
{
FLAC__Metadata_SimpleIterator *it;
FLAC__uint64 max_area_seen = 0;
FLAC__uint64 max_depth_seen = 0;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != picture);
*picture = 0;
it = FLAC__metadata_simple_iterator_new();
if(0 == it)
return false;
if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
FLAC__metadata_simple_iterator_delete(it);
return false;
}
do {
if(FLAC__metadata_simple_iterator_get_block_type(it) == FLAC__METADATA_TYPE_PICTURE) {
FLAC__StreamMetadata *obj = FLAC__metadata_simple_iterator_get_block(it);
FLAC__uint64 area = (FLAC__uint64)obj->data.picture.width * (FLAC__uint64)obj->data.picture.height;
/* check constraints */
if(
(type == (FLAC__StreamMetadata_Picture_Type)(-1) || type == obj->data.picture.type) &&
(mime_type == 0 || !strcmp(mime_type, obj->data.picture.mime_type)) &&
(description == 0 || !strcmp((const char *)description, (const char *)obj->data.picture.description)) &&
obj->data.picture.width <= max_width &&
obj->data.picture.height <= max_height &&
obj->data.picture.depth <= max_depth &&
obj->data.picture.colors <= max_colors &&
(area > max_area_seen || (area == max_area_seen && obj->data.picture.depth > max_depth_seen))
) {
if(*picture)
FLAC__metadata_object_delete(*picture);
*picture = obj;
max_area_seen = area;
max_depth_seen = obj->data.picture.depth;
}
else {
FLAC__metadata_object_delete(obj);
}
}
} while(FLAC__metadata_simple_iterator_next(it));
FLAC__metadata_simple_iterator_delete(it);
return (0 != *picture);
}
/****************************************************************************
*
* Level 1 implementation
*
***************************************************************************/
#define SIMPLE_ITERATOR_MAX_PUSH_DEPTH (1+4)
/* 1 for initial offset, +4 for our own personal use */
struct FLAC__Metadata_SimpleIterator {
FILE *file;
char *filename, *tempfile_path_prefix;
struct flac_stat_s stats;
FLAC__bool has_stats;
FLAC__bool is_writable;
FLAC__Metadata_SimpleIteratorStatus status;
FLAC__off_t offset[SIMPLE_ITERATOR_MAX_PUSH_DEPTH];
FLAC__off_t first_offset; /* this is the offset to the STREAMINFO block */
unsigned depth;
/* this is the metadata block header of the current block we are pointing to: */
FLAC__bool is_last;
FLAC__MetadataType type;
unsigned length;
};
FLAC_API const char * const FLAC__Metadata_SimpleIteratorStatusString[] = {
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ILLEGAL_INPUT",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_A_FLAC_FILE",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_NOT_WRITABLE",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_BAD_METADATA",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_READ_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_SEEK_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_WRITE_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_RENAME_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_UNLINK_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR",
"FLAC__METADATA_SIMPLE_ITERATOR_STATUS_INTERNAL_ERROR"
};
FLAC_API FLAC__Metadata_SimpleIterator *FLAC__metadata_simple_iterator_new(void)
{
FLAC__Metadata_SimpleIterator *iterator = calloc(1, sizeof(FLAC__Metadata_SimpleIterator));
if(0 != iterator) {
iterator->file = 0;
iterator->filename = 0;
iterator->tempfile_path_prefix = 0;
iterator->has_stats = false;
iterator->is_writable = false;
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
iterator->first_offset = iterator->offset[0] = -1;
iterator->depth = 0;
}
return iterator;
}
static void simple_iterator_free_guts_(FLAC__Metadata_SimpleIterator *iterator)
{
FLAC__ASSERT(0 != iterator);
if(0 != iterator->file) {
fclose(iterator->file);
iterator->file = 0;
if(iterator->has_stats)
set_file_stats_(iterator->filename, &iterator->stats);
}
if(0 != iterator->filename) {
free(iterator->filename);
iterator->filename = 0;
}
if(0 != iterator->tempfile_path_prefix) {
free(iterator->tempfile_path_prefix);
iterator->tempfile_path_prefix = 0;
}
}
FLAC_API void FLAC__metadata_simple_iterator_delete(FLAC__Metadata_SimpleIterator *iterator)
{
FLAC__ASSERT(0 != iterator);
simple_iterator_free_guts_(iterator);
free(iterator);
}
FLAC_API FLAC__Metadata_SimpleIteratorStatus FLAC__metadata_simple_iterator_status(FLAC__Metadata_SimpleIterator *iterator)
{
FLAC__Metadata_SimpleIteratorStatus status;
FLAC__ASSERT(0 != iterator);
status = iterator->status;
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_OK;
return status;
}
static FLAC__bool simple_iterator_prime_input_(FLAC__Metadata_SimpleIterator *iterator, FLAC__bool read_only)
{
unsigned ret;
FLAC__ASSERT(0 != iterator);
if(read_only || 0 == (iterator->file = flac_fopen(iterator->filename, "r+b"))) {
iterator->is_writable = false;
if(read_only || errno == EACCES) {
if(0 == (iterator->file = flac_fopen(iterator->filename, "rb"))) {
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
return false;
}
}
else {
iterator->status = FLAC__METADATA_SIMPLE_ITERATOR_STATUS_ERROR_OPENING_FILE;
return false;
}
}
else {
iterator->is_writable = true;
}
ret = seek_to_first_metadata_block_(iterator->file);
switch(ret) {
case 0:
iterator->depth = 0;
iterator->first_offset = iterator->offset[iterator->depth] = ftello(iterator->file);
return read_metadata_block_header_(iterator);
case 1:
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:
FLAC__ASSERT(0);
return false;
}
}
#if 0
@@@ If we decide to finish implementing this, put this comment back in metadata.h
/*
* The 'tempfile_path_prefix' allows you to specify a directory where
* tempfiles should go. Remember that if your metadata edits cause the
* FLAC file to grow, the entire file will have to be rewritten. If
* 'tempfile_path_prefix' is NULL, the temp file will be written in the
* same directory as the original FLAC file. This makes replacing the
* original with the tempfile fast but requires extra space in the same
* partition for the tempfile. If space is a problem, you can pass a
* directory name belonging to a different partition in
* 'tempfile_path_prefix'. Note that you should use the forward slash
* '/' as the directory separator. A trailing slash is not needed; it
* will be added automatically.
*/
FLAC__bool FLAC__metadata_simple_iterator_init(FLAC__Metadata_SimpleIterator *iterator, const char *filename, FLAC__bool preserve_file_stats, const char *tempfile_path_prefix);
#endif